DIRECTORY
Alloc: TYPE USING [Notifier],
Code:
TYPE
USING [
bodyComRetLabel, bodyOutRecord, bodyRetLabel, curctxlvl, fileindex,
firstTemp, framesz, inlineFileIndex, mainBody, tempcontext, tempstart],
CodeDefs:
TYPE
USING [
Base, codeType, Lexeme, StackIndex, StatementStateRecord, TempStateRecord],
ComData: TYPE USING [bodyIndex, globalFrameSize, mainCtx],
FOpCodes: TYPE USING [qFREE],
Log: TYPE USING [Error, ErrorSei],
P5: TYPE USING [PushLex],
P5U: TYPE USING [LabelAlloc, Out0, WordsForString],
PrincOps: TYPE USING [MaxFrameSize],
Stack: TYPE USING [Dump, New, Prefix],
SymbolOps: TYPE USING [MakeCtxSe, NewCtx, NextSe, SetSeLink],
Symbols:
TYPE
USING [
Base, BitAddress, bodyType, CTXNull, ctxType, HTNull, ISEIndex, ISENull, lZ,
seType, typeANY, WordLength];
Temp:
PROGRAM
IMPORTS MPtr: ComData, CPtr: Code, P5U, Log, P5, Stack, SymbolOps
EXPORTS CodeDefs, P5 =
BEGIN
OPEN CodeDefs;
imported definitions
BitAddress: TYPE = Symbols.BitAddress;
ISEIndex: TYPE = Symbols.ISEIndex;
ISENull: ISEIndex = Symbols.ISENull;
WordLength: CARDINAL = Symbols.WordLength;
InvalidHeapRelease: SIGNAL = CODE;
InvalidTempRelease: SIGNAL = CODE;
seb: Symbols.Base; -- semantic entry base (local copy)
ctxb: Symbols.Base; -- context entry base (local copy)
cb: CodeDefs.Base; -- code base (local copy)
bb: Symbols.Base; -- body table base (local copy)
TempNotify:
PUBLIC Alloc.Notifier =
BEGIN -- called by allocator whenever table area is repacked
seb ← base[Symbols.seType];
ctxb ← base[Symbols.ctxType];
cb ← base[codeType];
bb ← base[Symbols.bodyType];
END;
pendTempList, tempListPool, heapList: ISEIndex;
TempInit:
PUBLIC
PROC =
BEGIN -- called at beginning of MODULE to init stack stuff
pendTempList ← tempListPool ← heapList ← ISENull;
CPtr.tempcontext ← SymbolOps.NewCtx[Symbols.lZ];
END;
PushTempState:
PUBLIC
PROC [p:
POINTER
TO TempStateRecord, newfs:
CARDINAL] =
BEGIN
p^ ← [pendtemplist: pendTempList, templist: ISENull,
heaplist: heapList, tempctxlvl: ctxb[CPtr.tempcontext].level,
firstTemp: CPtr.firstTemp, tempstart: CPtr.tempstart,
framesz: CPtr.framesz];
pendTempList ← heapList ← ISENull;
ctxb[CPtr.tempcontext].level ← CPtr.curctxlvl;
CPtr.firstTemp ← CPtr.tempstart ← CPtr.framesz ← newfs;
END;
PopTempState:
PUBLIC
PROC [p:
POINTER
TO TempStateRecord] =
BEGIN
PurgePendTempList[];
[pendtemplist: pendTempList, templist: ,
heaplist: heapList, tempctxlvl: ctxb[CPtr.tempcontext].level,
tempstart: CPtr.tempstart, firstTemp: CPtr.firstTemp,
framesz: CPtr.framesz] ← p^;
END;
PushStatementState:
PUBLIC
PROC [p:
POINTER
TO StatementStateRecord] =
BEGIN
Stack.Dump[];
p^ ← [retLabel: CPtr.bodyRetLabel,
comRetLabel: CPtr.bodyComRetLabel,
outRecord: CPtr.bodyOutRecord,
pendtemplist: pendTempList,
stkPtr: Stack.New[],
inlineFileIndex: CPtr.inlineFileIndex];
CPtr.bodyRetLabel ← P5U.LabelAlloc[];
CPtr.bodyComRetLabel ← P5U.LabelAlloc[];
pendTempList ← ISENull;
CPtr.inlineFileIndex ← CPtr.fileindex;
END;
PopStatementState:
PUBLIC
PROC [p:
POINTER
TO StatementStateRecord] =
BEGIN
sp: StackIndex;
PurgePendTempList[];
[retLabel: CPtr.bodyRetLabel,
comRetLabel: CPtr.bodyComRetLabel,
pendtemplist: pendTempList,
outRecord: CPtr.bodyOutRecord,
stkPtr: sp,
inlineFileIndex: CPtr.inlineFileIndex] ← p^;
Stack.Prefix[sp];
END;
GenTempLex:
PUBLIC
PROC [nwords:
CARDINAL]
RETURNS [l: se Lexeme] =
BEGIN
l ← CreateTempLex[CPtr.tempstart, nwords];
ReleaseTempLex[l];
BumpTemps[nwords];
RETURN
END;
GenAnonLex:
PUBLIC
PROC [nwords:
CARDINAL]
RETURNS [l: se Lexeme] =
BEGIN
l ← CreateTempLex[CPtr.tempstart, nwords];
BumpTemps[nwords];
RETURN
END;
GenStringBodyLex:
PUBLIC
PROC [nchars:
CARDINAL]
RETURNS [l: se Lexeme] =
BEGIN
nwords: CARDINAL = P5U.WordsForString[nchars];
IF ~CPtr.mainBody THEN l ← GenAnonLex[nwords]
ELSE
BEGIN
l ← CreateTempLex[MPtr.globalFrameSize, nwords];
seb[l.lexsei].idCtx ← MPtr.mainCtx;
MPtr.globalFrameSize ← MPtr.globalFrameSize + nwords;
IF MPtr.globalFrameSize > PrincOps.MaxFrameSize
THEN
Log.Error[addressOverflow];
END;
RETURN
END;
BumpTemps:
PROC [n:
CARDINAL] =
BEGIN -- updates CPtr.tempstart (and CPtr.framesz, if necessary)
CPtr.framesz ← MAX[CPtr.tempstart ← CPtr.tempstart+n, CPtr.framesz];
IF CPtr.framesz > PrincOps.MaxFrameSize
THEN
Log.ErrorSei[addressOverflow, bb[MPtr.bodyIndex].id];
END;
PurgePendTempList:
PUBLIC
PROC =
BEGIN -- after each statment the temp sei's are released
sei: ISEIndex ← pendTempList;
nSei: ISEIndex;
WHILE sei # ISENull
DO
nSei ← SymbolOps.NextSe[sei];
ReleaseTempSei[sei];
sei ← nSei;
ENDLOOP;
pendTempList ← ISENull;
END;
PurgeHeapList:
PUBLIC
PROC [oldheaplist: ISEIndex] =
BEGIN -- after each statment the heap chunks are freed
sei: ISEIndex ← heapList;
nSei: ISEIndex;
l: se Lexeme ← Lexeme[se[TRASH]];
WHILE sei # ISENull
DO
nSei ← SymbolOps.NextSe[sei];
l.lexsei ← sei;
FreeHeapLex[l];
sei ← nSei;
ENDLOOP;
heapList ← oldheaplist;
END;
FreeHeapLex:
PUBLIC
PROC [l: se Lexeme] =
BEGIN
P5.PushLex[l];
P5U.Out0[FOpCodes.qFREE];
ReleaseTempSei[l.lexsei];
END;
PushHeapList:
PUBLIC
PROC
RETURNS [oldheaplist: ISEIndex] =
BEGIN
oldheaplist ← heapList;
heapList ← ISENull;
RETURN
END;
GenHeapLex:
PUBLIC
PROC
RETURNS [l: se Lexeme] =
BEGIN
l ← GenAnonLex[1];
SymbolOps.SetSeLink[l.lexsei, heapList];
heapList ← l.lexsei;
RETURN
END;
FreeTempSei:
PUBLIC
PROC [sei: ISEIndex] =
BEGIN -- de-links a temp sei from its chain
SymbolOps.SetSeLink[sei, tempListPool];
tempListPool ← sei;
END;
ReleaseTempSei:
PROC [sei: ISEIndex] =
BEGIN -- puts a temp sei on the templist
a: BitAddress = seb[sei].idValue;
CPtr.tempstart ← MIN[CPtr.tempstart, a.wd];
FreeTempSei[sei];
END;
CreateTempLex:
PUBLIC
PROC [wdoffset, nwords:
INTEGER]
RETURNS [se Lexeme] =
BEGIN -- inits (if nec) a new temp sei cell
sei: ISEIndex;
IF tempListPool # ISENull
THEN
BEGIN
sei ← tempListPool;
tempListPool ← SymbolOps.NextSe[sei];
seb[sei].idCtx ← CPtr.tempcontext;
END
ELSE
BEGIN
sei ← SymbolOps.MakeCtxSe[Symbols.HTNull, Symbols.CTXNull];
seb[sei].constant ← seb[sei].extended ← seb[sei].linkSpace ← FALSE;
seb[sei].immutable ← TRUE;
seb[sei].idCtx ← CPtr.tempcontext;
seb[sei].idType ← Symbols.typeANY;
END;
SymbolOps.SetSeLink[sei, ISENull];
seb[sei].idValue ← BitAddress[wd: wdoffset, bd: 0];
seb[sei].idInfo ← nwords*WordLength;
RETURN [[se[lexsei: sei]]]
END;
ReleaseTempLex:
PUBLIC
PROC [l: se Lexeme] =
BEGIN -- releases a cell of temporary storage
IF SymbolOps.NextSe[l.lexsei] = ISENull
THEN
BEGIN
SymbolOps.SetSeLink[l.lexsei, pendTempList];
pendTempList ← l.lexsei;
END;
END;
END.