Branch ast-stage-c. L6 = "classes/vtables, imports, nested modules".
Nested modules (f82f72b, tag v3-lower6-nested)
CanDecl accepts a nested NkUnit (with no imports).LowerDecls emits the nested unit's declarations and, when it has a
BEGIN body, BeginInit/body/EndInit (registering <nested>_init
so the enclosing BeginBody calls it).ReenterGlobals re-registers a nested module's non-exported globals in
the still-open enclosing module scope, so QbeGen.GlobalRef resolves
their "<outer>_<name>" symbols after the nested scope has been popped.lower_ok t_nestedmod.mod byte-matches. Suite 194/194; FIXPOINT OK
(3,328,857 bytes).-lower is invoked only from ProgModule's END (M2.atg), so Lower
re-emits only the last unit. But a session's image is accumulated
across all units (sessBuf): a program that IMPORTs a module pulls
that module's procs/init/globals into the same gen_ssa/<Prog>.ssa.
So re-emitting just the program cannot byte-match.
Supporting imports therefore needs a mechanism change: lower every
unit (definition/implementation/program) and accumulate a session image
(mirroring sessBuf), or otherwise compare per unit. That is the same
mechanism the L7 flip needs, so it is the natural next structural
step. Qualified names (M.x) additionally need SymTab.MaterializeAlias
at lowering time (module scope is open — workable) and qualified-call
resolution in LowerCall (currently CalleeName reads only the base
ident).
751a227 (methods, fields, sibling calls, inheritance) and 7aa21ff
(virtual dispatch, class pointers, empty class BEGIN).
BeginFunc/FuncParam/AbortFunc) so the backend temp counters
advance exactly as the legacy parse did.THIS
receiver, THIS pushed as the WITH base (bare field names resolve);
a BEGIN body emits <class>_init (empty BEGIN is marked with an
empty NkBlock in M2.atg so it is distinguishable from "no BEGIN").obj.Method, p^.Method and bare sibling names bind the
receiver (ArmRecv) and dispatch via VirtCallBegin/CallBegin.CanType accepts ClClass; methods are gated by CanMethod/
CanMethods with the class pushed as the WITH base.lower_ok: t_class, t_classinit, t_classmethod, t_classinherit,
t_classsibling, t_virtual. Suite 200/200; FIXPOINT OK
(3,378,633 bytes).
76048e0 (v3-lower6-qualified): M.x designators and M.P calls
resolve through MaterializeAlias + LoadDesignator /
SymTab.Proc*/Param*; CanLower no longer rejects imports.
Not yet byte-verifiable. Any multi-unit session contributes
code/data and consumes backend counters from the earlier units — e.g. a
definition-module CONST emits data $M_K, and a def-module proc
heading consumes a temp — while -lower re-emits only the last unit.
So imports can only be verified once the per-unit mechanism exists.
Lower is invoked only from ProgModule's END, so it re-emits one unit.
Making it re-emit every unit needs either a second backend state
(QbeGen is a singleton) or the flip — deleting the inline emit so
Lower becomes the sole emitter, running per unit with that unit's scope
still open (which is also what makes GlobalRef/MaterializeAlias
resolve module symbols naturally).
The flip is the L7 step. Because Lower must then handle everything the
compiler uses, the qualified-name support above is its prerequisite.