Iter 14d: remove Term::If as a redundancy
Term::If was semantically a subset of Term::Match on Bool. Per CLAUDE.md the language must contain no redundancies; two AST nodes for the same operation produces an authoring decision with no semantic content and a duplicate codegen path. Removed. Migration shape (applied to sum, sort, max3 fixtures): (if c a b) -> (match c (case (lit-bool true) a) (case _ b)) No schema version bump (per user direction): no third-party consumes ailang/v0, so version ceremony is pure overhead. Edited AST and fixtures in place; pinned hashes in hash.rs updated. Implementer deviation, called out and justified: a tightly-scoped lower_bool_match helper (~95 LOC) was needed in codegen because the existing match path rejects i1 scrutinees and Pattern::Lit. Helper accepts only the canonical two-arm migration shape, errors on anything else, emits the same br/phi IR Term::If used to. No generalisation of the ADT-match codegen. Diff: 13 files, +286/-221 (net +65 LOC). AST got smaller (one variant gone), form-(A) got smaller (one production gone), typecheck got smaller (one branch gone). Codegen got slightly larger by the bool-match helper. Hash deltas: sum.sum, sort.insert, max3.max, max3.max3 changed. All other defs (e.g. sum.main, sort.IntList, sort.sort, sort.print_list, max3.main) kept bit-identical hashes — confirms canonical-JSON byte format intact. Verification: 76/76 tests green; sum->55, max3->17, sort->[1,1,2, 3,3,4,5,5,5,6,9] (identical to pre-migration). cargo doc 0 warnings. Tail-call survey by implementer (informs 14e): print_list recursions are already in tail position (rhs of seq inside match arm); map/sort/insert recursions are NOT (constructor-blocked inside Cons applications). 14e annotation will benefit terminal recursions; ctor-blocked ones need accumulator-form rewrites in source, not a compiler-side transform. Decision 7 added to DESIGN.md. JOURNAL entry has the language- completion sequence (14d done, 14e tail-calls, 14f GC, 15a stdlib). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+28
-2
@@ -429,6 +429,31 @@ fixtures round-trip identically through `print → parse → canonical
|
||||
JSON`; the three hand-written `.ailx` exhibits parse to canonical
|
||||
JSON identical to their corresponding `.ail.json` files.
|
||||
|
||||
## Decision 7: redundancy removal — `Term::If` is not a primitive
|
||||
|
||||
`Term::If { cond, then, else_ }` is semantically a subset of
|
||||
`Term::Match` on `Bool`. Per CLAUDE.md the language must contain no
|
||||
redundancies; two AST nodes for the same operation produces an
|
||||
authoring decision with no semantic content and an extra codegen
|
||||
path. Iter 14d removes `Term::If`. Migration shape on the JSON side:
|
||||
|
||||
{"t":"if","cond":C,"then":A,"else":B}
|
||||
→
|
||||
{"t":"match","scrutinee":C,
|
||||
"arms":[
|
||||
{"pat":{"p":"lit","lit":{"kind":"bool","value":true}},"body":A},
|
||||
{"pat":{"p":"wild"},"body":B}]}
|
||||
|
||||
The wildcard arm satisfies the typechecker's
|
||||
`primitive-needs-wildcard` rule. A future iter may upgrade the
|
||||
exhaustiveness check to recognise the `true`+`false` arm pair as
|
||||
covering Bool without a wildcard; until then, wildcard is the
|
||||
canonical migration target.
|
||||
|
||||
No schema version bump (no third-party consumes `ailang/v0`).
|
||||
Hash invalidation for the three migrated fixtures (`sum`, `sort`,
|
||||
`max3`) is intentional; the new hashes become the new identity.
|
||||
|
||||
## Mangling scheme (Iter 5c)
|
||||
|
||||
All AILang functions are mangled to `@ail_<module>_<def>` — even in the
|
||||
@@ -492,7 +517,6 @@ hashes stay bit-identical.
|
||||
{ "t": "var", "name": "<id>" }
|
||||
{ "t": "app", "fn": Term, "args": [Term...] }
|
||||
{ "t": "let", "name": "<id>", "value": Term, "body": Term }
|
||||
{ "t": "if", "cond": Term, "then": Term, "else": Term }
|
||||
{ "t": "do", "op": "<eff>/<op>", "args": [Term...] }
|
||||
{ "t": "ctor", "type": "<id>", "ctor": "<id>", "args": [Term...] }
|
||||
{ "t": "match", "scrutinee": Term, "arms": [Arm...] }
|
||||
@@ -588,7 +612,9 @@ as iterations land; the JOURNAL records the exact iteration.
|
||||
What **is** supported (and used as the smoke test for the pipeline):
|
||||
|
||||
- Int, Bool, Unit, **Str** as primitive types.
|
||||
- `if`, `let`, function calls, recursion.
|
||||
- `let`, function calls, recursion. Bool branching is expressed via
|
||||
`match` on `Bool` with a `(lit-bool true)` arm and a wildcard
|
||||
fallback (Decision 7); there is no separate `if` AST node.
|
||||
- Effects on function signatures, with `do op(args)` for direct effect
|
||||
ops (`io/print_int`, `io/print_bool`, `io/print_str`).
|
||||
- **ADTs + flat pattern matching** (Iter 3). Sub-patterns of a Ctor
|
||||
|
||||
Reference in New Issue
Block a user