The backend first, then a freeze; any and drop are stashed

This commit is contained in:
Joseph Ferano 2026-09-13 17:23:05 +07:00
parent 3b15501c4f
commit 888915402e

70
NEXT.md
View File

@ -1,3 +1,73 @@
# Decided by the author, end of 2026-09-13: the backend, then a feature freeze
**Priority is finishing the x86 backend and tightening the dev workflow.** After the backend is done,
**feature freeze for the rest of the day.** Work in flight may finish; nothing new starts.
**Stashed, explicitly not wanted now:** `any` and `drop`. Both are designed, neither has a customer,
and the author's words are that they feel like extra language features. `any` is plan.org's opt-in
tagged union (two words, a pointer and a typeid, no GC). `drop` is `spec-memory.md`'s hook for owning
something that is not memory. Their old entries stand; do not schedule either.
## The backend, in the order that finishes it
`DISCUSS.md` item 16 is the report and its verdict is the sequencing: *"the wiring is done and it was
the easy half. What is left is conditions, and the measurement moved them from 'first obstacle' to
'the only obstacle'."* 40 of 111 programs lower today; the other 40 are refused by name.
1. **Conditions, entire.** The transfer-channel guard after every call, the landing pad, the transfer
exit, `fdefers` on it, `emit_restart_case` and `emit_with_alloc`. Several hundred lines of
`emit.ml` **reimplemented from `spec-conditions.md` rather than ported**, because `emit.ml` writes
LLVM control flow and this writes bytes. The semantics are settled and the LLVM path is the oracle:
compare program output, never disassembly.
The mechanism is three pieces. The transfer channel is a pointer passed as the last argument; after
every call, check whether it is set; a set channel jumps to a per-function landing pad that runs
the defers and either handles or re-propagates.
`check_no_transfer` is what makes today's omission sound rather than hopeful — it walks the linked
program and refuses by name. It is also the measure of progress: the 40 refusals are 27
`restart-case`, 7 `signal`, 4 `handler-bind`, 1 `with-allocator`, 1 `fdefers`.
2. **Bounds checks**, which are the same work — `check_at` and `check_slice` cannot exist without the
guard. **Until they do, `--x86` is silently a `--no-bounds-checks` build**, and `bounds.flan` is
the one program that DIFFERs (exit 139 against LLVM's 134). Item 16 says this out loud and calls
deciding what a bounds violation means in a build with no handler one of two cheap things worth
doing first. Do that before item 1, not after.
3. **`Rt` with an aggregate return**, and with it most of the container runtime. `Vec`, `Map` and
`Pool` have not been exercised through this backend at all.
4. **`Fnval`'s indirection cell.** `FnAddr (Fnval n)` emits the symbol, which is right for a
whole-program build and wrong the instant anything is redefined into it. There are no cells and no
`--dev` here, deliberately — **but this is the one that decides whether the backend ever serves the
dev loop**, which is the reason it exists. Item 15's question 5, still waiting.
5. **Size and speed, measured.** Nothing has a number on it. Every value is in memory, every
intermediate is a frame temporary, and a block copy is `rep movsb`. That is the trade the brief
asked for and nobody has checked what it cost.
6. **Debug information.** None; `--x86` and `--debug` are refused together.
Two known divergences that are deliberate and should stay written down: `(uninit)` is stable garbage
rather than `poison`, and `unreachable` is `ud2` rather than UB. Item 16 says to take item 15's
question 4 seriously now that there are two backends that can disagree.
## Tightening the dev workflow — what is already known to want doing
- **Finish the macro branch** (`worktree-agent-a859480edc827ab73`): `dune test` never ran on it.
`HANDOFF-macros.md` on that branch has six items. Its customer is `with-drawing`/`with-mode-2d`,
which removes a class of unbalanced-pair bug from every raylib program.
- **`slice-from-ptr`** — queued below. Blocks three raylib examples and leaves the hand-written `Font`
surface with no example caller.
- **`merged_serve`'s 10s warning path** (`lib/dev.ml:2322-2326`), the last item in `HANDOFF-f1.md`.
- **The memcheck half of the registry**`VALGRIND_MAKE_MEM_UNDEFINED` in `flan_arena_proc`. The
registry answer and the memcheck answer are different tools and must not be blurred.
## Not in the freeze, because it is already decided and unblocked
**Generic structs and `$n` array lengths** — queued below with the Odin citations. It is a language
feature and the freeze says do not start it. Left here so it is not lost, not so it is picked up.
# Where this is — end of 2026-09-13
**Branch `dev-loop` at `861f591`, working tree clean, `dune test` green.** Read this section first;