# Session summary — 2026-10-03 (two-phase frontend, slices 1–8) Branch **`ast-stage-c`** (off `1c93f19`; not merged to `master`). Suite **178/178**; self-hosting fixpoint **OK** (**3,021,285 bytes**). The day turned the two-phase plan (`docs/plan-two-phase.md`) from a document into a working, inert AST frontend: the parser now builds an AST **alongside** the legacy emit path, for essentially every declaration, statement and expression. Nothing consumes the tree yet, so the emitted `.ssa` is unchanged and the fixpoint stays byte-identical. ## Slices | Tag | Doc | What | | --- | --- | --- | | `v3-ast-slice1` | `summary_two-phase-slice1.md` | link `AST` into the build; `twoPhase` flag; `AST.Init` per unit | | `v3-ast-slice2` | `summary_two-phase-slice2.md` | expression spine + literals + parens + unary minus | | `v3-ast-slice3` | `summary_two-phase-slice3.md` | `Design`: identifiers, `[i]`, `.f`, `^`, qualified names | | `v3-ast-slice4` | `summary_two-phase-slice4.md` | calls/`NkCall` + actuals, `NOT`, builtins as named `NkCall`s | | `v3-ast-slice5` | `summary_two-phase-slice5.md` | statements: block, assign, `IF`/`WHILE`/`REPEAT`/`LOOP`/`EXIT`/`FOR`/`RETURN`/`HALT`, calls | | `v3-ast-slice6` | `summary_two-phase-slice6.md` | declarations: `NkDeclSeq`, `NkConstDecl`, `NkTypeDecl`, `NkVarDecl`, `NkProcDecl` | | `v3-ast-slice7` | `summary_two-phase-slice7.md` | unit root `NkUnit(name, decls, body)`; builtin statements as `NkCall`s | | `v3-ast-slice8` | `summary_two-phase-slice8.md` | `CASE` (`NkCase`/`NkCaseArm`/`NkSubrange`, ELSE arm) and `WITH` | Also tagged `v3-ast-session-2026-10-03` (state after slices 1–5). ## Conventions established - **Result slots** (module-level, saved into locals before the next operand): `astCur` (expressions), `astStmt` (statements), `astDecl` (declarations), `astUnit` (unit root). - **`Fact` disambiguation**: a per-invocation `astIsLit` local prevents a nested `Fact` from making an outer non-literal `Fact` look literal. - **Calls**: `ActParam` collects actuals into `astArgs`; the shared `AstCallNode` helper folds them into `NkCall`. - **Declarations reference types by `ty` index** (`SymTab.TypeIndex`) rather than building structural type-constructor trees. - **Incremental node building** for `IF`/`ELSIF`, `CASE`, `WITH`: the enclosing node is passed to child productions, so no local arrays (which are miscompiled) are needed and nested forms stay correct. - Every slice was gated by `build.sh` + `run_tests.sh` + `fixpoint.sh`, with the tree shape checked by a temporary `AST.Dump` (removed before commit). ## Finding (pre-existing, not fixed) **Local arrays inside a `PROCEDURE` are miscompiled** — module-level arrays are fine. Repro + detail: `docs/wip/local-array-bug.mod` (observed 1, want 60). It surfaced during self-hosting when `IfStat` used a local `ARRAY`; the grammar now avoids local arrays. Worth a dedicated fix, same family as the Stage-A array-of-record stride bug. ## Remaining - Expressions: **brace/set literals** (`NkBraceLit`/`NkSetLit`) and **`ResultComp`** call-result suffixes. - Declarations: imports (`NkImport`), `CLASS`, nested modules in the unit AST. - **`Lower` + `.ssa` byte-compare**, then delete the inline emit and the forward-patching machinery this whole refactor exists to remove. - Standalone fix for the local-array bug. ## Resume ```sh cd ~/Projets/Projets-Modula2/MyWork/m2compiler-V3 git checkout ast-stage-c cd compiler && ./build.sh && ./run_tests.sh # 178/178 cd .. && ./bootstrap/fixpoint.sh # FIXPOINT OK ```