juno-compiler/src/JunoAST.m3


 Copyright (C) 1992, Digital Equipment Corporation                         
 All rights reserved.                                                      
 See the file COPYRIGHT for a full description.                            
                                                                           
 Last modified on Mon Oct 31 10:06:18 PST 1994 by heydon                   
      modified on Fri Aug  7 21:54:02 PDT 1992 by myers                    

MODULE JunoAST;

IMPORT JunoASTUtils;
IMPORT Atom;

TYPE (* declare special Nil types *)
  NilExprT = Expr BRANDED "JunoAST.NilExprT" OBJECT END;

REVEAL
  T = TPub BRANDED "JunoAST.T" OBJECT OVERRIDES
    iterator := EmptyIt
  END;
  Assign = AssignPub BRANDED "JunoAST.Assign" OBJECT OVERRIDES
    iterator := AssignIt
  END;
  ProcCall = ProcCallPub BRANDED "JunoAST.ProcCall" OBJECT OVERRIDES
    iterator := ProcCallIt
  END;
  BodyCmd = BodyCmdPub BRANDED "JunoAST.BodyCmd" OBJECT OVERRIDES
    iterator := BodyCmdIt
  END;
  Proj = ProjPub BRANDED "JunoAST.Proj" OBJECT OVERRIDES
    iterator := ProjIt
  END;
  Guard = GuardPub BRANDED "JunoAST.Guard" OBJECT OVERRIDES
    iterator := GuardIt
  END;
  TwoCmd = TwoCmdPub BRANDED "JunoAST.TwoCmd" OBJECT OVERRIDES
    iterator := TwoCmdIt
  END;
  Query = QueryPub BRANDED "JunoAST.Query" OBJECT OVERRIDES
    iterator := QueryIt
  END;
  TwoForm = TwoFormPub BRANDED "JunoAST.TwoForm" OBJECT OVERRIDES
    iterator := TwoFormIt
  END;
  Not = NotPub BRANDED "JunoAST.Not" OBJECT OVERRIDES
    iterator := NotIt
  END;
  Exists = ExistsPub BRANDED "JunoAST.Exists" OBJECT OVERRIDES
    iterator := ExistsIt
  END;
  BIUPred = BIUPredPub BRANDED "JunoAST.BIUPred" OBJECT OVERRIDES
    iterator := BIUPredIt
  END;
  Relation = RelationPub BRANDED "JunoAST.Relation" OBJECT OVERRIDES
    iterator := RelationIt
  END;
  BIUFunc = BIUFuncPub BRANDED "JunoAST.BIUFunc" OBJECT OVERRIDES
    iterator := BIUFuncIt
  END;
  BIBFunc = BIBFuncPub BRANDED "JunoAST.BIBFunc" OBJECT OVERRIDES
    iterator := BIBFuncIt
  END;
  List = ListPub BRANDED "JunoAST.List" OBJECT OVERRIDES
    iterator := ListIt
  END;
  Call = CallPub BRANDED "JunoAST.Call" OBJECT OVERRIDES
    iterator := CallIt
  END;
  ExprList = ExprListPub  BRANDED "JunoAST.ExprList" OBJECT OVERRIDES
    iterator := ExprListIt
  END;
  ConjQuery = ConjQueryPub BRANDED "JunoAST.ConjQuery" OBJECT OVERRIDES
    iterator := ConjQueryIt
  END;
  GroupedExpr = GroupedExprPub BRANDED "JunoAST.GroupedExpr" OBJECT OVERRIDES
    iterator := GroupedExprIt
  END;
  NormalForm = NormalFormPub BRANDED "JunoAST.NormalForm" OBJECT OVERRIDES
    iterator := NormalFormIt
  END;
  NearVarList = NearVarListPub BRANDED "JunoAST.NearVarList" OBJECT OVERRIDES
    iterator := NearVarListIt
  END;

TYPE
  FieldIter = Iterator BRANDED "JunoAST.FieldIter" OBJECT
    field := 0
  END;
  AssignIter = FieldIter BRANDED "JunoAST.AssignIter" OBJECT
    ast: Assign
  END;
  ProcCallIter = FieldIter BRANDED "JunoAST.ProcCallIter" OBJECT
    ast: ProcCall
  END;
  BodyCmdIter = FieldIter BRANDED "JunoAST.BodyCmdIter" OBJECT
    ast: BodyCmd
  END;
  ProjIter = FieldIter BRANDED "JunoAST.ProjIter" OBJECT
    ast: Proj
  END;
  GuardIter = FieldIter BRANDED "JunoAST.GuardIter" OBJECT
    ast: Guard
  END;
  TwoCmdIter = FieldIter BRANDED "JunoAST.TwoCmdIter" OBJECT
    ast: TwoCmd
  END;
  QueryIter = FieldIter BRANDED "JunoAST.QueryIter" OBJECT
    ast: Query
  END;
  TwoFormIter = FieldIter BRANDED "JunoAST.TwoFormIter" OBJECT
    ast: TwoForm
  END;
  NotIter = FieldIter BRANDED "JunoAST.NotIter" OBJECT
    ast: Not
  END;
  ExistsIter = FieldIter BRANDED "JunoAST.ExistsIter" OBJECT
    ast: Exists
  END;
  BIUPredIter = FieldIter BRANDED "JunoAST.BIUPredIter" OBJECT
    ast: BIUPred
  END;
  RelationIter = FieldIter BRANDED "JunoAST.RelationIter" OBJECT
    ast: Relation
  END;
  BIUFuncIter = FieldIter BRANDED "JunoAST.BIUFuncIter" OBJECT
    ast: BIUFunc
  END;
  BIBFuncIter = FieldIter BRANDED "JunoAST.BIBFuncIter" OBJECT
    ast: BIBFunc
  END;
  ExprListIter = Iterator BRANDED "JunoAST.ExprListIter" OBJECT
    curr: ExprLink
  END;
  CallIter = FieldIter BRANDED "JunoAST.CallIter" OBJECT
    ast: Call
  END;
  GrpExprIter = FieldIter BRANDED "JunoAST.GrpExprIter" OBJECT
    ast: GroupedExpr
  END;
  ConjQueryIter = Iterator BRANDED "JunoAST.ConjQueryIter" OBJECT
    forms: REF Formulas;
    curr := 0
  END;
  NormalFormIter = Iterator BRANDED "JunoAST.NormalFormIter" OBJECT
    forms: REF Formulas;
    curr := 0
  END;
  NVListIter = Iterator BRANDED "JunoAST.NVListIter" OBJECT
    curr: NearVarLink
  END;

PROCEDURE EmptyIt(<*UNUSED*> ast: T): Iterator =
  BEGIN RETURN NEW(Iterator, next := NoNext) END EmptyIt;

PROCEDURE NoNext(
    <*UNUSED*> it: Iterator;
    <*UNUSED*> VAR (*OUT*) child: T):
    BOOLEAN =
  BEGIN RETURN FALSE END NoNext;

PROCEDURE AssignIt(ast: Assign): Iterator =
  BEGIN RETURN NEW(AssignIter, ast := ast, next := AssignNext) END AssignIt;

PROCEDURE AssignNext(it: AssignIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.vars
    | 1 => child := it.ast.exprs
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END AssignNext;

PROCEDURE ProcCallIt(ast: ProcCall): Iterator =
  BEGIN
    RETURN NEW(ProcCallIter, ast := ast, next := ProcCallNext)
  END ProcCallIt;

PROCEDURE ProcCallNext(it: ProcCallIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.outs
    | 1 => child := it.ast.inouts
    | 2 => child := it.ast.name
    | 3 => child := it.ast.ins
    | 4 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END ProcCallNext;

PROCEDURE BodyCmdIt(ast: BodyCmd): Iterator =
  BEGIN RETURN NEW(BodyCmdIter, ast := ast, next := BodyCmdNext) END BodyCmdIt;

PROCEDURE BodyCmdNext(it: BodyCmdIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.body
    | 1 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END BodyCmdNext;

PROCEDURE ProjIt(ast: Proj): Iterator =
  BEGIN RETURN NEW(ProjIter, ast := ast, next := ProjNext) END ProjIt;

PROCEDURE ProjNext(it: ProjIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.vars
    | 1 => child := it.ast.body
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END ProjNext;

PROCEDURE GuardIt(ast: Guard): Iterator =
  BEGIN RETURN NEW(GuardIter, ast := ast, next := GuardNext) END GuardIt;

PROCEDURE GuardNext(it: GuardIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.grd
    | 1 => child := it.ast.body
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END GuardNext;

PROCEDURE TwoCmdIt(ast: TwoCmd): Iterator =
  BEGIN RETURN NEW(TwoCmdIter, ast := ast, next := TwoCmdNext) END TwoCmdIt;

PROCEDURE TwoCmdNext(it: TwoCmdIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.c1
    | 1 => child := it.ast.c2
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END TwoCmdNext;

PROCEDURE QueryIt(ast: Query): Iterator =
  BEGIN RETURN NEW(QueryIter, ast := ast, next := QueryNext) END QueryIt;

PROCEDURE QueryNext(it: QueryIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.f
    | 1 => child := it.ast.vars
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END QueryNext;

PROCEDURE ConjQueryIt(ast: ConjQuery): Iterator =
  BEGIN
    RETURN NEW(ConjQueryIter, forms := ast.conj, next := ConjQueryNext)
  END ConjQueryIt;

PROCEDURE ConjQueryNext(it: ConjQueryIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    IF it.curr > LAST(it.forms^) THEN RETURN FALSE END;
    child := it.forms[it.curr];
    INC(it.curr);
    RETURN TRUE
  END ConjQueryNext;

PROCEDURE TwoFormIt(ast: TwoForm): Iterator =
  BEGIN RETURN NEW(TwoFormIter, ast := ast, next := TwoFormNext) END TwoFormIt;

PROCEDURE TwoFormNext(it: TwoFormIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.f1
    | 1 => child := it.ast.f2
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END TwoFormNext;

PROCEDURE NotIt(ast: Not): Iterator =
  BEGIN RETURN NEW(NotIter, ast := ast, next := NotNext) END NotIt;

PROCEDURE NotNext(it: NotIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.f
    | 1 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END NotNext;

PROCEDURE ExistsIt(ast: Exists): Iterator =
  BEGIN RETURN NEW(ExistsIter, ast := ast, next := ExistsNext) END ExistsIt;

PROCEDURE ExistsNext(it: ExistsIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.vars
    | 1 => child := it.ast.f
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END ExistsNext;

PROCEDURE BIUPredIt(ast: BIUPred): Iterator =
  BEGIN RETURN NEW(BIUPredIter, ast := ast, next := BIUPredNext) END BIUPredIt;

PROCEDURE BIUPredNext(it: BIUPredIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.e
    | 1 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END BIUPredNext;

PROCEDURE RelationIt(ast: Relation): Iterator =
  BEGIN
    RETURN NEW(RelationIter, ast := ast, next := RelationNext)
  END RelationIt;

PROCEDURE RelationNext(it: RelationIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.e1
    | 1 => child := it.ast.e2
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END RelationNext;

PROCEDURE BIUFuncIt(ast: BIUFunc): Iterator =
  BEGIN RETURN NEW(BIUFuncIter, ast := ast, next := BIUFuncNext) END BIUFuncIt;

PROCEDURE BIUFuncNext(it: BIUFuncIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.e
    | 1 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END BIUFuncNext;

PROCEDURE BIBFuncIt(ast: BIBFunc): Iterator =
  BEGIN RETURN NEW(BIBFuncIter, ast := ast, next := BIBFuncNext) END BIBFuncIt;

PROCEDURE BIBFuncNext(it: BIBFuncIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.e1
    | 1 => child := it.ast.e2
    | 2 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END BIBFuncNext;

PROCEDURE ListIt(ast: List): Iterator =
  BEGIN
    RETURN NEW(ExprListIter, curr := ast.elts.head, next := ExprListNext)
  END ListIt;

PROCEDURE ExprListIt(ast: ExprList): Iterator =
  BEGIN
    RETURN NEW(ExprListIter, curr := ast.head, next := ExprListNext)
  END ExprListIt;

PROCEDURE ExprListNext(it: ExprListIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    IF it.curr = NIL THEN RETURN FALSE END;
    child := it.curr.expr;
    it.curr := it.curr.next;
    RETURN TRUE
  END ExprListNext;

PROCEDURE CallIt(ast: Call): Iterator =
  BEGIN RETURN NEW(CallIter, ast := ast, next := CallNext) END CallIt;

PROCEDURE CallNext(it: CallIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.inouts
    | 1 => child := it.ast.name
    | 2 => child := it.ast.ins
    | 3 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END CallNext;

PROCEDURE GroupedExprIt(ast: GroupedExpr): Iterator =
  BEGIN
    RETURN NEW(GrpExprIter, ast := ast, next := GroupedExprNext)
  END GroupedExprIt;

PROCEDURE GroupedExprNext(it: GrpExprIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    CASE it.field OF <* NOWARN *>
      0 => child := it.ast.expr
    | 1 => RETURN FALSE
    END;
    INC(it.field);
    RETURN TRUE
  END GroupedExprNext;

PROCEDURE NormalFormIt(ast: NormalForm): Iterator =
  BEGIN
    RETURN NEW(NormalFormIter, forms := ast.conj, next := NormalFormNext)
  END NormalFormIt;

PROCEDURE NormalFormNext(it: NormalFormIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    IF it.curr > LAST(it.forms^) THEN RETURN FALSE END;
    child := it.forms[it.curr];
    INC(it.curr);
    RETURN TRUE
  END NormalFormNext;

PROCEDURE NearVarListIt(ast: NearVarList): Iterator =
  BEGIN
    RETURN NEW(NVListIter, curr := ast.head, next := NearVarListNext)
  END NearVarListIt;

PROCEDURE NearVarListNext(it: NVListIter; VAR (*OUT*) child: T): BOOLEAN =
  BEGIN
    IF it.curr = NIL THEN RETURN FALSE END;
    child := it.curr.hint;
    it.curr := it.curr.next;
    RETURN TRUE
  END NearVarListNext;

REVEAL
  Block = T BRANDED "JunoAST.Block" OBJECT END;
  Decl = DeclPublic BRANDED "JunoAST.Decl" OBJECT END;
  Cmd = T BRANDED "JunoAST.Cmd" OBJECT END;
  LitPred = Formula BRANDED "JunoAST.LitPred" OBJECT END;
  AtomicExpr = Expr BRANDED "JunoAST.AtomicExpr" OBJECT END;
  BuiltInPred = Expr BRANDED "JunoAST.BuiltInPred" OBJECT END;
  BuiltInFunc = Expr BRANDED "JunoAST.BuiltInFunc" OBJECT END;

PROCEDURE Predecessor(ast: T): T =
  VAR node: T := ast; BEGIN
    WHILE node # NIL AND node.bp # End DO node := node.bp END;
    <* ASSERT node = NIL OR node.bp = End *>
    RETURN node
  END Predecessor;

BEGIN
  (* Initialize special Nil variables *)
  NilId   := Atom.FromText("*NilId*");
  NilExpr := NEW(NilExprT);

  (* Initialize empty lists *)
  EmptyIdList := NEW(IdList);
  EmptyNVList := NEW(NearVarList);
  EmptyQIdList := NEW(QIdList);
  EmptyExprList := EmptyQIdList;

  (* Initialize constant structures *)
  End := NEW(T);
  SkipVal  := NEW(Skip,  bp := End);
  AbortVal := NEW(Abort, bp := End);
  HaltVal  := NEW(Halt,  bp := End);
  FailVal  := NEW(Fail,  bp := End);
  TrueVal  := NEW(True,  bp := End);
  FalseVal := NEW(False, bp := End);
  NilVal   := NEW(Nil,   bp := End);

  (* Initialize pred and func names *)
  CongName   := JunoASTUtils.QIdFromText("_CONG");
  ParaName   := JunoASTUtils.QIdFromText("_PARA");
  HorName    := JunoASTUtils.QIdFromText("_HOR");
  VerName    := JunoASTUtils.QIdFromText("_VER");
  UMinusName := JunoASTUtils.QIdFromText("_UMINUS");
  CarName    := JunoASTUtils.QIdFromText("_CAR");
  CdrName    := JunoASTUtils.QIdFromText("_CDR");
  MinusName  := JunoASTUtils.QIdFromText("_MINUS");
  DivideName := JunoASTUtils.QIdFromText("_DIVIDE");
  RelName    := JunoASTUtils.QIdFromText("_REL");
END JunoAST.