spec: 22 — drop Prelude-for-primitives, tighten 22c to existing vocabulary

This commit is contained in:
2026-05-09 22:34:30 +02:00
parent 692899867b
commit 2102dadb3d
+74
View File
@@ -318,3 +318,77 @@ all `examples/*.ail.json` pass round-trip") is satisfied by 22b.4a.
The `test_22b2_*` and `test_22b3_*` filters added subsequently are The `test_22b2_*` and `test_22b3_*` filters added subsequently are
also retired here. No further round-trip gate work is required for also retired here. No further round-trip gate work is required for
22 milestone close. 22 milestone close.
### 2026-05-09 — 22b.4b dropped: Prelude-for-primitives deferred to post-22
The 22b.4 → 22b.4a + 22b.4b split (recorded above) further reduces:
22b.4b is removed from milestone-22 scope entirely. Acceptance
criterion 1 amends to read "22b.1 + 22b.2 + 22b.3 + 22b.4a + 22c
JOURNAL entries committed".
Substantive rationale, per the project's feature-acceptance
criterion (LLM utility):
1. **No runtime primitive for `int_to_str` yet.** Show#Int's body
needs to convert an `i64` to a heap-allocated `Str`. AILang
currently only has constant interned strings (`@.str_*` LLVM
globals). A heap-string ABI — runtime alloc, RC-count, drop —
is independently new infrastructure. Wiring it through a class
method first stacks risk: typeclass cascade + heap-string ABI
+ new C-runtime function + new codegen arm in one iter.
2. **Low LLM-utility for primitive Show.** An LLM that needs to
render an `Int` writes `int_to_str x` (a direct primitive call)
more naturally than `show x` (which routes through a Prelude
class with one instance). Class dispatch shines when the LLM
defines a user type and wants polymorphism; for primitives, the
Prelude class is a thin wrapper with negative entropy (extra
indirection, no new property).
3. **22c covers the user-class e2e independently.** The milestone's
typeclass-machinery property is exercised end-to-end by 22c's
user-class fixture (class Foo a + data Bar + instance Foo Bar
+ main calling foo). The Prelude path adds no semantic capability
beyond what 22c demonstrates.
When does Prelude-for-primitives return? When concrete LLM-author
code surfaces a case that genuinely benefits from `Show a` /
`Eq a` / `Ord a` over per-type primitive functions — that case
becomes the brainstorm trigger for a post-22 Prelude milestone.
Until then, `int_to_str` ships as a plain primitive (or not at
all) the day a fixture needs it.
### 2026-05-09 — 22c scope tightened to vocabulary AILang already has
The original 22c spec (§"Components" row) sketched the e2e fixture
as `class Greet a where greet : a borrow -> String` + `data Person
{ name : String }` + `instance Greet Person where greet p = "Hello,
" ++ p.name`. That sketch references three constructs AILang does
not currently support:
- **`++` for `Str`** — no concat operator in `crates/ailang-check/src/builtins.rs::list()`.
- **Named-field record syntax `Person { name = "world" }`** — AILang's `data`/`ctor` form is positional (`(ctor MkPerson Str)`), not record-with-named-fields.
- **`print` polymorphic on `Show`** — see preceding amendment.
22c's acceptance property is "user-defined class + user-defined data
type + instance + call site, monomorphised, runs, prints right value".
That property holds with any vocabulary AILang has. The fixture is
re-scoped to:
```
class Foo a where
foo : (a borrow) -> Int
data IntBox = MkIntBox Int
instance Foo IntBox where
foo = λb. (match b { MkIntBox v => v })
fn main : () -> Unit !IO
body: do io/print_int (foo (MkIntBox 42))
```
Stdout: `42\n`. No new primitives, no new surface syntax, no new
codegen paths beyond what 22b.3 shipped. The property the original
sketch was reaching for (typeclass dispatch over a user-defined ADT,
end-to-end, with a hand-readable expected output) holds identically.