summary_two-phase-slice4.md 2.1 KB

Two-phase refactor — slice 4 (calls, NOT, builtins → AST)

Branch ast-stage-c. Suite 178/178; self-hosting fixpoint OK (2,987,484 bytes; slice 3 was 2,970,007).

What landed

Fact now covers calls, logical NOT, and the builtin pseudo-calls (they build an NkCall whose callee is an NkIdent naming the builtin).

Construct AST
P(a, b, …) NkCall — child 0 = designator P, children 1.. = actuals
bare F / designator unchanged (NkDesignator)
NOT x / ~ x NkUnary(OpNot, x) (OpNot = 14 added to AST.def)
CHR ORD/ORDL CAP UCHR CHR8 UORD ABS NkCall(NkIdent "…", arg)
ADR SIZE/TSIZE HIGH/LEN MIN/MAX NkCall(NkIdent "…", designator)
SHIFT/ROTATE NkCall(NkIdent "…", target, amount)
VAL(T, x) NkCall(NkIdent "VAL", NkIdent "T", x)

Actual arguments are collected by ActParam (each Expr's node into astArgs), and Fact folds them into the NkCall after ArgList. Node-building actions are inserted before each builtin's existing emit action, so they read the argument node still sitting in astCur and then let the emit code run unchanged.

Verified (temporary AST.Dump, then removed)

  • P(2,3) → NkCall(Ident P, 2, 3)
  • ABS(-3) → NkCall(Ident ABS, Unary(Sub,3))
  • CHR(65)+1 → Add(NkCall(Ident CHR,65), 1)
  • HIGH(a) → NkCall(Ident HIGH, NkDesignator a)
  • VAL(INTEGER, x) → NkCall(Ident VAL, Ident INTEGER, NkDesignator x)
  • SHIFT(s,1) → NkCall(Ident SHIFT, NkDesignator s, 1)
  • x + MIN(x) → Add(NkDesignator x, NkCall(Ident MIN, NkDesignator x))

Deliberately deferred

  • Brace literals (T{…}) and set literals ({…}) still leave astCur := NoNode.
  • ResultComp suffixes after a call (F()[i], F().f, F()^) are not yet nodes (the call itself is).
  • Lower + .ssa byte-compare still not started.

Next

Statements (Block/Stat: NkAssign/NkIf/NkWhile/NkRepeat/ NkFor/NkCase/NkCall/…), then brace/set literals and ResultComp, then declarations and the Lower walk.