
<<file Temp.mesa>>
<<last modified by Sweet, 9-Oct-81 11:38:06>>
<<last modified by Satterthwaite, April 18, 1986 2:30:00 pm PST>>

DIRECTORY
Alloc: TYPE USING [Notifier],
Code: TYPE USING [
bodyComRetLabel, bodyOutRecord, bodyRetLabel, curctxlvl, fileLoc, 
firstTemp, framesz, inlineFileLoc, mainBody, tempcontext, tempstart],
CodeDefs: TYPE USING [
Base, codeType, Lexeme, FrameStateRecord, StackIndex, StatementStateRecord, TempStateRecord],
ComData: TYPE USING [bodyIndex, globalFrameSize, mainCtx],
FOpCodes: TYPE USING [qFF],
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 [CtxLevel, MakeCtxSe, NewCtx, NextSe, SetCtxLevel, SetSeLink],
Symbols: TYPE USING [
Base, BitAddress, bodyType, ContextLevel, 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 RETURNS [p: TempStateRecord] =
        BEGIN
        p.heaplist _ PushHeapList[];
        p.pendtemplist _ pendTempList;  pendTempList _ ISENull;
        RETURN
        END;

    PopTempState:  PUBLIC PROC [p: TempStateRecord] =
        BEGIN
        PurgePendTempList[];
        PurgeHeapList[p.heaplist];
        pendTempList _ p.pendtemplist;
        END;


PushFrameState: PUBLIC PROC [p: POINTER TO FrameStateRecord, newfs: CARDINAL] =
BEGIN
p^ _ [pendtemplist: pendTempList,
heaplist: heapList, tempctxlvl: SymbolOps.CtxLevel[CPtr.tempcontext],
firstTemp: CPtr.firstTemp, tempstart: CPtr.tempstart,
framesz: CPtr.framesz];
pendTempList _ heapList _ ISENull;
SymbolOps.SetCtxLevel[CPtr.tempcontext, CPtr.curctxlvl];
CPtr.firstTemp _ CPtr.tempstart _ CPtr.framesz _ newfs;
END;

PopFrameState:  PUBLIC PROC [p: POINTER TO FrameStateRecord] =
BEGIN
tctxlvl: Symbols.ContextLevel;
PurgePendTempList[];
[pendtemplist: pendTempList,
heaplist: heapList, tempctxlvl: tctxlvl,
tempstart: CPtr.tempstart, firstTemp: CPtr.firstTemp,
framesz: CPtr.framesz] _ p^;
SymbolOps.SetCtxLevel[CPtr.tempcontext, tctxlvl];
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[], 
inlineFileLoc: CPtr.inlineFileLoc];
CPtr.bodyRetLabel _ P5U.LabelAlloc[];
CPtr.bodyComRetLabel _ P5U.LabelAlloc[];
pendTempList _ ISENull;
CPtr.inlineFileLoc _ CPtr.fileLoc;
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,
inlineFileLoc: CPtr.inlineFileLoc] _ p^;
Stack.Prefix[sp];
END;


GenTempLex:  PUBLIC PROC [nwords: CARDINAL] RETURNS [l: Lexeme.se] =
BEGIN
l _ CreateTempLex[CPtr.tempstart, nwords];
ReleaseTempLex[l];
BumpTemps[nwords];
RETURN
END;


GenAnonLex:  PUBLIC PROC [nwords: CARDINAL] RETURNS [l: Lexeme.se] =
BEGIN
l _ CreateTempLex[CPtr.tempstart, nwords];
BumpTemps[nwords];
RETURN
END;


GenStringBodyLex:  PUBLIC PROC [nchars: CARDINAL] RETURNS [l: Lexeme.se] =
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: Lexeme.se _ 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: Lexeme.se] =
BEGIN
P5.PushLex[l];
P5U.Out0[FOpCodes.qFF];
ReleaseTempSei[l.lexsei];
END;

PushHeapList: PUBLIC PROC RETURNS [oldheaplist: ISEIndex] =
BEGIN
oldheaplist _ heapList;
heapList _ ISENull;
RETURN
END;


GenHeapLex: PUBLIC PROC RETURNS [l: Lexeme.se] =
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 [Lexeme.se] =
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: Lexeme.se] =
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.

