Branch state (2026-10-19): work is on master, tree clean.
Baseline: suite 241/241, fixpoint OK (3,853,285 bytes), corpus 411/612, 0 crashes.
Policy: follow Modula-2, not gm2 degradation — declaration
before use (only a POINTER's base may forward-reference). In
docs/gaps/, the decl-order and gm2-ext classes are not targets
except where gm2 compatibility was explicitly chosen (gap22, gap09).
Fixed on 2026-10-19. The bug was not EnterTypeParamBound (each
instance re-binds T correctly). It was in Lowering: after
EndUnit, Lower re-emitted each unit in globScope, so
Lower.MaterializeGlobals copied the unit's types into globScope; a
generic instance leaked its NodeRec there, and the second instance's
POINTER TO NodeRec picked it up via ForwardType (a forward pointer
base made it visible; direct records did not). See
docs/analysis_gaps.md §10 for the full trail.
SymTab.EnterLowerScope/LeaveLowerScope + Lower re-emits each
unit in its own module scope (also around the ExitCode probe in
Lower.EndSession).Lower.ReenterImports re-materialises a nested module's FROM-imports
in the enclosing scope (the nested scope is popped before lowering).compiler/tests/g_twice{,i,c,p} (GTwiceProg, 42).Follow-up: showcase24 can now use two instantiations of one generic
(simplify it, or add a demo) — optional.
Chosen with the user despite the gm2-ext class (compatibility mode).
gap22 __FILE__/__LINE__ — done (v3-file-line): scanner
allows a leading _, both names are reserved literals folded to the
file-name string / line-number integer. +3 corpus.gap09 scalar → ARRAY OF BYTE — done (v3-bytebuf): a
parse-time marker on ARRAY OF BYTE open formals, accepted for
scalar/pointer/string actuals; a scalar is wrapped in a stack
descriptor [count=SIZE(actual)][copy]. +3 corpus. See the
caveats in docs/gaps/README.md (writes reach the copy; string
HIGH is one less than gm2; BYTE is still 32-bit).gap12 variant records: empty arms, ELSE, untagged inner
CASE (5 files).gap11 bare procedure value as a statement.gap10 VAR-param type leniency (decide whether to adopt gm2's
same-size rule — non-standard).gap13 remainder: de-reserve the standard builtins (ORD,
CHR, VAL, …) — contextual-keyword parser refactor (ORDL is done).gap18 set-typed CASE labels.Forward references to module-level variables/procedures from a procedure body still work (the two-phase parse defers bodies). Strict declaration-before-use would require order-aware body checking; high risk, touches self-hosting. The declaration part is already strict.
The size-sensitive V3 miscompile is still unroot-caused. Note: the
2026-10-19 Lowering change moved code around, so re-check whether the
old symptom ("removing ASTDUMP breaks the fixpoint") still reproduces
before bisecting. Dedicated session; a real correctness landmine.
docs/summary_*.md (see docs/INDEX.md).resolve-check → master: done.)compiler/build.sh → compiler/run_tests.sh (must stay 100%) →
bootstrap/fixpoint.sh (byte-identical) → tools/v3-corpus/corpus.sh
(record OK/CRASH + note) → update docs/gaps/ + STATUS/README →
commit with a v3-* tag.
cd .../m2compiler-V3
git checkout master
cd compiler && ./build.sh && ./run_tests.sh # 241/241
cd .. && TMP="$PWD/.scratch/fixpoint" ./bootstrap/fixpoint.sh
tools/v3-corpus/corpus.sh # 411 OK, 0 crash
Recommendation: P1 (two bounded wins) next, then reserve a separate session for P4.