DIRECTORY
AMBridge USING [TVForGFHReferent, GFHFromTV, TVToProc, FHFromTV, ContextPC, GetWorld, RemoteGlobalFrameHandle, IsRemote, RemoteGFHFromTV, RemoteFHFromTV, TVToRemoteProc, GetWorldIncarnation, nilRemoteGlobalFrameHandle, TVForRemoteGFHReferent, RemotePD],
AMMiniModel USING [GetInterfaceRecordFromType, GetInterfaceRecordNames, GetInterfaceRecord],
AMModel USING [Class, Context, PartialInterfaceInstance],
AMModelPrivate USING [FGIndex, FGNull, EPI, PCToFGI, SectionRec, RefTVRec, ConfigContext, ConfigContextObj, StatementContext, StatementContextObj, GetLocalBCD, GetRemoteBCD],
AMTypes USING [GlobalParent, Procedure, TVType, Error, TVToName, TypeToName, TV],
BcdDefs USING [NullVersion, VersionStamp, MTIndex, FTSelf, NameRecord, IMPIndex, EXPIndex, CTIndex, CTNull, BcdBase, MTHandle, NameString, IMPHandle, EXPHandle, CTHandle],
BcdOps USING [ProcessModules, ProcessImports, ProcessExports, ProcessConfigs],
ConvertUnsafe USING [SubString, SubStringToRope],
IO USING [PutFR],
LoadState USING [Acquire, local, ConfigInfo, Release, Handle, nullConfig, GetChangeCount, GlobalFrameToModule, ConfigID, ModuleIndex, EnumerateAllModules, ModuleToGlobalFrame, EnumerateModulesInConfig, EnumerateConfigs, nullModule, CopiesList, ModuleInfo],
PrincOps USING [GlobalFrameHandle, BytePC],
PrincOpsUtils USING [GlobalFrameAndEntryPoint],
RemotePrincOpsUtils USING [RemoteGlobalFrameAndEntryPoint],
Rope USING [ROPE, Concat, Substr, SkipTo, Index, Length, Match, Cat],
RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle, SymbolIndex, SymbolIdIndex, SymbolConstructorIndex],
RTSymbolOps USING [EnumerateCtxIseis, STBToModuleName, AcquireType, SEUnderType, STBDirectoryCtx, ISEPublic, ISEType],
RTSymbols USING [GetTypeSymbols, AcquireSTB, ReleaseSTB, AcquireSTBFromSGI, AcquireSTBFromGFH, GetSTHForModule],
RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD],
RTTypesPrivate USING [GetEp],
RTTypesRemotePrivate USING [AcquireRemoteBCD, GetRemoteEp, AcquireSTBFromRemoteGFH, ReleaseRemoteBCD],
SafeStorage USING [Type, fhType, gfhType],
Table USING [Base],
WorldVM USING [LocalWorld, World, WorldName, CurrentIncarnation, Lock, Unlock, Loadstate, Incarnation, Read, Address];
AMModelContextImpl:
MONITOR
-- protects WorldGFNameLists
IMPORTS AMBridge, AMModelPrivate, AMTypes, BcdOps, IO, ConvertUnsafe, LoadState, PrincOpsUtils, RemotePrincOpsUtils, Rope, AMMiniModel, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesPrivate, RTTypesRemotePrivate, WorldVM
EXPORTS AMModel, AMModelPrivate
= { OPEN AMBridge, AMMiniModel, AMModel, AMModelPrivate, AMTypes, PrincOps, RemotePrincOpsUtils, Rope, RTSymbolDefs, RTSymbolOps, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate, SafeStorage, 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;
WorldGFNameList: TYPE = LIST OF WorldGFNames;
WorldGFNames: TYPE = REF WorldGFNameListRec;
WorldGFNameListRec:
TYPE =
RECORD[
world: World,
incarnation: Incarnation,
loadStateChangeCount: INT,
gfList: LIST OF GFContextRec];
GFContextRec: TYPE = RECORD[name: ROPE, context: Context];
worldGFNameList: WorldGFNameList ← NIL;
PROCs dealing with Contexts (loadstate entries, global or local frames, statements, IR instances)
RootContext:
PUBLIC
PROC [world: World]
RETURNS [Context] = {
a "rootContext" represents a Loadstate. Immediate children are the Contexts of loadstate configs for individually loaded program modules and bound configs.
IF world = NIL THEN world ← WorldVM.LocalWorld[];
RETURN[
NEW[ConfigContextObj
← [world: world,
worldIncarnation: CurrentIncarnation[world],
configIndex: LoadState.nullConfig]]];
};
ContextClass:
PUBLIC
PROC [context: Context]
RETURNS [Class] = {
WITH context
SELECT
FROM
sc: StatementContext => RETURN[statement];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN RETURN[world]
ELSE RETURN[model];
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType => RETURN[prog];
fhType => RETURN[proc];
ENDCASE => RETURN[interface];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
ContextWorld:
PUBLIC
PROC [context: Context]
RETURNS [World] = {
WITH context
SELECT
FROM
sc: StatementContext => RETURN[GetWorld[sc.localFrameTV]];
cc: ConfigContext => RETURN[cc.world];
ENDCASE => RETURN[GetWorld[context]];
};
ContextName:
PUBLIC
PROC [context: Context]
RETURNS [ans:
ROPE ←
NIL] = {
SectionName with instance info
IF context = NIL THEN RETURN[NIL];
WITH context
SELECT
FROM
sc: StatementContext => {
ans ←
IO.PutFR["%g:FGT#%g",
[rope[ContextName[sc.localFrameTV]]],
[cardinal[NARROW[ContextSection[context], REF statement SectionObj].fgtIndex.fgCard]]];
};
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType => {
gfhBits:
CARDINAL =
IF GetWorld[tv] # LocalWorld[]
THEN LOOPHOLE[RemoteGFHFromTV[tv].gfh, CARDINAL]
ELSE LOOPHOLE[GFHFromTV[tv], CARDINAL];
ans ← TVToName[tv ! AMTypes.Error => CONTINUE];
ans ← IO.PutFR["%g:gfh#%b", [rope[ans]], [cardinal[gfhBits]]];
};
fhType => {
fhBits:
CARDINAL =
IF GetWorld[tv] # LocalWorld[]
THEN LOOPHOLE[RemoteFHFromTV[tv].fh, CARDINAL]
ELSE LOOPHOLE[FHFromTV[tv], CARDINAL];
ans ← TVToName[Procedure[tv ! AMTypes.Error =>
CONTINUE]
! AMTypes.Error => CONTINUE];
ans ← IO.PutFR["%g:fh#%b", [rope[ans]], [cardinal[fhBits]]];
};
ENDCASE => {
ans ← Cat["Interface:", TypeToName[TVType[tv]]];
}; -- assume an IR
IF GetWorld[tv] # LocalWorld[]
THEN
ans ← Cat[ans, ",world:", WorldName[GetWorld[tv]]];
};
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN ans ← Rope.Cat["World:", WorldName[mc.world]]
ELSE {
FindRootConfig:
PROC [cth: BcdDefs.CTHandle, cti: BcdDefs.CTIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
IF cth.config = BcdDefs.CTNull THEN RETURN[TRUE];
};
IF mc.world = LocalWorld[]
THEN {
bcd: BcdDefs.BcdBase;
ctHandle: BcdDefs.CTHandle;
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex
! UNWIND => LoadState.local.Release[]].bcd;
LoadState.local.Release[];
IF bcd = NIL THEN ERROR;
[ctHandle,] ← BcdOps.ProcessConfigs[bcd, FindRootConfig];
ans ←
IO.PutFR[
"%g:ConfigIndex#%g",
[rope[BcdNameToRope[bcd, ctHandle.name]]],
[cardinal[LOOPHOLE[mc.configIndex, CARDINAL]]]
];
}
ELSE {
bcd: BcdDefs.BcdBase;
ctHandle: BcdDefs.CTHandle;
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
bcd ← AcquireRemoteBCD
[mc.world, mc.worldIncarnation, h.ConfigInfo[mc.configIndex].bcd];
};
h.Release[];
};
Unlock[mc.world];
IF bcd = NIL THEN ERROR;
{
ENABLE
UNWIND => ReleaseRemoteBCD[bcd];
[ctHandle,] ← BcdOps.ProcessConfigs[bcd, FindRootConfig];
ans ←
IO.PutFR["%g:ConfigIndex#%g,world:%g",
[rope[BcdNameToRope[bcd, ctHandle.name]]],
[cardinal[LOOPHOLE[mc.configIndex, CARDINAL]]],
[rope[WorldName[mc.world]]] ];
};
ReleaseRemoteBCD[bcd];
};
}; -- end ELSE arm (mc.configIndex # LoadState.nullConfig)
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
MostRecentNamedContext:
PUBLIC
PROC [name:
ROPE, context:
--world or model-- Context]
RETURNS [ans: Context ←
NIL] = {
EXAMPLE USAGE: given a module name and a world context, this returns a Context for the most recently loaded global frame for a program with that name. name must identify a model or prog (someday interface) if context identifies a world, or a prog (someday interface) if context identifies a model. The format of the name should be the same as that produced by ContextName, with elided fields meaning "don't care". The result will be either a model or prog (someday interface) context.
WITH context
SELECT
FROM
mc: ConfigContext => {
IF mc.configIndex = LoadState.nullConfig -- the model of a world
THEN {
p: PROC [name: ROPE, gf: TV] RETURNS [stop: BOOL ← TRUE] = {NULL};
ans ← FindMatchingGlobalFrames[ContextWorld[context], name, p];
IF ans # NIL THEN RETURN;
};
here to look for a named config or a module of a config
{
p:
PROC [c: Context]
RETURNS [stop:
BOOL ←
FALSE] = {
n: ROPE = ContextName[c];
len: INT ← Rope.Index[s1: n, s2: ":"];
nPart: ROPE ← IF len = Rope.Length[n] THEN n ELSE Rope.Substr[base: n, len: len];
IF name.Match[nPart, FALSE] THEN {ans ← c; stop ← TRUE};
};
[] ← ContextChildren[context, p];
};
};
ENDCASE =>
ERROR AMTypes.Error
[reason: notImplemented,
msg: "MostRecentNamedContext for other than a world or model Context"];
};
LoadStateChangeCount:
INTERNAL
PROC [world: World]
RETURNS [ans:
INT] = {
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
ans ← LoadState.GetChangeCount[h];
h.Release[];
};
FindWorldGFNames:
INTERNAL
PROC [world: World]
RETURNS [WorldGFNames] = {
FOR wgfnl: WorldGFNameList ← worldGFNameList,
wgfnl.rest
UNTIL wgfnl =
NIL
DO
IF world = wgfnl.first.world
THEN {
IF (CurrentIncarnation[world] # wgfnl.first.incarnation)
OR (LoadStateChangeCount[world] # wgfnl.first.loadStateChangeCount)
THEN {
wgfnl.first.gfList ← NIL;
wgfnl.first.incarnation ← CurrentIncarnation[world];
wgfnl.first.loadStateChangeCount ← LoadStateChangeCount[world];
};
RETURN[wgfnl.first];
};
ENDLOOP;
worldGFNameList ←
CONS[
NEW[WorldGFNameListRec
← [world: world,
incarnation: CurrentIncarnation[world],
loadStateChangeCount: LoadStateChangeCount[world],
gfList: NIL]],
worldGFNameList];
RETURN[worldGFNameList.first];
};
FindMatchingGlobalFrames:
PUBLIC ENTRY
PROC [ world: World, name:
ROPE, proc:
PROC [
ROPE, Context]
RETURNS [
--stop:--
BOOL] ]
RETURNS [ans: Context ←
NIL] = {
ENABLE UNWIND => NULL;
gfNames: WorldGFNames;
WorldVM.Lock[world];
{
ENABLE
UNWIND => WorldVM.Unlock[world];
gfNames ← FindWorldGFNames[world];
IF gfNames.gfList =
NIL
THEN {
h: LoadState.Handle = WorldVM.Loadstate[world];
p:
PROC [ci: LoadState.ConfigID, mx: LoadState.ModuleIndex]
RETURNS [stop: BOOL ← FALSE] = {
rgfh: RemoteGlobalFrameHandle
= [world: world,
worldIncarnation: CurrentIncarnation[world],
gfh: LOOPHOLE[h.ModuleToGlobalFrame[ci, mx]]];
gfNames.gfList
← CONS[[name: NIL, context: TVForRemoteGFHReferent[rgfh]], gfNames.gfList];
};
h.Acquire[];
[] ← h.EnumerateAllModules[oldestFirst, p ! UNWIND => h.Release[]];
h.Release[];
};
}; -- ENABLE UNWIND => WorldVM.Unlock[world];
WorldVM.Unlock[world];
FOR gfList:
LIST
OF GFContextRec ← gfNames.gfList, gfList.rest
UNTIL gfList =
NIL DO
RRA: In all cases where we do not already have the name we should fill in the name. If we get an AMTypes.Error when trying to execute the caller's proc we just go on to the next frame.
IF gfList.first.name =
NIL THEN
gfList.first.name ← AMTypes.TVToName[gfList.first.context];
IF name.Match[gfList.first.name,
FALSE]
AND proc[gfList.first.name, gfList.first.context
! AMTypes.Error => LOOP]
THEN RETURN[gfList.first.context];
ENDLOOP;
};
NamedContexts:
PUBLIC
PROC [name:
ROPE, context: Context, proc:
PROC [Context]
RETURNS [stop:
BOOL]]
RETURNS [ans: Context ←
NIL] = {
an enumerator. Like MostRecentNamedContext, but gets 'em all.
lookForNamedContext:
PROC [c: Context]
RETURNS [stop:
BOOL ←
FALSE] = {
n: ROPE = ContextName[c];
len: INT ← Rope.Index[s1: n, s2: ":"];
nPart: ROPE ← IF len = Rope.Length[n] THEN n ELSE Rope.Substr[base: n, len: len];
IF name.Match[nPart,
FALSE]
--Rope.Equal[name, nPart]
THEN {stop ← proc[c]; IF stop THEN ans ← c}
ELSE
SELECT ContextClass[c]
FROM
model => {ans ← NamedContexts[name, c, proc]; IF ans # NIL THEN stop ← TRUE};
ENDCASE;
};
start HERE
[] ← ContextChildren[context, lookForNamedContext];
};
ContextSection:
PUBLIC
PROC [context: Context]
RETURNS [ans: Section ←
NIL] = {
param to creator of context
WITH context
SELECT
FROM
sc: StatementContext => {
parentContext: Context ← ParentContext[context];
UNTIL ContextClass[parentContext] = prog
DO parentContext ← ParentContext[parentContext]; ENDLOOP;
RETURN[
NEW[SectionObj
← [statement[prog:
NARROW[ContextSection[parentContext],
REF prog SectionObj],
fgtIndex: StatementContextToFGI[sc]]]]];
};
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType =>
-- program module
RETURN[
NEW[SectionObj
← [prog
[moduleName: TVToName[tv],
versionStamp:
IF IsRemote[tv]
THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
someGFHTV: tv]]]];
fhType => {
procTV: RefTVRec = NARROW[Procedure[tv]]; -- procedure
ep: CARDINAL;
IF IsRemote[procTV]
THEN {
rpd: AMBridge.RemotePD = AMBridge.TVToRemoteProc[procTV];
ep ← RemoteGlobalFrameAndEntryPoint[rpd.world, rpd.pd].ep;
}
ELSE ep ← PrincOpsUtils.GlobalFrameAndEntryPoint[ LOOPHOLE[TVToProc[procTV]]].ep;
RETURN[
NEW[SectionObj
← [proc[prog:
NARROW[ContextSection[GlobalParent[tv]]],
entryPointIndex: ep,
procTV: procTV]]]];
};
ENDCASE => {
-- better be a TV for an interface record
type: Type = TVType[tv];
stb: SymbolTableBase;
sei: SymbolIndex;
mn: ROPE;
vs: BcdDefs.VersionStamp;
[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
definition => vs ← t.e.stHandle.version;
ENDCASE => ERROR;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[
NARROW[csei, SymbolConstructorIndex.y].e]
SELECT
FROM
definition => vs ← t.e.stHandle.version;
ENDCASE => ERROR;
ENDCASE => ERROR;
mn ← STBToModuleName[stb];
};
ReleaseSTB[stb];
RETURN[NEW[SectionObj ← [interface[moduleName: mn, versionStamp: vs]]]];
};
};
mc: ConfigContext =>
IF mc.world = LocalWorld[]
THEN {
bcd: BcdDefs.BcdBase;
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex
! UNWIND => LoadState.local.Release[]].bcd;
LoadState.local.Release[];
IF bcd = NIL THEN ERROR;
ans ←
NEW[SectionObj ←
[model[configName: StripExtension[BcdNameToRope[bcd, bcd.source]],
versionStamp: bcd.version,
configContext: mc]]];
}
ELSE {
bcd: BcdDefs.BcdBase;
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
bcd ← AcquireRemoteBCD
[mc.world, mc.worldIncarnation, h.ConfigInfo[mc.configIndex].bcd];
};
h.Release[];
};
Unlock[mc.world];
IF bcd = NIL THEN ERROR;
{
ENABLE
UNWIND => ReleaseRemoteBCD[bcd];
ans ← NEW[SectionObj ← [model[configName: StripExtension[BcdNameToRope[bcd, bcd.source]], versionStamp: bcd.version, configContext: mc]]];
};
ReleaseRemoteBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
ParentContext:
PUBLIC
PROC [context: Context]
RETURNS [Context] = {
world => NIL
model => world
prog => model
proc => prog
statement => proc
WITH context
SELECT
FROM
sc: StatementContext => RETURN[sc.localFrameTV];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN RETURN[NIL]
ELSE
-- the loadstate has only one level of structure
RETURN[
NEW[ConfigContextObj ←
[world: mc.world, worldIncarnation: mc.worldIncarnation, configIndex: LoadState.nullConfig]]];
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType => {
world: World ← GetWorld[tv];
ci: LoadState.ConfigID;
IF
NOT IsRemote[tv]
THEN {
gfh: PrincOps.GlobalFrameHandle = GFHFromTV[tv];
LoadState.local.Acquire[];
ci ← LoadState.local.GlobalFrameToModule[gfh].config;
LoadState.local.Release[];
}
ELSE {
-- remote case
rgfh: RemoteGlobalFrameHandle = RemoteGFHFromTV[tv];
Lock[world];
{
ENABLE
UNWIND => Unlock[world];
h: LoadState.Handle ← WorldVM.Loadstate[world];
h.Acquire[];
ci ← h.GlobalFrameToModule[
LOOPHOLE[rgfh.gfh]
! UNWIND => h.Release[]].config;
h.Release[];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[world];
};
RETURN[
NEW[ConfigContextObj ← [
world: world,
worldIncarnation: GetWorldIncarnation[tv],
configIndex: ci]]];
};
fhType => RETURN[GlobalParent[tv]];
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
ContextChildren:
PUBLIC
PROC [context: Context, proc:
PROC [Context]
RETURNS [stop:
BOOL]]
RETURNS [ans: Context ←
NIL
--NIL if not stopped--] = {
world -> model or prog (TV for a global frame)
model -> prog
proc -> statement
FOR c: Context ← FirstChildContext[context], NextSiblingContext[c]
UNTIL c = NIL DO IF proc[c] THEN RETURN[c]; ENDLOOP;
};
FirstChildContext:
PROC [context: Context]
RETURNS [ans: Context] = {
WITH context
SELECT
FROM
sc: StatementContext => RETURN[NIL]; -- do statements have substructure?
tv: RefTVRec =>
SELECT TVType[tv]
FROM
fhType => RETURN[NEW[StatementContextObj ← [localFrameTV: tv]]];
gfhType => RETURN[NIL];
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN {
IF mc.world = LocalWorld[]
THEN {
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
composite: BOOL;
LoadState.local.Acquire[];
{
ENABLE
UNWIND => LoadState.local.Release[];
mx: LoadState.ModuleIndex;
p: PROC [LoadState.ConfigID, LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
[config, mx] ← LoadState.local.EnumerateAllModules[newestFirst, p];
composite ← IsComposite[LoadState.local.ConfigInfo[config].bcd];
gfh ← LoadState.local.ModuleToGlobalFrame[config, mx];
IF gfh = NIL THEN ERROR;
}; -- ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
IF composite
THEN
RETURN[
NEW[ConfigContextObj ←
[world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForGFHReferent[gfh]];
}
ELSE {
-- remote world
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
composite: BOOL;
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
mx: LoadState.ModuleIndex;
p: PROC [LoadState.ConfigID, LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
[config, mx] ← h.EnumerateAllModules[newestFirst, p];
composite ← IsRemoteBCDComposite[mc.world, h.ConfigInfo[config].bcd];
gfh ← h.ModuleToGlobalFrame[config, mx];
IF gfh = NIL THEN ERROR;
rgfh ← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
}; -- ENABLE UNWIND => h.Release[];
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
IF composite
THEN
RETURN[
NEW[ConfigContextObj ← [
world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForRemoteGFHReferent[rgfh]];
};
} -- end world config case
ELSE {
IF mc.world = LocalWorld[]
THEN {
gfh: GlobalFrameHandle;
p: PROC [LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
LoadState.local.Acquire[];
[gfh: gfh] ← LoadState.local.EnumerateModulesInConfig[mc.configIndex, p
! UNWIND => LoadState.local.Release[]];
LoadState.local.Release[];
RETURN[TVForGFHReferent[gfh]];
}
ELSE {
gfh: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
p: PROC [LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
h.Acquire[];
[gfh: gfh] ← h.EnumerateModulesInConfig[mc.configIndex, p
! UNWIND => h.Release[]];
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
rgfh ← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
RETURN[TVForRemoteGFHReferent[rgfh]];
};
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
NextSiblingContext:
PROC [context: Context]
RETURNS [ans: Context ←
NIL] = {
model -> model or prog (TV for a global frame)
prog -> model or prog
returns NIL if nomore
IF context = NIL THEN RETURN[NIL];
WITH context
SELECT
FROM
sc: StatementContext => RETURN[NIL]; -- substructure?
mc: ConfigContext => {
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
IF mc.world = LocalWorld[]
THEN {
nextIsIt: BOOL ← FALSE;
composite: BOOL;
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
LoadState.local.Acquire[];
{
ENABLE
UNWIND => LoadState.local.Release[];
p:
PROC [config: LoadState.ConfigID]
RETURNS [
BOOL] = {
IF nextIsIt THEN RETURN[TRUE];
IF config = mc.configIndex THEN nextIsIt ← TRUE;
RETURN[FALSE];
};
q: PROC [LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
config ← LoadState.local.EnumerateConfigs[newestFirst, p];
IF config = LoadState.nullConfig
THEN {LoadState.local.Release[]; RETURN[NIL]};
composite ← IsComposite[LoadState.local.ConfigInfo[config].bcd];
[gfh: gfh] ← LoadState.local.EnumerateModulesInConfig[config, q];
};
LoadState.local.Release[];
IF composite
THEN
RETURN[
NEW[ConfigContextObj ← [
world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForGFHReferent[gfh]];
}
ELSE {
nextIsIt: BOOL ← FALSE;
composite: BOOL;
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
p:
PROC [config: LoadState.ConfigID]
RETURNS [
BOOL] = {
IF nextIsIt THEN RETURN[TRUE];
IF config = mc.configIndex THEN nextIsIt ← TRUE;
RETURN[FALSE];
};
q: PROC [LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
config ← h.EnumerateConfigs[newestFirst, p];
IF config = LoadState.nullConfig
THEN {h.Release[]; WorldVM.Unlock[mc.world]; RETURN[NIL]};
composite ← IsRemoteBCDComposite[mc.world, h.ConfigInfo[config].bcd];
IF NOT composite THEN [gfh: gfh] ← h.EnumerateModulesInConfig[config, q];
};
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
IF composite
THEN
RETURN[
NEW[ConfigContextObj ← [
world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE {
rgfh: RemoteGlobalFrameHandle
← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
RETURN[TVForRemoteGFHReferent[rgfh]];
};
};
};
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType =>
IF IsRemote[tv]
THEN {
-- remote case
world: World = GetWorld[tv];
WorldVM.Lock[world];
{
ENABLE
UNWIND => WorldVM.Unlock[world];
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
gfh: GlobalFrameHandle = LOOPHOLE[RemoteGFHFromTV[tv].gfh];
config: LoadState.ConfigID ← h.GlobalFrameToModule[gfh].config;
IF IsRemoteBCDComposite[world, h.ConfigInfo[config].bcd]
THEN {
nextGFH: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
lastWasIt: BOOL ← FALSE;
q:
PROC [mx: LoadState.ModuleIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
mgfh: GlobalFrameHandle;
copies: LoadState.CopiesList;
[gfh: mgfh, copies: copies] ← h.ModuleInfo[config, mx];
IF lastWasIt THEN {nextGFH ← mgfh; RETURN[TRUE]};
IF gfh = mgfh
THEN
{
IF copies =
NIL
THEN {lastWasIt ← TRUE; RETURN[FALSE]}
ELSE {nextGFH ← copies.first; RETURN[TRUE]}}
ELSE
IF copies #
NIL
THEN {
FOR x: LoadState.CopiesList ← copies, x.rest
UNTIL x =
NIL
DO
IF lastWasIt THEN {nextGFH ← x.first; RETURN[TRUE]};
IF x.first = gfh THEN lastWasIt ← TRUE;
ENDLOOP;
};
};
nextModule: LoadState.ModuleIndex ←
h.EnumerateModulesInConfig[config, q].module;
rgfh ← [world, CurrentIncarnation[world], LOOPHOLE[nextGFH]];
ans ←
IF nextModule = LoadState.nullModule
THEN
NIL
ELSE TVForRemoteGFHReferent[rgfh];
}
ELSE {
-- not a composite config
lastWasIt: BOOL ← FALSE;
p:
PROC [ci: LoadState.ConfigID]
RETURNS [
BOOL] = {
IF lastWasIt THEN RETURN[TRUE];
IF ci = config THEN lastWasIt ← TRUE;
RETURN[FALSE];
};
nextConfig: LoadState.ConfigID ←
h.EnumerateConfigs[newestFirst, p];
IF nextConfig = LoadState.nullConfig
THEN ans ←
NIL
ELSE {
r:
PROC [LoadState.ModuleIndex]
RETURNS [
BOOL] =
{RETURN[TRUE]};
IF IsRemoteBCDComposite[world, h.ConfigInfo[nextConfig].bcd]
THEN {
ans ←
NEW[ConfigContextObj ←
[world: world,
worldIncarnation: CurrentIncarnation[world],
configIndex: nextConfig]];
}
ELSE ans ← TVForRemoteGFHReferent
[[ world,
CurrentIncarnation[world],
LOOPHOLE[h.EnumerateModulesInConfig[nextConfig, r].gfh]]];
};
};
}; -- end ENABLE UNWIND => h.Release[]
h.Release[];
}; -- end ENABLE UNWIND => WorldVM.Unlock[world];
WorldVM.Unlock[world];
}
ELSE {
-- local case
LoadState.local.Acquire[];
{
ENABLE
UNWIND => LoadState.local.Release[];
gfh: GlobalFrameHandle = GFHFromTV[tv];
config: LoadState.ConfigID ← LoadState.local.GlobalFrameToModule[gfh].config;
IF IsComposite[LoadState.local.ConfigInfo[config].bcd]
THEN {
nextGFH: GlobalFrameHandle;
lastWasIt: BOOL ← FALSE;
q:
PROC [mx: LoadState.ModuleIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
mgfh: GlobalFrameHandle;
copies: LoadState.CopiesList;
[gfh: mgfh, copies: copies] ← LoadState.local.ModuleInfo[config, mx];
IF lastWasIt THEN {nextGFH ← mgfh; RETURN[TRUE]};
IF gfh = mgfh
THEN {
IF copies =
NIL
THEN {lastWasIt ← TRUE; RETURN[FALSE]}
ELSE {nextGFH ← copies.first; RETURN[TRUE]}}
ELSE
IF copies #
NIL
THEN {
FOR x: LoadState.CopiesList ← copies, x.rest
UNTIL x =
NIL DO
IF lastWasIt THEN {nextGFH ← x.first; RETURN[TRUE]};
IF x.first = gfh THEN lastWasIt ← TRUE;
ENDLOOP;
};
};
nextModule: LoadState.ModuleIndex ←
LoadState.local.EnumerateModulesInConfig[config, q].module;
ans ←
IF nextModule = LoadState.nullModule
THEN
NIL
ELSE TVForGFHReferent[nextGFH];
}
ELSE {
-- not a composite config
lastWasIt: BOOL ← FALSE;
p:
PROC [ci: LoadState.ConfigID]
RETURNS [
BOOL] = {
IF lastWasIt THEN RETURN[TRUE];
IF ci = config THEN lastWasIt ← TRUE;
RETURN[FALSE];
};
nextConfig: LoadState.ConfigID ←
LoadState.local.EnumerateConfigs[newestFirst, p];
IF nextConfig = LoadState.nullConfig
THEN ans ←
NIL
ELSE {
r: PROC [LoadState.ModuleIndex] RETURNS [BOOL] = {RETURN[TRUE]};
IF IsComposite[LoadState.local.ConfigInfo[nextConfig].bcd]
THEN {
ans ←
NEW[ConfigContextObj ← [
world: LocalWorld[],
worldIncarnation: CurrentIncarnation[LocalWorld[]],
configIndex: nextConfig]];
}
ELSE ans ← TVForGFHReferent [
LoadState.local.EnumerateModulesInConfig[nextConfig, r].gfh];
};
};
}; -- end ENABLE UNWIND => LoadState.local.Release[]
LoadState.local.Release[];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR;
}; -- end NextSiblingContext
Imports:
PUBLIC
PROC [context: Context]
RETURNS [ans:
LIST
OF PartialInterfaceInstance ←
NIL] = {
... dealing with PartialInterfaceInstances
Implemented only for loadstate entries and global frames sharing
WITH context
SELECT
FROM
mc: ConfigContext => {
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
AcquireIR:
PROC [imph: BcdDefs.IMPHandle, impi: BcdDefs.IMPIndex]
RETURNS [stop: BOOL ← FALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase
← AcquireSTB[
GetSTHForModule
[stamp: ftb[imph.file].version,
fileName: BcdNameToRope[bcd, ftb[imph.file].name],
moduleName: BcdNameToRope[bcd, imph.name]]];
p:
PROC [stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS [stop:
BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]} ELSE RETURN[FALSE];
};
IF
NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, mc.world], usingList: NIL], ans]; -- NOTE
};
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
IF mc.world # LocalWorld[]
THEN {
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
bcd ← h.ConfigInfo[mc.configIndex].bcd;
IF bcd = NIL THEN ERROR;
bcd ← AcquireRemoteBCD[mc.world, mc.worldIncarnation, bcd];
IF bcd = NIL THEN ERROR;
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
{
ENABLE
UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessImports[bcd, AcquireIR];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD ...
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
}
ELSE {
-- local case
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex].bcd;
LoadState.local.Release[];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessImports[bcd, AcquireIR];
};
};
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType => {
gets top level imports from the loadstate, via the minimodel. Encapsulation awaits the modeller.
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp:
IF IsRemote[tv]
THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
shortFileNameHint: Rope.Concat[TVToName[tv], ".bcd"]
];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
AcquireIR: PROC [imph: BcdDefs.IMPHandle, impi: BcdDefs.IMPIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB
[GetSTHForModule
[stamp: ftb[imph.file].version,
fileName: BcdNameToRope[bcd, ftb[imph.file].name],
moduleName: BcdNameToRope[bcd, imph.name]
]
];
p:
PROC [stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS [stop:
BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF
NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, GetWorld[tv]], usingList: NIL], ans];
};
IF IsComposite[bcd] THEN {RTSymbolsPrivate.ReleaseBCD[bcd]; ERROR};--disaster
single module bcd
[] ← BcdOps.ProcessImports[bcd, AcquireIR
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
NOTE interface modules import stuff.
};
ENDCASE => ERROR;
};
Exports:
PUBLIC
PROC [context: Context]
RETURNS [ans:
LIST
OF PartialInterfaceInstance ←
NIL] = {
Implemented only for loadstate entries and global frames; sharing!
WITH context
SELECT
FROM
mc: ConfigContext => {
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
AcquireIR:
PROC [exph: BcdDefs.EXPHandle, expi: BcdDefs.EXPIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB [
GetSTHForModule [
stamp: ftb[exph.file].version,
fileName: BcdNameToRope[bcd, ftb[exph.file].name],
moduleName: BcdNameToRope[bcd, exph.name]]];
p:
PROC [stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS [stop:
BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF
NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, mc.world], usingList: NIL], ans];
};
IF mc.configIndex = LoadState.nullConfig
THEN {
FOR irNames:
LIST
OF
ROPE ← GetInterfaceRecordNames[mc.world], irNames.rest
UNTIL irNames = NIL DO
ans ← CONS[[ir: GetInterfaceRecord[irNames.first, mc.world], usingList: NIL], ans];
ENDLOOP;
RETURN;
};
IF mc.world # LocalWorld[]
THEN {
Lock[mc.world];
{
ENABLE
UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
bcd ← h.ConfigInfo[mc.configIndex].bcd;
IF bcd = NIL THEN ERROR;
bcd ← AcquireRemoteBCD[mc.world, mc.worldIncarnation, bcd];
IF bcd = NIL THEN ERROR;
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
{
ENABLE
UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessExports[bcd, AcquireIR];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD ...
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
}
ELSE {
-- local case
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex].bcd;
LoadState.local.Release[];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessExports[bcd, AcquireIR];
};
};
tv: RefTVRec => {
SELECT TVType[tv]
FROM
gfhType => {
gets top level imports from the loadstate, via the minimodel; Encapsulation awaits the modeller.
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [
versionStamp:
IF IsRemote[tv]
THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
shortFileNameHint: Rope.Concat[TVToName[tv], ".bcd"]];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
AcquireIR:
PROC [exph: BcdDefs.EXPHandle, expi: BcdDefs.EXPIndex]
RETURNS [stop: BOOL ← FALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB [
GetSTHForModule [
stamp: ftb[exph.file].version,
fileName: BcdNameToRope[bcd, ftb[exph.file].name],
moduleName: BcdNameToRope[bcd, exph.name]]];
p:
PROC [stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS [stop:
BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF
NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, GetWorld[tv]], usingList: NIL], ans];
};
IF IsComposite[bcd] THEN {RTSymbolsPrivate.ReleaseBCD[bcd]; ERROR};--disaster
single module bcd
[] ← BcdOps.ProcessExports[bcd, AcquireIR
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR;
};
Private Procedures
StripExtension:
PROC [name:
ROPE]
RETURNS [
ROPE] = {
RETURN[Rope.Substr[base: name, start: 0, len: Rope.SkipTo[s: name, pos: 0, skip: "."]]];
};
IsComposite: PROC [bcd: BcdDefs.BcdBase] RETURNS [BOOL] = {RETURN[bcd.nConfigs # 0]};
IsRemoteBCDComposite:
PROC [world: World, bcd: BcdDefs.BcdBase]
RETURNS [
BOOL] = {
RETURN[WorldVM.Read[world, LOOPHOLE[@bcd.nConfigs, WorldVM.Address]] # 0];
};
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]];
};
RemoteGFHToVersionStamp:
PROC [gfh: RemoteGlobalFrameHandle]
RETURNS [version: BcdDefs.VersionStamp ← BcdDefs.NullVersion] = {
mx: LoadState.ModuleIndex;
config: LoadState.ConfigID;
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
h: LoadState.Handle;
FindModuleVersion:
PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
IF mx
IN [mth.gfi .. mth.gfi + mth.ngfi)
THEN {
version ← IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version;
RETURN[TRUE];
};
};
start RemoteGFHToVersionStamp here
IF gfh = nilRemoteGlobalFrameHandle THEN RETURN;
h ← WorldVM.Loadstate[gfh.world];
h.Acquire[];
{
ENABLE
UNWIND => h.Release[];
[config, mx] ← h.GlobalFrameToModule[LOOPHOLE[gfh.gfh]];
IF config = LoadState.nullConfig THEN {h.Release[]; RETURN};
bcd ← AcquireRemoteBCD[gfh.world, gfh.worldIncarnation, h.ConfigInfo[config].bcd];
{
ENABLE
UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleVersion];
}; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
};
GFHToVersionStamp:
PROC [gfh: PrincOps.GlobalFrameHandle]
RETURNS [version: BcdDefs.VersionStamp ← BcdDefs.NullVersion] = {
mx: LoadState.ModuleIndex;
config: LoadState.ConfigID;
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
FindModuleVersion:
PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [stop:
BOOL ←
FALSE] = {
IF mx
IN [mth.gfi .. mth.gfi + mth.ngfi)
THEN {
version ← IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version;
RETURN[TRUE];
};
};
start GFHToVersionStamp here
IF gfh = NIL THEN RETURN;
LoadState.local.Acquire[];
{
ENABLE
UNWIND => LoadState.local.Release[];
[config, mx] ← LoadState.local.GlobalFrameToModule[gfh];
IF config = LoadState.nullConfig THEN {LoadState.local.Release[]; RETURN};
bcd ← LoadState.local.ConfigInfo[config].bcd;
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleVersion];
}; -- end ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
};
ProgPCToFGI:
PUBLIC
PROC [prog: AMTypes.
TV
--globalFrame--, pc: PrincOps.BytePC]
RETURNS [ans: FGIndex ← FGNull] = {
stb: SymbolTableBase;
IF IsRemote[prog]
THEN stb ← AcquireSTBFromRemoteGFH[RemoteGFHFromTV[prog]]
ELSE stb ← AcquireSTBFromGFH[GFHFromTV[prog]];
{
ENABLE
UNWIND => ReleaseSTB[stb];
now compute the epi and the relative pc
epi: EPI;
startPC: PrincOps.BytePC;
IF IsRemote[prog]
THEN [epi, startPC] ← RTTypesRemotePrivate.GetRemoteEp [pc: pc, gf: RemoteGFHFromTV[prog], stb: stb]
ELSE [epi, startPC] ← RTTypesPrivate.GetEp [pc: pc, gf: GFHFromTV[prog], stb: stb];
ans ← PCToFGI[stb, epi, pc - startPC];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};
StatementContextToFGI:
PROC [sc: StatementContext]
RETURNS [ans: FGIndex ← FGNull] = {
[local frame, PC] => FGIndex (wrt prog module bcd)
prog: REF prog SectionObj ← NIL;
bcd: BcdDefs.BcdBase;
c: Context ← sc;
world: World;
local: BOOL ← FALSE;
UNTIL ContextClass[c] = prog DO c ← ParentContext[c]; ENDLOOP;
world ← GetWorld[c];
prog ← NARROW[ContextSection[c]];
local ← (world = LocalWorld[]);
IF local
THEN bcd ← GetLocalBCD[GFHFromTV[c]]
ELSE bcd ← GetRemoteBCD[RemoteGFHFromTV[c]];
{
ENABLE
UNWIND =>
IF
NOT local
THEN ReleaseRemoteBCD[bcd];
mth: BcdDefs.MTHandle;
stb: SymbolTableBase;
GetModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {RETURN[TRUE]};
[mth,] ← BcdOps.ProcessModules[bcd, GetModule];
IF mth = NIL THEN ERROR;
stb ← AcquireSTBFromSGI[bcd: bcd, sgi: mth.sseg];
{
ENABLE
UNWIND => ReleaseSTB[stb];
now compute the epi and the relative pc
pc: PrincOps.BytePC = AMBridge.ContextPC[sc.localFrameTV];
epi: EPI;
startPC: PrincOps.BytePC;
IF IsRemote[sc.localFrameTV]
THEN [epi, startPC] ← RTTypesRemotePrivate.GetRemoteEp
[pc: pc, gf: RemoteGFHFromTV[GlobalParent[sc.localFrameTV]], stb: stb]
ELSE [epi, startPC] ← RTTypesPrivate.GetEp
[pc: pc, gf: FHFromTV[sc.localFrameTV].accesslink, stb: stb];
ans ← PCToFGI[stb, epi, pc - startPC];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD;
IF NOT local THEN ReleaseRemoteBCD[bcd];
}; -- end StatementContextToFGI
}.