AMModelSourceImpl.mesa
Last Modified On December 12, 1983 11:12 am By Paul Rovner
moduleName, configName should not be source name
DIRECTORY
AMBridge USING [GetWorld, GFHFromTV, RemoteGFHFromTV],
AMFiles USING [OpenIt],
AMModel USING [Class, Context, Source, SourceObj, CharIndex,
SourceFileName, SourceClass, ContextChildren, ContextClass, SectionVersion,
SectionSource, ContextSection, MostRecentNamedContext],
AMModelPrivate USING [FGIndex, FGNull, EPI, FGIToEPI, GetLocalBCD, GetRemoteBCD,
CharIndexToFGI, SectionRec, RefTVRec, ConfigContext],
AMTypes USING [Error, TVType, GlobalParent],
BasicTime USING [ToNSTime],
BcdDefs USING [VersionStamp, MTIndex, FTSelf, BcdBase, MTHandle],
BcdOps USING [ProcessModules],
FS USING [OpenFile, nullOpenFile, GetInfo, Close],
LoadState USING [nullConfig],
Rope USING [ROPE, Concat, Equal, Find, Substr, Match],
RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle, nullHandle, nullBase],
RTSymbols USING [ReleaseSTB, AcquireSTBFromSGI, AcquireSTB, GetSTHForModule],
RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD],
RTTypesRemotePrivate USING [ReleaseRemoteBCD],
SafeStorage USING [gfhType, fhType],
Table USING [Base],
WorldVM USING [LocalWorld, World];
AMModelSourceImpl: PROGRAM
IMPORTS AMBridge, AMFiles, AMTypes, BasicTime, BcdOps, AMModel, AMModelPrivate, FS, LoadState, RTSymbols, Rope, RTSymbolsPrivate, RTTypesRemotePrivate, WorldVM
EXPORTS AMModel, AMModelPrivate
= { OPEN AMBridge, AMModel, AMModelPrivate, AMTypes, Rope, RTSymbolDefs, RTSymbols, 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;
PROCs
... dealing with Source
FileSource: PUBLIC PROC[fileName: ROPE, class: --model, prog, interface--Class]
RETURNS[s: Source ← NIL] = {
f: FS.OpenFile ← FS.nullOpenFile;
IF class = model THEN {
IF NOT Rope.Match["*.config*", fileName, FALSE]
THEN fileName ← fileName.Concat[".config"];
}
ELSE {
IF NOT Rope.Match["*.mesa*", fileName, FALSE]
THEN fileName ← fileName.Concat[".mesa"];
};
f ← AMFiles.OpenIt[fileName].openFile;
IF f # FS.nullOpenFile
THEN {
s ← NEW[SourceObj ←
[fileName: fileName,
class: class,
versionStamp: [0, 0, BasicTime.ToNSTime[FS.GetInfo[f].created]],
sourceRange: entire[]]];
FS.Close[f];
};
};
Use SourceSection to figure out (given a proc or statement source location)
where to place a breakpoint.
The list of prog Contexts returned by SourceSection is meaningful for
prog, proc and statement sources. It will be ordered "most-recently-loaded first".
Strictly speaking, a source can have multiple sections: one for each set of "SectionParams".
Someday we'll accommodate such, but not this week.
NOTE context = NIL oughta mean to find the section even though it's not loaded
SourceSection: PUBLIC PROC[source: Source, context: --worldRoot or model--Context]
RETURNS[section: Section ← NIL, contexts: LIST OF --prog--Context ← NIL] =
{SELECT SourceClass[source] FROM
statement =>
{[section, contexts]
← SourceSection
[NEW[SourceObj ← [fileName: source.fileName,
class: prog,
versionStamp: source.versionStamp,
sourceRange: entire[]]],
context];
section ← NEW[SectionObj ← [statement[prog: NARROW[section],
fgtIndex: SourceToFirstFGI
[source,
NARROW[section]]]]];
};
proc =>
{[section, contexts]
← SourceSection
[NEW[SourceObj ← [fileName: source.fileName,
class: prog,
versionStamp: source.versionStamp,
sourceRange: entire[]]],
context];
section ← NEW[SectionObj ← [proc[prog: NARROW[section],
entryPointIndex: SourceToEPI
[source, NARROW[section]]]]];
};
prog =>
look thru all global frames in context for ones with the source name.
Construct section for the first one found, thereafter check version stamp.
For each found, cons onto contexts
{ WITH context SELECT FROM
tv: RefTVRec =>
{SELECT TVType[tv] FROM
gfhType =>
{ section ← ContextSection[context];
IF Rope.Equal[SourceFileName[source],
SourceFileName[SectionSource[section]],
FALSE]
THEN contexts ← CONS[context, NIL]
ELSE section ← NIL;
RETURN};
fhType =>
{[section, contexts] ← SourceSection[source, GlobalParent[tv]];
RETURN};
ENDCASE => ERROR Error[typeFault];
};
mc: ConfigContext =>
{context: Context;
fn: ROPE = SourceFileName[source];
i: INT ← Rope.Find[s1: fn, s2: ".", pos1: 0, case: FALSE];
mn: ROPEIF i = -1 THEN fn ELSE Rope.Substr[base: fn, len: i];
context ← MostRecentNamedContext[mn, mc];
IF context = NIL
THEN ERROR AMTypes.Error
[reason: notImplemented,
msg: "Finding an object location for a source not loaded"];
section ← ContextSection[context];
contexts ← CONS[context, contexts];
IF TRUE THEN RETURN;
IF mc.configIndex = LoadState.nullConfig
THEN
{proc: PROC[context: Context] RETURNS[stop: BOOLFALSE] =
{ IF ContextClass[context] = model
THEN {s: Section;
cl: LIST OF Context;
[s, cl] ← SourceSection[source, context];
IF s # NIL
THEN { IF section = NIL
THEN section ← s
ELSE
{IF SectionVersion[section]
# SectionVersion[s]
THEN
ERROR
Error
[reason: notImplemented,
msg: "different sections for the same source"]};
UNTIL cl = NIL
DO contexts ← CONS[cl.first, contexts];
cl ← cl.rest;
ENDLOOP;
};
RETURN};
IF Rope.Equal[SourceFileName[source],
SourceFileName[SectionSource[ContextSection[context]]],
FALSE]
THEN {IF section = NIL
THEN section ← ContextSection[context]
ELSE {IF SectionVersion[ContextSection[context]]
# SectionVersion[section]
THEN ERROR
Error[reason: notImplemented,
msg: "different sections for the same source"]};
contexts ← CONS[context, contexts];
};
}; -- end proc defn
[] ← ContextChildren[context, proc];
} -- end IF mc.configIndex = LoadState.nullConfig
ELSE
{proc: PROC[context: Context] RETURNS[stop: BOOLFALSE] =
{ IF Rope.Equal[SourceFileName[source],
SourceFileName[SectionSource[ContextSection[context]]],
FALSE]
THEN {IF section = NIL
THEN section ← ContextSection[context]
ELSE {IF SectionVersion[ContextSection[context]]
# SectionVersion[section]
THEN ERROR
Error[reason: notImplemented,
msg: "different sections for the same source"]};
contexts ← CONS[context, contexts];
};
};
[] ← ContextChildren[context, proc];
};
};
ENDCASE => ERROR
};
model =>
ERROR AMTypes.Error[
reason: notImplemented,
msg: "SourceSection[model source]"];
interface =>
ERROR AMTypes.Error[
reason: notImplemented,
msg: "SourceSection[interface source]"];
ENDCASE => ERROR}; -- end SourceSection
[prog module bcd, CharIndex] => FGIndex (wrt prog module bcd)
SourceToFirstFGI: PROC[source: Source, prog: REF prog SectionObj]
RETURNS[ans: FGIndex ← FGNull] =
{IF prog.someGFHTV # NIL
THEN -- prog loaded
{world: World = GetWorld[prog.someGFHTV];
local: BOOL ← (world = LocalWorld[]);
IF local
THEN
{bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[prog.someGFHTV]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp];
ans ← CharIndexToFGI[stb,
(WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]}
ELSE
{bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[prog.someGFHTV]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp
! UNWIND => ReleaseRemoteBCD[bcd]];
ReleaseRemoteBCD[bcd];
ans ← CharIndexToFGI[stb,
(WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0)
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]};
}
ELSE -- prog not loaded
{bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: prog.versionStamp,
shortFileNameHint:
Rope.Concat[prog.moduleName,
".bcd"]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
RTSymbolsPrivate.ReleaseBCD[bcd];
ans ← CharIndexToFGI[stb,
(WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0)
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]};
};
[prog module bcd, CharIndex] => entryPointIndex (wrt prog module bcd)
SourceToEPI: PROC[source: Source, prog: REF prog SectionObj] RETURNS[ans: EPI ← 0] =
{IF prog.someGFHTV # NIL
THEN -- prog loaded
{world: World = GetWorld[prog.someGFHTV];
local: BOOL ← (world = LocalWorld[]);
IF local
THEN
{bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[prog.someGFHTV]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp];
fgi: FGIndex ← CharIndexToFGI[stb, (WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0) ! UNWIND => ReleaseSTB[stb]];
ans ← FGIToEPI[stb, fgi ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
}
ELSE
{bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[prog.someGFHTV]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp
! UNWIND => ReleaseRemoteBCD[bcd]];
fgi: FGIndex;
ReleaseRemoteBCD[bcd];
fgi ← CharIndexToFGI[stb, (WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0)
! UNWIND => ReleaseSTB[stb]];
ans ← FGIToEPI[stb, fgi
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]};
}
ELSE -- prog not loaded
{bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp: prog.versionStamp,
shortFileNameHint:
Rope.Concat[prog.moduleName,
".bcd"]];
stb: SymbolTableBase ← GetModuleSTB[bcd, prog.versionStamp
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
fgi: FGIndex;
RTSymbolsPrivate.ReleaseBCD[bcd];
fgi ← CharIndexToFGI[stb, (WITH s: source SELECT FROM
field => s.firstCharIndex
ENDCASE => 0)
! UNWIND => ReleaseSTB[stb]];
ans ← FGIToEPI[stb, fgi
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]};
};
GetModuleSTB: PUBLIC PROC[bcd: BcdDefs.BcdBase, versionStamp: BcdDefs.VersionStamp]
RETURNS[stb: SymbolTableBase ← nullBase] =
{ FindModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS[stop: BOOLEANFALSE] =
{version: BcdDefs.VersionStamp ← IF mth.file = BcdDefs.FTSelf
THEN bcd.version ELSE ftb[mth.file].version;
IF version = versionStamp
THEN {stb ← AcquireSTBFromSGI[bcd, mth.sseg]; RETURN[TRUE]}};
start GetModuleSTB here
sth: SymbolTableHandle ← nullHandle;
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
sth ← GetSTHForModule[versionStamp, NIL, NIL ! ANY => CONTINUE];
IF sth = nullHandle
THEN [] ← BcdOps.ProcessModules[bcd, FindModule]
ELSE stb ← AcquireSTB[sth];
};
}.