-- file Pass4.Mesa
-- last modified by Satterthwaite,  3-Nov-81 14:02:20

DIRECTORY
  Alloc: TYPE USING [Notifier, AddNotify, DropNotify],
  ComData: TYPE USING [matched, monitored, table, tC0, tC1, textIndex, zone],
  CompilerUtil: TYPE USING [],
  P4: TYPE USING [
    Repr, none,
    BCDNotify, DeclNotify, LayoutNotify,
    ExpANotify, ExpBNotify, ExpCNotify, OpsNotify, StmtNotify,
    AssignEntries, AssignImports, Body, DeclItem, ExpInit, ExpReset,
    FinishBCD, InitBCD, MatchBCD,
    ProcessDirectory, ProcessExports, ProcessImports, VarInit],
  Symbols: TYPE USING [
    Base, CSEIndex, RecordSEIndex, RecordSENull, RootBti, typeANY],
  Tree: TYPE USING [Base, Index, Link, NullIndex, treeType],
  TreeOps: TYPE USING [FreeNode, GetNode];

Pass4: PROGRAM
    IMPORTS
      Alloc, TreeOps, P4,
      dataPtr: ComData
    EXPORTS CompilerUtil = PUBLIC {
  OPEN TreeOps, Symbols;

  tb: Tree.Base;	-- tree base address (local copy)
  seb: Symbols.Base;	-- se table base (local copy)
  ctxb: Symbols.Base;	-- context table base (local copy)

  tTRUE: Tree.Link;
  tFALSE: Tree.Link;


  P4Notify: Alloc.Notifier = {
    -- called by allocator whenever table area is repacked
    tb ← base[Tree.treeType];
    P4.BCDNotify[base]; P4.DeclNotify[base];
    P4.LayoutNotify[base];
    P4.StmtNotify[base];
    P4.OpsNotify[base];
    P4.ExpANotify[base];  P4.ExpBNotify[base];  P4.ExpCNotify[base]};


 -- intermediate result bookkeeping

  returnRecord, resumeRecord: RecordSEIndex;

  implicitType: CSEIndex;		-- assumed type of empty
  implicitBias: INTEGER;		-- assumed bias of empty
  implicitRep: P4.Repr;	-- assumed representation of empty

  lockNode: Tree.Index;
  resident: BOOLEAN;

 -- overall control

  P4Unit: PROC [unit: Tree.Link] = {
    node: Tree.Index;
    (dataPtr.table).AddNotify[P4Notify];
    tTRUE ← dataPtr.tC1;  tFALSE ← dataPtr.tC0;
    node ← GetNode[unit];
    P4.ExpInit[dataPtr.zone];
    Module[node ! P4.VarInit => {RESUME [TRUE]}];
    P4.ExpReset[];
    FreeNode[node];
    (dataPtr.table).DropNotify[P4Notify]};

  Module: PRIVATE PROC [node: Tree.Index] = {
    subNode: Tree.Index = GetNode[tb[node].son[6]];
    saveIndex: CARDINAL = dataPtr.textIndex;
    implicitType ← typeANY;  implicitBias ← 0;  implicitRep ← P4.none;
    resumeRecord ← RecordSENull;
    dataPtr.textIndex ← tb[subNode].info;
    P4.InitBCD[tb[subNode].son[1], dataPtr.zone];
    dataPtr.textIndex ← tb[node].info;
    lockNode ← IF ~dataPtr.monitored THEN Tree.NullIndex ELSE GetNode[tb[node].son[5]];
    resident ← tb[node].attr1;
    P4.AssignEntries[Symbols.RootBti];
    P4.AssignImports[tb[node].son[2]];
    P4.DeclItem[tb[node].son[6]];
    P4.Body[Symbols.RootBti];
    P4.ProcessDirectory[tb[node].son[1]];
    P4.ProcessImports[tb[node].son[2]];
    tb[node].son[3] ← P4.ProcessExports[tb[node].son[3]];
    P4.FinishBCD[tb[subNode].son[1]];
    IF dataPtr.matched THEN dataPtr.matched ← P4.MatchBCD[];
    dataPtr.textIndex ← saveIndex};

  }.