DIRECTORY Alloc: TYPE USING [Handle, Notifier, AddNotify, DropNotify, Top, Words], ComData: TYPE USING [ idINT, interface, mainCtx, ownSymbols, switches, typeATOM, typeRefANY], ConvertUnsafe: TYPE USING [SubString], Literals: TYPE USING [STIndex], LiteralOps: TYPE USING [Find], RTBcd: TYPE USING [RefLitIndex, TypeIndex], Symbols: TYPE USING [ Base, SERecord, Name, Type, ISEIndex, CSEIndex, CTXIndex, MDIndex, BitAddress, nullType, ISENull, CTXNull, StandardContext, lZ, OwnMdi, MDNull, typeANY, ctxType, seType], SymbolOps: TYPE USING [ ClusterSe, EnterString, FirstCtxSe, MakeCtxSe, MakeNonCtxSe, NextSe, TypeForm, UnderType], SymbolSegment: TYPE USING [atType], SymLiteralOps: TYPE USING [RefLitItem], Table: TYPE USING [Base, Limit, Selector], Tree: TYPE USING [Link, NullIndex], TreeOps: TYPE USING [PopTree, PushLit, PushNode, PushSe, SetAttr, SetInfo], Types: TYPE USING [Equivalent]; SymLiteralPack: PROGRAM IMPORTS Alloc, LiteralOps, SymbolOps, TreeOps, Types, dataPtr: ComData EXPORTS SymLiteralOps = { OPEN Symbols; RefLitItem: TYPE = SymLiteralOps.RefLitItem; SymLitRecord: TYPE = RECORD [ SELECT tag: * FROM type => [canonical: BOOL, typeCode: Type], lit => [info: RefLitItem] ENDCASE]; SymLitIndex: TYPE = Table.Base RELATIVE ORDERED POINTER[0..Table.Limit) TO SymLitRecord; table: Alloc.Handle; atType: Table.Selector = SymbolSegment.atType; slb: Table.Base; seb: Symbols.Base; ctxb: Symbols.Base; UpdateBases: Alloc.Notifier = { seb _ base[seType]; ctxb _ base[ctxType]; slb _ base[atType]; seb _ base[seType]}; Matched: SIGNAL [m1, m2: Type] RETURNS [BOOL] = CODE; NameEqual: PROC [key, entry: Type] RETURNS [BOOL] = { RETURN [(key = entry) OR Isomorphic[key, entry ! Matched => {RESUME [FALSE]}]]}; Isomorphic: PROC [key, entry: Type] RETURNS [BOOL] = { RETURN [WITH type1: seb[key] SELECT FROM id => (SymbolOps.ClusterSe[key] = SymbolOps.ClusterSe[entry]), cons => WITH type2: seb[entry] SELECT FROM cons => WITH t1: type1 SELECT FROM record => WITH t2: type2 SELECT FROM record => (t1.fieldCtx = t2.fieldCtx) OR (~t1.painted AND ~t2.painted AND ( (SIGNAL Matched[key, entry]) OR IsoFields[t1.fieldCtx, t2.fieldCtx ! Matched => {IF m1=key AND m2=entry THEN RESUME [TRUE]}])), ENDCASE => FALSE, ref => WITH t2: type2 SELECT FROM ref => (t1.counted = t2.counted) AND (t1.ordered = t2.ordered) AND (t1.readOnly = t2.readOnly) AND Isomorphic[t1.refType, t2.refType], ENDCASE => FALSE, long => WITH t2: type2 SELECT FROM long => Isomorphic[t1.rangeType, t2.rangeType], ENDCASE => FALSE, any => WITH t2: type2 SELECT FROM any => TRUE, ENDCASE => FALSE, ENDCASE => (key = entry), ENDCASE => FALSE, ENDCASE => ERROR]}; IsoFields: PROC [ctx1, ctx2: CTXIndex] RETURNS [BOOL] = { sei1: ISEIndex _ SymbolOps.FirstCtxSe[ctx1]; sei2: ISEIndex _ SymbolOps.FirstCtxSe[ctx2]; UNTIL sei1 = sei2 DO IF seb[sei1].hash # seb[sei2].hash OR ~Isomorphic[seb[sei1].idType, seb[sei2].idType] THEN RETURN [FALSE]; sei1 _ SymbolOps.NextSe[sei1]; sei2 _ SymbolOps.NextSe[sei2]; ENDLOOP; RETURN [sei1 = sei2]}; Equivalent: PROC [key, entry: Type] RETURNS [BOOL] = { RETURN [(key = entry) OR ( Types.Equivalent[ [dataPtr.ownSymbols, SymbolOps.UnderType[key]], [dataPtr.ownSymbols, SymbolOps.UnderType[entry]]] AND ~Fuzzy[key, entry])]}; Fuzzy: PROC [sei1, sei2: Type] RETURNS [BOOL] = INLINE { RETURN [SymbolOps.TypeForm[sei1] = array AND (~seb[sei1].mark4 OR ~seb[sei2].mark4)]}; UTypeId: PUBLIC PROC [type: Type] RETURNS [mdi: MDIndex, index: Type] = { sei: Type = SymbolOps.ClusterSe[type]; WITH se: seb[sei] SELECT FROM id => { ctx: CTXIndex = se.idCtx; WITH c: ctxb[ctx] SELECT FROM included => IF c.level = lZ THEN {index _ sei; mdi _ OwnMdi} ELSE {index _ se.idValue; mdi _ c.module}; ENDCASE => { index _ sei; mdi _ IF Predeclared[sei] THEN MDNull ELSE OwnMdi}}; cons => { index _ sei; mdi _ WITH t: se SELECT FROM basic => MDNull, enumerated => IF t.valueCtx IN StandardContext THEN MDNull ELSE OwnMdi, record => IF t.fieldCtx IN StandardContext THEN MDNull ELSE OwnMdi, opaque => IF Predeclared[t.id] THEN MDNull ELSE OwnMdi, ENDCASE => OwnMdi}; ENDCASE; RETURN}; Predeclared: PROC [type: Type] RETURNS [BOOL] = { RETURN [type = nullType OR ( WITH se: seb[type] SELECT FROM id => se.idCtx IN (CTXNull .. StandardContext.LAST], ENDCASE => FALSE)]}; minTypes: CARDINAL = 2; -- type fragment, if any, at least this big (avoid global 0) nTypes: CARDINAL; nTypeRefs: CARDINAL; typeMapId: ISEIndex; EnterType: PUBLIC PROC [type: Type, canonical: BOOL] = { sei: Type = SymbolOps.ClusterSe[type]; slLimit: SymLitIndex = table.Top[SymbolSegment.atType]; nTypeRefs _ nTypeRefs + 1; FOR sli: SymLitIndex _ SymLitIndex.FIRST, sli+SymLitRecord.SIZE UNTIL sli = slLimit DO WITH s: slb[sli] SELECT FROM type => IF canonical = s.canonical AND (IF canonical THEN Equivalent ELSE NameEqual)[sei, s.typeCode] THEN EXIT; ENDCASE; REPEAT FINISHED => InsertType[sei, canonical]; ENDLOOP}; TypeIndex: PUBLIC PROC [type: Type, canonical: BOOL] RETURNS [RTBcd.TypeIndex] = { sei: Type = SymbolOps.ClusterSe[type]; i: CARDINAL _ 0; FOR sli: SymLitIndex _ SymLitIndex.FIRST, sli+SymLitRecord.SIZE WHILE i < nTypes DO WITH s: slb[sli] SELECT FROM type => IF canonical = s.canonical AND (IF canonical THEN Equivalent ELSE NameEqual)[sei, s.typeCode] THEN EXIT; ENDCASE; i _ i+1; REPEAT FINISHED => ERROR; ENDLOOP; RETURN [[i]]}; TypeRef: PUBLIC PROC [type: Type, canonical: BOOL] RETURNS [Tree.Link] = { RETURN [IndexedRef[typeMapId, TypeIndex[type, canonical], typeANY]]}; DescribeTypes: PUBLIC PROC RETURNS [offset, length: CARDINAL] = { RETURN [offset: WordOffset[typeMapId], length: nTypes]}; EnumerateTypes: PUBLIC PROC [scan: PROC [canonical: BOOL, type: Type]] = { i: CARDINAL _ 0; FOR sli: SymLitIndex _ SymLitIndex.FIRST, sli+SymLitRecord.SIZE WHILE i < nTypes DO WITH s: slb[sli] SELECT FROM type => scan[s.canonical, s.typeCode]; ENDCASE; i _ i + 1; ENDLOOP}; InsertType: PROC [type: Type, canonical: BOOL] = { sli: SymLitIndex = table.Words[atType, SymLitRecord.SIZE]; slb[sli] _ [type[canonical: canonical, typeCode: type]]; nTypes _ nTypes + 1}; PadTypes: PROC [pad: BOOL] = INLINE { IF nTypes # 0 THEN { totalTypes: CARDINAL = (IF pad THEN ((nTypes+3)/4)*4 ELSE nTypes); FOR i: NAT IN [nTypes .. MAX[minTypes, totalTypes]) DO InsertType[Symbols.nullType, FALSE] ENDLOOP}}; minLitRefs: CARDINAL = 1; -- ref lit fragment, if any, at least this big (avoid global 0) nLits: CARDINAL; nLitRefs: CARDINAL; firstLit: SymLitIndex; -- tight bound after Reset litMapId: ISEIndex; EnterLit: PROC [item: RefLitItem] = { key: SymLitRecord = [lit[item]]; slLimit: SymLitIndex = table.Top[SymbolSegment.atType]; nLitRefs _ nLitRefs + 1; FOR sli: SymLitIndex _ SymLitIndex.FIRST, sli+SymLitRecord.SIZE UNTIL sli = slLimit DO IF slb[sli] = key THEN EXIT; REPEAT FINISHED => InsertLit[item]; ENDLOOP}; LitIndex: PROC [item: RefLitItem] RETURNS [RTBcd.RefLitIndex] = { key: SymLitRecord = [lit[item]]; i: CARDINAL _ 0; FOR sli: SymLitIndex _ firstLit, sli+SymLitRecord.SIZE WHILE i < nLits DO IF slb[sli] = key THEN EXIT; i _ i+1; REPEAT FINISHED => ERROR; ENDLOOP; RETURN [[i]]}; InsertLit: PROC [item: RefLitItem] = { sli: SymLitIndex = table.Words[atType, SymLitRecord.SIZE]; slb[sli] _ [lit[item]]; nLits _ nLits + 1}; EnterAtom: PUBLIC PROC [name: Name] = {EnterLit[[atom[pName: name]]]}; AtomIndex: PUBLIC PROC [name: Name] RETURNS [RTBcd.RefLitIndex] = { RETURN [LitIndex[[atom[pName: name]]]]}; AtomRef: PUBLIC PROC [name: Name] RETURNS [Tree.Link] = { RETURN [IndexedRef[litMapId, AtomIndex[name], dataPtr.typeATOM]]}; EnterText: PUBLIC PROC [sti: Literals.STIndex] = {EnterLit[[text[value: sti]]]}; TextIndex: PUBLIC PROC [sti: Literals.STIndex] RETURNS [RTBcd.RefLitIndex] = { RETURN [LitIndex[[text[value: sti]]]]}; TextRef: PUBLIC PROC [sti: Literals.STIndex] RETURNS [Tree.Link] = { RETURN [IndexedRef[litMapId, TextIndex[sti], dataPtr.typeRefANY]]}; DescribeRefLits: PUBLIC PROC RETURNS [offset, length: CARDINAL] = { temp: INTEGER _ WordOffset[litMapId]; IF dataPtr.switches['z] THEN temp _ - temp; RETURN [offset: LOOPHOLE[temp, CARDINAL], length: nLits]; }; EnumerateRefLits: PUBLIC PROC [scan: PROC [RefLitItem]] = { i: CARDINAL _ 0; FOR sli: SymLitIndex _ firstLit, sli+SymLitRecord.SIZE WHILE i < nLits DO WITH s: slb[sli] SELECT FROM lit => {scan[s.info]; i _ i+1}; ENDCASE; ENDLOOP}; PadRefLits: PROC [pad: BOOL] = INLINE { IF nLits # 0 THEN { totalLits: CARDINAL = (IF pad THEN ((nLits+3)/4)*4 ELSE nLits); someLit: RefLitItem; -- need a null RefLitItem FindLit: PROC [item: RefLitItem] = {someLit _ item}; EnumerateRefLits[FindLit]; FOR i: NAT IN [nLits .. MAX[minLitRefs, totalLits]) DO InsertLit[someLit] ENDLOOP}}; Initialize: PUBLIC PROC [ownTable: Alloc.Handle] = { table _ ownTable; table.AddNotify[UpdateBases]; nLits _ nLitRefs _ 0; nTypes _ nTypeRefs _ 0; firstLit _ SymLitIndex.FIRST; -- see Reset typeMapId _ litMapId _ ISENull}; Reset: PUBLIC PROC [pad: BOOL] = { PadTypes[pad]; PadRefLits[pad]; IF nLits # 0 AND ~dataPtr.interface THEN { IF dataPtr.switches['z] THEN { mapType: CSEIndex _ CreateUnnamedMap[dataPtr.typeRefANY, nLits+1]; intermediateType _ LOOPHOLE[mapType]; litMapId _ CreateMap["&map"L, dataPtr.typeRefANY, 1, 1]; } ELSE litMapId _ CreateMap["&refs"L, dataPtr.typeRefANY, nLits, nLitRefs]; }; IF nTypes # 0 THEN { slLimit: SymLitIndex = table.Top[atType]; lastType: SymLitIndex; t: SymLitRecord; lastType _ slLimit - SymLitRecord.SIZE; DO UNTIL firstLit = slLimit OR slb[firstLit].tag = lit DO firstLit _ firstLit + SymLitRecord.SIZE ENDLOOP; UNTIL slb[lastType].tag = type DO lastType _ lastType - SymLitRecord.SIZE ENDLOOP; IF lastType < firstLit THEN EXIT; t _ slb[firstLit]; slb[firstLit] _ slb[lastType]; slb[lastType] _ t; ENDLOOP; IF ~dataPtr.interface THEN typeMapId _ CreateMap["&types"L, typeANY, nTypes, nTypeRefs]}}; Finalize: PUBLIC PROC = {table.DropNotify[UpdateBases]; table _ NIL}; CreateMap: PROC [id: LONG STRING, cType: Type, nEntries, nRefs: CARDINAL] RETURNS [sei: ISEIndex] = { desc: ConvertUnsafe.SubString _ [base:id, offset:0, length:id.length]; mapType: CSEIndex _ CreateUnnamedMap[cType, nEntries]; sei _ SymbolOps.MakeCtxSe[SymbolOps.EnterString[desc], dataPtr.mainCtx]; seb[sei].idType _ mapType; seb[sei].public _ seb[sei].extended _ seb[sei].constant _ seb[sei].linkSpace _ FALSE; seb[sei].immutable _ TRUE; seb[sei].idValue _ Tree.NullIndex; seb[sei].idInfo _ nRefs; seb[sei].mark3 _ seb[sei].mark4 _ TRUE; RETURN; }; CreateUnnamedMap: PROC [cType: Type, nEntries: CARDINAL] RETURNS [mapType: CSEIndex] = { iType: CSEIndex _ SymbolOps.MakeNonCtxSe[SERecord.cons.subrange.SIZE]; seb[iType].typeInfo _ subrange[ filled: TRUE, empty: FALSE, rangeType: dataPtr.idINT, origin: 0, range: nEntries-1]; seb[iType].mark3 _ seb[iType].mark4 _ TRUE; mapType _ SymbolOps.MakeNonCtxSe[SERecord.cons.array.SIZE]; seb[mapType].typeInfo _ array[packed: FALSE, indexType: iType, componentType: cType]; seb[mapType].mark3 _ seb[mapType].mark4 _ TRUE; RETURN; }; MakeRefType: PROC [referent: CSEIndex] RETURNS [Type] = { refCSE: CSEIndex _ SymbolOps.MakeNonCtxSe[SERecord.cons.ref.SIZE]; longCSE: CSEIndex _ SymbolOps.MakeNonCtxSe[SERecord.cons.long.SIZE]; seb[longCSE].typeInfo _ long[rangeType: LOOPHOLE[refCSE]]; seb[longCSE].mark3 _ seb[longCSE].mark4 _ TRUE; seb[refCSE].typeInfo _ ref[counted: TRUE, readOnly: TRUE, ordered: FALSE, list: FALSE, var: FALSE, basing: FALSE, refType: LOOPHOLE[referent]]; seb[refCSE].mark3 _ seb[refCSE].mark4 _ TRUE; RETURN [LOOPHOLE[refCSE]]; }; intermediateType: Type; WordOffset: PROC [sei: ISEIndex] RETURNS [offset: CARDINAL] = { IF sei = ISENull THEN offset _ 0 ELSE { addr: BitAddress = seb[sei].idValue; offset _ addr.wd}; RETURN; }; IndexedRef: PROC [array: ISEIndex, item: CARDINAL, type: CSEIndex] RETURNS [Tree.Link] = { OPEN TreeOps; IF dataPtr.switches['z] AND type # typeANY THEN { PushSe[array]; PushNode[uparrow, 1]; SetAttr[1, TRUE]; SetAttr[2, TRUE]; SetInfo[intermediateType]; PushLit[LiteralOps.Find[item+1]]; PushNode[index, 2]; } ELSE { PushSe[array]; PushLit[LiteralOps.Find[item]]; PushNode[index, 2]; }; SetAttr[2, FALSE]; SetInfo[type]; RETURN [PopTree[]]; }; }. *file SymLiteralPack.mesa last modified by Satterthwaite, April 15, 1983 1:28 pm Last Edited by: Maxwell, July 28, 1983 10:21 am Russ Atkinson (RRA) March 4, 1985 11:21:44 am PST types bases auxiliary type predicates universal type fingers typeIds atoms and REFs to literals state transitions The new way Hold on to this type in order to generate the double indirection Now the literal is a REF to an array (with a dummy word in front) that will hold the actual references The old way utility routines Must go one level indirect Use the old method Κ~˜Icodešœ™Kšœ6™6™/K™1—K˜šΟk ˜ Kšœœœ7˜Hšœ œœ˜K˜G—Kšœœœ ˜&Kšœ œœ ˜Kšœ œœ˜Kšœœœ˜+šœ œœ˜K˜K˜>K˜@K˜—šœ œœ˜K˜NK˜ —Kšœœœ ˜#Kšœœœ˜'Kšœœœ˜*Kšœœœ˜#Kšœ œœ8˜KKšœœœ˜K˜—šœ˜š˜K˜-K˜—Kšœ˜Kšœ ˜ K˜Kšœ œ˜,K˜Kšœ™˜šœœœ˜šœ˜Kšœœ˜*K˜Kšœ˜ K˜——Kš œ œœœœœ˜XK˜—Kšœ™˜K˜K˜K˜.K˜K˜K˜K˜˜K˜)K˜(K˜K˜——Kšœ™˜Kš œ œœœœ˜5K˜šΟn œœœœ˜5Kšœœ%œœ˜PK˜—šž œœœœ˜6šœœœ˜(K˜>˜šœœ˜"˜šœ œ˜˜ šœ œ˜˜ šœ˜šœ œ œ˜"šœœ˜Kš˜˜"Kš œœœ œœœ˜<—————Kšœœ˜——˜šœ œ˜˜šœœ˜;Kšœœ$˜C——Kšœœ˜——˜šœ œ˜K˜/Kšœœ˜——Kš œœ œœœœœ˜@Kšœ˜——Kšœœ˜——Kšœœ˜K˜——šž œœœœ˜9K˜,K˜,šœ ˜šœ!œ1˜ZKšœœ˜—K˜>Kšœ˜—Kšœ˜K˜K˜—šž œœœœ˜6šœœ˜˜K˜/K˜1Kšœ˜K˜———š žœœœœœ˜8Kšœ#œœ˜VK˜K˜——Kšœ™˜šžœœœœ ˜IK˜&šœœ˜˜K˜šœœ˜˜ Kšœœ˜0Kšœ&˜*—šœ˜ K˜ Kšœœœœ ˜4———˜ K˜ šœœœ˜K˜Kš œœ œœœ˜GKš œ œ œœœ˜CKšœ œœœ˜7Kšœ ˜——Kšœ˜—Kšœ˜K˜—šž œœœœ˜1šœœ˜šœœ˜Kšœœœ˜4Kšœœ˜K˜K˜————Kšœ™˜Kšœ œΟc<˜TK˜Kšœœ˜Kšœ œ˜K˜K˜šž œœœœ˜8K˜&K˜7K˜š œ œœœ˜Všœ œ˜˜šœ˜Kš œœ œ œœœ˜I——Kšœ˜—š˜Kšœ˜'—Kšœ˜ K˜——š ž œœœœœ˜RK˜&Kšœœ˜š œ œœœ ˜Sšœ œ˜˜šœ˜Kš œœ œ œœœ˜I——Kšœ˜—K˜š˜Kšœœ˜—Kšœ˜—Kšœ˜K˜—š žœœœœœ˜JKšœ?˜EK˜—š ž œœœœœ˜AKšœ2˜8K˜—š žœœœœ œ˜JKšœœ˜š œ œœœ ˜Sšœ œ˜K˜&Kšœ˜—K˜ Kšœ˜ K˜K˜——šž œœœ˜2Kšœ4œ˜:K˜8K˜K˜—šžœœœœ˜%šœ œ˜Kš œ œœœœ ˜Bš œœœ œ˜6Kšœœœ˜.K˜K˜————Kšœ™˜Kšœ œŸ?˜YK˜Kšœœ˜Kšœ œ˜KšœŸ˜1K˜K˜šžœœ˜%K˜ K˜7K˜š œ œœœ˜VKšœœœ˜š˜Kšœ˜—Kšœ˜ K˜——šžœœœ˜AK˜ Kšœœ˜šœ/œœ ˜IKšœœœ ˜&š˜Kšœœ˜—Kšœ˜—Kšœ˜K˜—šž œœ˜&Kšœ4œ˜:K˜K˜K˜K˜—Kšž œœœ0˜FK˜šž œœœœ˜CKšœ"˜(K˜—šžœœœœ˜9Kšœ<˜BK˜K˜—Kšž œœœ:˜PK˜šž œœœœ˜NKšœ!˜'K˜—šžœœœœ˜DKšœ=˜CK˜K˜—š žœœœœœ˜CKšœœ˜%Kšœœ˜+Kšœ œœ˜9Kšœ˜K˜—šžœœœœ˜;Kšœœ˜šœ/œœ ˜Išœ œ˜K˜Kšœ˜—Kšœ˜ K˜——šž œœœœ˜'šœ œ˜Kš œ œœœœ˜?KšœŸ˜.K˜Kšžœœ'˜4K˜K˜š œœœ œ˜6Kšœœ˜K˜K˜————Kšœ™˜šž œœœ˜4K˜/K˜.KšœœŸ ˜*K˜ K˜—šžœœœœ˜"K˜ šœ œœ˜*šœ˜šœ˜Kšœ ™ KšœB˜Bšœœ ˜%Kšœ@™@—šœ8˜8Kšœf™f—K˜—š˜Kšœ ™ KšœD˜D——K˜—šœ œ˜K˜)K˜K˜Kšœ"œ˜'š˜šœœ˜6Kšœ#œœ˜0—šœ˜!Kšœ#œœ˜0—Kšœœœ˜!K˜FKšœ˜—šœ˜Kšœ@˜DK˜———Kšžœœœ+œ˜EK˜K˜—Kšœ™˜š ž œœœœ œœ˜eK˜FKšœ6˜6K˜HK˜KšœOœ˜UKšœœ˜K˜œ˜DKšœ(œ ˜:Kšœ*œ˜/Kšœ$œ œ œœœ œ œ ˜Kšœ(œ˜-Kšœœ ˜K˜K˜—šœ˜K˜—šž œœœ œ˜?šœ˜Kšœ ˜šœ˜K˜$K˜——Kš˜Kšœ˜K˜—˜K˜—šž œœœœ˜ZKšœ ˜ šœœ˜*šœ˜Kšœ™K˜%Kšœ œœ˜@K˜6K˜—šœ˜Kšœ™K˜DK˜——Kšœ œ˜"Kšœ ˜Kšœ˜K˜—K˜K˜K˜———…—/xA