DIRECTORY
Alloc: TYPE USING [Notifier],
Code: TYPE USING [fileLoc, tailJumpOK, xtracting, xtractlex, xtractsei],
CodeDefs:
TYPE
USING [
Base, BoVarIndex, codeType, Lexeme, NullLex, StoreOptions,
VarComponent, VarIndex, VarNull, wordlength],
Counting: TYPE USING [VarVarAssignCounted],
FOpCodes: TYPE USING [qBLZL, qDB, qFF, qLP, qSL],
P5:
TYPE
USING [
All, Construct, Exp, GenTempLex, LogHeapFree, MultiZero, PushLProcDesc,
RowCons, VariantConstruct],
P5L:
TYPE
USING [
AdjustComponent, ComponentForSE, CopyToTemp, EasilyLoadable, EasyToLoad,
FieldOfComponent, FieldOfVar, GenVarItem, LoadAddress, LoadComponent,
LoadVar, MakeBo, ModComponent, OVarItem, ReleaseVarItem, ReusableCopies,
StoreComponent, TOSAddrLex, TOSComponent, TOSLex, VarForLex, VarVarAssign,
Words],
P5S: TYPE USING [],
P5U:
TYPE
USING [
BitsForOperand, LongTreeAddress, NextVar, OperandType, Out0, Out1,
PrevVar, PushLitVal, WordAligned],
SourceMap: TYPE USING [Up],
Stack: TYPE USING [Clear, Dup, Pop],
SymbolOps: TYPE USING [FirstCtxSe, FnField, NextSe, RecField],
Symbols:
TYPE
USING [
Base, BitAddress, bodyType, CBTIndex, ContextLevel, ISEIndex, ISENull, lG,
RecordSEIndex, seType],
Tree: TYPE USING [Base, Index, Link, Null, treeType],
TreeOps: TYPE USING [GetNode, OpName, NthSon, ReverseUpdateList, ScanList];
ExtractFrom:
PUBLIC
PROC [
t1: Tree.Link, tsei: RecordSEIndex, r: VarIndex, transferrec: BOOL] =
BEGIN
saveExtractState:
RECORD [
xtracting:
BOOL, xtractlex: Lexeme, xtractsei: Symbols.ISEIndex] =
[CPtr.xtracting, CPtr.xtractlex, CPtr.xtractsei];
fa:
PROC [ISEIndex]
RETURNS [BitAddress,
CARDINAL] =
IF seb[tsei].argument THEN FnField ELSE RecField;
startsei: ISEIndex = FirstCtxSe[seb[tsei].fieldCtx];
sei: ISEIndex ← startsei;
isei: ISEIndex ← startsei;
node: Tree.Index = TreeOps.GetNode[t1];
soncount: CARDINAL ← 0;
tbase, toffset: VarComponent;
onStack, useDup: BOOL ← FALSE;
totalBits: CARDINAL;
trashOnStack: CARDINAL ← 0;
XCount:
PROC [t: Tree.Link] =
BEGIN
IF t # Tree.Null THEN soncount ← soncount+1;
END;
ExtractItem:
PROC [t: Tree.Link]
RETURNS [v: Tree.Link] =
BEGIN
posn: BitAddress;
size: CARDINAL;
v ← t;
[posn, size] ← fa[sei];
IF t # Tree.Null
THEN
BEGIN
subNode: Tree.Index = TreeOps.GetNode[t];
rr: VarIndex;
offset, base: VarComponent;
soncount ← soncount-1;
IF onStack THEN offset ← toffset -- original record on stack
ELSE
BEGIN
IF useDup
THEN
BEGIN
IF (transferrec OR soncount > 0) THEN Stack.Dup[load: FALSE];
base ← P5L.TOSComponent[1];
END
ELSE base ← tbase;
offset ← toffset;
END;
P5L.FieldOfComponent[
var: @offset, wd: posn.wd, bd: posn.bd,
wSize: size/wordlength, bSize: size MOD wordlength];
IF fa # FnField
AND totalBits <= wordlength
THEN
P5L.AdjustComponent[var: @offset, rSei: tsei, fSei: sei, tBits: totalBits];
IF onStack THEN rr ← P5L.OVarItem[offset]
ELSE
BEGIN
rr ← P5L.GenVarItem[bo];
cb[rr] ← [body: bo[base: base, offset: offset]];
END;
CPtr.xtractlex ← [bdo[rr]];
CPtr.xtractsei ← sei;
SELECT tb[subNode].name
FROM
assign => Assign[subNode];
extract => SExtract[subNode];
ENDCASE => ERROR;
END
ELSE IF onStack THEN Stack.Pop[size/wordlength];
sei ← P5U.PrevVar[startsei, sei];
RETURN
END; -- of ExtractItem
xlist: Tree.Link ← tb[node].son[1];
UNTIL (isei ← NextSe[sei]) = ISENull
DO
isei ← P5U.NextVar[isei];
IF isei = ISENull THEN EXIT;
sei ← isei;
ENDLOOP;
WITH cc: cb[r]
SELECT
FROM
o =>
WITH vv: cc.var
SELECT
FROM
stack =>
IF P5U.WordAligned[tsei]
THEN
BEGIN
trashOnStack ← vv.wd;
vv.wd ← 0;
toffset ← cc.var;
IF trashOnStack # 0
THEN
P5L.ModComponent[var: @toffset, wd: trashOnStack];
P5L.ReleaseVarItem[r];
onStack ← TRUE;
END
ELSE
BEGIN -- copy whole thing to temp
var: VarComponent ← P5L.CopyToTemp[r].var;
r ← P5L.OVarItem[var];
END;
ENDCASE;
ENDCASE;
IF ~onStack
THEN
BEGIN
bor: BoVarIndex ← P5L.MakeBo[r];
IF bor = VarNull
THEN
-- not addressable
BEGIN -- r was not freed in this case
var: VarComponent ← P5L.CopyToTemp[r].var;
r ← P5L.OVarItem[var];
bor ← P5L.MakeBo[r]; -- it will work this time
END;
tbase ← cb[bor].base; toffset ← cb[bor].offset;
P5L.ReleaseVarItem[bor];
IF tbase.wSize > 1 THEN tbase ← P5L.EasilyLoadable[tbase, store]
ELSE
IF ~P5L.EasyToLoad[tbase, store]
THEN
BEGIN
P5L.LoadComponent[tbase];
useDup ← TRUE;
END;
END;
totalBits ← toffset.wSize * wordlength + toffset.bSize;
TreeOps.ScanList[xlist, XCount];
IF soncount = 0
THEN
BEGIN
IF onStack
THEN
trashOnStack ← trashOnStack + (totalBits+(wordlength-1))/wordlength;
END
ELSE
BEGIN
CPtr.xtracting ← TRUE;
tb[node].son[1] ← TreeOps.ReverseUpdateList[xlist, ExtractItem];
END;
IF transferrec
THEN
BEGIN
IF ~useDup THEN P5L.LoadComponent[tbase];
P5U.Out0[FOpCodes.qFF];
END;
THROUGH [0..trashOnStack) DO Stack.Pop[] ENDLOOP;
[CPtr.xtracting, CPtr.xtractlex, CPtr.xtractsei] ← saveExtractState;
END;
ProbablyDumpStack:
PUBLIC
PROC [t: Tree.Link]
RETURNS [
BOOL] =
BEGIN -- only a hint
node: Tree.Index;
WITH t
SELECT
FROM
subtree => node ← index;
ENDCASE => RETURN [FALSE];
RETURN [
SELECT tb[node].name
FROM
loophole, pad, chop, uparrow, dot, dollar, not =>
ProbablyDumpStack[tb[node].son[1]],
and, or, plus, minus, times, div, mod,
index, dindex, seqindex =>
ProbablyDumpStack[tb[node].son[2]]
OR
ProbablyDumpStack[tb[node].son[1]],
ifx =>
ProbablyDumpStack[tb[node].son[3]]
OR
ProbablyDumpStack[tb[node].son[2]] OR
ProbablyDumpStack[tb[node].son[1]],
IN [relE..notin] =>
ProbablyDumpStack[tb[node].son[2]]
OR
ProbablyDumpStack[tb[node].son[1]],
IN [callx..joinx] => TRUE,
ENDCASE => FALSE]
END;