summary_two-phase-session-2026-10-03.md 3.5 KB

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 NkCalls
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 NkCalls
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

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