DEFINITION MODULE Lower; (* AST -> QBE walk for the two-phase frontend (docs/plan-lower.md). The driver (compiler.frm) drives a per-unit re-emit through BeginSession/BeginUnit/LowerUnitNow/EndSession: the grammar's own inline emit runs suppressed, and Lower emits each unit's AST into the one session image. Symbol resolution is self-contained (zero SymTab surface): the grammar records each declaration's kind/type and each procedure's signature in the tables below while the scope is open, so the walk can resolve names after SymTab has popped their scopes. *) IMPORT AST, SymTab, QbeGen; PROCEDURE BeginSession (progName: ARRAY OF CHAR); PROCEDURE SetLegacyOpen1D; (* Bootstrap compatibility: use legacy {count,data} 1-D open ABI. *) PROCEDURE SetSeparate (b: BOOLEAN); (* M2 -c: bodyless modules emit an empty _init for cross-object init calls. *) PROCEDURE SetDefUnit (b: BOOLEAN); (* Lowering the target's own .def just to emit exported data; do not emit a second init. *) PROCEDURE BeginUnit; PROCEDURE LowerUnitNow (unit: AST.Node; isProg: BOOLEAN); PROCEDURE EndSession; (* The expression/statement/declaration walkers are mutually recursive. gm2's link pass rejects FORWARD and V3 has no whole-module pass, so they are declared here (definition-visible throughout the implementation) instead of being forward-declared. *) PROCEDURE IsBuiltin (nm: ARRAY OF CHAR): BOOLEAN; PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal); PROCEDURE LowerStmt (seq: AST.Node); PROCEDURE LowerDecls (seq: AST.Node); PROCEDURE Reset; PROCEDURE NoteVar (name: ARRAY OF CHAR; kind: INTEGER; t: SymTab.TypeIndex); PROCEDURE NoteConstVal (val: ARRAY OF CHAR); PROCEDURE NoteSetMask (name: ARRAY OF CHAR; mask: ARRAY OF CARDINAL; words: CARDINAL; lo: INTEGER); (* Records a SET CONST's mask (bit i is value lo+i). *) PROCEDURE SetConstMaskOf (n: AST.Node; VAR mask: ARRAY OF CARDINAL; VAR words: CARDINAL; VAR lo: INTEGER): BOOLEAN; (* TRUE when n is a compile-time set constant; mask gets its bits (relative to lo) and words its 32-bit width. The grammar calls this for a SET CONST declaration, then NoteSetMask on success. *) PROCEDURE ScopeEnter; PROCEDURE ScopeLeave; (* Procedure-scope stack: Enter pushes the enclosing owner, Leave seals the top and pops. ReenterScopeProc resumes a noted entry for the re-parse pass without re-registering it. *) PROCEDURE ReenterScopeProc (ty: INTEGER); PROCEDURE CurScopeProc (): INTEGER; (* The proc entry NoteProc most recently made current. *) PROCEDURE NoteProc (name: ARRAY OF CHAR; uid: CARDINAL; res: SymTab.TypeIndex; depth: CARDINAL; ext: BOOLEAN); PROCEDURE AliasProc (name: ARRAY OF CHAR; uid: CARDINAL; res: SymTab.TypeIndex; depth: CARDINAL; ext: BOOLEAN); (* Bind a generic procedure formal to an actual (proc-table alias). *) PROCEDURE MarkProcExternal; PROCEDURE NoteCProc (name: ARRAY OF CHAR); PROCEDURE NoteImportedProc (name: ARRAY OF CHAR); PROCEDURE NoteProcNode (n: AST.Node); PROCEDURE SetProcRes (t: SymTab.TypeIndex); PROCEDURE NoteParam (name: ARRAY OF CHAR; t: SymTab.TypeIndex; isVar: BOOLEAN); END Lower.