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

Next session — handoff (2026-10-18)

State: branch resolve-check, tree clean. Suite 239/239, fixpoint OK (3,812,771 bytes), corpus 405/612, 0 crashes. Tags include v3-enum-import, v3-ordl, v3-showcase24, v3-convert, v3-set-word, v3-strict-decl-order, v3-m2-conformance, v3-gap-examples.

Policy (decided)

Follow Modula-2, not gm2 degradation: declaration before use (only a POINTER's base may forward-reference). docs/gaps/ classifies every remaining case; decl-order and gm2-ext are not targets (gm2 accepts non-conforming code; V3 correctly rejects it). The corpus is gm2's testsuite, so its number mixes both; the undeclared identifier bucket (44) is now inflated by the decl-order files — don't chase it blindly.

The corpus harness now resolves transitive imports (2026-10-18); that is the measurement method from here.

P0 — generics: two instantiations of one generic (a real bug)

analysis_gaps.md §10: instantiating one generic twice with arguments from different families fails on the second instantiation (GStack(INTEGER) + GStack(CHAR) → incompatible assignment at n^.val := v); INTEGER+CARDINAL passes only because the wrong binding still type-checks. Each type argument alone works.

Likely culprit: SymTab.EnterTypeParamBound (SymTab.mod ~line 675):

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

During an instantiation re-parse the formal is already visible, so it returns without rebinding to the new actual — the first instantiation's binding sticks.

First steps: reproduce with a five-file session (GBox(T) generic def/mod + two instantiations + a program); check how the driver establishes the scope for each re-parse (InstBegin/Reenter, compiler frame); make the formal binding per-instantiation (fresh alias), then add a regression test (two instantiations, distinct scalar families) and re-run fixpoint (generics are used in the compiler's own generics tests, not its source).

P1 — quick, bounded corpus wins

  • gap22 __FILE__/__LINE__ (packed): gm2 predefined constants; __/_ are not legal identifier chars in V3. Either add the two pseudo-constants or leave as gm2-ext (+1 file).
  • gap09 scalar actual into ARRAY OF BYTE (gm2's untyped byte buffer; aochar, arrayofbyte, bytearray): accept a scalar/ ADDRESS actual for an ARRAY OF BYTE/VAR ARRAY OF BYTE formal by passing its address (+ ~3 files).
  • gap16/gap17 set span: raise the cap / handle SET OF CARDINAL (low value).

P2 — structural (parser / semantics)

  • gap12 variant records: empty variant arms, ELSE, untagged inner CASE (varient2/3/8, tsize/2).
  • gap11 bare procedure value as a statement (tinyproc2/4).
  • gap10 VAR actual type leniency (gm2 same-size rule; testparam2/3) — decide whether to adopt it (non-standard).
  • gap13 remainder: the standard built-ins (ORD, CHR, VAL, MOD, …) are still Coco/R keyword tokens; de-reserving them needs contextual-keyword parsing (predeclared identifiers). ORDL (the corpus case) is done.
  • gap18 set-typed CASE labels (bitset5).

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; decide whether to pursue (high risk, touches self-hosting). The declaration part itself is already strict.

P4 — latent correctness

The size-sensitive V3 miscompile (historical "removing ASTDUMP breaks the fixpoint") is still unroot-caused. Worth a dedicated bisection session: it is a correctness landmine, unlike the remaining language gaps.

P5 — housekeeping

  • Consolidate docs/summary_*.md (see docs/INDEX.md).
  • Decide merge/push of resolve-check (no pushes so far).

Gates for every step

./build.sh, ./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 resolve-check
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