| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- DEFINITION MODULE AST;
- (* Abstract syntax tree for m2compiler-V3 (Stage A: node store only).
- This is the foundation for a two-phase frontend: productions build
- nodes here while parsing, and a later walk resolves names and
- lowers to QBE. Until the grammar is converted, nothing calls it.
- Design notes
- ------------
- - Nodes live in a flat, pre-allocated arena and are referenced by an
- integer index (`Node`), exactly like `SymTab.TypeIndex`. This
- avoids pointers in the interface and keeps the structure
- self-hosting-friendly (no GC, bounded memory).
- - Every node has a `kind` (NKind) and a `ty` (a SymTab.TypeIndex set
- by the checker), plus up to `MaxChild` children. This mirrors the
- `armornick/CocoR` AST.java pattern (a Node base with per-construct
- subclasses) but flattened into one record array so Modula-2 can
- store it without variant-class machinery.
- - Text (identifiers, literals, operator spellings) is kept in a
- pooled string table; `TxtIndex` is an index into it.
- - `NoNode` is the null node. *)
- CONST
- NoNode = -1;
- NoTxt = -1;
- (* how many children a node may carry. Statements/expressions in
- Modula-2 nest shallowly (a body is a list, an expression is a
- spine); 8 covers every construct in the current grammar with room
- to spare. *)
- MaxChild = 8;
- (* ---- node kinds ----
- Grouped by role; the numeric values are stable and may be stored
- in listings. *)
- (* module / unit structure *)
- NkUnit = 0; (* [0]=name txt, [1]=decls, [2]=body *)
- NkDefUnit = 1;
- NkImplUnit = 2;
- NkDeclSeq = 3; (* [0..n)=declarations *)
- NkImport = 4; (* [0]=module txt, [1..n)=names (or FROM list) *)
- (* declarations *)
- NkConstDecl = 10; (* [0]=name txt, [1]=value expr *)
- NkTypeDecl = 11; (* [0]=name txt, [1]=type *)
- NkVarDecl = 12; (* [0..n)=name txt, [1]=type (names then type) *)
- NkProcDecl = 13; (* [0]=name, [1]=formals, [2]=result type,
- [3]=body, [4]=forward flag node *)
- NkClassDecl = 14;
- NkFieldDecl = 15;
- (* type constructors *)
- NkTypeIdent = 20; (* [0]=name txt (possibly qualified: a.b) *)
- NkSubrange = 21; (* [0]=lo expr, [1]=hi expr *)
- NkEnum = 22; (* [0..n)=literal name txts *)
- NkArray = 23; (* [0..n-2)=index types, [last]=element type *)
- NkRecord = 24; (* [0..n)=fields *)
- NkSet = 25; (* [0]=base type *)
- NkPointer = 26; (* [0]=base type *)
- NkProcType = 27; (* [0]=formals, [1]=result type *)
- (* statements *)
- NkAssign = 40; (* [0]=designator, [1]=value *)
- NkCall = 41; (* [0]=callee, [1..n)=actuals *)
- NkIf = 42; (* [0]=cond, [1]=then, [2]=else (or NoNode) *)
- NkWhile = 43; (* [0]=cond, [1]=body *)
- NkRepeat = 44; (* [0]=body, [1]=until cond *)
- NkLoop = 45; (* [0]=body *)
- NkExit = 46;
- NkFor = 47; (* [0]=control var, [1]=lo, [2]=hi, [3]=by, [4]=body *)
- NkCase = 48; (* [0]=selector, [1..n)=case arms *)
- NkCaseArm = 49; (* [0..n-1)=labels, [n]=body *)
- NkWith = 50; (* [0..n-1)=designators, [n]=body *)
- NkReturn = 51; (* [0]=expr (or NoNode) *)
- NkBlock = 52; (* [0..n)=statements *)
- NkHalt = 53;
- NkGoto = 54; (* [0]=label ident *)
- NkLabel = 55; (* [0]=label ident *)
- (* expressions *)
- NkBinExpr = 70; (* [0]=left, [1]=right; `op` holds the operator *)
- NkUnary = 71; (* [0]=operand; `op` holds the operator *)
- NkDesignator = 72; (* [0]=base, [1..n)=selectors *)
- NkSelector = 73; (* .field / [idx] / ^ ; `op` distinguishes *)
- NkIdent = 74; (* [0]=name txt, [1]=qualifier txt (or NoTxt) *)
- NkIntLit = 75; (* [0]=digits txt *)
- NkRealLit = 76;
- NkStrLit = 77;
- NkCharLit = 78;
- NkBraceLit = 79; (* [0]=type, [1..n)=elements *)
- NkSetLit = 80;
- (* ---- relational / arithmetic / selector operator codes ---- *)
- OpAdd = 0; OpSub = 1; OpOr = 2;
- OpMul = 3; OpDiv = 4; OpMod = 5; OpAnd = 6;
- OpEq = 7; OpNe = 8; OpLt = 9; OpLe = 10; OpGt = 11; OpGe = 12;
- OpIn = 13; OpNot = 14;
- (* selector codes (NkSelector.op) *)
- SelField = 0; SelIndex = 1; SelDeref = 2;
- TYPE
- Node = INTEGER; (* index into the arena, or NoNode *)
- TxtIndex = INTEGER; (* index into the text pool, or NoTxt *)
- (* ---------------- lifecycle ---------------- *)
- PROCEDURE Init;
- (* Clears the arena and text pool. *)
- (* ---------------- text pool ---------------- *)
- PROCEDURE AddTxt (s : ARRAY OF CHAR) : TxtIndex;
- (* Interns s, returning its index (deduplicated). *)
- PROCEDURE Txt (i : TxtIndex; VAR s : ARRAY OF CHAR);
- (* Copies the i-th text into s (empty when out of range). *)
- (* ---------------- node construction ---------------- *)
- PROCEDURE MakeNode (kind : INTEGER) : Node;
- (* A fresh node of the given kind, no children, ty = SymTab.InvalidType
- (the caller sets it). NoNode when the arena is full. *)
- PROCEDURE MakeLeaf (kind : INTEGER; name : ARRAY OF CHAR) : Node;
- (* A fresh node with child[0] set to the interned text of name. *)
- PROCEDURE MakeBin (kind, op : INTEGER; l, r : Node) : Node;
- (* A fresh node with op and two children (binary expr, assign, …). *)
- PROCEDURE MakeUn (kind, op : INTEGER; e : Node) : Node;
- (* A fresh node with op and one child (unary expr, selector, …). *)
- (* ---------------- node accessors ---------------- *)
- PROCEDURE Kind (n : Node) : INTEGER;
- PROCEDURE Op (n : Node) : INTEGER;
- PROCEDURE SetOp (n : Node; op : INTEGER);
- PROCEDURE Ty (n : Node) : INTEGER;
- (* The SymTab.TypeIndex attached by the checker (InvalidType until
- then). Declared as INTEGER to avoid a circular import with
- SymTab. *)
- PROCEDURE SetTy (n : Node; t : INTEGER);
- PROCEDURE NChild (n : Node) : CARDINAL;
- PROCEDURE Child (n : Node; i : CARDINAL) : Node;
- PROCEDURE AddChild (n : Node; c : Node) : BOOLEAN;
- PROCEDURE SetChild (n : Node; i : CARDINAL; c : Node);
- (* Replaces child i, extending the node when i = NChild. *)
- (* ---------------- listing (debug) ---------------- *)
- PROCEDURE Dump (n : Node; depth : CARDINAL);
- (* Writes a one-line-per-node indented tree to StdOut (via FileIO).
- Used by the Stage-A self-test and future debugging. *)
- END AST.
|