-- file Temp.mesa
-- last modified by Sweet, November 19, 1979  10:20 PM

DIRECTORY
  AltoDefs: FROM "altodefs" USING [BYTE, wordlength],
  Code: FROM "code" USING [
    bodyComRetLabel, bodyOutRecord, bodyRetLabel, curctxlvl, fileindex, 
    framesz, inlineFileIndex, mainBody, tempcontext, tempstart],
  CodeDefs: FROM "codedefs" USING [
    Lexeme, StackIndex, StatementStateRecord, TempStateRecord],
  ComData: FROM "comdata" USING [bodyIndex, mainCtx, objectFrameSize],
  ControlDefs: FROM "controldefs" USING [MaxFrameSize],
  FOpCodes: FROM "fopcodes" USING [qFREE],
  Log: FROM "log" USING [ErrorSei],
  P5: FROM "p5" USING [PushLex],
  P5U: FROM "p5u" USING [LabelAlloc, Out0],
  Stack: FROM "stack" USING [Dump, New, Prefix],
  StringDefs: FROM "stringdefs" USING [WordsForString],
  SymbolOps: FROM "symbolops" USING [NewCtx, NextSe, SetSeLink],
  Symbols: FROM "symbols" USING [
    BitAddress, bodyType, ContextLevel, CSEIndex, CTXIndex, ctxType, HTIndex, 
    HTNull, ISEIndex, ISENull, lG, lZ, SEIndex, SENull, SERecord, seType, 
    typeANY],
  Table: FROM "table" USING [Allocate, Base, Notifier],
  Tree: FROM "tree" USING [treeType];


Temp: PROGRAM
    IMPORTS MPtr: ComData, CPtr: Code, P5U, Log, P5, Stack,
      StringDefs, SymbolOps, Table 
    EXPORTS CodeDefs, P5 =
  BEGIN
  OPEN CodeDefs;


  -- imported definitions

  BYTE: TYPE = AltoDefs.BYTE;
  wordlength: CARDINAL = AltoDefs.wordlength;

  BitAddress: TYPE = Symbols.BitAddress;
  ContextLevel: TYPE = Symbols.ContextLevel;
  CSEIndex: TYPE = Symbols.CSEIndex;
  CTXIndex: TYPE = Symbols.CTXIndex;
  HTIndex: TYPE = Symbols.HTIndex;
  HTNull: HTIndex = Symbols.HTNull;
  ISEIndex: TYPE = Symbols.ISEIndex;
  ISENull: ISEIndex = Symbols.ISENull;
  lZ: ContextLevel = Symbols.lZ;
  lG: ContextLevel = Symbols.lG;
  SEIndex: TYPE = Symbols.SEIndex;
  SENull: SEIndex = Symbols.SENull;
  SERecord: TYPE = Symbols.SERecord;
  typeANY: CSEIndex = Symbols.typeANY;


  InvalidHeapRelease: SIGNAL = CODE;
  InvalidTempRelease: SIGNAL = CODE;

  seb: Table.Base;		-- semantic entry base (local copy)
  ctxb: Table.Base;		-- context entry base (local copy)
  cb: Table.Base;		-- code base (local copy)
  bb: Table.Base;		-- body table base (local copy)

  TempNotify:  PUBLIC Table.Notifier =
    BEGIN  -- called by allocator whenever table area is repacked
    seb ← base[Symbols.seType];
    ctxb ← base[Symbols.ctxType];
    cb ← base[Tree.treeType];
    bb ← base[Symbols.bodyType];
    RETURN
    END;


  pendTempList, tempListPool, heapList: ISEIndex;

  TempInit: PUBLIC PROCEDURE =
    BEGIN -- called at beginning of MODULE to init stack stuff
    pendTempList ← tempListPool ← heapList ← ISENull;
    CPtr.tempcontext ← SymbolOps.NewCtx[lZ];
    RETURN
    END;



  PushTempState: PUBLIC PROCEDURE [p: POINTER TO TempStateRecord, newfs: CARDINAL] =
    BEGIN
    p↑ ← TempStateRecord[pendtemplist: pendTempList, templist: ISENull,
	    heaplist: heapList, tempctxlvl: ctxb[CPtr.tempcontext].level,
	    tempstart: CPtr.tempstart, framesz: CPtr.framesz];
    pendTempList ← heapList ← ISENull;
    ctxb[CPtr.tempcontext].level ← CPtr.curctxlvl;
    CPtr.tempstart ← CPtr.framesz ← newfs;
    RETURN
    END;



  PopTempState:  PUBLIC PROCEDURE [p: POINTER TO TempStateRecord] =
    BEGIN
    PurgePendTempList[];
    [pendtemplist: pendTempList, templist: ,
      heaplist: heapList, tempctxlvl: ctxb[CPtr.tempcontext].level,
      tempstart: CPtr.tempstart, framesz: CPtr.framesz] ← p↑;
    RETURN
    END;


  PushStatementState: PUBLIC PROCEDURE [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;
    RETURN
    END;



  PopStatementState:  PUBLIC PROCEDURE [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];
    RETURN
    END;


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


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


  GenStringBodyLex:  PUBLIC PROCEDURE [nchars: CARDINAL] RETURNS [l: se Lexeme] =
    BEGIN
    nwords: CARDINAL ← StringDefs.WordsForString[nchars];
    IF ~CPtr.mainBody THEN RETURN [GenAnonLex[nwords]];
    l ← CreateTempLex[MPtr.objectFrameSize, nwords];
    seb[l.lexsei].idCtx ← MPtr.mainCtx;
    MPtr.objectFrameSize ← MPtr.objectFrameSize + nwords;
    RETURN
    END;


  BumpTemps: PROCEDURE [n: CARDINAL] =
    BEGIN -- updates CPtr.tempstart (and CPtr.framesz, if necessary)
    CPtr.framesz ← MAX[CPtr.tempstart ← CPtr.tempstart+n, CPtr.framesz];
    IF CPtr.framesz > ControlDefs.MaxFrameSize THEN
      Log.ErrorSei[addressOverflow, bb[MPtr.bodyIndex].id];
    RETURN
    END;


  PurgePendTempList:  PUBLIC PROCEDURE =
    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;
    RETURN
    END;


  PurgeHeapList: PUBLIC PROCEDURE[oldheaplist: ISEIndex] =
    BEGIN -- after each statment the heap chunks are freed
    sei: ISEIndex ← heapList;
    nsei: ISEIndex;
    l: se Lexeme ← Lexeme[se[NULL]];

    WHILE sei # ISENull DO
      nsei ← SymbolOps.NextSe[sei];
      l.lexsei ← sei;
      FreeHeapLex[l];
      sei ← nsei;
      ENDLOOP;
    heapList ← oldheaplist;
    RETURN
    END;


  FreeHeapLex: PUBLIC PROCEDURE [l: se Lexeme] =
    BEGIN
    P5.PushLex[l];
    P5U.Out0[FOpCodes.qFREE];
    ReleaseTempSei[l.lexsei];
    RETURN
    END;

  PushHeapList: PUBLIC PROCEDURE RETURNS[oldheaplist: ISEIndex] =
    BEGIN
    oldheaplist ← heapList;
    heapList ← ISENull;
    RETURN
    END;


  GenHeapLex: PUBLIC PROCEDURE RETURNS[l: se Lexeme] =
    BEGIN
    l ← GenAnonLex[1];
    SymbolOps.SetSeLink[l.lexsei, heapList];
    heapList ← l.lexsei;
    RETURN
    END;


  FreeTempSei: PUBLIC PROCEDURE [sei: ISEIndex] =
    BEGIN -- de-links a temp sei from its chain
    SymbolOps.SetSeLink[sei, tempListPool];
    tempListPool ← sei;
    RETURN
    END;


  ReleaseTempSei:  PROCEDURE [sei: ISEIndex] =
    BEGIN -- puts a temp sei on the templist
    a: BitAddress ← seb[sei].idValue;

    CPtr.tempstart ← MIN[CPtr.tempstart, a.wd];
    FreeTempSei[sei];
    RETURN
    END;


  CreateTempLex: PROCEDURE [wdoffset, nwords: INTEGER] RETURNS [l: se Lexeme] =
    BEGIN -- inits (if nec) a new temp sei cell
    sei: ISEIndex;
    a: BitAddress;

    IF tempListPool # SENull THEN
      BEGIN
      sei ← tempListPool;
      tempListPool ← SymbolOps.NextSe[sei];
      seb[sei].idCtx ← CPtr.tempcontext;
      END
    ELSE
      BEGIN
      sei ← Table.Allocate[Symbols.seType, SIZE[linked id SERecord]];
      seb[sei] ← SERecord[mark3: , mark4: ,
	body: id[extended: FALSE, public: , immutable: TRUE, linkSpace: FALSE,
	constant: FALSE, idCtx: CPtr.tempcontext, hash:HTNull , 
	idType: typeANY, idInfo: , idValue: , ctxLink: linked[LOOPHOLE[0]]]];
      END;
    SymbolOps.SetSeLink[sei, LOOPHOLE[0]];
    a ← BitAddress[wd: wdoffset, bd: 0];
    seb[sei].idValue ← a;
    seb[sei].idInfo ← nwords*wordlength;
    l ← Lexeme[se[lexsei: sei]];
    RETURN
    END;


  ReleaseTempLex: PUBLIC PROCEDURE [l: se Lexeme] =
    BEGIN -- releases a cell of temporary storage
    IF SymbolOps.NextSe[l.lexsei] # LOOPHOLE[0, ISEIndex] THEN RETURN;
    SymbolOps.SetSeLink[l.lexsei, pendTempList];
    pendTempList ← l.lexsei;
    RETURN
    END;

END...