handoff-2026-10-18-next.md 3.4 KB

Next session — plan

Branch state (2026-10-18): master and resolve-check are both at 95ca4d6 (merged, fast-forward) and pushed to origin. Work on master.

Baseline: suite 239/239, fixpoint OK (3,812,771 bytes), corpus 405/612, 0 crashes. The corpus harness resolves transitive imports (method from 2026-10-18).

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; the 44-file "undeclared identifier" bucket is inflated by them.


P0 — generics: two instantiations of one generic (real bug, do first)

Instantiating one generic twice with arguments from different families fails on the second instantiation:

GENERIC DEFINITION MODULE GStack (T : TYPE);
TYPE NodeRec = RECORD val : T; next : Node END; ...

GStack(CHAR) alone works; GStack(INTEGER) alone works; together, the second fails (incompatible assignment at n^.val := v). INTEGER + CARDINAL appears to pass only because the stale binding still type-checks.

Likely culprit: SymTab.EnterTypeParamBound returns early when the formal is already visible, so the first instantiation's binding sticks:

IF Lookup(name) AND (SymKind(name) = KindType) THEN RETURN TRUE END;

Steps: five-file repro (generic def/mod + two instantiations + a program); make the substitution per-instantiation (fresh alias); add a regression test with two distinct scalar families; keep the fixpoint green.

P1 — quick, bounded corpus wins

  • gap22 __FILE__/__LINE__ (packed, +1).
  • gap09 scalar actual → ARRAY OF BYTE (aochar, arrayofbyte, bytearray, +~3).

P2 — structural

  • 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.

P3 — conformance remainder (architectural)

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.

P4 — latent correctness

The size-sensitive V3 miscompile ("removing ASTDUMP breaks the fixpoint") is still unroot-caused. Dedicated bisection session; a real correctness landmine.

P5 — housekeeping

  • Consolidate docs/summary_*.md (see docs/INDEX.md).
  • (Merge of resolve-check → master: done.)

Gates for every step

compiler/build.sh → compiler/run_tests.sh (must stay 100%) → bootstrap/fixpoint.sh (byte-identical) → corpusx.sh (record OK/CRASH + note) → update docs/gaps/ + STATUS/README → commit with a v3-* tag.

Resume

cd .../m2compiler-V3
git checkout master
cd compiler && ./build.sh && ./run_tests.sh   # 239/239
cd .. && TMP="$PWD/.scratch/fixpoint" ./bootstrap/fixpoint.sh
M2FLAGS="" ./.scratch/corpusx.sh              # 405 OK, 0 crash

Recommendation: P0 first (a real defect), then two P1 wins, and reserve a separate session for P4.