Branch ast-stage-c. Suite 182/182; fixpoint OK
(3,147,849 bytes; L2 was 3,123,487). L3 is not enabled — see the
finding; it stays out of CanLower, so the comparisons cannot false-fail.
Lower: NkCall in expressions (value) and
statements (discard), mirroring ArgList/ActParam — CallBegin,
per-actual CallArg (VAR via AddrOfVal, value via ArgClass + real
widening), CallEnd. CanCallArgs checks arity.SymTab.ParamName (new, read-only) — the i-th formal's name, for
the header.LowerDecls: Mangled/BeginFunc/FuncParam
for each formal/SetFuncRes/EndFuncHeader/EndFunc.Block now records its local NkDeclSeq (astBlkDecls), stored as
NkProcDecl child 2 — so a proc's VAR locals are in the AST.NkCall child 0 is an NkDesignator, not a
bare NkIdent; CalleeName unwraps it (this fixed calls mangling as
$_0).Lower runsThe L3 comparison does not match, and the reason is structural, not a missing emit:
SymTab.CloseProc (and EndUnit) close the scope that the inline
actions lowered inside of. Lower runs at the end (module end), by
which time a procedure's locals/params are no longer resolvable — so
LowerDesign("s") fails and the body emits nothing.
EndUnit, so L0–L2 (program body) work.This is exactly the "flip" the plan anticipated (§3 phase 3): the walk
cannot be one end-of-unit pass for everything; body lowering has to
happen at each procedure while SymTab still has its scope. Options:
Lower.LowerProc(node) right before SymTab.CloseProc
(and the program body before EndUnit) — i.e. per-unit-piece lowering,
still writing the L image.SymTab keep enough per-symbol info (kind/type/param names)
accessible after the scope closes (a durable "codegen view"), so one
end-of-unit walk works.Option 1 matches the existing inline timing and is the lower-risk route;
it also foreshadows the flip, where Lower replaces the inline emit at
that same point.
t_exit, t_arith, t_lower1,
t_lower2); t_lower3 is gated out of CanLower.Decide option 1 vs 2 for scope timing, then finish L3 (procedures). The rest of the subset order (L4+) is unchanged.