-- AMModelBridgeImpl.Mesa
-- last modified on July 14, 1983 10:25 am by Paul Rovner

DIRECTORY
AMBridge USING[
IsRemote, TVToRemoteProc, TVToProc, GetWorld, GetWorldIncarnation,
RemoteGFHFromTV, RemoteGlobalFrameHandle, nilRemoteGlobalFrameHandle,
TVForRemoteProc, TVForProc, GFHFromTV],
AMModel USING[Context, Section, ContextSection],
AMModelBridge USING[LoadedSection, ContextForFrame, FrameFromContext],
AMModelPrivate USING[SectionRec, ProgPCToFGI],
AMTypes USING[GlobalParent, TV],
PrincOps USING[BytePC, ControlLink, EPRange, GlobalFrameHandle, ProcDesc],
PrincOpsUtils USING[GlobalFrameAndEntryPoint],
RemotePrincOpsUtils USING[RemoteGlobalFrameAndEntryPoint],
RTTypesPrivate USING[GetPc],
RTTypesRemotePrivate USING[GetRemotePc, GetRemoteGFHeader],
WorldVM USING[World, CurrentIncarnation];

AMModelBridgeImpl: PROGRAM
IMPORTS AMBridge, AMModel, AMModelBridge, AMModelPrivate, AMTypes,
PrincOpsUtils, RemotePrincOpsUtils, RTTypesPrivate, RTTypesRemotePrivate, WorldVM
EXPORTS AMModel, AMModelBridge

= BEGIN OPEN AMModel, AMModelBridge, PrincOps, RTTypesPrivate, RTTypesRemotePrivate;

-- 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 = AMModelPrivate.SectionRec;

LoadedSection: TYPE = AMModelBridge.LoadedSection;
-- A LoadedSection is a convenience for clients of AMModelBridge. Each represents one of:
-- loaded compiler output bundle for a prog module [prog, prog]
-- loaded compiler output bundle for a proc [proc, prog]
-- loaded compiler output bundle for a statement [statement, prog]

LoadedSectionForProc: PUBLIC PROC[tv: AMTypes.TV--proc--]
RETURNS[ans: LoadedSection ← [NIL, NIL, [0]]] =
{ c: Context;
s: Section;
ep: CARDINAL;
gf: AMTypes.TV ← AMTypes.GlobalParent[tv];
ans.context ← AMModelBridge.ContextForFrame[gf];
c ← ans.context;
s ← ContextSection[c];
IF AMBridge.IsRemote[tv]
THEN {
world: WorldVM.World = AMBridge.GetWorld[tv];
rgfh: AMBridge.RemoteGlobalFrameHandle ← AMBridge.nilRemoteGlobalFrameHandle;
gfh: PrincOps.GlobalFrameHandle;
[gfh, ep] ← RemotePrincOpsUtils.RemoteGlobalFrameAndEntryPoint
[world, AMBridge.TVToRemoteProc[tv].pd];
rgfh ← [world, WorldVM.CurrentIncarnation[world], LOOPHOLE[gfh]];
ans.pc ← RTTypesRemotePrivate.GetRemotePc[rgfh, ep];
}
ELSE {
gfh: PrincOps.GlobalFrameHandle;
[gfh, ep] ← PrincOpsUtils.GlobalFrameAndEntryPoint[AMBridge.TVToProc[tv]];
ans.pc ← RTTypesPrivate.GetPc[gfh, ep];
};
ans.section ← NEW[SectionObj
← [proc[prog: NARROW[s],
entryPointIndex: ep,
procTV: NARROW[tv]]]];
};

LoadedSectionForProgPC: PUBLIC PROC[prog: Context, pc: BytePC]
RETURNS[ans: LoadedSection ← [NIL, NIL, [0]]] =
{ s: Section = ContextSection[prog];
ans.context ← prog;
ans.section ← NEW[SectionObj
← [statement
[prog: NARROW[s],
fgtIndex: AMModelPrivate.ProgPCToFGI[FrameFromContext[prog], pc]]]];
ans.pc ← pc;
};

ProcFromLoadedSection: PUBLIC PROC[proc: LoadedSection] RETURNS[AMTypes.TV--proc--] =
{s: Section = proc.section;
sr: REF proc SectionObj ← NARROW[s];
IF sr.procTV # NIL
THEN RETURN[sr.procTV]
ELSE {IF AMBridge.IsRemote[FrameFromContext[proc.context]]
THEN
{pd: PrincOps.ProcDesc ← PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]];
pd.gfi ← GetRemoteGFHeader
[AMBridge.RemoteGFHFromTV[FrameFromContext[proc.context]]].gfi
+ sr.entryPointIndex/PrincOps.EPRange;
pd.ep ← sr.entryPointIndex MOD PrincOps.EPRange;
RETURN[AMBridge.TVForRemoteProc
[[world: AMBridge.GetWorld[FrameFromContext[proc.context]],
worldIncarnation:
AMBridge.GetWorldIncarnation
[FrameFromContext[proc.context]],
pd: pd]]]}
ELSE
{pd: PrincOps.ProcDesc ← PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]];
pd.gfi ← AMBridge.GFHFromTV[FrameFromContext[proc.context]].gfi
+ sr.entryPointIndex/PrincOps.EPRange;
pd.ep ← sr.entryPointIndex MOD PrincOps.EPRange;
RETURN[AMBridge.TVForProc[LOOPHOLE[pd]]]}
};
};

END.