# Handoff — L3 via option 2: 183/183 but self-host blocked by V3 codegen Branch **`ast-stage-c`**, HEAD **`edf24d9`**. Suite **182/182**; fixpoint **OK** (**3,147,849 bytes**). Clean except `toto.mod`. ## Headline Option 2 (zero `SymTab` surface) is **functionally complete** and **byte-verified**: `t_lower3` matches the legacy image and the suite reaches **183/183** with `lower_ok t_lower3`. It **still does not self-host**, and the cause is now a *different* V3 codegen bug, not the table design. ## What was built and verified this session `compiler/src/Lower.def` / `Lower.mod`: - Owned, **flat** tables (no arrays of records — see the bug below): `symName : ARRAY OF CHAR` (stride 64), `symKind`, `symTy`, and `procs : ARRAY OF ProcEnt` with a flat `pname` (stride 64). Helpers `Reset`, `NoteVar`, `NoteParam`, `NoteProc`, `SetProcRes`, no-op `ScopeEnter`/`ScopeLeave`, `CopyN`/`CopySpan`, `FindSym`/ `FindProc`/`Resolve`/`ProcInfo`/`ParamInfo`. **No `SymTab` edits.** - All `SymTab.ProcUid/ProcNPar/ParamType/...` call-sites switched to `ProcInfo`/`ParamInfo`; `LowerDesign`/`IsSimpleScalar`/`IsCall` to `Resolve`/`FindProc`. - Grammar hooks (inert): `M2` root `Lower.Reset`; `VarDecl`/`ConstDecl` `Lower.NoteVar`; `ProcHeading` `Lower.ScopeEnter`+`NoteProc`+ `SetProcRes`; `ParamSection` `Lower.NoteParam`/`NoteVar`; `ProcDecl` `Lower.ScopeLeave` + `AST.SetOp(astNode, 0)`. - `ScopeLeave` is a **no-op**: parse-time notes must survive until the end-of-unit walk. Result: `t_lower3` (function + VAR-param procedure + calls + RETURN) **byte-matches**; suite **183/183**. ## New finding — nested-array record field miscompiles Repro `docs/wip/nested-array-field-bug.mod`: ```modula2 TYPE PE = RECORD name : ARRAY [0..63] OF CHAR; pname : ARRAY [0..3] OF ARRAY [0..63] OF CHAR; (* nested *) END; VAR procs : ARRAY [0..3] OF PE; ... procs[nProcs-1].pname[j][i] := name[i]; ``` `./M2` compiles it, but the **generated program segfaults** (rc 139; want 42). A **flat** `pname : ARRAY [0..2047] OF CHAR` (manual stride) works. This is a real user-facing bug — likely the element stride / descriptor-pointer setup for a nested-array field (same family as the Stage-A array-of-record stride fix in `QbeGen.ElemSize`, and `docs/wip/local-array-bug.mod`). It was hit directly: the V3-built compiler (`m2s2`) crashed on **every** input when `Lower`'s formal-name table used a nested-array field. Flattening fixed that crash. ## Why self-host still fails After flattening, `m2s2` works on small programs (`t_exit`, a `CONST` program) but **still crashes (SIGABRT) on the full compiler input** (empty output). Shrinking the tables (`MaxSym` 2048→512, `MaxProc` 512→64) did **not** help, so it is not table size — it is a **size/complexity-triggered latent V3 codegen bug** in the compiled `Lower`/`M2P` code. HEAD self-hosts; the ~250 added lines tip it over. This is the third instance of the same compiler fragility (local arrays, nested-array fields, and now this). Finding the exact construct needs a bisect of the added code with a V3-built compiler — a dedicated task. ## Next steps 1. **Fix the nested-array-field bug in `QbeGen`** (like the Stage-A stride fix): make `arr[i].field[j][k]` correct. Add the repro to the suite. This is a real, self-contained bug and may also matter for the size-triggered failure. 2. **Bisect the size-triggered self-host crash**: build `m2s2`, then compile subsets of the added `Lower`/`M2P` code with it to find the construct that crashes. Candidates: the flat-stride indexing, the `CopySpan` offsets, or a specific grammar hook. 3. Once self-host is green: keep `lower_ok t_lower3`, expect 183/183 + FIXPOINT OK. ## Do NOT - No `FORWARD` (breaks gm2 whole-program pass). - No `SymTab` edits. - No arrays of records with aggregate (nested-array) fields in `Lower`. - No committed `ASTDUMP`. ## Resume ```sh cd ~/Projets/Projets-Modula2/MyWork/m2compiler-V3 git checkout ast-stage-c cd compiler && ./build.sh && ./run_tests.sh # 182/182 cd .. && ./bootstrap/fixpoint.sh # FIXPOINT OK ```