RTTSupportImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Russ Atkinson, July 19, 1984 3:15:22 pm PDT
Richard Koo, July 2, 1984 9:35:44 am PDT
DIRECTORY
AMTypes USING[Error],
Atom USING[MakeAtom],
BcdDefs USING[VersionStamp, NullVersion],
BrandXSymbolDefs USING[SymbolTableBase, SymbolIndex, SymbolContextIndex, nullHandle,
StandardSymbolContextIndex, contextLevelZero, PreDefinedSEI],
BrandYSymbolDefs USING[SymbolTableBase, SymbolIndex, SymbolContextIndex, nullHandle,
StandardSymbolContextIndex, contextLevelZero, PreDefinedSEI],
ConvertUnsafe USING[SubString, SubStringToRope, EqualSubStrings],
RCMap USING[Index],
RCMapOps USING[Acquire],
Rope USING[ROPE],
RTSymbolDefs USING[SymbolTableHandle, nullHandle, SymbolTableBase, SymbolIndex,
SymbolRecordIndex, SymbolNameIndex, nullBase,
SymbolConstructorIndex, nullSymbolIndex, SymbolIdIndex,
symbolIndexForANY],
RTSymbolOps USING[EnumerateCtxIseis, PeelAllButLast, SEUnderType, SETagIDP, NullISEI,
SubStringForName, IsSequence, NullStb, NullSth, ISEName],
RTSymbols USING[Outer, AcquireSTBFromMDI, AcquireSTB, ReleaseSTB, BaseToHandle,
GetSTHForModule],
RTSymbolsPrivate USING[AcquireSTHFromSTX],
RTTypesBasicPrivate USING[UniqueTypeFinger, SymbolAccess,
STDesc, SymbolTableIndex, FindSTI, PTypeDesc, MakeNewType, MapTiTd, MapStiStd, GetLastTypeIndex, FindCanonicalPTD, Enter, FindPTD],
SafeStorage USING[TypeIndex, Type, nullType, unspecType, anyType],
TypeStrings USING[Create, TypeString],
UnsafeStorage USING[GetSystemUZone];
RTTSupportImpl: PROGRAM
IMPORTS
AMTypes, Atom, ConvertUnsafe, RCMapOps, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesBasicPrivate, TypeStrings, UnsafeStorage
EXPORTS RTSymbolOps, RTSymbols
= BEGIN OPEN
bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XRCMapOps: RCMapOps, YRCMapOps: RCMapOps, XTypeStrings: TypeStrings, YTypeStrings: TypeStrings, RTSymbolDefs, RTSymbolOps, RTSymbols, RTSymbolsPrivate, SafeStorage, TypeStrings;
ROPE: TYPE = Rope.ROPE;
standardXSTH: SymbolTableHandle ← [x[bx.nullHandle]];
standardYSTH: SymbolTableHandle ← [y[by.nullHandle]];
typeStringZone: UNCOUNTED ZONE = UnsafeStorage.GetSystemUZone[];
*****************************
S U P P O R T F O R T H E D E B U G G E R
AcquireType: PUBLIC PROC[stb: SymbolTableBase,
seIndex: SymbolIndex,
canonicalize: BOOLFALSE,
rcmi: RCMap.Index ← LAST[RCMap.Index]]
RETURNS[type: Type] = {inner: PROC =
{ ptd: RTTypesBasicPrivate.PTypeDesc;
utf: RTTypesBasicPrivate.UniqueTypeFinger;
ustb: SymbolTableBase;
usei: SymbolIndex;
csei: SymbolConstructorIndex = SEUnderType[stb, seIndex];
isConsType: BOOL = NOT SETagIDP[stb, seIndex];
MakePredefinedType: PROC[preType: Type] =
INLINE{utf: RTTypesBasicPrivate.UniqueTypeFinger;
ustb: SymbolTableBase;
usei: SymbolIndex;
std: RTTypesBasicPrivate.STDesc;
[utf, ustb, usei] ← ComputeUTF[stb, seIndex];
std ← STDescFromSTB[ustb];
IF stb # ustb THEN ReleaseSTB[ustb];
IF rcmi = LAST[RCMap.Index]
THEN {rcmi ← WITH stb SELECT FROM
t: SymbolTableBase.x =>
XRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.x].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
t: SymbolTableBase.y =>
YRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.y].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
ENDCASE => ERROR;
EXITS rcMapAcquisitionError =>
ERROR AMTypes.Error[reason: notImplemented,
msg: "RCMaps for this type"]};
[] ← RTTypesBasicPrivate.MakeNewType
[utf, std, usei,
WITH stb SELECT FROM
t: SymbolTableBase.x =>
XTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.x].e,
typeStringZone],
t: SymbolTableBase.y =>
YTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.y].e,
typeStringZone],
ENDCASE => ERROR,
rcmi, FALSE, FALSE, preType]};
IF NullISEI[LOOPHOLE[seIndex]] THEN ERROR;
IF csei = symbolIndexForANY THEN
{IF RTTypesBasicPrivate.MapTiTd[unspecType] = NIL THEN MakePredefinedType[unspecType];
type ← unspecType;
RETURN};
IF isConsType THEN
{ isRefAny: BOOLFALSE;
isAny: BOOLFALSE;
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
any => isAny ← TRUE;
ENDCASE;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
any => isAny ← TRUE;
ENDCASE;
ENDCASE => ERROR;
IF isAny THEN
{IF RTTypesBasicPrivate.MapTiTd[anyType] = NIL THEN MakePredefinedType[anyType];
type ← anyType;
RETURN}};
IF canonicalize
THEN {ts: TypeString;
[ptd, ts, utf] ← FindCanonicalType[stb, csei]; -- ts new storage only if ptd = NIL
IF ptd # NIL
THEN {type ← ptd.equivalentType; RETURN}
ELSE {std: RTTypesBasicPrivate.STDesc = STDescFromSTB[stb];
IF rcmi = LAST[RCMap.Index]
THEN
{rcmi ← WITH stb SELECT FROM
t: SymbolTableBase.x =>
XRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.x].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
t: SymbolTableBase.y =>
YRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.y].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
ENDCASE => ERROR;
EXITS rcMapAcquisitionError =>
ERROR AMTypes.Error[reason: notImplemented,
msg: "RCMaps for this type"]};
type ← RTTypesBasicPrivate.MakeNewType[utf, std, LOOPHOLE[csei, SymbolIndex],
ts, rcmi, TRUE];
RETURN}}
ELSE { IF NOT isConsType
THEN seIndex ← LOOPHOLE[PeelAllButLast[stb, LOOPHOLE[seIndex,
SymbolIdIndex]],
SymbolIndex];
[ptd, utf, ustb, usei] ← FindUTF[stb, seIndex];
IF ptd # NIL
THEN {IF stb # ustb THEN ReleaseSTB[ustb];
type ← ptd.myType;
RETURN}
ELSE {std: RTTypesBasicPrivate.STDesc = STDescFromSTB[ustb];
IF stb # ustb THEN ReleaseSTB[ustb];
IF rcmi = LAST[RCMap.Index]
THEN {rcmi ←
WITH stb SELECT FROM
t: SymbolTableBase.x =>
XRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.x].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
t: SymbolTableBase.y =>
YRCMapOps.Acquire
[t.e, NARROW[csei, SymbolConstructorIndex.y].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
ENDCASE => ERROR;
EXITS rcMapAcquisitionError =>
ERROR AMTypes.Error[reason: notImplemented,
msg: "RCMaps for this type"]};
type ← RTTypesBasicPrivate.MakeNewType
[utf, std, usei,
WITH stb SELECT FROM
t: SymbolTableBase.x =>
XTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.x].e,
typeStringZone],
t: SymbolTableBase.y =>
YTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.y].e,
typeStringZone],
ENDCASE => ERROR,
rcmi];
RETURN}}};
RTTypesBasicPrivate.Enter[inner ! AMTypes.Error => REJECT; UNWIND => NULL; ANY => GOTO unwind];
EXITS unwind => ERROR};
AcquireSequenceType: PUBLIC PROC[stb: SymbolTableBase,
sei: SymbolIndex, -- of sequence part
recordSTB: SymbolTableBase,
recordSEIndex: SymbolRecordIndex]
RETURNS[type: Type] = {inner: PROC =
{ ptd: RTTypesBasicPrivate.PTypeDesc;
utf: RTTypesBasicPrivate.UniqueTypeFinger;
ustb: SymbolTableBase;
usei: SymbolIndex;
csei: SymbolConstructorIndex = SEUnderType[stb, sei];
IF NOT IsSequence[stb, sei] THEN ERROR;
IF SETagIDP[stb, sei]
THEN sei ← LOOPHOLE[PeelAllButLast[stb, LOOPHOLE[sei, SymbolIdIndex]], SymbolIndex];
[ptd, utf, ustb, usei] ← FindUTF[stb, sei];
IF ptd # NIL
THEN {IF stb # ustb THEN ReleaseSTB[ustb];
type ← ptd.myType}
ELSE {rcmi: RCMap.Index;
std: RTTypesBasicPrivate.STDesc = STDescFromSTB[ustb];
{rcmi ← WITH recordSTB SELECT FROM
t: SymbolTableBase.x =>
XRCMapOps.Acquire
[t.e, NARROW[recordSEIndex, SymbolRecordIndex.x].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
t: SymbolTableBase.y =>
YRCMapOps.Acquire
[t.e, NARROW[recordSEIndex, SymbolRecordIndex.y].e
! AMTypes.Error => REJECT;
UNWIND => NULL;
ANY => GOTO rcMapAcquisitionError],
ENDCASE => ERROR;
EXITS rcMapAcquisitionError =>
ERROR AMTypes.Error[reason: notImplemented,
msg: "RCMaps for this type"]};
IF stb # ustb THEN ReleaseSTB[ustb];
type ← RTTypesBasicPrivate.MakeNewType
[utf,
std,
usei,
WITH recordSTB SELECT FROM
t: SymbolTableBase.x =>
XTypeStrings.Create
[t.e,
NARROW[recordSEIndex, SymbolRecordIndex.x].e,
typeStringZone],
t: SymbolTableBase.y =>
YTypeStrings.Create
[t.e,
NARROW[recordSEIndex, SymbolRecordIndex.y].e,
typeStringZone],
ENDCASE => ERROR,
rcmi]}};
RTTypesBasicPrivate.Enter[inner ! AMTypes.Error => REJECT; UNWIND => NULL; ANY => GOTO unwind];
EXITS unwind => ERROR};
AcquireRope: PUBLIC PROC[stb: SymbolTableBase, hti: SymbolNameIndex]
RETURNS[ROPE] = {RETURN[ConvertUnsafe.SubStringToRope[SubStringForName[stb, hti]]]};
AcquireAtom: PUBLIC PROC[stb: SymbolTableBase, hti: SymbolNameIndex]
RETURNS[atom: ATOM] ={RETURN[Atom.MakeAtom[AcquireRope[stb, hti]]]};
EnumerateTypes: PROC[p: PROC[Type] RETURNS[stop: BOOL]]
RETURNS[stopped: BOOLFALSE] =
{FOR t: TypeIndex IN [FIRST[TypeIndex]..RTTypesBasicPrivate.GetLastTypeIndex[]]
DO IF p[[t]] THEN RETURN[TRUE] ENDLOOP};
ErrorRecord: TYPE = RECORD [type: Type, name: ROPE];
errList: LIST OF ErrorRecord ← NIL;
GetTypeSymbols: PUBLIC PROC[type: Type]
RETURNS[stb: SymbolTableBase, sei: SymbolIndex] = {
moduleName: ROPE;
IF type = nullType THEN ERROR AMTypes.Error[reason: typeFault, type: type];
[stb, sei, moduleName] ← DoGetTypeSymbols[type];
IF NullStb[stb] THEN {
FOR each: LIST OF ErrorRecord ← errList, each.rest WHILE each # NIL DO
IF each.first.type = type THEN GO TO gleep;
ENDLOOP;
errList ← CONS[[type, moduleName], errList];
GO TO gleep;
EXITS gleep => ERROR AMTypes.Error[reason: noSymbols, msg: moduleName];
};
};
GetOriginalTypeSymbols: PUBLIC PROC[type: Type]
RETURNS[stb: SymbolTableBase, sei: SymbolIndex] =
{ IF type = nullType THEN ERROR AMTypes.Error[reason: typeFault, type: type];
[stb, sei,] ← DoGetTypeSymbols[type, TRUE];
IF NullStb[stb] THEN ERROR AMTypes.Error[reason: noSymbols]};
IsPreDefinedSEI: PROC[sei: SymbolIndex] RETURNS[BOOL] =
{RETURN[WITH sei SELECT FROM
t: SymbolIndex.x => LOOPHOLE[t.e, CARDINAL] IN bx.PreDefinedSEI,
t: SymbolIndex.y => LOOPHOLE[t.e, CARDINAL] IN by.PreDefinedSEI,
ENDCASE => ERROR]};
DoGetTypeSymbols: PROC[type: Type, originalOnly: BOOLFALSE]
RETURNS[stb: SymbolTableBase, sei: SymbolIndex, moduleName: ROPENIL] = {
ptd: RTTypesBasicPrivate.PTypeDesc = RTTypesBasicPrivate.MapTiTd[type];
stInfo: RTTypesBasicPrivate.SymbolAccess ← ptd.symbolAccess;
sth: SymbolTableHandle ← IF originalOnly THEN nullHandle ELSE RTTypesBasicPrivate.MapStiStd[stInfo.sti].sth;
mn: ROPENIL;
anySTHWillDo: BOOL
← (ptd.utf.umid = BcdDefs.NullVersion AND IsPreDefinedSEI[ptd.utf.seIndex]);
originalUTF: BOOL
NOT(ptd.utf.umid = BcdDefs.NullVersion OR IsPreDefinedSEI[ptd.utf.seIndex]);
sei ← IF originalOnly AND originalUTF THEN ptd.utf.seIndex ELSE stInfo.sei;
IF NullSth[sth] THEN
IF anySTHWillDo
THEN { -- standard symbol; any table will do
IF NOT (IF sei.brand = x THEN NullSth[standardXSTH] ELSE NullSth[standardYSTH])
THEN sth ← (IF sei.brand = x THEN standardXSTH ELSE standardYSTH)
ELSE
FOR i: RTTypesBasicPrivate.SymbolTableIndex IN [1..RTTypesBasicPrivate.MapStiStd.length)
DO
IF RTTypesBasicPrivate.MapStiStd[i] = NIL THEN LOOP
ELSE IF NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth] THEN {sth ← RTTypesBasicPrivate.MapStiStd[i].sth; EXIT}
ELSE { -- go find the symbol table bits
[sth: sth, moduleName: mn] ← AcquireSTHFromSTX[i];
IF moduleName = NIL THEN moduleName ← mn;
RTTypesBasicPrivate.MapStiStd[i].sth ← sth;
IF NOT NullSth[sth] THEN EXIT; -- found one
};
ENDLOOP;
}
ELSE { -- go find the symbol table bits
IF originalOnly AND originalUTF
THEN sth ← GetSTHForModule[ptd.utf.umid, NIL, NIL
    ! AMTypes.Error => CONTINUE]
ELSE {
[sth: sth, moduleName: moduleName] ← AcquireSTHFromSTX[stInfo.sti];
RTTypesBasicPrivate.MapStiStd[stInfo.sti].sth ← sth;
IF NullSth[sth] AND originalUTF
THEN { -- try for the original defining module
std: RTTypesBasicPrivate.STDesc = [symbolsStamp: ptd.utf.umid, bcd: RTTypesBasicPrivate.MapStiStd[stInfo.sti].bcd];
sei ← ptd.utf.seIndex;
IF anySTHWillDo
THEN {
IF NOT (IF sei.brand = x THEN NullSth[standardXSTH]
  ELSE NullSth[standardYSTH])
THEN sth ← (IF sei.brand = x THEN standardXSTH
    ELSE standardYSTH)
ELSE
FOR i: RTTypesBasicPrivate.SymbolTableIndex IN [1..RTTypesBasicPrivate.MapStiStd.length)
DO
IF RTTypesBasicPrivate.MapStiStd[i] = NIL THEN LOOP
ELSE IF NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth]
THEN {sth ← RTTypesBasicPrivate.MapStiStd[i].sth; EXIT}
ELSE { -- go find the symbol table bits
[sth: sth, moduleName: mn] ← AcquireSTHFromSTX[i];
IF moduleName = NIL THEN moduleName ← mn;
RTTypesBasicPrivate.MapStiStd[i].sth ← sth;
IF NOT NullSth[sth] THEN EXIT; -- found one
};
ENDLOOP;
}
ELSE {
[sth: sth, moduleName: mn] ← AcquireSTHFromSTX[RTTypesBasicPrivate.FindSTI[std]];
IF moduleName = NIL THEN moduleName ← mn;
};
};
};
};
IF NullSth[sth]
THEN stb ← nullBase
ELSE {
WITH sth SELECT FROM
t: SymbolTableHandle.x => IF NullSth[standardXSTH] THEN standardXSTH ← sth;
t: SymbolTableHandle.y => IF NullSth[standardYSTH] THEN standardYSTH ← sth;
ENDCASE => ERROR;
stb ← AcquireSTB[sth];
};
};
Creation of new runtime Type descriptors
ts new storage only if ptd = NIL
FindCanonicalType: PROC[stb: SymbolTableBase, csei: SymbolConstructorIndex]
RETURNS[ptd: RTTypesBasicPrivate.PTypeDesc, ts: TypeString, utf: RTTypesBasicPrivate.UniqueTypeFinger] =
{ ts ← WITH stb SELECT FROM
t: SymbolTableBase.x => XTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.x].e,
typeStringZone],
t: SymbolTableBase.y => YTypeStrings.Create
[t.e,
NARROW[csei, SymbolConstructorIndex.y].e,
typeStringZone],
ENDCASE => ERROR;
ptd ← RTTypesBasicPrivate.FindCanonicalPTD[ts];
IF ptd # NIL
THEN {typeStringZone.FREE[@ts]; RETURN[ptd, NIL, ptd.utf]}
ELSE {[utf,,] ← ComputeUTF[stb, LOOPHOLE[csei, SymbolIndex]]; RETURN[NIL, ts, utf]}};
Recognize identical type previously entered
hash map: UniqueTypeFinger -> TypeIndex
FindUTF: PROC [stb: SymbolTableBase, sei: SymbolIndex]
RETURNS[ptd: RTTypesBasicPrivate.PTypeDesc,
utf: RTTypesBasicPrivate.UniqueTypeFinger,
ustb: SymbolTableBase,
usei: SymbolIndex] =
{ [utf, ustb, usei] ← ComputeUTF[stb, sei];
RETURN[RTTypesBasicPrivate.FindPTD[utf], utf, ustb, usei]};
ComputeUTF might return a new (ustb, usei) only if sei is a SymbolIdIndex
ComputeUTF: PROC [outerSTB: SymbolTableBase, sei: SymbolIndex]
RETURNS[utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] =
{ WITH outerSTB SELECT FROM
t: SymbolTableBase.x =>
[utf, ustb, usei] ← ComputeUTFX[t.e, NARROW[sei, SymbolIndex.x].e];
t: SymbolTableBase.y =>
[utf, ustb, usei] ← ComputeUTFY[t.e, NARROW[sei, SymbolIndex.y].e];
ENDCASE => ERROR};
ComputeUTFX: PROC [outerSTB: bx.SymbolTableBase, sei: bx.SymbolIndex]
RETURNS[utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] =
{ ustb ← [x[outerSTB]];
usei ← [x[sei]];
WITH ser: outerSTB.seb[sei] SELECT FROM
id => IF ser.idCtx IN bx.StandardSymbolContextIndex
THEN utf ← [umid: BcdDefs.NullVersion, seIndex: usei] -- a primitive type
ELSE
WITH ctxr: outerSTB.ctxb[ser.idCtx] SELECT FROM
included =>
IF ctxr.level # bx.contextLevelZero
THEN utf ← [umid: outerSTB.mdb[ctxr.module].stamp,
seIndex: [x[LOOPHOLE[ser.idValue, bx.SymbolIndex]]]]
ELSE
{ inner: PROC[stb: SymbolTableBase] =
{ p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS[stop: BOOL] =
{ ssd1: ConvertUnsafe.SubString
= SubStringForName[[x[outerSTB]], [x[ser.hash]]];
ssd2: ConvertUnsafe.SubString
= SubStringForName[stb, ISEName[stb, isei]];
IF ConvertUnsafe.EqualSubStrings[ssd1, ssd2]
THEN
{utf ← [umid: NARROW[stb, SymbolTableBase.x].e.stHandle.version,
seIndex: LOOPHOLE[isei, SymbolIndex]];
usei ← LOOPHOLE[isei, SymbolIndex];
RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: [x[ctxr.map]], proc: p]
THEN ERROR;
};
Outer[stb: [x[outerSTB]], mdi: [x[ctxr.module]], inner: inner];
ustb ← AcquireSTBFromMDI[[x[outerSTB]], [x[ctxr.module]]];
RETURN
};
ENDCASE => utf ← [umid: outerSTB.stHandle.version, seIndex: [x[sei]]];
cons => utf ← [umid: (IF IsPreDefinedSEI[[x[sei]]]
THEN BcdDefs.NullVersion
ELSE outerSTB.stHandle.version), -- NOTE
seIndex: [x[sei]]];
ENDCASE => ERROR};
ComputeUTFY: PROC [outerSTB: by.SymbolTableBase, sei: by.SymbolIndex]
RETURNS[utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] =
{ ustb ← [y[outerSTB]];
usei ← [y[sei]];
WITH ser: outerSTB.seb[sei] SELECT FROM
id => IF ser.idCtx IN by.StandardSymbolContextIndex
THEN utf ← [umid: BcdDefs.NullVersion, seIndex: usei] -- a primitive type
ELSE
WITH ctxr: outerSTB.ctxb[ser.idCtx] SELECT FROM
included =>
IF ctxr.level # by.contextLevelZero
THEN utf ← [umid: outerSTB.mdb[ctxr.module].stamp,
seIndex: [y[LOOPHOLE[ser.idValue, by.SymbolIndex]]]]
ELSE
{ inner: PROC[stb: SymbolTableBase] =
{ p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS[stop: BOOL] =
{ ssd1: ConvertUnsafe.SubString
= SubStringForName[[y[outerSTB]], [y[ser.hash]]];
ssd2: ConvertUnsafe.SubString
= SubStringForName[stb, ISEName[stb, isei]];
IF ConvertUnsafe.EqualSubStrings[ssd1, ssd2]
THEN
{utf ← [umid: NARROW[stb, SymbolTableBase.y].e.stHandle.version,
seIndex: LOOPHOLE[isei, SymbolIndex]];
usei ← LOOPHOLE[isei, SymbolIndex];
RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: [y[ctxr.map]], proc: p]
THEN ERROR;
};
Outer[stb: [y[outerSTB]], mdi: [y[ctxr.module]], inner: inner];
ustb ← AcquireSTBFromMDI[[y[outerSTB]], [y[ctxr.module]]];
RETURN
};
ENDCASE => utf ← [umid: outerSTB.stHandle.version, seIndex: [y[sei]]];
cons => utf ← [umid: (IF IsPreDefinedSEI[[y[sei]]]
THEN BcdDefs.NullVersion
ELSE outerSTB.stHandle.version), -- NOTE
seIndex: [y[sei]]];
ENDCASE => ERROR};
STDescFromSTB: PROC[stb: SymbolTableBase] RETURNS[RTTypesBasicPrivate.STDesc] =
{ version: BcdDefs.VersionStamp =
(WITH stb SELECT FROM
t: SymbolTableBase.x => t.e.stHandle.version,
t: SymbolTableBase.y => t.e.stHandle.version
ENDCASE => ERROR);
RETURN[[symbolsStamp: version, sth: RTSymbols.BaseToHandle[stb]]]};
END.