Ver Fonte

docs: next-session plan (master merged; P0-P5, gates, resume)

Eric Streit há 3 dias atrás
pai
commit
ede4c52098
1 ficheiros alterados com 61 adições e 68 exclusões
  1. 61 68
      docs/handoff-2026-10-18-next.md

+ 61 - 68
docs/handoff-2026-10-18-next.md

@@ -1,107 +1,100 @@
-# Next session — handoff (2026-10-18)
+# Next session — plan
 
-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`.
+**Branch state (2026-10-18):** `master` and `resolve-check` are both at
+`95ca4d6` (merged, fast-forward) and pushed to `origin`.  Work on
+`master`.
 
-## Policy (decided)
+**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).
 
-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.
+**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.
 
-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)
+## P0 — generics: two instantiations of one generic (real bug, do first)
 
-`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.
+Instantiating one generic twice with arguments from different families
+fails on the second instantiation:
 
-**Likely culprit:** `SymTab.EnterTypeParamBound` (SymTab.mod ~line 675):
+```mod
+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:
 
 ```mod
 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).
+*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`): 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`).
+- **`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; decide
-whether to pursue (high risk, touches self-hosting).  The declaration
-part itself is already 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** (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.
+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`).
-- Decide merge/push of `resolve-check` (no pushes so far).
+- (Merge of `resolve-check` → `master`: **done**.)
+
+---
 
 ## 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.
+`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
 
 ```sh
 cd .../m2compiler-V3
-git checkout resolve-check
+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.