瀏覽代碼

docs: AST Stage A summary + array-of-record stride fix note

Eric Streit 1 周之前
父節點
當前提交
c91695c5b3
共有 1 個文件被更改,包括 90 次插入 和 0 次删除
  1. 90 0
      docs/summary_ast-stageA.md

+ 90 - 0
docs/summary_ast-stageA.md

@@ -0,0 +1,90 @@
+# Session summary — 2026-10-02: AST Stage A + array-of-record fix
+
+Suite **178/178**; self-hosting fixpoint **OK** (**2,900,782 bytes**).
+Tag `v3-ast-stageA`.
+
+This is the first step of the **AST / two-phase frontend** refactor
+(option 1): make it possible to build a syntax tree while parsing and
+lower it in a later pass, so forward references (variables, procedures,
+typed constants, `CONST` constructors) resolve naturally and the
+text-patching machinery can be deleted.
+
+## 1. Stage A — the AST module (`compiler/src/AST.def/.mod`)
+
+An **arena-backed** node store, referenced by an integer index (`Node`),
+mirroring `SymTab.TypeIndex` (no pointers in the interface, no GC,
+bounded memory — self-hosting-friendly).
+
+- `NodeRec` = `kind`, `op`, `ty`, `nch`, `child[0..MaxChild-1]` — one
+  flat record array; every construct is expressed with a kind + up to
+  8 children (the `armornick/CocoR` `AST.java` pattern, flattened).
+- Node kinds for units, declarations, type constructors, statements and
+  expressions (`NkUnit`, `NkVarDecl`, `NkProcDecl`, `NkArray`,
+  `NkAssign`, `NkIf`, `NkWhile`, `NkBinExpr`, `NkSelector`, …).
+- Operator and selector codes (`OpAdd`…`OpIn`, `SelField`/`SelIndex`/
+  `SelDeref`) in the node's `op`.
+- An **interned text pool** (`AddTxt`/`Txt`/`TxtLen`) for identifiers
+  and literal spellings.
+- Constructors `MakeNode`/`MakeLeaf`/`MakeBin`/`MakeUn`, accessors
+  (`Kind`/`Op`/`Ty`/`NChild`/`Child`/`AddChild`/`SetChild`), and a
+  debug `Dump`.
+
+**Nothing in the grammar calls it yet** — this is purely additive; the
+suite and fixpoint are unaffected.  `tests/t_ast.mod` builds a small
+tree (`a := b + 2`, an unary node, a block) and walks it: exit 42.
+
+## 2. Bug found and fixed — array-of-record element stride
+
+`QbeGen.ElemSize` computed an array element's stride from its **class**,
+and `ClRecord`/`ClClass`/`ClSet` fell through to **4**.  So
+
+```modula2
+TYPE R = RECORD kind, op : INTEGER; child : ARRAY [0..7] OF INTEGER END;
+VAR a : ARRAY [0..3] OF R;
+```
+
+used stride 4 instead of 48: consecutive elements overlapped, and
+`a[i].op` / `a[i].child[0]` read neighbouring elements' fields (and the
+array descriptor's count).  A single record, and a 2-element array,
+happened to work; 4 elements did not.
+
+Fix: record/class/set elements use `SymTab.TypeSize(elemT)` (the inline
+footprint).  Repro that now passes: `rec3.mod` (exit 42); previously
+`rc=1`.
+
+This is what blocked the AST self-test (which stores
+`child : ARRAY [0..7] OF Node` in a record), and it is a real
+user-facing bug for any array of records with inline array fields.
+
+## 3. Two false alarms (recorded so they are not re-chased)
+
+- “Nested calls mis-order arguments” — **not a bug**.  `rc` is the
+  process exit status modulo 256, so a test encoding `1234` observed
+  `210`, `1274` observed `250`.  A proper equality check (`P(1,2,3,4)`
+  → `rc=42`) confirmed the call and codegen are correct.
+- `wrapc`/time wrappers — unaffected.
+
+## 4. Next (Stage B, option 2)
+
+Convert **declarations** to two-phase: parse all `CONST`/`TYPE`/`VAR`/
+`PROCEDURE` headings into the symbol table before lowering any body.
+That removes the forward-variable text-patching (`FwdPatchAll` /
+`FixLoadClass` / `FixStoreClass`) without a full AST, and is the
+stepping stone to Stage C (statements/expressions → AST → lowering).
+
+Branch-first discipline: after every increment run `fixpoint.sh` **and**
+`run_tests.sh`; revert the increment if either fails.
+
+## Resume
+
+```sh
+cd .../m2compiler-V3
+./bootstrap/fixpoint.sh                       # FIXPOINT OK
+cd compiler && ./build.sh && ./run_tests.sh   # 178/178
+```
+
+## Files
+
+`compiler/src/AST.def`, `compiler/src/AST.mod`,
+`compiler/src/QbeGen.mod` (`ElemSize`), `compiler/tests/t_ast.mod`,
+`compiler/run_tests.sh`, this doc.