-- AMModelSectionImpl.mesa
-- Last Modified On August 10, 1983 12:45 pm By Paul Rovner
-- moduleName, configName should not be source name

DIRECTORY
AMBridge USING [TVForGFHReferent, TVForRemoteGFHReferent, GFHFromTV,
RemoteGFHFromTV, GetWorld, RemoteGlobalFrameHandle,
nilRemoteGlobalFrameHandle],
AMMiniModel USING [AcquireIRType],
AMModel USING [Class, Source, SourceObj, CharIndex],
AMModelPrivate USING [FGIndex, FGNull, EPI, EPIToFirstFGI, GetModuleSTB,
EPIToLastFGI, FGIToFirstChar, FGIToLastChar, FGIToEPI,
NextFGI, SectionRec, RefTVRec, GetLocalBCD, GetRemoteBCD],
AMTypes USING [TVType, Error, TVToName, TV],
BcdDefs USING [MTIndex, NameRecord, BcdBase, MTHandle, NameString, VersionStamp, ModuleIndex],
BcdOps USING [ProcessModules],
BrandXSymbolDefs USING[BodyIndex, rootBodyIndex, nullBodyIndex, SymbolTableBase,
FineGrainTableHeader],
BrandYSymbolDefs USING[BodyIndex, rootBodyIndex, nullBodyIndex, SymbolTableBase,
FineGrainTableHeader],
ConvertUnsafe USING [ToRope, SubStringToRope, SubString],
IO USING [PutR, card],
LoadState USING [local, Acquire, Release, Handle, ConfigInfo, ModuleToGlobalFrame, ConfigID, GlobalFrameToModule],
PrincOps USING [wordsPerPage, GlobalFrameHandle],
Rope USING [ROPE, Concat],
RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle],
RTSymbolOps USING [AcquireRope, AcquireType, STBSourceVersion],
RTSymbols USING [AcquireSTB, ReleaseSTB, GetSTHForModule],
RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD],
RTTypesRemotePrivate USING [AcquireRemoteBCD, ReleaseRemoteBCD],
SafeStorage USING [Type],
Table USING [Base],
WorldVM USING [World, Lock, Unlock, LocalWorld, Loadstate, CurrentIncarnation, Incarnation];

AMModelSectionImpl: PROGRAM
IMPORTS AMBridge, AMMiniModel, AMModelPrivate, AMTypes, BcdOps, ConvertUnsafe,
IO, LoadState, Rope, RTSymbolOps, RTSymbols,
RTSymbolsPrivate, RTTypesRemotePrivate, WorldVM
EXPORTS AMModel

= { OPEN AMBridge, AMMiniModel, AMTypes, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, PrincOps,
Rope, AMModel, AMModelPrivate,
RTSymbolDefs, RTSymbolOps, RTSymbols, RTTypesRemotePrivate, WorldVM;


-- TYPEs

-- either binder output bundle for a config, or compiler output bundle
-- for a prog module, DEFs module, proc, or statement
Section: TYPE = REF SectionObj;
SectionObj: PUBLIC TYPE = SectionRec;

-- PROCs dealing with Sections

SectionClass: PUBLIC PROC[section: Section] RETURNS[Class] =
{RETURN[section.class]};

SectionName: PUBLIC PROC[section: Section] RETURNS[ans: ROPENIL] =
{WITH s: section SELECT FROM
model => RETURN[s.configName];
prog => RETURN[s.moduleName];
interface => RETURN[s.moduleName];
proc => IF s.procTV # NIL
THEN RETURN[TVToName[s.procTV]]
ELSE {sth: SymbolTableHandle
= GetSTHForModule
[stamp: s.prog.versionStamp,
fileName: Rope.Concat[s.prog.moduleName, ".bcd"],
moduleName: s.prog.moduleName];
stb: SymbolTableBase ← AcquireSTB[sth];
FindProcX: PROC[bti: bx.BodyIndex] RETURNS[stop: BOOLEANFALSE] =
{xstb: bx.SymbolTableBase = NARROW[stb, SymbolTableBase.x].e;
WITH b: xstb.bb[bti] SELECT FROM
Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex
THEN {ans ← AcquireRope[stb, [x[xstb.seb[b.id].hash]]];
RETURN[TRUE]};
ENDCASE};
FindProcY: PROC[bti: by.BodyIndex] RETURNS[stop: BOOLEANFALSE] =
{ystb: by.SymbolTableBase = NARROW[stb, SymbolTableBase.y].e;
WITH b: ystb.bb[bti] SELECT FROM
Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex
THEN {ans ← AcquireRope[stb, [y[ystb.seb[b.id].hash]]];
RETURN[TRUE]};
ENDCASE};

WITH stb SELECT FROM
t: SymbolTableBase.x =>
IF t.e.EnumerateBodies[bx.rootBodyIndex, FindProcX
! UNWIND => ReleaseSTB[stb]] = bx.nullBodyIndex
THEN {ReleaseSTB[stb]; ERROR};
t: SymbolTableBase.y =>
IF t.e.EnumerateBodies[by.rootBodyIndex, FindProcY
! UNWIND => ReleaseSTB[stb]] = by.nullBodyIndex
THEN {ReleaseSTB[stb]; ERROR};
ENDCASE => ERROR;
ReleaseSTB[stb];
RETURN[ans]}; -- figure it out from the ep# and the prog section
statement => RETURN[Rope.Concat[Rope.Concat[s.prog.moduleName, "."],
IO.PutR[IO.card[s.fgtIndex.fgCard]]]]
ENDCASE => ERROR
};

-- param to creator of section.
SectionSource: PUBLIC PROC[section: Section] RETURNS[ans: Source] =
--param to creator of section
{WITH s: section SELECT FROM
model => { IF s.configContext # NIL
THEN -- loaded model section
{IF s.configContext.world = LocalWorld[]
THEN {
bcd: BcdDefs.BcdBase;
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
bcd ← LoadState.local.ConfigInfo[s.configContext.configIndex].bcd;
}; -- end ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
ans ← NEW[SourceObj ← [fileName: BcdNameToRope[bcd, bcd.source],
class: model,
versionStamp: bcd.sourceVersion,
sourceRange: entire[]]];
RETURN;
}
ELSE
{fileName: ROPE;
v: BcdDefs.VersionStamp;
world: World = s.configContext.world;

Lock[world];
{ ENABLE UNWIND => Unlock[world];
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
bcd: BcdDefs.BcdBase = AcquireRemoteBCD[
world: world,
incarnation: CurrentIncarnation[world],
bcd: h.ConfigInfo
[s.configContext.configIndex].bcd];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
fileName ← BcdNameToRope[bcd, bcd.source];
v ← bcd.sourceVersion;
}; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
ans ← NEW[SourceObj ← [fileName: fileName,
class: model,
versionStamp: v,
sourceRange: entire[]]];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[world];
RETURN;
}
}
ELSE { -- model section, not loaded. Get the binder output bcd, given the
-- config name and its version stamp
bcd: BcdDefs.BcdBase
= RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.versionStamp,
shortFileNameHint: Rope.Concat[s.configName,
".bcd"]];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
ans ← NEW[SourceObj ← [fileName: BcdNameToRope[bcd, bcd.source],
class: model,
versionStamp: bcd.sourceVersion,
sourceRange: entire[]]];
RTSymbolsPrivate.ReleaseBCD[bcd];
}};
prog =>
{ -- get the compiler output bcd, given the module name and
-- its version stamp. Could poke around in the loadstate, but painful.
IF s.someGFHTV = NIL
THEN -- unloaded prog section
{bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.versionStamp,
shortFileNameHint: Rope.Concat[s.moduleName,
".bcd"]];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
ans ← NEW[SourceObj ← [fileName: BcdNameToRope[bcd, bcd.source],
class: prog,
versionStamp: bcd.sourceVersion,
sourceRange: entire[]]];
RTSymbolsPrivate.ReleaseBCD[bcd]}
ELSE -- loaded prog section; get the bcd from the loadstate
{ptv: TV = s.someGFHTV;
world: World ← GetWorld[ptv];
IF world = LocalWorld[]
THEN
{bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: prog,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange: entire[]]]};
t: SymbolTableBase.y =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: prog,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange: entire[]]]};
ENDCASE => ERROR;
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}
ELSE -- remote world
{bcd: BcdDefs.BcdBase ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: prog,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange: entire[]]]};
t: SymbolTableBase.y =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: prog,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange: entire[]]]};
ENDCASE => ERROR;
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
};
interface =>
{ -- get the compiler output bcd, given the module name and its version stamp.
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.versionStamp,
shortFileNameHint: Rope.Concat[s.moduleName,
".bcd"]];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
ans ← NEW[SourceObj ← [fileName: BcdNameToRope[bcd, bcd.source],
class: interface,
versionStamp: bcd.sourceVersion,
sourceRange: entire[]]];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
proc =>
{ IF s.prog.someGFHTV = NIL
THEN -- unloaded proc section
{bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.prog.versionStamp,
shortFileNameHint: Rope.Concat[s.prog.moduleName,
".bcd"]];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
ans ← NEW[SourceObj
← [fileName: BcdNameToRope[bcd, bcd.source],
class: proc,
versionStamp: bcd.sourceVersion,
sourceRange:
field[firstCharIndex: ProcToFirstCI[NARROW[section]],
lastCharIndex:
ProcToLastCI[NARROW[section]]]]];
RTSymbolsPrivate.ReleaseBCD[bcd]}
ELSE -- loaded proc section; get the bcd from the loadstate
{ptv: TV = s.prog.someGFHTV;
world: World ← GetWorld[ptv];
IF world = LocalWorld[]
THEN
{bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.prog.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: proc,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange:
field[firstCharIndex: ProcToFirstCI[NARROW[section]],
lastCharIndex:
ProcToLastCI[NARROW[section]]]]]};
t: SymbolTableBase.y =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: proc,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange:
field[firstCharIndex: ProcToFirstCI[NARROW[section]],
lastCharIndex:
ProcToLastCI[NARROW[section]]]]]};
ENDCASE => ERROR;
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}
ELSE -- remote world
{bcd: BcdDefs.BcdBase ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.prog.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: proc,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange:
field[firstCharIndex: ProcToFirstCI[NARROW[section]],
lastCharIndex:
ProcToLastCI[NARROW[section]]]]]};
t: SymbolTableBase.y =>
{ns: LONG STRING
= @LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile;
ans ← NEW[SourceObj ← [fileName: ConvertUnsafe.ToRope[ns],
class: proc,
versionStamp: t.e.stHandle.sourceVersion,
sourceRange:
field[firstCharIndex: ProcToFirstCI[NARROW[section]],
lastCharIndex:
ProcToLastCI[NARROW[section]]]]]};
ENDCASE => ERROR;
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
};

statement =>
{ IF s.prog.someGFHTV = NIL
THEN -- unloaded proc section
{bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.prog.versionStamp,
shortFileNameHint: Rope.Concat[s.prog.moduleName,
".bcd"]];
fci, lci: INT;
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
fci ← StatementToFirstCI[NARROW[section]];
lci ← StatementToLastCI[NARROW[section]];
IF fci = lci THEN lci ← fci-1;
ans ← NEW[SourceObj
← [fileName: BcdNameToRope[bcd, bcd.source],
class: statement,
versionStamp: bcd.sourceVersion,
sourceRange:
field[firstCharIndex: fci,
lastCharIndex: lci]]];
RTSymbolsPrivate.ReleaseBCD[bcd]}
ELSE -- loaded proc section; get the bcd from the loadstate
{ptv: TV = s.prog.someGFHTV;
world: World ← GetWorld[ptv];
IF world = LocalWorld[]
THEN
{bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.prog.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
ns: LONG STRING
= WITH stb SELECT FROM
t: SymbolTableBase.x =>
@LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile,
t: SymbolTableBase.y =>
@LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile,
ENDCASE => ERROR;
fci, lci: INT;
fci ← StatementToFirstCI[NARROW[section]];
lci ← StatementToLastCI[NARROW[section]];
IF fci = lci THEN lci ← fci-1;
ans ← NEW[SourceObj
← [fileName: ConvertUnsafe.ToRope[ns],
class: statement,
versionStamp: STBSourceVersion[stb],
sourceRange:
field[firstCharIndex: fci,
lastCharIndex: lci]]];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}
ELSE -- remote world
{bcd: BcdDefs.BcdBase ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.prog.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
ns: LONG STRING
= WITH stb SELECT FROM
t: SymbolTableBase.x =>
@LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO bx.FineGrainTableHeader].sourceFile,
t: SymbolTableBase.y =>
@LOOPHOLE
[t.e.stHandle
+ t.e.stHandle.fgRelPgBase*wordsPerPage,
LONG POINTER TO by.FineGrainTableHeader].sourceFile,
ENDCASE => ERROR;
fci, lci: INT;
fci ← StatementToFirstCI[NARROW[section]];
lci ← StatementToLastCI[NARROW[section]];
IF fci = lci THEN lci ← fci-1;
ans ← NEW[SourceObj
← [fileName: ConvertUnsafe.ToRope[ns],
class: statement,
versionStamp: STBSourceVersion[stb],
sourceRange:
field[firstCharIndex: fci,
lastCharIndex: lci]]];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
};
ENDCASE => ERROR
}; -- end SectionSource

-- param to creator of section.
-- (DIRECTORY entries)
-- Implemented only for model, prog and interface sections
SectionParams: PUBLIC PROC[section: Section] RETURNS[list: LIST OF SafeStorage.Type ← NIL] =
--ditto (DIRECTORY entries)
{WITH s: section SELECT FROM
model => ERROR; --NOTE enumerate the directory entries;
prog => ERROR; --NOTE enumerate the directory entries;
interface => ERROR; --NOTE enumerate the directory entries;
proc => ERROR AMTypes.Error[reason: notImplemented];
statement => ERROR AMTypes.Error[reason: notImplemented];
ENDCASE => ERROR
};

-- containers:
-- prog module for a proc
-- proc for a statement
ParentSection: PUBLIC PROC[section: Section] RETURNS[Section] =
{WITH s: section SELECT FROM
proc => RETURN[s.prog];
statement => RETURN[NEW[SectionObj ← [proc[prog: s.prog,
entryPointIndex:
StatementToParentEPI
[NARROW[section]]
]
]]];
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
}; -- end ParentSections

-- parts: modules of a model, procs of a module, statements of a proc
SectionChildren: PUBLIC PROC[section: Section, proc: PROC[Section] RETURNS[stop: BOOL]]
RETURNS[ans: Section ← NIL--NIL if not stopped--] =
{x: INT ← 0;
NextSection: PROC[parent, child: Section] RETURNS[s: Section ← NIL] =
{[s, x] ← NextSiblingSection[parent: parent, child: child, indexInParent: x]};

FOR s: Section ← FirstChildSection[section], NextSection[section, s]
UNTIL s = NIL DO IF proc[s] THEN RETURN[s]; ENDLOOP;
};

-- parts: modules of a model, procs of a module, statements of a proc
FirstChildSection: PROC[section: Section] RETURNS[ans: Section] =
{WITH s: section SELECT FROM
model => IF s.configContext # NIL
THEN
{IF s.configContext.world = LocalWorld[]
THEN -- section has a local configContext
{bcd: BcdDefs.BcdBase;
ftb: Table.Base;
mth: BcdDefs.MTHandle;
p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOL] = {RETURN[TRUE]};

LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[s.configContext.configIndex].bcd;
IF bcd = NIL
THEN {LoadState.local.Release[];
ERROR AMTypes.Error[reason: noSymbols]};
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
mth ← BcdOps.ProcessModules[bcd, p].mth;
ans ← NEW
[SectionObj
← [prog[moduleName: BcdNameToRope[bcd, mth.name],
versionStamp: ftb[mth.file].version,
someGFHTV:
NARROW
[TVForGFHReferent
[LoadState.local.ModuleToGlobalFrame
[s.configContext.configIndex, mth.gfi]
]
]
]
]
];
LoadState.local.Release[];
RETURN;
}
ELSE -- section has a remote configContext
{world: World = s.configContext.world;
cx: LoadState.ConfigID = s.configContext.configIndex;
moduleName: ROPE;
v: BcdDefs.VersionStamp;
mx: BcdDefs.ModuleIndex;

Lock[world];
{ ENABLE UNWIND => Unlock[world];
incarnation: Incarnation ← CurrentIncarnation[world];
rgfh: GlobalFrameHandle;
newState: LoadState.Handle = WorldVM.Loadstate[world];
newState.Acquire[];
{ ENABLE UNWIND => newState.Release[];
bcd: BcdDefs.BcdBase
= AcquireRemoteBCD[
world: world,
incarnation: CurrentIncarnation[world],
bcd: newState.ConfigInfo[cx].bcd];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOL] = {RETURN[TRUE]};
mth: BcdDefs.MTHandle = BcdOps.ProcessModules[bcd, p].mth;
v ← ftb[mth.file].version;
moduleName ← BcdNameToRope[bcd, mth.name];
mx ← mth.gfi;
}; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd]
ReleaseRemoteBCD[bcd];
rgfh ← newState.ModuleToGlobalFrame[cx, mx];
}; -- end ENABLE UNWIND => newState.Release[]
newState.Release[];
ans ← NEW[SectionObj
← [prog[moduleName: moduleName,
versionStamp: v,
someGFHTV:
NARROW
[TVForRemoteGFHReferent
[ [world: world,
worldIncarnation: incarnation,
gfh: LOOPHOLE[rgfh]
]
]]

]
]
];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[world];
RETURN;
}
}
ELSE -- here if model section is not loaded
{ -- get the binder output bcd, given the config name and
-- its version stamp
bcd: BcdDefs.BcdBase
= RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: s.versionStamp,
shortFileNameHint: Rope.Concat[s.configName,
".bcd"]];
ftb: Table.Base;
mth: BcdDefs.MTHandle;
p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOLEAN] = {RETURN[TRUE]};

IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];

mth ← BcdOps.ProcessModules[bcd, p].mth;
ans ← NEW[SectionObj ← [prog[moduleName: BcdNameToRope
[bcd, mth.name],
versionStamp: ftb[mth.file].version,
someGFHTV: NIL
]
]
];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
prog => RETURN[NEW[SectionObj ← [proc[prog: NARROW[section, REF prog SectionObj],
entryPointIndex: 0]]]]; --ep# wizardry: StartProc.
interface => RETURN[NIL];

proc => RETURN[NEW[SectionObj ← [statement[prog: s.prog,
fgtIndex: ProcToFirstFGI
[NARROW[section]]]]]];

statement => RETURN[NIL];
ENDCASE => ERROR
}; -- end FirstChildSection

-- parts: modules of a model, procs of a module, statements of a proc
-- NextSiblingSection will never get a child that represents a loadstate entry
-- for children that are progs, indexInParent # 0 means use it to pass over previous modules
-- returns NIL if nomore
NextSiblingSection: PROC[parent, child: Section, indexInParent: INT ← 0]
RETURNS[ans: Section ← NIL, newIndexInParent: INT ← 0] =
{IF parent = NIL THEN RETURN[NIL];
WITH s: child SELECT FROM
model => ERROR AMTypes.Error[reason: notImplemented];
prog =>
{ lastWasOldChild: BOOLFALSE;
ftb: Table.Base ← NIL;

FindNextModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [stop: BOOLFALSE] = {
newIndexInParent ← newIndexInParent + 1;
IF lastWasOldChild THEN RETURN[TRUE];
IF (indexInParent = 0 OR newIndexInParent >= indexInParent)
AND s.versionStamp = ftb[mth.file].version
THEN lastWasOldChild ← TRUE;
};

IF s.someGFHTV # NIL
THEN -- the sections are loaded
{ world: World = GetWorld[s.someGFHTV];
IF world = LocalWorld[]
THEN {gfh: GlobalFrameHandle ← NIL;
bcd: BcdDefs.BcdBase;
mth: BcdDefs.MTHandle;
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
config: LoadState.ConfigID
= LoadState.local.GlobalFrameToModule
[GFHFromTV[s.someGFHTV]].config;
bcd ← LoadState.local.ConfigInfo[config].bcd;
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
mth ← BcdOps.ProcessModules[bcd, FindNextModule].mth;
IF mth # NIL
THEN gfh ← LoadState.local.ModuleToGlobalFrame[config, mth.gfi];
}; -- ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
IF gfh # NIL
THEN
ans ← NEW
[SectionObj
← [prog[moduleName: BcdNameToRope[bcd, mth.name],
versionStamp: ftb[mth.file].version,
someGFHTV: NARROW[TVForGFHReferent[gfh]]
]
]
];
}
ELSE -- NextSiblingSection, prog child, the sections are loaded, remote world
{ Lock[world];
{ ENABLE UNWIND => Unlock[world];
v: BcdDefs.VersionStamp;
moduleName: ROPE;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
config: LoadState.ConfigID = h.GlobalFrameToModule
[LOOPHOLE[RemoteGFHFromTV[s.someGFHTV].gfh]].config;
bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[s.someGFHTV]];
IF bcd = NIL THEN ERROR;
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
mth: BcdDefs.MTHandle
= BcdOps.ProcessModules[bcd, FindNextModule].mth;
IF mth # NIL
THEN {gfh: GlobalFrameHandle
= h.ModuleToGlobalFrame[config, mth.gfi];
v ← ftb[mth.file].version;
moduleName ← BcdNameToRope[bcd, mth.name];
rgfh ← [world, CurrentIncarnation[world], LOOPHOLE[gfh]]};
}; -- ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ReleaseRemoteBCD[bcd];
}; -- ENABLE UNWIND => h.Release[];
h.Release[];
IF rgfh # nilRemoteGlobalFrameHandle
THEN
ans ← NEW
[SectionObj
← [prog[moduleName: moduleName,
versionStamp: v,
someGFHTV:
NARROW[TVForRemoteGFHReferent[rgfh]]
]
]
];
}; -- ENABLE UNWIND => Unlock[world];
}; -- end ELSE
} -- end case where the sections are loaded
ELSE -- NextSiblingSection, prog child, not loaded
{ -- get the binder output bcd, given the config name and version stamp
p: REF model SectionObj = NARROW[parent];
mth: BcdDefs.MTHandle;
bcd: BcdDefs.BcdBase ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: p.versionStamp,
shortFileNameHint: Rope.Concat[p.configName,
".bcd"]];
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
{ ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
mth ← BcdOps.ProcessModules[bcd, FindNextModule].mth;
IF mth # NIL
THEN ans ← NEW[SectionObj
← [prog[moduleName: BcdNameToRope[bcd, mth.name],
versionStamp: ftb[mth.file].version,
someGFHTV: NIL -- not loaded
]
]
];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
RTSymbolsPrivate.ReleaseBCD[bcd];
}}; -- end prog child case of NextSiblingSection
interface => ERROR AMTypes.Error[reason: notImplemented];
proc => {sth: SymbolTableHandle
= GetSTHForModule
[stamp: s.prog.versionStamp,
fileName: Rope.Concat[s.prog.moduleName, ".bcd"],
moduleName: s.prog.moduleName];
stb: SymbolTableBase ← AcquireSTB[sth];
maxEI: EPI ← 0;
GetMaxX: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
WITH NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM
Callable => IF ~inline THEN maxEI ← MAX[maxEI, entryIndex];
ENDCASE};
GetMaxY: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
WITH NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM
Callable => IF ~inline THEN maxEI ← MAX[maxEI, entryIndex];
ENDCASE};
WITH stb SELECT FROM
t: SymbolTableBase.x => [] ← t.e.EnumerateBodies[bx.rootBodyIndex, GetMaxX];
t: SymbolTableBase.y => [] ← t.e.EnumerateBodies[by.rootBodyIndex, GetMaxY];
ENDCASE => ERROR;
IF s.entryPointIndex = maxEI
THEN ans ← NIL
ELSE ans ← NEW[SectionObj ←
[proc[prog: NARROW[parent, REF prog SectionObj],
entryPointIndex: s.entryPointIndex + 1]]];
ReleaseSTB[stb]}; -- end proc child case of NextSiblingSection
statement => {nextFGI: FGIndex = NextStatementFGI[NARROW
[child,
REF statement SectionObj]];
IF nextFGI = FGNull
THEN RETURN[NIL]
ELSE RETURN[NEW[SectionObj ←
[statement[prog: NARROW[parent,
REF proc SectionObj].prog,
fgtIndex: nextFGI
]]]];
}; -- end statement child case of NextSiblingSection
ENDCASE => ERROR
}; -- end NextSiblingSection


-- Implemented only for proc sections
SectionType: PUBLIC PROC[section: Section] RETURNS[--procedure--type: SafeStorage.Type] =
{WITH s: section SELECT FROM
model => ERROR AMTypes.Error[reason: notImplemented];
prog => ERROR AMTypes.Error[reason: notImplemented];
interface => RETURN[AcquireIRType[defsName: s.moduleName, version: s.versionStamp]];
proc => IF s.procTV = NIL
THEN {sth: SymbolTableHandle
= GetSTHForModule
[stamp: s.prog.versionStamp,
fileName: Rope.Concat[s.prog.moduleName, ".bcd"],
moduleName: s.prog.moduleName];
stb: SymbolTableBase ← AcquireSTB[sth];
FindProcX: PROC[bti: bx.BodyIndex] RETURNS[stop: BOOLEANFALSE] =
{WITH b: NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM
Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex
THEN {type ← AcquireType[stb, [x[b.ioType]]];
RETURN[TRUE]};
ENDCASE};
FindProcY: PROC[bti: by.BodyIndex] RETURNS[stop: BOOLEANFALSE] =
{WITH b: NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM
Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex
THEN {type ← AcquireType[stb, [y[b.ioType]]];
RETURN[TRUE]};
ENDCASE};

WITH stb SELECT FROM
t: SymbolTableBase.x =>
IF t.e.EnumerateBodies[bx.rootBodyIndex, FindProcX
! UNWIND => ReleaseSTB[stb]] = bx.nullBodyIndex
THEN {ReleaseSTB[stb]; ERROR};
t: SymbolTableBase.y =>
IF t.e.EnumerateBodies[by.rootBodyIndex, FindProcY
! UNWIND => ReleaseSTB[stb]] = by.nullBodyIndex
THEN {ReleaseSTB[stb]; ERROR};
ENDCASE => ERROR;

ReleaseSTB[stb];
RETURN[type]} -- figure it out from the ep# and the prog section
ELSE RETURN[TVType[s.procTV]];
statement => ERROR AMTypes.Error[reason: notImplemented];
ENDCASE => ERROR
};


SectionVersion: PUBLIC PROC[section: Section] RETURNS[BcdDefs.VersionStamp] =
{WITH s: section SELECT FROM
model => RETURN[s.versionStamp];
prog => RETURN[s.versionStamp];
interface => RETURN[s.versionStamp];
proc => RETURN[s.prog.versionStamp];
statement => RETURN[s.prog.versionStamp];
ENDCASE => ERROR;
};

-- Private Procedures

BcdNameToRope: PROC[bcd: BcdDefs.BcdBase, n: BcdDefs.NameRecord] RETURNS[ROPE] =
{ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
ssd: ConvertUnsafe.SubString ← [base: @ssb.string, offset: n, length: ssb.size[n]];
RETURN[ConvertUnsafe.SubStringToRope[ssd]]};

-- [prog module bcd, entryPointIndex] => CharIndex
ProcToFirstCI: PROC[proc: REF proc SectionObj] RETURNS[ans: CharIndex ← 0] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = proc.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- proc not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: proc.prog.versionStamp,
shortFileNameHint:
Rope.Concat[proc.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, proc.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← FGIToFirstChar[stb, EPIToFirstFGI[stb, proc.entryPointIndex, TRUE]];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, entryPointIndex] => CharIndex
ProcToLastCI: PROC[proc: REF proc SectionObj] RETURNS[ans: CharIndex ← 0] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = proc.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- proc not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: proc.prog.versionStamp,
shortFileNameHint:
Rope.Concat[proc.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, proc.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← FGIToLastChar[stb, EPIToLastFGI[stb, proc.entryPointIndex]];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, FGIndex] => CharIndex
StatementToFirstCI: PROC[statement: REF statement SectionObj] RETURNS[ans: CharIndex ← 0] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = statement.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- statement not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: statement.prog.versionStamp,
shortFileNameHint:
Rope.Concat[statement.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, statement.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← FGIToFirstChar[stb, statement.fgtIndex];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, FGIndex] => CharIndex
StatementToLastCI: PROC[statement: REF statement SectionObj] RETURNS[ans: CharIndex ← 0] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = statement.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- statement not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: statement.prog.versionStamp,
shortFileNameHint:
Rope.Concat[statement.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, statement.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← FGIToLastChar[stb, statement.fgtIndex];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, FGIndex] => entryPointIndex (maybe 0)
StatementToParentEPI: PROC[statement: REF statement SectionObj] RETURNS[ans: EPI ← 0] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = statement.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- statement not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: statement.prog.versionStamp,
shortFileNameHint:
Rope.Concat[statement.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, statement.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← FGIToEPI[stb, statement.fgtIndex];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, entryPointIndex] => FGIndex
ProcToFirstFGI: PROC[proc: REF proc SectionObj] RETURNS[ans: FGIndex ← FGNull] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = proc.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- proc not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: proc.prog.versionStamp,
shortFileNameHint:
Rope.Concat[proc.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, proc.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← EPIToFirstFGI[stb, proc.entryPointIndex, TRUE];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

-- [prog module bcd, FGIndex, entryPointIndex] => FGIndex
-- (or FGNull if in a different proc than entryPointIndex)
NextStatementFGI: PROC[statement: REF statement SectionObj]
RETURNS[ans: FGIndex ← FGNull] =
{localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
bcd: BcdDefs.BcdBase;
ptv: TV = statement.prog.someGFHTV;
stb: SymbolTableBase;
IF ptv = NIL -- statement not loaded
THEN {bcd ← RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: statement.prog.versionStamp,
shortFileNameHint:
Rope.Concat[statement.prog.moduleName,
".bcd"]];
versionBCD ← TRUE}
ELSE IF GetWorld[ptv] = LocalWorld[]
THEN {bcd ← GetLocalBCD[GFHFromTV[ptv]];
localBCD ← TRUE}
ELSE { bcd ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remoteBCD ← TRUE};
{ ENABLE UNWIND => IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
stb ← GetModuleSTB[bcd, statement.prog.versionStamp];
}; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd];
{ ENABLE UNWIND => ReleaseSTB[stb];
IF versionBCD
THEN RTSymbolsPrivate.ReleaseBCD[bcd]
ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd];
ans ← NextFGI[stb, statement.fgtIndex, StatementToParentEPI[statement]];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};

}.