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 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 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 NoteProc (name: ARRAY OF CHAR; uid: CARDINAL; res: SymTab.TypeIndex; depth: CARDINAL; ext: BOOLEAN); 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.