summary_m2comp_step3.md 3.0 KB

m2comp step 3 — AST layer (tag: m2comp-step3)

Coco/R frontend + SymTab checks (steps 1–2) + an abstract syntax tree built alongside parsing, per H. Mössenböck, "How to Build Abstract Syntax Trees with Coco/R" (docs/AST.pdf): every nonterminal carries an output attribute returning its subtree, built with plain semantic actions. No codegen yet (step 4: MC64 MGen walking this tree).

What was built

  • src/AST.def/.mod — 30 node kinds in three families: decls (Module/Block/Import/ImpName/Export/Const/Type/Var/ Member/Param/Proc), statements (Assign/Call/If/While/Repeat/ Loop/For/Return/Exit), expressions (Bin/Un/Name/Int/Real/Char/ Str/Field/Index/Deref/CallExpr). Nodes are heap pointer records (NEW) with child links (left/right/extra/more) and a sibling link (next) — the dsc/next shape borrowed from the Oberon SymTable (docs/oberon-master), while SymTab itself stays flat. Types are stored as descriptor indices (no type subtree); unary ops use opNot/opNeg/opPos, binary ops reuse SymTab codes. Error-tolerant: nodes build even with InvalidType, so rejected sources still dump. Includes Append, SetChainType (identifier lists typed after the fact), ParseInt (decimal + H hex), and a NIL-safe depth-capped DumpTree.
  • src/M2comp.atg — full attribution with step-2 checks untouched: MkModule/MkBlock roots dumped by the Module action; ELSIF chains attach at the deepest else (standard If(a,A,If(b,B,C)) nesting); MkFor carries optional BY; calls share the step-2 frame machinery (MkCall/MkCallExpr with pnum); designators become Name/Field/Index/Deref chains (indices appended per bracket); literals folded (0FFH→255, 'q'→113, reals/strings kept as text).
  • run_tests.sh — new expect_dump assertions on tree content (Module Showcase, Proc Work, CallExpr, Field q, Int 255, Proc P).

Tests — 25/25

19/19 accept/reject from step 2 unchanged + 6 AST content checks.

Bugs found (both fixed, both covered)

  • ParseInt detected hex only when the digit scan stopped at H, so 0FFH dumped as Int 0. Fixed by checking the trailing H first, then hex-parsing the prefix.
  • NEW on POINTER TO RECORD needs FROM Storage IMPORT ALLOCATE under gm2 -fiso (ISO rule).

Notes

  • Dump verified by hand on showcase: nested procs, recursion, p^, m[1,2], Local.q, ELSIF nesting, LOOP/EXIT, FOR with/without BY, precedence (Min(3,4)+(2*3-4/2)).
  • Known simplifications for step 4: string/real literals kept as text (truncated at 63 chars); record members build nodes that the Type alternative discards (types resolve via SymTab).

Next

Step 4: MC64 MGen backend — tree-walking emitter (mc64-spec.md §11 opcodes, frames §5.2, .MC4 images runnable under mcint), reusing the m2c lowering as reference. SymTab (ProcNum, ByNum queries, export tables) and AST (pnum/typ on nodes) are already backend-ready.