-- FakeCompiler.mesa
-- Last edited by Bruce;  13-Jan-81 16:56:24
-- Last edited by Lewis on 13-Jan-81 17:12:26
-- Last edited by Sweet on 13-Feb-81 15:07:17
-- Last edited by Satterthwaite on  5-May-82 15:50:32

DIRECTORY
  Alloc: TYPE USING [Base, Index, Handle, Notifier, OrderedIndex, Selector],
  CBinary: TYPE USING [DebugTab],
  CharIO: TYPE USING [Handle],
  CompilerUtil: TYPE USING [StreamId, TableId],
  ListerDefs: TYPE USING [AddNotify, Bounds, DropNotify],
  OutputDefs: TYPE USING [GetOutputStream, PutChar, PutDecimal, PutOctal, PutLongString],
  Runtime: TYPE USING [GetTableBase, GlobalFrame],
  Stream: TYPE USING [Handle],
  Strings: TYPE USING [String],
  Tree: TYPE USING [Base, Index, Link, Node, Scan, Null, NullIndex, treeType],
  TreeOps: TYPE USING [];

FakeCompiler: PROGRAM
    IMPORTS CBinary, ListerDefs, OutputDefs, Runtime 
    EXPORTS CompilerUtil, CharIO, Alloc, TreeOps = { 
  
-- TreeOps

  EndIndex: Tree.Index = LAST[Tree.Index];
  EndMark: Tree.Link = [subtree[index: EndIndex]];

  tb: PRIVATE Tree.Base;		-- tree base

  UpdateBase: PRIVATE Alloc.Notifier = {tb ← base[Tree.treeType]};

  Initialize: PUBLIC PROC [Alloc.Handle, UNCOUNTED ZONE] = {
    AddNotify[NIL, UpdateBase]};
  Finalize: PUBLIC PROC = {DropNotify[NIL, UpdateBase]};
  
  ScanSons: PUBLIC PROC [root: Tree.Link, action: Tree.Scan] = {
    IF root # Tree.Null THEN
      WITH root SELECT FROM
	subtree => {
	  node: Tree.Index = index;
	  FOR i: CARDINAL IN [1 .. SonCount[node]] DO
	    action[tb[node].son[i]] ENDLOOP};
	ENDCASE;
    RETURN};

  SonCount: PRIVATE PROC [node: Tree.Index] RETURNS [CARDINAL] = {
    RETURN [SELECT node FROM
      Tree.NullIndex, EndIndex => 0,
      ENDCASE => IF tb[node].name = list AND tb[node].nSons = 0
	THEN ListLength[[subtree[index: node]]] + 1
	ELSE tb[node].nSons]};

  ListLength: PUBLIC PROC [t: Tree.Link] RETURNS [CARDINAL] = {
    IF t = Tree.Null THEN RETURN [0];
    WITH t SELECT FROM
      subtree => {
	node: Tree.Index = index;
	n: CARDINAL;
	IF tb[node].name # list THEN RETURN [1];
	n ← tb[node].nSons;
	IF n # 0 THEN RETURN [n];
	FOR i: CARDINAL ← 1, i+1 UNTIL tb[node].son[i] = EndMark DO
	  n ← n+1 ENDLOOP;
	RETURN [n]};
      ENDCASE => RETURN [1]};

  GetNode: PUBLIC PROC [t: Tree.Link] RETURNS [Tree.Index] = {
    RETURN [WITH t SELECT FROM subtree => index, ENDCASE => ERROR]};

-- Alloc

  Failure: PUBLIC ERROR [h: Alloc.Handle, table: Alloc.Selector] = CODE;

  GetChunk: PUBLIC PROC [h: Alloc.Handle, size: CARDINAL, table: Alloc.Selector]
      RETURNS [Alloc.Index] = {
    IF table # Tree.treeType OR size # SIZE[Tree.Node] THEN ERROR; -- called to reserve empty
    RETURN [FIRST[Alloc.Index]]};

  FreeChunk: PUBLIC PROC [
    h: Alloc.Handle, index: Alloc.Index, size: CARDINAL, table: Alloc.Selector] = {};

  Words: PUBLIC PROC [h: Alloc.Handle, table: Alloc.Selector, size: CARDINAL]
    RETURNS [Alloc.OrderedIndex] = {ERROR};

  AddNotify: PUBLIC PROC [h: Alloc.Handle, proc: Alloc.Notifier] = {
    ListerDefs.AddNotify[proc]};
  DropNotify: PUBLIC PROC [h: Alloc.Handle, proc: Alloc.Notifier] = {
    ListerDefs.DropNotify[proc]};
    
  Bounds: PUBLIC PROC [h: Alloc.Handle, table: Alloc.Selector]
      RETURNS [base: Alloc.Base, size: CARDINAL] = {
    [base, size] ← ListerDefs.Bounds[table]};

-- CompilerUtil

  AcquireTable: PUBLIC PROC [id: CompilerUtil.TableId] RETURNS [LONG POINTER] = {
    RETURN[
      IF id # debug THEN NIL
      ELSE Runtime.GetTableBase[Runtime.GlobalFrame[CBinary.DebugTab]]]};
    
  ReleaseTable: PUBLIC PROC [CompilerUtil.TableId] = {};

  AcquireStream: PUBLIC PROC [id: CompilerUtil.StreamId] RETURNS [Stream.Handle] = {
    RETURN[IF id = log THEN OutputDefs.GetOutputStream[] ELSE NIL]};
    
  ReleaseStream: PUBLIC PROC [CompilerUtil.StreamId] = {};    
  
-- CharIO
  
  PutDecimal: PUBLIC PROC [h: CharIO.Handle, i: INTEGER] = {OutputDefs.PutDecimal[i]};
    
  PutOctal: PUBLIC PROC [h: CharIO.Handle, u: UNSPECIFIED] = {OutputDefs.PutOctal[u]};
    
  PutString: PUBLIC PROC [h: CharIO.Handle, s: Strings.String] = {OutputDefs.PutLongString[s]};
  
  PutChar: PUBLIC PROC [out: CharIO.Handle, c: CHARACTER] = {OutputDefs.PutChar[c]};
    
  }.