AMTypesAImpl.Mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
NOTE do Equal, AsGoodAs
try to avoid acquisition of already acquired symbol tables
status stuff is wrong.
Paul Rovner, June 29, 1983 4:50 pm
Russ Atkinson, February 11, 1985 7:37:09 pm PST
DIRECTORY
AMBridge USING [SetTVFromLC, SetTVFromLI],
AMTypes USING [Class, Index, Status, TypedVariable, ErrorReason, New, TypeClass, Size],
BrandXSymbolDefs USING [nullSymbolIndex, SymbolConstructorIndex, SymbolIdIndex, symbolIndexForANY, SymbolModuleIndex, thisModuleIndex],
BrandYSymbolDefs USING [nullSymbolIndex, SymbolConstructorIndex, SymbolIdIndex, symbolIndexForANY, SymbolModuleIndex, thisModuleIndex],
Rope USING [Equal, ROPE],
RTSymbolDefs USING [nullBase, SymbolConstructorIndex, SymbolContextIndex, SymbolIdIndex, SymbolIndex, SymbolRecordIndex, SymbolTableBase],
RTSymbolOps USING [AcquireRope, AcquireSequenceType, AcquireType, CountComponents, EnumerateCtxIseis, EnumerateRecordIseis, IDCardinalValue, ISEConstant, ISEImmutable, ISEInfo, ISEName, ISEType, SEUnderType, STBToModuleName],
RTSymbols USING [GetTypeSymbols, GetOriginalTypeSymbols, ReleaseSTB],
RTTCache USING [ComponentEntry, ComponentMap, FillIntEntry, FillNameComponent, FillRefEntry, FillTypeComponent, GetComponentAtIndex, GetComponentForName, IntEntry, LookupInt, LookupRef, NewComponentMap, RefEntry],
RTTypesPrivate USING[],
SafeStorage USING [nullType, Type, unspecType];
AMTypesAImpl: PROGRAM
IMPORTS AMBridge, AMTypes, Rope, RTSymbolOps, RTSymbols, RTTCache
EXPORTS AMTypes, RTTypesPrivate
= BEGIN OPEN AMBridge, AMTypes, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, SafeStorage, RTSymbolOps, RTSymbolDefs, RTSymbols;
T Y P E S
ROPE: TYPE = Rope.ROPE;
E R R O R
Error: PUBLIC ERROR[ reason: ErrorReason,
msg: ROPENIL,
type: Type ← nullType,-- used with TypeFault, IncompatibleTypes
otherType: Type ← nullType -- used with IncompatibleTypes
] = CODE;
P U B L I C P R O C E D U R E S
These procedures have applicability restrictions, noted as comments
NComponents: PUBLIC SAFE PROC [type: Type--record, structure--] RETURNS [ans: Index] = TRUSTED {
entry: RTTCache.IntEntry;
int: INT;
IF type = nullType THEN RETURN[0];
entry ← RTTCache.LookupInt[type, NComponents];
int ← entry.int;
IF int >= 0 THEN RETURN [int];
{stb: SymbolTableBase;
sei: SymbolIndex;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei: SymbolConstructorIndex ← SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
record => ans ← CountComponents[stb, LOOPHOLE[csei]];
definition =>
{proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] =
{ans ← ans + 1; RETURN[FALSE]};
ans ← 0;
[] ← EnumerateCtxIseis[stb, [x[ser.defCtx]], proc]};
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
record => ans ← CountComponents[stb, LOOPHOLE[csei]];
definition =>
{proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] =
{ans ← ans + 1; RETURN[FALSE]};
ans ← 0;
[] ← EnumerateCtxIseis[stb, [y[ser.defCtx]], proc]};
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb]};
[] ← RTTCache.FillIntEntry[entry, ans];
};
IndexToType: PUBLIC SAFE PROC [type: Type--record, structure, union--, index: Index] RETURNS[ans: Type] = TRUSTED {
This returns the Type of the specified component of instances of the type. index starts at 1.
proc1: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] = {
ans ← IF index = 0
THEN AcquireType[stb, ISEType[stb, isei]]
ELSE AcquireType[stb, ISEInfo[stb, isei]]};
proc2: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] = {
sei: SymbolIndex ← ISEType[stb, isei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH cse: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.x].e]] SELECT FROM
sequence => {
recstb: SymbolTableBase;
recsei: SymbolIndex;
[recstb, recsei] ← GetTypeSymbols[type];
ans ← AcquireSequenceType[stb, sei, recstb,
LOOPHOLE[SEUnderType[recstb, recsei],
SymbolRecordIndex]
! UNWIND => ReleaseSTB[recstb]];
ReleaseSTB[recstb]};
ref => {
IF cse.var THEN sei ← [x[cse.refType]];
ans ← AcquireType[stb, sei]};
ENDCASE => ans ← AcquireType[stb, sei];
t: SymbolTableBase.y =>
WITH cse: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.y].e]] SELECT FROM
sequence => {
recstb: SymbolTableBase;
recsei: SymbolIndex;
[recstb, recsei] ← GetTypeSymbols[type];
ans ← AcquireSequenceType[stb, sei, recstb,
LOOPHOLE[SEUnderType[recstb, recsei],
SymbolRecordIndex]
! UNWIND => ReleaseSTB[recstb]];
ReleaseSTB[recstb]};
ref => {
IF cse.var THEN sei ← [y[cse.refType]];
ans ← AcquireType[stb, sei]};
ENDCASE => ans ← AcquireType[stb, sei];
ENDCASE => ERROR;
};
entry: RTTCache.RefEntry;
map: RTTCache.ComponentMap;
class: Class;
n: NAT ← 0;
type ← UnderType[type];
class ← TypeClass[type];
SELECT class FROM
record, structure => n ← NComponents[type];
union => n ← NValues[Domain[type]];
ENDCASE => ERROR Error[reason: typeFault, type: type];
entry ← RTTCache.LookupRef[type, IndexToType];
map ← NARROW[entry.ref, RTTCache.ComponentMap];
IF map # NIL AND index IN [1..map.len] AND map[index-1].validType
THEN RETURN [map[index-1].type];
SELECT class FROM
record, structure => RecordComponentISEI[type, index, proc2];
union => ComponentISEI[type, index, proc1];
ENDCASE => ERROR Error[reason: typeFault, type: type];
IF n > 0 AND index IN [1..n] THEN {
put the answer back into the cache
IF map = NIL THEN
[] ← RTTCache.FillRefEntry[entry, map ← RTTCache.NewComponentMap[n]];
[] ← RTTCache.FillTypeComponent[map, index-1, ans]};
};
IndexToStatus: PUBLIC PROC [type: Type--record, structure--, index: Index] RETURNS[ans: Status] = {
This returns the Status of the specified component of instances of the type. index starts at 1.
proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] = {
ans ← (IF ISEImmutable[stb, isei] THEN readOnly
ELSE IF ISEConstant[stb, isei] THEN const
ELSE mutable)};
RecordComponentISEI[type, index, proc];
};
NameToIndex: PUBLIC SAFE PROC [type: Type--record, structure, union, enumerated--, name: ROPE] RETURNS [ans: CARDINAL ← 0] = TRUSTED {
index starts at 1
raises typeFault, badName
enumerated: BOOLFALSE;
stb: SymbolTableBase;
sei: SymbolIndex;
class: Class;
n: INT ← 0;
found: BOOLFALSE;
entry: RTTCache.RefEntry;
map: RTTCache.ComponentMap;
proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
IF enumerated THEN ans ← IDCardinalValue[stb, isei] + 1 ELSE ans ← ans + 1;
stop ← Rope.Equal[name, AcquireRope[stb, ISEName[stb, isei]]]};
type ← UnderType[type];
class ← TypeClass[type];
SELECT class FROM
record, structure => n ← NComponents[type];
enumerated => n ← NValues[type];
union => n ← NValues[Domain[type]];
ENDCASE;
IF n IN [1..256) THEN {
entry ← RTTCache.LookupRef[type, IndexToType];
map ← NARROW[entry.ref, RTTCache.ComponentMap];
IF map # NIL THEN {
int: INT ← RTTCache.GetComponentForName[map, name].index;
IF int >= 0 THEN RETURN [int+1]}};
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
{csei: bx.SymbolConstructorIndex ← t.e.UnderType[NARROW[sei, SymbolIndex.x].e];
WITH ser: t.e.seb[csei] SELECT FROM
record => {srx: SymbolIndex = [x[csei]];
found ← EnumerateRecordIseis[stb,
LOOPHOLE[srx, SymbolRecordIndex],
proc]};
definition => found ← EnumerateCtxIseis[stb, [x[ser.defCtx]], proc];
union => found ← EnumerateCtxIseis[stb, [x[ser.caseCtx]], proc];
enumerated =>
{enumerated ← TRUE; found ← EnumerateCtxIseis[stb, [x[ser.valueCtx]], proc]};
ENDCASE => ERROR Error[reason: typeFault, type: type]};
t: SymbolTableBase.y =>
{csei: by.SymbolConstructorIndex ← t.e.UnderType[NARROW[sei, SymbolIndex.y].e];
WITH ser: t.e.seb[csei] SELECT FROM
record => {srx: SymbolIndex = [y[csei]];
found ← EnumerateRecordIseis[stb,
LOOPHOLE[srx, SymbolRecordIndex],
proc]};
definition => found ← EnumerateCtxIseis[stb, [y[ser.defCtx]], proc];
union => found ← EnumerateCtxIseis[stb, [y[ser.caseCtx]], proc];
enumerated =>
{enumerated ← TRUE; found ← EnumerateCtxIseis[stb, [y[ser.valueCtx]], proc]};
ENDCASE => ERROR Error[reason: typeFault, type: type]};
ENDCASE => ERROR;
};
ReleaseSTB[stb];
IF NOT found THEN ERROR Error[reason: badName, type: type, msg: name];
IF ans > 0 AND n IN [1..256) THEN {
IF map = NIL THEN
[] ← RTTCache.FillRefEntry[entry, map ← RTTCache.NewComponentMap[n]];
[] ← RTTCache.FillNameComponent[map, ans-1, name]};
}; -- end NameToIndex
IndexToName: PUBLIC SAFE PROC [type: Type--record, structure, union, enumerated--, index: CARDINAL] RETURNS[ans: ROPE] = TRUSTED {
proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] = {
ans ← AcquireRope[stb, ISEName[stb, isei]]};
n: INT ← 0;
class: Class;
entry: RTTCache.RefEntry;
map: RTTCache.ComponentMap ← NIL;
type ← UnderType[type];
class ← TypeClass[type];
SELECT class FROM
record, structure => n ← NComponents[type];
enumerated => n ← NValues[type];
union, sequence =>
IF index = 0
THEN {
RRA: the tag name is cached differently from other component names
entry ← RTTCache.LookupRef[type, IndexToName];
IF entry.valid THEN RETURN [NARROW[entry.ref]];
ComponentISEI[type, 0, proc];
entry.ref ← ans;
entry.valid ← TRUE;
RETURN}
ELSE {
RRA: only union types are further processed
IF class = sequence THEN GO TO err;
n ← NValues[Domain[type]];
};
ENDCASE;
IF n IN [1..256) THEN {
entry ← RTTCache.LookupRef[type, IndexToType];
map ← NARROW[entry.ref, RTTCache.ComponentMap];
IF map = NIL
THEN [] ← RTTCache.FillRefEntry[entry, map ← RTTCache.NewComponentMap[n]];
IF index IN [1..map.len] THEN {
comp: RTTCache.ComponentEntry ←
RTTCache.GetComponentAtIndex[map, index-1];
IF comp.validName THEN RETURN [comp.name]};
};
SELECT class FROM
record, structure => RecordComponentISEI[type, index, proc];
union, enumerated => ComponentISEI[type, index, proc];
ENDCASE => GO TO err;
IF map # NIL THEN [] ← RTTCache.FillNameComponent[map, index-1, ans];
EXITS
err => ERROR Error[reason: typeFault, type: type];
};
IsPacked: PUBLIC SAFE PROC [type: Type--array, sequence--] RETURNS [ans: BOOL] = TRUSTED {
stb: SymbolTableBase;
sei: SymbolIndex;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.x].e]] SELECT FROM
array => ans ← ser.packed;
sequence => ans ← ser.packed;
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.y].e]] SELECT FROM
array => ans ← ser.packed;
sequence => ans ← ser.packed;
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb];
};
Domain: PUBLIC SAFE PROC [type: Type] RETURNS[ans: Type] = TRUSTED {
domain: type  {array, sequence, union, transfer, descriptor, longDescriptor, relativePointer}
stb: SymbolTableBase;
sei: SymbolIndex;
entry: RTTCache.IntEntry ← RTTCache.LookupInt[type ← UnderType[type], Domain];
int: INT ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.x].e]] SELECT FROM
relative => ans ← AcquireType[stb, [x[ser.offsetType]]];
array => ans ← AcquireType[stb, [x[ser.indexType]]];
sequence => ans ← AcquireType[stb, [x[t.e.seb[ser.tagSei].idType]]];
union => ans ← AcquireType[stb, [x[t.e.seb[ser.tagSei].idType]]];
transfer => ans ← (IF ser.typeIn = bx.nullSymbolIndex
THEN nullType
ELSE AcquireType[stb, [x[ser.typeIn]]]);
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.y].e]] SELECT FROM
relative => ans ← AcquireType[stb, [y[ser.offsetType]]];
array => ans ← AcquireType[stb, [y[ser.indexType]]];
sequence => ans ← AcquireType[stb, [y[t.e.seb[ser.tagSei].idType]]];
union => ans ← AcquireType[stb, [y[t.e.seb[ser.tagSei].idType]]];
transfer => ans ← (IF ser.typeIn = by.nullSymbolIndex
THEN nullType
ELSE AcquireType[stb, [y[ser.typeIn]]]);
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb];
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[ans, CARDINAL]];
};
Range: PUBLIC SAFE PROC[type: Type] RETURNS[ans: Type] = TRUSTED {
domain: type  {array, sequence, procedure, signal, process, address} (not atom, rope)
stb: SymbolTableBase;
sei: SymbolIndex;
entry: RTTCache.IntEntry ← RTTCache.LookupInt[type ← UnderType[type], Range];
int: INT ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
SELECT TypeClass[type] FROM
array, sequence, procedure, signal, process,
list, ref, pointer, longPointer, descriptor,
longDescriptor, relativePointer, basePointer => NULL;
ENDCASE => ERROR Error[reason: typeFault, type: type];
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.x].e]] SELECT FROM
array => ans ← AcquireType[stb, [x[ser.componentType]]];
sequence => ans ← AcquireType[stb, [x[ser.componentType]]];
transfer => ans ← (IF ser.typeOut = bx.nullSymbolIndex
THEN nullType
ELSE AcquireType[stb, [x[ser.typeOut]]]);
relative => ans ← Range[AcquireType[stb, [x[ser.resultType]]]];
ref => {IF ser.counted THEN ERROR Error[reason: typeFault, type: type];
ans ← (IF t.e.UnderType[ser.refType] = bx.symbolIndexForANY
THEN unspecType
ELSE AcquireType[stb, [x[ser.refType]]])};
arraydesc => ans ← AcquireType[stb, [x[ser.describedType]]];
long => WITH rse: t.e.seb[t.e.UnderType[ser.rangeType]] SELECT FROM
ref => ans ← (IF t.e.UnderType[rse.refType] = bx.symbolIndexForANY
THEN unspecType
ELSE AcquireType[stb, [x[rse.refType]]]);
arraydesc => ans ← AcquireType[stb, [x[rse.describedType]]];
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.y].e]] SELECT FROM
array => ans ← AcquireType[stb, [y[ser.componentType]]];
sequence => ans ← AcquireType[stb, [y[ser.componentType]]];
transfer => ans ← (IF ser.typeOut = by.nullSymbolIndex
THEN nullType
ELSE AcquireType[stb, [y[ser.typeOut]]]);
relative => ans ← Range[AcquireType[stb, [y[ser.resultType]]]];
ref => {IF ser.counted THEN ERROR Error[reason: typeFault, type: type];
ans ← (IF t.e.UnderType[ser.refType] = by.symbolIndexForANY
THEN unspecType
ELSE AcquireType[stb, [y[ser.refType]]])};
arraydesc => ans ← AcquireType[stb, [y[ser.describedType]]];
long => WITH rse: t.e.seb[t.e.UnderType[ser.rangeType]] SELECT FROM
ref => ans ← (IF t.e.UnderType[rse.refType] = by.symbolIndexForANY
THEN unspecType
ELSE AcquireType[stb, [y[rse.refType]]]);
arraydesc => ans ← AcquireType[stb, [y[rse.describedType]]];
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
ReleaseSTB[stb]}; -- END ENABLE UNWIND
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[ans, CARDINAL]];
};
ReferentStatus: PUBLIC SAFE PROC [type: Type] RETURNS [ans: Status] = TRUSTED {
stb: SymbolTableBase;
sei: SymbolIndex;
readOnlyReferent: BOOLFALSE;
entry: RTTCache.IntEntry ← RTTCache.LookupInt[type ← UnderType[type], ReferentStatus];
int: INT ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
SELECT TypeClass[type] FROM
rope, atom => RETURN [readOnly];
basePointer => GO TO fault;
list, ref, pointer, longPointer, descriptor, longDescriptor, relativePointer => {};
ENDCASE => GO TO fault;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.x].e]] SELECT FROM
long => WITH ser1: t.e.seb[t.e.UnderType[ser.rangeType]] SELECT FROM
arraydesc => readOnlyReferent ← ser1.readOnly;
ref => readOnlyReferent ← ser1.readOnly;
ENDCASE => GO TO fault;
ref => readOnlyReferent ← ser.readOnly;
relative => WITH ser2: t.e.seb[t.e.UnderType[ser.resultType]] SELECT FROM
long => WITH ser1: t.e.seb[t.e.UnderType[ser2.rangeType]] SELECT FROM
ref => readOnlyReferent ← ser1.readOnly;
ENDCASE => GO TO fault;
ref => readOnlyReferent ← ser2.readOnly;
ENDCASE => GO TO fault;
arraydesc => readOnlyReferent ← ser.readOnly;
ENDCASE => GO TO fault;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[t.e.UnderType[NARROW[sei, SymbolIndex.y].e]] SELECT FROM
long => WITH ser1: t.e.seb[t.e.UnderType[ser.rangeType]] SELECT FROM
arraydesc => readOnlyReferent ← ser1.readOnly;
ref => readOnlyReferent ← ser1.readOnly;
ENDCASE => ERROR Error[reason: typeFault, type: type];
ref => readOnlyReferent ← ser.readOnly;
relative => WITH ser2: t.e.seb[t.e.UnderType[ser.resultType]] SELECT FROM
long => WITH ser1: t.e.seb[t.e.UnderType[ser2.rangeType]] SELECT FROM
ref => readOnlyReferent ← ser1.readOnly;
ENDCASE => GO TO fault;
ref => readOnlyReferent ← ser2.readOnly;
ENDCASE => GO TO fault;
arraydesc => readOnlyReferent ← ser.readOnly;
ENDCASE => GO TO fault;
ENDCASE => ERROR;
};
ReleaseSTB[stb];
ans ← IF readOnlyReferent THEN readOnly ELSE mutable;
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[ans, CARDINAL]];
EXITS fault => ERROR Error[reason: typeFault, type: type];
};
TypeToName: PUBLIC SAFE PROC [type: Type, moduleName, fileName: REF ROPENIL] RETURNS [ans: ROPE] = TRUSTED {
class: Class ← TypeClass[type];
SELECT class FROM
nil => RETURN[NIL];
unspecified => RETURN ["UNSPECIFIED"];
localFrame => RETURN ["%localFrame"];
globalFrame => RETURN["%globalFrame"];
type => RETURN["TYPE"];
any => RETURN["ANY"];
atom => RETURN["ATOM"];
rope => RETURN["ROPE"];
cardinal => RETURN["CARDINAL"];
longCardinal => RETURN["CARD"];
integer => RETURN["INTEGER"];
longInteger => RETURN["INT"];
real => RETURN["REAL"];
character => RETURN["CHAR"];
ENDCASE;
{ stb: SymbolTableBase ← nullBase;
sei: SymbolIndex;
IF moduleName # NIL OR fileName # NIL THEN
[stb, sei] ← GetOriginalTypeSymbols[type ! Error => CONTINUE];
IF stb = nullBase THEN [stb, sei] ← GetTypeSymbols[type];
WITH stb SELECT FROM
t: SymbolTableBase.x => {
ENABLE UNWIND => ReleaseSTB[stb];
mdi: bx.SymbolModuleIndex ← bx.thisModuleIndex;
WITH ser: t.e.seb[NARROW[sei, SymbolIndex.x].e] SELECT FROM
id => {ans ← AcquireRope[stb, [x[ser.hash]]];
IF moduleName # NIL OR fileName # NIL THEN {
WITH cer: t.e.ctxb[ser.idCtx] SELECT FROM
included => mdi ← cer.module;
ENDCASE;
IF moduleName # NIL THEN
moduleName^ ← AcquireRope[stb, [x[t.e.mdb[mdi].moduleId]]];
IF fileName # NIL THEN
fileName^ ← AcquireRope[stb, [x[t.e.mdb[mdi].fileId]]]}};
ENDCASE => {
csei: bx.SymbolConstructorIndex = t.e.UnderType[NARROW[sei, SymbolIndex.x].e];
IF moduleName # NIL THEN moduleName^ ← STBToModuleName[stb];
WITH ser: t.e.seb[csei] SELECT FROM
definition => ans ← STBToModuleName[stb]; -- interface type
ENDCASE => ans ← NIL};
};
t: SymbolTableBase.y => {
ENABLE UNWIND => ReleaseSTB[stb];
mdi: by.SymbolModuleIndex ← by.thisModuleIndex;
WITH ser: t.e.seb[NARROW[sei, SymbolIndex.y].e] SELECT FROM
id => {
ans ← AcquireRope[stb, [y[ser.hash]]];
IF moduleName # NIL OR fileName # NIL THEN {
WITH cer: t.e.ctxb[ser.idCtx] SELECT FROM
included => mdi ← cer.module;
ENDCASE;
IF moduleName # NIL THEN
moduleName^ ← AcquireRope[stb, [y[t.e.mdb[mdi].moduleId]]];
IF fileName # NIL THEN
fileName^ ← AcquireRope[stb, [y[t.e.mdb[mdi].fileId]]]}};
ENDCASE => {
csei: by.SymbolConstructorIndex = t.e.UnderType[NARROW[sei, SymbolIndex.y].e];
IF moduleName # NIL THEN moduleName^ ← STBToModuleName[stb];
WITH ser: t.e.seb[csei] SELECT FROM
definition => ans ← STBToModuleName[stb]; -- interface type
ENDCASE => ans ← NIL};
};
ENDCASE => ERROR;
ReleaseSTB[stb];
};
};
Ground: PUBLIC SAFE PROC [type: Type] RETURNS [ans: Type] = TRUSTED {
peels off one layer from a definition or subrange type
stb: SymbolTableBase;
sei: SymbolIndex;
entry: RTTCache.IntEntry;
int: INT;
entry ← RTTCache.LookupInt[type, Ground];
int ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
SELECT TypeClass[type] FROM
definition, subrange => {};
ENDCASE => GO TO fault;
[stb, sei] ← GetTypeSymbols[type];
{ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[sei, SymbolIndex.x].e] SELECT FROM
id => ans ← AcquireType[stb, [x[ser.idInfo]]]; -- a definition
ENDCASE => {
csei: bx.SymbolConstructorIndex ← t.e.UnderType[NARROW[sei, SymbolIndex.x].e];
WITH ser: t.e.seb[csei] SELECT FROM
subrange => ans ← AcquireType[stb, [x[ser.rangeType]]];
ENDCASE;
};
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[sei, SymbolIndex.y].e] SELECT FROM
id => ans ← AcquireType[stb, [y[ser.idInfo]]]; -- a definition
ENDCASE => {
csei: by.SymbolConstructorIndex ← t.e.UnderType[NARROW[sei, SymbolIndex.y].e];
WITH ser: t.e.seb[csei] SELECT FROM
subrange => ans ← AcquireType[stb, [y[ser.rangeType]]];
ENDCASE;
};
ENDCASE => ERROR;
};
ReleaseSTB[stb];
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[ans, CARDINAL]];
EXITS fault => ERROR Error[reason: typeFault, type: type];
};
GroundStar: PUBLIC SAFE PROC [type: Type--definition, subrange--] RETURNS [Type] = TRUSTED {
peels off one layer from a definition or subrange type (no change for other types)
entry: RTTCache.IntEntry ← RTTCache.LookupInt[type, GroundStar];
int: INT ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
DO
SELECT TypeClass[type] FROM
definition, subrange => type ← Ground[type];
ENDCASE => EXIT;
ENDLOOP;
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[type, CARDINAL]];
RETURN[type];
};
UnderType: PUBLIC SAFE PROC [type: Type] RETURNS [Type] = TRUSTED {
entry: RTTCache.IntEntry;
int: INT;
entry ← RTTCache.LookupInt[type, UnderType];
int ← entry.int;
IF int >= 0 THEN {card: CARDINAL ← int; RETURN [LOOPHOLE[card]]};
UNTIL TypeClass[type] # definition DO type ← Ground[type]; ENDLOOP;
[] ← RTTCache.FillIntEntry[entry, LOOPHOLE[type, CARDINAL]];
RETURN[type];
};
UnderClass: PUBLIC SAFE PROC [type: Type] RETURNS [Class] = TRUSTED {
RETURN[TypeClass[UnderType[type]]];
};
First: PUBLIC SAFE PROC [type: Type--enumerated, subrange, basic--] RETURNS [tv: TypedVariable] = TRUSTED {
class: Class = TypeClass[UnderType[type]];
IF class = subrange THEN {
stb: SymbolTableBase;
sei: SymbolIndex;
csei: SymbolConstructorIndex;
[stb, sei] ← GetTypeSymbols[type];
csei ← SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
subrange => {empty: BOOL = ser.empty;
ReleaseSTB[stb];
IF empty THEN ERROR Error[reason: rangeFault]};
ENDCASE => {ReleaseSTB[stb]; ERROR};
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
subrange => {empty: BOOL = ser.empty;
ReleaseSTB[stb];
IF empty THEN ERROR Error[reason: rangeFault]};
ENDCASE => {ReleaseSTB[stb]; ERROR};
ENDCASE => ERROR;
tv ← New[type];
RETURN}; -- the "0" that's there already is always the right stored representation!!
tv ← New[type];
SELECT class FROM
enumerated => SetTVFromLC[tv, 0];
cardinal => SetTVFromLC[tv, FIRST[CARDINAL]];
integer => SetTVFromLI[tv, LONG[FIRST[INTEGER]]];
character => SetTVFromLC[tv, LONG[LOOPHOLE[FIRST[CHARACTER], CARDINAL]]];
longInteger => SetTVFromLI[tv, FIRST[LONG INTEGER]];
longCardinal => SetTVFromLC[tv, FIRST[LONG CARDINAL]];
ENDCASE => ERROR Error[reason: typeFault, type: type];
};
Last: PUBLIC SAFE PROC [type: Type--enumerated, subrange, basic--] RETURNS[tv: TypedVariable] = TRUSTED {
class: Class = TypeClass[UnderType[type]];
tv ← New[type];
SELECT class FROM
enumerated, subrange => {
stb: SymbolTableBase;
sei: SymbolIndex;
i: INTEGER;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei: SymbolConstructorIndex ← SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
enumerated => i ← LOOPHOLE[ser.nValues - 1, INTEGER];
subrange => {
IF ser.empty THEN ERROR Error[reason: rangeFault];
i ← ser.origin + ser.range};
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
enumerated => i ← LOOPHOLE[ser.nValues - 1, INTEGER];
subrange => {
IF ser.empty THEN ERROR Error[reason: rangeFault];
i ← ser.origin + ser.range};
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb];
IF class = enumerated
THEN SetTVFromLC[tv, LONG[LOOPHOLE[i, CARDINAL]]]
ELSE SetTVFromLI[tv, LONG[i]];
};
cardinal => SetTVFromLC[tv, LAST[CARDINAL]];
integer => SetTVFromLI[tv, LONG[LAST[INTEGER]]];
character => SetTVFromLC[tv, LONG[LOOPHOLE[LAST[CHARACTER], CARDINAL]]];
longInteger => SetTVFromLI[tv, LAST[LONG INTEGER]];
longCardinal => SetTVFromLC[tv, LAST[LONG CARDINAL]];
ENDCASE => ERROR Error[reason: typeFault, type: type];
};
NValues: PUBLIC SAFE PROC [type: Type--enumerated, subrange--] RETURNS [int: INT] = TRUSTED {
stb: SymbolTableBase;
sei: SymbolIndex;
csei: SymbolConstructorIndex;
entry: RTTCache.IntEntry;
type ← UnderType[type];
entry ← RTTCache.LookupInt[type, NValues];
int ← entry.int;
IF int >= 0 THEN RETURN[int];
[stb, sei] ← GetTypeSymbols[type];
{ENABLE UNWIND => ReleaseSTB[stb];
csei ← SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
enumerated => int ← IF ser.nValues = 0 THEN 200000B ELSE ser.nValues;
subrange => int ← IF ser.empty THEN 0 ELSE 1 + ser.range;
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
enumerated => int ← IF ser.nValues = 0 THEN 200000B ELSE ser.nValues;
subrange => int ← IF ser.empty THEN 0 ELSE 1 + ser.range;
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb];
[] ← RTTCache.FillIntEntry[entry, int];
};
Value: PUBLIC SAFE PROC [type: Type--enumerated--, index: CARDINAL] RETURNS [tv: TypedVariable] = TRUSTED {
raises typeFault, badIndex
index range is [1..NValues[type]]
type ← UnderType[type];
IF TypeClass[type] # enumerated THEN ERROR Error[reason: typeFault, type: type];
IF index > NValues[type] THEN ERROR Error[reason: badIndex];
tv ← AMTypes.New[type];
SetTVFromLC[tv, index-1];
};
ComponentISEI: PUBLIC PROC [type: Type--union, enumerated--, index: CARDINAL, p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]] = {
This is exported to RTTypesPrivate, and is imported by RTTypedVariablesImpl
stb: SymbolTableBase;
sei: SymbolIndex;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei: SymbolConstructorIndex ← SEUnderType[stb, sei];
n: CARDINAL ← 0;
ctxi: SymbolContextIndex;
enumeration: BOOLFALSE;
looker: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
n ← n + 1;
IF enumeration
THEN {
IF index-1 = IDCardinalValue[stb, isei]
THEN {p[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
}
ELSE
IF n = index
THEN {p[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
union =>
IF index = 0
THEN {p[stb, [x[ser.tagSei]]]; ReleaseSTB[stb]; RETURN}
ELSE ctxi ← [x[ser.caseCtx]];
sequence => {
RRA: to get the name of a sequence tag
p[stb, [x[ser.tagSei]]]; ReleaseSTB[stb]; RETURN};
enumerated => {enumeration ← TRUE; ctxi ← [x[ser.valueCtx]]};
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
union =>
IF index = 0
THEN {p[stb, [y[ser.tagSei]]]; ReleaseSTB[stb]; RETURN}
ELSE ctxi ← [y[ser.caseCtx]];
sequence => {
RRA: to get the name of a sequence tag
p[stb, [y[ser.tagSei]]]; ReleaseSTB[stb]; RETURN};
enumerated => {enumeration ← TRUE; ctxi ← [y[ser.valueCtx]]};
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
IF NOT EnumerateCtxIseis[stb, ctxi, looker] THEN ERROR Error[reason: badIndex];
};
ReleaseSTB[stb];
};
RecordComponentISEI: PUBLIC PROC [type: Type--record, structure--, index: Index, p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]] = {
stb: SymbolTableBase;
sei: SymbolIndex;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei: SymbolConstructorIndex ← SEUnderType[stb, sei];
n: Index ← 0;
looker: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
n ← n + 1;
IF n = index
THEN {p[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE]};
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
record =>
IF NOT EnumerateRecordIseis[stb, LOOPHOLE[csei, SymbolRecordIndex], looker]
THEN ERROR Error[reason: badIndex];
definition =>
IF NOT EnumerateCtxIseis[stb, [x[ser.defCtx]], looker]
THEN ERROR Error[reason: badIndex];
ENDCASE => ERROR Error[reason: typeFault, type: type];
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
record =>
IF NOT EnumerateRecordIseis[stb, LOOPHOLE[csei, SymbolRecordIndex], looker]
THEN ERROR Error[reason: badIndex];
definition =>
IF NOT EnumerateCtxIseis[stb, [y[ser.defCtx]], looker]
THEN ERROR Error[reason: badIndex];
ENDCASE => ERROR Error[reason: typeFault, type: type];
ENDCASE => ERROR;
};
ReleaseSTB[stb];
};
... NOTE and procedures for dealing with code TypedVariables...
Procedures private to this module
CtxEntries: PROC[stb: SymbolTableBase, ctx: SymbolContextIndex] RETURNS[CARDINAL] = {
n: CARDINAL ← 0;
counter: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
n ← n + 1;
RETURN[FALSE];
};
[] ← EnumerateCtxIseis[stb, ctx, counter];
RETURN[n];
};
GetOrigin: PUBLIC SAFE PROC[type: Type] RETURNS[origin: INTEGER ← 0] = TRUSTED {
stb: SymbolTableBase;
sei: SymbolIndex;
csei: SymbolConstructorIndex;
entry: RTTCache.IntEntry ← NIL;
IF Size[type] > 1 THEN RETURN[0]; -- no subranges in long domain
entry ← RTTCache.LookupInt[type, GetOrigin];
IF entry.int # -1 THEN RETURN[entry.int];
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei ← SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
subrange => origin ← ser.origin
ENDCASE;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
subrange => origin ← ser.origin
ENDCASE;
ENDCASE => ERROR;
};
ReleaseSTB[stb];
IF entry # NIL THEN [] ← RTTCache.FillIntEntry[entry, origin];
};
END.