RTTSupportImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
designed by Paul Rovner
Richard Koo, July 2, 1984 9:35:44 am PDT
Russ Atkinson (RRA) August 28, 1985 3:06:25 pm PDT
DIRECTORY
AMTypes USING [Error],
Atom USING [MakeAtom],
BcdDefs USING [NullVersion, VersionStamp],
BrandXSymbolDefs USING [contextLevelZero, nullHandle, PreDefinedSEI, StandardSymbolContextIndex, SymbolContextIndex, SymbolIndex, SymbolTableBase],
BrandYSymbolDefs USING [contextLevelZero, nullHandle, PreDefinedSEI, StandardSymbolContextIndex, SymbolContextIndex, SymbolIndex, SymbolTableBase],
ConvertUnsafe USING [EqualSubStrings, SubString, SubStringToRope],
RCMap USING [Index],
RCMapOps USING [Acquire],
Rope USING [ROPE],
RTSymbolDefs USING [nullBase, nullHandle, SymbolConstructorIndex, SymbolIdIndex, SymbolIndex, symbolIndexForANY, SymbolNameIndex, SymbolRecordIndex, SymbolTableBase, SymbolTableHandle],
RTSymbolOps USING [EnumerateCtxIseis, PeelAllButLast, SEUnderType, SETagIDP, NullISEI, SubStringForName, IsSequence, NullStb, NullSth, ISEName],
RTSymbols USING [AcquireSTB, AcquireSTBFromMDI, BaseToHandle, GetSTHForModule, OuterFromMDI, ReleaseSTB],
RTSymbolsPrivate USING [AcquireSTHFromSTX],
RTTypesBasicPrivate USING [Enter, FindCanonicalPTD, FindPTD, FindSTI, GetLastTypeIndex, MakeNewType, MapStiStd, MapTiTd, PTypeDesc, STDesc, SymbolAccess, SymbolTableIndex, UniqueTypeFinger],
RuntimeError USING [UNCAUGHT],
SafeStorage USING [anyType, nullType, Type, TypeIndex, unspecType],
TypeStrings USING [Create, TypeString],
UnsafeStorage USING [GetSystemUZone];
RTTSupportImpl:
PROGRAM
IMPORTS AMTypes, Atom, ConvertUnsafe, RCMapOps, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesBasicPrivate, RuntimeError, TypeStrings, UnsafeStorage
EXPORTS RTSymbolOps, RTSymbols
= BEGIN OPEN bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XRCMapOps: RCMapOps, YRCMapOps: RCMapOps, XTypeStrings: TypeStrings, YTypeStrings: TypeStrings, RTSymbolDefs, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RuntimeError, 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:
BOOL ←
FALSE, 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] =
{
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],
t: SymbolTableBase.y =>
YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e],
ENDCASE => ERROR;
};
[] ← 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 {
WITH stb
SELECT
FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[
NARROW[csei, SymbolConstructorIndex.x].e]
SELECT
FROM
any => GO TO isAny;
ENDCASE;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[
NARROW[csei, SymbolConstructorIndex.y].e]
SELECT
FROM
any => GO TO isAny;
ENDCASE;
ENDCASE => ERROR;
EXITS isAny => {
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],
t: SymbolTableBase.y =>
YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e],
ENDCASE => ERROR;
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],
t: SymbolTableBase.y =>
YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e],
ENDCASE => ERROR;
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; UNCAUGHT => GOTO unwind];
EXITS unwind => ERROR;
};
AcquireSequenceType:
PUBLIC
PROC [stb: SymbolTableBase, sei: SymbolIndex, 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 {
std: RTTypesBasicPrivate.STDesc = STDescFromSTB[ustb];
rcmi: RCMap.Index ←
WITH recordSTB
SELECT
FROM
t: SymbolTableBase.x =>
XRCMapOps.Acquire[t.e, NARROW[recordSEIndex, SymbolRecordIndex.x].e],
t: SymbolTableBase.y =>
YRCMapOps.Acquire[t.e, NARROW[recordSEIndex, SymbolRecordIndex.y].e],
ENDCASE => ERROR;
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; UNCAUGHT => 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:
BOOL ←
FALSE] = {
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] = {
IF type = nullType THEN ERROR AMTypes.Error[reason: typeFault, type: type];
[stb, sei,] ← DoGetTypeSymbols[type];
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];
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:
BOOL ←
FALSE]
RETURNS [stb: SymbolTableBase, sei: SymbolIndex, moduleName:
ROPE ←
NIL] = {
ptd: RTTypesBasicPrivate.PTypeDesc = RTTypesBasicPrivate.MapTiTd[type];
stInfo: RTTypesBasicPrivate.SymbolAccess ← ptd.symbolAccess;
sth: SymbolTableHandle ← IF originalOnly THEN nullHandle ELSE RTTypesBasicPrivate.MapStiStd[stInfo.sti].sth;
mn: ROPE ← NIL;
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;
IF
NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth]
THEN {
sth ← RTTypesBasicPrivate.MapStiStd[i].sth; EXIT};
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;
IF
NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth]
THEN {
sth ← RTTypesBasicPrivate.MapStiStd[i].sth; EXIT};
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];
};
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];
};
Creation of new runtime Type descriptors
FindCanonicalType:
PROC [stb: SymbolTableBase, csei: SymbolConstructorIndex]
RETURNS [ptd: RTTypesBasicPrivate.PTypeDesc, ts: TypeString, utf: RTTypesBasicPrivate.UniqueTypeFinger] = {
ts new storage only if ptd = NIL
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:
PROC [outerSTB: SymbolTableBase, sei: SymbolIndex]
RETURNS [utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] = {
ComputeUTF might return a new (ustb, usei) only if sei is a SymbolIdIndex
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 (stop ← ConvertUnsafe.EqualSubStrings[ssd1, ssd2])
THEN {
utf ← [umid: NARROW[stb, SymbolTableBase.x].e.stHandle.version, seIndex: LOOPHOLE[isei, SymbolIndex]];
usei ← LOOPHOLE[isei, SymbolIndex];
}
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: [x[ctxr.map]], proc: p] THEN ERROR;
};
OuterFromMDI[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 (stop ← ConvertUnsafe.EqualSubStrings[ssd1, ssd2])
THEN {
utf ← [umid: NARROW[stb, SymbolTableBase.y].e.stHandle.version, seIndex: LOOPHOLE[isei, SymbolIndex]];
usei ← LOOPHOLE[isei, SymbolIndex];
}
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: [y[ctxr.map]], proc: p] THEN ERROR;
};
OuterFromMDI[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.