summary_lower_l4_l5.md 3.1 KB

Lower phase — L4 and L5 status (2026-10-05)

Branch ast-stage-c. All slices below are byte-verified (cmp gen_ssa/<Mod>.ssa gen_ssa/<Mod>L.ssa), gated by the suite and the self-hosting fixpoint.

Landed

Tag Commit Content
v3-lower4 53a1d15 builtins, CASE, WITH
v3-lower5-core ab507e2 records, arrays, designators, aggregate copies
v3-lower5-lit 5e23bfe char/real/string/set literals, IN, typed relations
v3-lower5-sets 081869f set arithmetic, string concatenation
v3-lower5-params 0b22c8a aggregate formals, value open arrays

Suite 191/191; FIXPOINT OK (stage2 == stage3, 3,304,549 bytes).

Design

  • Unified walk. LowerExprFull(n, ..., asAddr) handles both value and address contexts; LowerExpr is the value wrapper and LowerDesign the address wrapper. Selectors (.field / [i] / ^) are walked once, then FinalLoad applies Fact's trailing scalar/pointer load (aggregates keep the address).
  • Gate. CanType/CanDesign/CanCaseLabel/CanBuiltin mirror the walk's supported subset; CanLower accepts TYPE declarations and aggregate VAR/proc types.
  • Builtins dispatch by callee name (before user calls): ABS CAP CHR ORD SIZE/TSIZE MIN/MAX SHIFT ROTATE ADR, statements INC/DEC INCL/EXCL NEW/DISPOSE.
  • CASE is a compare-chain mirroring CaseStat/CaseAlt/CaseLabel (value and lo..hi labels, ELSE arm).
  • WITH uses a withRec/withTop stack shared by the gate and the walk; bare field idents resolve through WithField + QbeGen.TopWith.
  • Relations dispatch on operand type: IN, pointer (CmpL), set (CmpSet), string (StrEq), long (CmpLong), else Cmp.
  • Arithmetic covers set + - * / (SetBinOp) and string + (StrFold/StrCat), plus proper long/real result types.
  • Open arrays: a value ARRAY OF T formal is passed by descriptor address (FuncParam(..., isV OR IsOpenArray(t))), matching the grammar.

Tests

t_lower4 (builtins/sets/pointers), t_lower4case, t_lower4with, t_lower5 (records/arrays), t_lower5arr (open-array + VAR record params), t_lower5lit (literals/IN), t_lower5set (set arithmetic + string concat).

Remaining (documented, not blocking)

  • UString literals/ops.
  • Aggregate constants (record/array CONST values).
  • Qualified names / imports / class methods — L6 territory.

Fixed after L5

  • Nested arrays (ARRAY OF ARRAY record fields): QbeGen.ArrBodyItems now expands array-of-record elements per element (nested EmitRec) when the record recursively has a nested-array field, and ArrData emits the matching per-element sub-descriptors (nested EmitRecStatics). Plain record arrays stay a compact zero blob, so AST.arena does not balloon. Regression: tests/t_nestarr.mod (was docs/wip/nested-array-field-bug.mod). Suite 192/192; FIXPOINT OK (3,322,779 bytes).

Not touched

QbeGen remains at its committed state (stride fix only); the general array-of-record array-field fix stays deferred (docs/summary_l3_selfhost_fix.md).