AMModelPrivateImpl.Mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) October 14, 1985 6:59:25 pm PDT
DIRECTORY
AMModel USING [CharIndex],
AMModelPrivate USING [EPI, FGIndex, FGNull, NullPCOffset, PCOffset],
BrandXSymbolDefs USING [SymbolTableBase, BodyTableEntry, FineGrainTableEntry, rootBodyIndex, BodyIndex, nullBodyIndex],
BrandYSymbolDefs USING [SymbolTableBase, BodyTableEntry, FineGrainTableEntry, rootBodyIndex, BodyIndex, nullBodyIndex],
RTSymbolDefs USING [SymbolTableBase];
RRA: Each normal FGT entry may be preceded by zero or more source and object steps. The effect of the normal entry, combined with the preceding source and object steps, is to describe the source and object range for a "statement". Dick Sweet claims that the "right" thing to do is to ONLY return FGIs corresponding to "normal" steps, and he knows more about this than I do.
AMModelPrivateImpl: PROGRAM
EXPORTS AMModelPrivate
= BEGIN OPEN AMModel, AMModelPrivate, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, RTSymbolDefs;
local type definitions
XBodyPtr: TYPE = LONG POINTER TO bx.BodyTableEntry;
YBodyPtr: TYPE = LONG POINTER TO by.BodyTableEntry;
EPIndex: TYPE = AMModelPrivate.EPI;
FGCard: TYPE = CARDINAL;
XFGPtr: TYPE = LONG POINTER TO bx.FineGrainTableEntry;
YFGPtr: TYPE = LONG POINTER TO by.FineGrainTableEntry;
kludge for the missing FGI
fudge: INT ← 8; -- number of characters to assume beyond the last fgi in a procedure
procedures exported to AMModelPrivate
FGIToEPI: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex] RETURNS [EPIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToEPIX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToEPIY[t.e, fgi]];
ENDCASE => ERROR;
};
FGIToEPIX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [epi: EPIndex ← 0] = {
returns first fine grain index for the given procedure
(0 for start proc OR invalid fgi)
IF fgi # FGNull THEN {
bti: bx.BodyIndex = FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM
Callable => epi ← ext.entryIndex;
ENDCASE => RETURN;
};
};
};
FGIToEPIY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [epi: EPIndex ← 0] = {
returns first fine grain index for the given procedure
(0 for start proc OR invalid fgi)
IF fgi # FGNull THEN {
bti: by.BodyIndex = FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM
Callable => epi ← ext.entryIndex;
ENDCASE => RETURN;
};
};
};
EPIToFirstFGI: PUBLIC PROC [stb: SymbolTableBase, epi: EPIndex, skipArgs: BOOL] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToFirstFGIX[t.e, epi, skipArgs]];
t: SymbolTableBase.y => RETURN[EPIToFirstFGIY[t.e, epi, skipArgs]];
ENDCASE => ERROR;
};
EPIToFirstFGIX: PROC [stb: bx.SymbolTableBase, epi: EPIndex, skipArgs: BOOL] RETURNS [fgi: FGIndex ← FGNull] = {
returns first fine grain index for the given procedure (FGNull for invalid epi)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {
body: XBodyPtr ← @stb.bb[bti];
fgi ← [fgCard: info.startIndex, fudge: FALSE];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
tpc: PCOffset ← 0;
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
fgi.fgCard ← tfgi;
IF NOT skipArgs THEN RETURN;
skipArgs ← FALSE;
};
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
ENDCASE;
};
EPIToFirstFGIY: PROC [stb: by.SymbolTableBase, epi: EPIndex, skipArgs: BOOL] RETURNS [fgi: FGIndex ← FGNull] = {
returns first fine grain index for the given procedure (FGNull for invalid epi)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {
body: XBodyPtr ← @stb.bb[bti];
fgi ← [fgCard: info.startIndex, fudge: FALSE];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
tpc: PCOffset ← 0;
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
fgi.fgCard ← tfgi;
IF NOT skipArgs THEN RETURN;
skipArgs ← FALSE;
};
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
ENDCASE;
};
EPIToLastFGI: PUBLIC PROC [stb: SymbolTableBase, epi: EPIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToLastFGIX[t.e, epi]];
t: SymbolTableBase.y => RETURN[EPIToLastFGIY[t.e, epi]];
ENDCASE => ERROR;
};
EPIToLastFGIX: PROC [stb: bx.SymbolTableBase, epi: EPIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns last fine grain index for the given procedure
(FGNull for invalid epi)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External =>
fgi ← [fgCard: info.startIndex + MAX[info.indexLength, 1] - 1, fudge: TRUE];
ENDCASE;
};
EPIToLastFGIY: PROC [stb: by.SymbolTableBase, epi: EPIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns last fine grain index for the given procedure
(FGNull for invalid epi)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External =>
fgi ← [fgCard: info.startIndex + MAX[info.indexLength, 1] - 1, fudge: TRUE];
ENDCASE;
};
EPIToFirstPC: PUBLIC PROC [stb: SymbolTableBase, epi: EPIndex, skipArgs: BOOL] RETURNS [PCOffset] = {
fgi: FGIndex ← EPIToFirstFGI[stb, epi, skipArgs];
IF fgi = FGNull THEN RETURN [NullPCOffset];
RETURN [FGIToFirstPC[stb, fgi]];
};
EPIToLastPC: PUBLIC PROC [stb: SymbolTableBase, epi: EPIndex] RETURNS [PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToLastPCX[t.e, epi]];
t: SymbolTableBase.y => RETURN[EPIToLastPCY[t.e, epi]];
ENDCASE => ERROR;
};
EPIToLastPCX: PROC [stb: bx.SymbolTableBase, epi: EPIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the procedure (may be padding byte)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {pc ← info.bytes; pc ← pc - 1};
ENDCASE;
};
EPIToLastPCY: PROC [stb: by.SymbolTableBase, epi: EPIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the procedure (may be padding byte)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {pc ← info.bytes; pc ← pc - 1};
ENDCASE;
};
CharIndexToFGI: PUBLIC PROC [stb: SymbolTableBase, ci: CharIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[CharIndexToFGIX[t.e, ci]];
t: SymbolTableBase.y => RETURN[CharIndexToFGIY[t.e, ci]];
ENDCASE => ERROR;
};
CharIndexToFGIX: PROC [stb: bx.SymbolTableBase, ci: CharIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given char index (FGNull for invalid position)
bti: bx.BodyIndex ← CItoBTIX[stb, ci];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex;
adjust: CharIndex ← 0;
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
adjust ← adjust + deltaSource;
IF adjust # 0 THEN {
fgi.fgCard ← tfgi;
thisCI ← thisCI+adjust;
IF thisCI > ci THEN RETURN;
adjust ← 0;
};
};
step => IF which = source THEN adjust ← adjust + delta;
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
CharIndexToFGIY: PROC [stb: by.SymbolTableBase, ci: CharIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given char index (FGNull for invalid position)
bti: by.BodyIndex ← CItoBTIY[stb, ci];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex;
adjust: CharIndex ← 0;
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
adjust ← adjust + deltaSource;
IF adjust # 0 THEN {
fgi.fgCard ← tfgi;
thisCI ← thisCI+adjust;
IF thisCI > ci THEN RETURN;
adjust ← 0;
};
};
step => IF which = source THEN adjust ← adjust + delta;
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
PCToFGI: PUBLIC PROC [stb: SymbolTableBase, epi: EPIndex, pc: PCOffset] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[PCToFGIX[t.e, epi, pc]];
t: SymbolTableBase.y => RETURN[PCToFGIY[t.e, epi, pc]];
ENDCASE => ERROR;
};
PCToFGIX: PROC [stb: bx.SymbolTableBase, epi: EPIndex, pc: PCOffset] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given pc offset in the given procedure
(FGNull for invalid epi or invalid pc)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
rem: INT ← pc;
IF pc >= info.bytes THEN RETURN [FGNull];
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
rem ← rem - deltaObject;
fgi.fgCard ← tfgi;
IF rem < 0 THEN RETURN;
};
step => IF which = object THEN rem ← rem - delta;
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
PCToFGIY: PROC [stb: by.SymbolTableBase, epi: EPIndex, pc: PCOffset] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given pc offset in the given procedure
(FGNull for invalid epi or invalid pc)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
rem: INT ← pc;
IF pc >= info.bytes THEN RETURN [FGNull];
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
rem ← rem - deltaObject;
fgi.fgCard ← tfgi;
IF rem < 0 THEN RETURN;
};
step => IF which = object THEN rem ← rem - delta;
ENDCASE;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
NextFGI: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex, epi: EPIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[NextFGIX[t.e, fgi, epi]];
t: SymbolTableBase.y => RETURN[NextFGIY[t.e, fgi, epi]];
ENDCASE => ERROR;
};
NextFGIX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex, epi: EPIndex] RETURNS [nfgi: FGIndex ← FGNull] = {
takes a FGIndex & entry point, returns the next FGIndex
returns FGNull if next fgi is in a different proc than entryPointIndex
OR the given FGIndex or entry point was not valid
bti: bx.BodyIndex;
IF fgi = FGNull OR fgi.fudge THEN RETURN;
bti ← EPItoBTIX[stb, epi];
IF bti # bx.nullBodyIndex THEN
WITH info: stb.bb[bti].info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fudge OR fgi.fgCard NOT IN [firstFGI..lastFGI] THEN RETURN;
IF fgi.fgCard = lastFGI
THEN fgi.fudge ← TRUE
ELSE fgi.fgCard ← fgi.fgCard + 1;
nfgi ← fgi;
};
ENDCASE;
};
NextFGIY: PROC [stb: by.SymbolTableBase, fgi: FGIndex, epi: EPIndex] RETURNS [nfgi: FGIndex ← FGNull] = {
takes a FGIndex & entry point, returns the next FGIndex
returns FGNull if next fgi is in a different proc than entryPointIndex
OR the given FGIndex or entry point was not valid
bti: by.BodyIndex;
IF fgi = FGNull OR fgi.fudge THEN RETURN;
bti ← EPItoBTIY[stb, epi];
IF bti # by.nullBodyIndex THEN
WITH info: stb.bb[bti].info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fgCard NOT IN [firstFGI..lastFGI] THEN RETURN;
IF fgi.fgCard = lastFGI
THEN fgi.fudge ← TRUE
ELSE fgi.fgCard ← fgi.fgCard + 1;
nfgi ← fgi;
};
ENDCASE;
};
FGIToFirstChar: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex] RETURNS [CharIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToFirstCharX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToFirstCharY[t.e, fgi]];
ENDCASE => ERROR;
};
FGIToFirstCharX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the first character position
-1 for invalid fgi
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
stop: FGCard = IF fgi.fudge THEN fgi.fgCard + 1 ELSE fgi.fgCard;
tci: CharIndex ← ci ← body.sourceIndex;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
IF tfgi >= stop THEN EXIT ELSE {
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← tci ← tci + deltaSource;
step => IF which = source THEN tci ← tci + delta;
ENDCASE;
};
ENDLOOP;
};
ENDCASE;
};
};
FGIToFirstCharY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the first character position
-1 for invalid fgi
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
stop: FGCard = IF fgi.fudge THEN fgi.fgCard + 1 ELSE fgi.fgCard;
tci: CharIndex ← ci ← body.sourceIndex;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
IF tfgi >= stop THEN EXIT ELSE {
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← tci ← tci + deltaSource;
step => IF which = source THEN tci ← tci + delta;
ENDCASE;
};
ENDLOOP;
};
ENDCASE;
};
};
FGIToLastChar: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex] RETURNS [CharIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToLastCharX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToLastCharY[t.e, fgi]];
ENDCASE => ERROR;
};
FGIToLastCharX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the last character position
-1 for invalid fgi
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
ci ← body.sourceIndex;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← ci + deltaSource;
step => IF which = source THEN ci ← ci + delta;
ENDCASE;
ENDLOOP;
IF fgi.fudge
THEN ci ← ci + fudge --XXX
ELSE ci ← ci - 1;
};
ENDCASE;
};
};
FGIToLastCharY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the last character position
-1 for invalid fgi
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
ci ← body.sourceIndex;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← ci + deltaSource;
step => IF which = source THEN ci ← ci + delta;
ENDCASE;
ENDLOOP;
IF fgi.fudge
THEN ci ← ci + fudge --XXX
ELSE ci ← ci - 1;
};
ENDCASE;
};
};
FGIToFirstPC: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex] RETURNS [PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToFirstPCX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToFirstPCY[t.e, fgi]];
ENDCASE => ERROR;
};
FGIToFirstPCX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
takes a FGIndex, returns the first PC (NullPCOffset for invalid fgi)
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
stop: FGCard = IF fgi.fudge THEN fgi.fgCard+1 ELSE fgi.fgCard;
tpc: PCOffset ← pc ← 0;
pending: BOOLTRUE;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
IF tfgi >= stop THEN EXIT ELSE {
fp: XFGPtr = @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
tpc ← tpc + deltaObject;
IF pending OR deltaSource # 0 THEN {pc ← tpc; pending ← FALSE};
};
step => IF which = object THEN tpc ← tpc + delta ELSE pending ← TRUE;
ENDCASE;
};
ENDLOOP;
};
ENDCASE;
};
};
FGIToFirstPCY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
takes a FGIndex, returns the first PC (NullPCOffset for invalid fgi)
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
stop: FGCard = IF fgi.fudge THEN fgi.fgCard+1 ELSE fgi.fgCard;
tpc: PCOffset ← pc ← 0;
pending: BOOLTRUE;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
IF tfgi >= stop THEN EXIT ELSE {
fp: YFGPtr = @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => {
tpc ← tpc + deltaObject;
IF pending OR deltaSource # 0 THEN {pc ← tpc; pending ← FALSE};
};
step => IF which = object THEN tpc ← tpc + delta ELSE pending ← TRUE;
ENDCASE;
};
ENDLOOP;
};
ENDCASE;
};
};
FGIToLastPC: PUBLIC PROC [stb: SymbolTableBase, fgi: FGIndex] RETURNS [PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToLastPCX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToLastPCY[t.e, fgi]];
ENDCASE => ERROR;
};
FGIToLastPCX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the fine grain entry
(NullPCOffset for invalid fgi)
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
IF fgi.fudge THEN {pc ← INT[info.bytes] - 1; RETURN};
pc ← 0;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => pc ← pc + deltaObject;
step => IF which = object THEN pc ← pc + delta;
ENDCASE;
ENDLOOP;
pc ← pc - 1;
};
ENDCASE;
};
};
FGIToLastPCY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the fine grain entry
(NullPCOffset for invalid fgi)
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
IF fgi.fudge THEN {pc ← INT[info.bytes] - 1; RETURN};
pc ← 0;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => pc ← pc + deltaObject;
step => IF which = object THEN pc ← pc + delta;
ENDCASE;
ENDLOOP;
pc ← pc - 1;
};
ENDCASE;
};
};
implementation procedures
EPItoBTIX: PROC[stb: bx.SymbolTableBase, epi: EPIndex] RETURNS [outerBti: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & entry point
returns a Callable BTI for the entry point
or nullBodyIndex if that can't be done
innerEPItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External =>
IF epi = thisEPI THEN {outerBti ← bti; stop ← TRUE};
ENDCASE;
};
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerEPItoBTI];
};
EPItoBTIY: PROC[stb: by.SymbolTableBase, epi: EPIndex] RETURNS [outerBti: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & entry point
returns a Callable BTI for the entry point
or nullBodyIndex if that can't be done
innerEPItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External =>
IF epi = thisEPI THEN {outerBti ← bti; stop ← TRUE};
ENDCASE;
};
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerEPItoBTI];
};
FGItoBTIX: PROC [stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [outerBti: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & FGIndex
returns a Callable BTI containing the FGIndex
or nullBodyIndex if that can't be done
innerFGItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fgCard IN [firstFGI..lastFGI] THEN {
outerBti ← bti;
stop ← TRUE};
};
ENDCASE;
};
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerFGItoBTI];
};
FGItoBTIY: PROC [stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [outerBti: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & FGIndex
returns a Callable BTI containing the FGIndex
or nullBodyIndex if that can't be done
innerFGItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fgCard IN [firstFGI..lastFGI] THEN {
outerBti ← bti;
stop ← TRUE};
};
ENDCASE;
};
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerFGItoBTI];
};
CItoBTIX: PROC [stb: bx.SymbolTableBase, ci: CharIndex] RETURNS [bestBTI: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & character position
returns a Callable BTI containing the FGIndex or nullBodyIndex if that can't be done
bestCI: CharIndex ← 0;
the start CharIndex of the smallest enclosing (of ci) Callable body, initialized to the start CharIndex of the module
bti1, fgi1, and ci1 get the largest point where ci1 < ci. Note that ci1 is the character index after fgi1 has been applied.
bti1: bx.BodyIndex ← bx.nullBodyIndex;
fgi1: FGCard ← 0;
ci1: CharIndex ← 0;
bti2, fgi2, and ci2 get the smallest point where ci2 >= ci. Note that ci2 is the character index before fgi2 has been applied.
bti2: bx.BodyIndex ← bx.nullBodyIndex;
fgi2: FGCard ← 0;
ci2: CharIndex ← 0;
innerCItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
lastCI: CharIndex ← thisCI; -- the first sourceIndex of the current statement
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
Compute (fgt2) the smallest fgt entry startIndex where ci2 >= ci
IF (lastCI < ci2 OR bti2 = bx.nullBodyIndex) AND lastCI >= ci THEN {
bti2 ← bti; fgi2 ← tfgi; ci2 ← lastCI;
};
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
Compute (fgt1) the largest fgt entry startIndex where ci1 < ci
IF (lastCI >= ci1 OR bti1 = bx.nullBodyIndex) AND lastCI < ci
THEN {bti1 ← bti; fgi1 ← tfgi; ci1 ← lastCI};
ENDLOOP;
};
ENDCASE;
};
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerCItoBTI];
bestBTI ← bti1;
IF bti1 # bti2 THEN {
IF ci = ci2 OR bti1 = bx.nullBodyIndex THEN bestBTI ← bti2;
};
};
CItoBTIY: PROC [stb: by.SymbolTableBase, ci: CharIndex] RETURNS [bestBTI: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & character position
returns a Callable BTI containing the FGIndex or nullBodyIndex if that can't be done
bestCI: CharIndex ← 0;
the start CharIndex of the smallest enclosing (of ci) Callable body, initialized to the start CharIndex of the module
bti1, fgi1, and ci1 get the largest point where ci1 < ci. Note that ci1 is the character index after fgi1 has been applied.
bti1: by.BodyIndex ← by.nullBodyIndex;
fgi1: FGCard ← 0;
ci1: CharIndex ← 0;
bti2, fgi2, and ci2 get the smallest point where ci2 >= ci. Note that ci2 is the character index before fgi2 has been applied.
bti2: by.BodyIndex ← by.nullBodyIndex;
fgi2: FGCard ← 0;
ci2: CharIndex ← 0;
innerCItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
lastCI: CharIndex ← thisCI; -- the first sourceIndex of the current statement
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
Compute (fgt2) the smallest fgt entry startIndex where ci2 >= ci
IF (lastCI < ci2 OR bti2 = by.nullBodyIndex) AND lastCI >= ci THEN {
bti2 ← bti; fgi2 ← tfgi; ci2 ← lastCI;
};
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
Compute (fgt1) the largest fgt entry startIndex where ci1 < ci
IF (lastCI >= ci1 OR bti1 = by.nullBodyIndex) AND lastCI < ci
THEN {bti1 ← bti; fgi1 ← tfgi; ci1 ← lastCI};
ENDLOOP;
};
ENDCASE;
};
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerCItoBTI];
bestBTI ← bti1;
IF bti1 # bti2 THEN {
IF ci = ci2 OR bti1 = by.nullBodyIndex THEN bestBTI ← bti2;
};
};
END.