1631f6065c
Closes the gap between Iter 13a (parameterised ADTs in the checker) and end-to-end execution. ADT ctor code stays inlined at every use site — no mono-queue for types, no new symbols — but LLVM field types are now derived per use site via substitution. `CtorRef` gains `type_vars: Vec<String>` so use sites can identify which fields reference rigid vars. `cref.fields` (precomputed LLVM strings) is documented as monomorphic-only and read past for parameterised ADTs. `lower_ctor`: derives a `BTreeMap<String, Type>` substitution from `synth_arg_type` of each arg via `unify_for_subst`, then maps every `ail_field` through `apply_subst_to_type` + `llvm_type` for the per-store types. Monomorphic ADTs hit the original fast path. `lower_match`: builds `arm_subst` from `s_ail.args` ↔ `cref.type_vars`, substitutes through each `cref.ail_fields[idx]`, and uses the substituted type both for the LLVM `load` AND as the AILang slot of the local — so a downstream `unbox(b)` sees `b: Int`, not `b: a`. `synth_arg_type` for `Term::Ctor`: returns concrete type-args derived from the ctor's term-args. Vars left unpinned (e.g. `None` for `Maybe a`) fall back to `Type::unit()`. `llvm_type(Type::Var)` now hard-errors. Earlier this silently fell through to `ptr` (the ADT-via-ptr fallback), producing garbage IR. Failing loudly here surfaces missed substitutions in the test suite. Two e2e tests (`box.ail.json`, `maybe_int.ail.json`) cover ctor lower with substituted field types and match-arm field substitution. 64 tests green; clippy clean (two pre-existing warnings untouched). Hash invariant holds. Out of scope per agent assignment: poly-fn-as-value, higher-rank polymorphism, DESIGN/JOURNAL updates (deferred to 13c).
88 lines
1.9 KiB
JSON
88 lines
1.9 KiB
JSON
{
|
|
"schema": "ailang/v0",
|
|
"name": "box",
|
|
"imports": [],
|
|
"defs": [
|
|
{
|
|
"kind": "type",
|
|
"name": "Box",
|
|
"vars": ["a"],
|
|
"doc": "A unary box around a polymorphic value.",
|
|
"ctors": [
|
|
{
|
|
"name": "MkBox",
|
|
"fields": [{ "k": "var", "name": "a" }]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"kind": "fn",
|
|
"name": "unbox",
|
|
"type": {
|
|
"k": "forall",
|
|
"vars": ["a"],
|
|
"body": {
|
|
"k": "fn",
|
|
"params": [
|
|
{
|
|
"k": "con",
|
|
"name": "Box",
|
|
"args": [{ "k": "var", "name": "a" }]
|
|
}
|
|
],
|
|
"ret": { "k": "var", "name": "a" },
|
|
"effects": []
|
|
}
|
|
},
|
|
"params": ["b"],
|
|
"doc": "Polymorphic projection out of a Box.",
|
|
"body": {
|
|
"t": "match",
|
|
"scrutinee": { "t": "var", "name": "b" },
|
|
"arms": [
|
|
{
|
|
"pat": {
|
|
"p": "ctor",
|
|
"ctor": "MkBox",
|
|
"fields": [{ "p": "var", "name": "x" }]
|
|
},
|
|
"body": { "t": "var", "name": "x" }
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"kind": "fn",
|
|
"name": "main",
|
|
"type": {
|
|
"k": "fn",
|
|
"params": [],
|
|
"ret": { "k": "con", "name": "Unit" },
|
|
"effects": ["IO"]
|
|
},
|
|
"params": [],
|
|
"doc": "Round-trip 42 through MkBox + unbox.",
|
|
"body": {
|
|
"t": "do",
|
|
"op": "io/print_int",
|
|
"args": [
|
|
{
|
|
"t": "app",
|
|
"fn": { "t": "var", "name": "unbox" },
|
|
"args": [
|
|
{
|
|
"t": "ctor",
|
|
"type": "Box",
|
|
"ctor": "MkBox",
|
|
"args": [
|
|
{ "t": "lit", "lit": { "kind": "int", "value": 42 } }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|