Unions and macros go ahead of Handle; generics wait for a customer

This commit is contained in:
Joseph Ferano 2026-09-12 14:47:27 +07:00
parent 9669ff23d0
commit a380f6f2fe

30
NEXT.md
View File

@ -429,11 +429,37 @@ run one lane at a time; item 4 is disjoint and runs alongside any of them.
reference; `#_`; hex, binary and addresses on primitives in the inspector. The indentation one is worth doing first
within this batch — it costs friction on every keystroke today.
5. **`Handle` and the pool.** A reference to something that can die, that reports that it died rather than silently
5. **Union values, then the macro expander, then `Result`/`try`.** Promoted above `Handle` on the author's call —
macros are the thing most worth wanting, and unions are the only thing between here and them.
**Unions are closer than the milestone number suggests.** `Tast.arm` already carries `acase` (a case name) and
`binds` (the slots a payload binds to) — that is union shape, built and exercised, because `Option` is a two-case
union wearing a special coat and `match` over it works today. What is missing is the declared layout (a tag plus the
largest variant), construction, and letting `match` bind payloads from a user-declared union. `defunion` already
parses and its shape is already checked; `check.ml:312` and `:1075` are the two refusals to remove.
**Then macros**, which are blocked on exactly this and nothing else: a macro is `[Form] -> Form`, so `Form` has to be
a Flan union whose *layout* the compiler and the `dlopen`ed macro agree on byte for byte. `NEXT.md`'s macro section
has the expander design — a pre-pass fixpoint before `Parse`, `gensym` as a compiler-side counter, quasiquote as a
desugaring over `Form`. The exit criterion is already written: move `when` or `cond` out of `parse.ml` into the
prelude as a `defmacro` with the existing tests unchanged and still green.
Macros are what buy `with-drawing` and `with-mode-2d` over raylib's begin/end pairs, the hiccup DSL if a JS backend
ever happens, and the removal of special forms from the compiler.
**`Result`/`try`** follows, being another union.
**Generics are deliberately NOT here.** They feel adjacent and are not urgent, and today is the evidence: `Vec` and
`Map` were the obvious customer and needed none — they are type-erased, with the compiler emitting sizes and the
hash/equality pair per call site, which is Odin's design. The remaining customers are user-written allocators and
escaping closures, and both actually want **function values**, which is a separate milestone-5 feature. Leave
generics until something concrete needs them.
6. **`Handle` and the pool.** A reference to something that can die, that reports that it died rather than silently
resolving to whatever reused the slot. Wanted on its own terms for entities referred to across frames, and it is the
real gate on classes. Buildable now that the allocator exists.
6. **Signature generations and stale-caller warnings.** The biggest remaining hole in "you never restart the program" —
7. **Signature generations and stale-caller warnings.** The biggest remaining hole in "you never restart the program" —
a changed signature is still refused rather than versioned. Last because it is the largest and nothing else waits on
it.