# Two-phase refactor — slice 1 (`twoPhase` flag + AST scaffolding) Branch `ast-stage-c` off `1c93f19` (`v3-two-phase-plan`). Suite **178/178**; self-hosting fixpoint **OK** (**2,957,466 bytes**; +56,684 vs 2,900,782 — the AST module is now linked into the compiler). ## What landed `docs/plan-two-phase.md` §4 slice 1: the parser now builds AST nodes **alongside** the legacy emit path, and the AST module is part of the compiler build. The nodes are **inert** — nothing reads them, so the generated `.ssa` is unchanged (stage2 == stage3 byte-for-byte). | File | Change | | --- | --- | | `compiler/src/M2.atg` | `IMPORT … , AST`; `VAR twoPhase : BOOLEAN`; the `M2` root production runs `AST.Init; twoPhase := TRUE;`; the `integer` expression leaf also builds `NkIntLit` via `AST.MakeLeaf`; `Fact` gets a throwaway `astScratch : AST.Node` | | `compiler/build.sh` | compile and link `AST` (after `FileIO`) | | `compiler/src/M2.lst` | regenerated CR listing | `M2P.mod` now imports `AST` and calls `AST.Init` once per parsed unit (the root production runs per source file), so every unit starts with a fresh arena. The new `AST.def/.mod` are picked up transitively by M2make during stages 2/3 of the fixpoint. ## Notes - `twoPhase` is a grammar-level BOOLEAN, set TRUE in the root production. Later slices gate the new lowering walk on it; for now it only guards the inert `NkIntLit` build. - `Compilation ended with LL(1) errors.` from CR is **pre-existing** (benign) and unchanged. - No new test: every existing test already exercises the path (each integer literal builds a node), and there is no observable behaviour to assert yet. ## Next Slice 2 (`docs/plan-two-phase.md` §4): `Expr` / `SimExpr` / `Term` / `Fact` build `NkBinExpr` / `NkUnary` / `NkIdent` / literals in addition to emitting; add `Lower` for expressions, exercised by a test-only `.ssa` byte-compare.