Branch ast-stage-c. L7 = "flip: lower from the AST instead of
inline; delete the inline emit + Fwd* machinery".
The flip makes Lower the sole emitter. The obstacle is that QbeGen
holds one session state, used by the inline emit during parse; a
per-unit Lower emit would be clobbered by the next unit's inline emit.
So the flip is a big-bang: either remove/suppress the grammar's 533
QbeGen.* call sites, or give QbeGen two states — neither is a
byte-verifiable step.
The pragmatic path is therefore a session re-emit: collect every
unit's AST and re-emit the whole session with Lower after parsing.
That is byte-comparable against the legacy session image and becomes the
flip once the inline emit is removed.
d30abfd, tag v3-lower7-scaffold)Lower.LowerSession/LowerOneUnit/MaterializeGlobals.compiler.frm) collects GetUnit() per file and calls
Lower.LowerSession under -lower.SymTab.Materialize makes a unit's own VAR/CONST visible in
globScope, so GlobalRef resolves "<unit>_<name>" at session end
(the unit scopes are closed by then).Lower.Reset from the M2 root so the owned tables persist
across a session.Still scaffolding (inline emit untouched); suite 200/200, FIXPOINT OK (3,401,129 bytes).
ce2fc67, tag v3-lower7-session)DefUnit now builds an AST (proc headings recorded as
NkProcDecl); LowerDecls replays a bodyless proc as a heading.lower_ok_files added,
and DBasicProg, DQualProg, TQual (def-CONST), TQualP
(def-PROC) byte-match. Fixes: image named after the program module;
MaterializeGlobals also materializes TYPE/CLASS names;
SymTab.ReenterModGlobal keeps nested-module globals'
"<outer>_<name>" symbols; AST.Init once per session under -lower.Suite 204/204; FIXPOINT OK (3,405,813 bytes).
LowerSession needs every unit's
AST alive at once, but AST.MaxNodes = 65536 is sized for one unit;
the compiler's session overflows it (MakeNode → NoNode, later
units dump (nil)). Growing the arena past the 4 MiB sessBuf is
not viable. So the session re-emit cannot handle the compiler —
the flip must instead emit per unit at each unit's END (AST valid,
scope open), which is the two-state / inline-emit-removal problem.storage_prog differs: Lower emits
$malloc_6(l link, ...) where the legacy emits $malloc(...) — the
ext flag in Lower.NoteProc is hardcoded FALSE and Mangled's
ProcLink fails after scopes close.The session re-emit is a useful verification tool for small sessions, but the flip needs per-unit emission. Concretely:
NoteProc should record IsExternal at
the EXTERNAL arm, not at the heading).QbeGen states, or remove the
grammar's inline QbeGen calls. Either is a big, non-incremental
change; the fixpoint is the gate.Lower runs per unit (AST valid, scope open), which also makes
the external-proc and module-level resolution work naturally.