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, CtxLevel, 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];
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}
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]]};
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 {
-- must go one level indirect
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[]]};
}.