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.
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).NkUnit, NkVarDecl, NkProcDecl, NkArray,
NkAssign, NkIf, NkWhile, NkBinExpr, NkSelector, …).OpAdd…OpIn, SelField/SelIndex/
SelDeref) in the node's op.AddTxt/Txt/TxtLen) for identifiers
and literal spellings.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.
QbeGen.ElemSize computed an array element's stride from its class,
and ClRecord/ClClass/ClSet fell through to 4. So
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.
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.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.
cd .../m2compiler-V3
./bootstrap/fixpoint.sh # FIXPOINT OK
cd compiler && ./build.sh && ./run_tests.sh # 178/178
compiler/src/AST.def, compiler/src/AST.mod,
compiler/src/QbeGen.mod (ElemSize), compiler/tests/t_ast.mod,
compiler/run_tests.sh, this doc.