Second handoff: the backend is correct and is not yet the dev backend

This commit is contained in:
Joseph Ferano 2026-09-13 21:27:03 +07:00
parent e725a5aab4
commit b1cc67b36f

70
NEXT.md
View File

@ -1,3 +1,73 @@
# Where this is — end of 2026-09-13, second handoff
**Branch `dev-loop` at `e725a5a`, working tree clean, `dune test` green, every lane merged.**
Nothing is running and nothing is half-built. Read this first.
## The x86 backend is correct, and is not yet the dev backend
`spike/x86/survey.sh` builds every program in `test/programs` and every probe in `spike/x86` both
ways and compares **stdout, stderr and exit status**: **97 MATCH, 0 DIFFER, 0 refused by name.** That
is up from 41/1/41 at the start of the day. Conditions, bounds checks, `Fnval`'s indirection cell and
`--x86 --dev` all landed. `DISCUSS.md` items 16, 17 and 18 are the three reports.
**`HANDOFF-x86-rt.md` at the root has the remaining seven items in order.** Item 1 is the substantial
one and is the reason the backend exists:
> **A redefinition emitter in `lib/x86.ml`** — the counterpart to `Emit.redefinition`, producing a
> `.so`. Until it exists the backend builds whole programs and cannot serve a single `C-c C-c`, which
> is where `DISCUSS.md` item 13's ~21ms of a 35ms redefinition actually lives.
**And the constraint the last lane found, which is the thing not to rediscover:** publishing a cell an
LLVM-built module can store into puts an edge on `lib/x86.ml`'s own licence that *"a dev build is
compiled entirely by this backend and a release build entirely by LLVM, and the two never meet in one
process."* The two conventions agree on scalars and **disagree on every aggregate**, so an
`Emit.redefinition` module dlopened into an `--x86` host is correct right up until the first redefined
function takes or returns a struct. The answer is a redefinition emitter in `x86.ml`, not an aggregate
classifier. It is written into both files' headers.
Items 2, 4 and 5 on that list are small. Item 3 (`f64``i64` out of range, `INT64_MIN / -1`) is a
**language decision and not backend work** — the two backends differ there today, deliberately.
Items 6 and 7 are debug information and a size/speed measurement, neither started.
## Two things that were true this morning and are not now
Worth stating because the notes elsewhere may still read the old way:
- **`Rt` with an aggregate return was never a gap.** Every `rt` builder in `check.ml` answers `Unit`,
an `Int`, a `Ptr`, an `Alloc` or a `Handle`, with aggregates leaving through an out-pointer, and
`crossable` refuses an aggregate return from a `declare` outright. The refusal in `call_native` is
unreachable and building sret behind it would have been *wrong* — that path is the C boundary, where
SysV returns a 16-byte slice in `rax:rdx` rather than by hidden pointer. `Vec`, `Map` and `Pool` all
match; item 16's "unexercised" line was stale.
- **The header check is not opt-in.** `vendor/raylib/raylib-5.5.h` is committed and
`vendor/raylib/headers` names it directly. There is no `FLAN_RAYLIB_H`.
## The dev loop, as it now stands
Everything below works today on the LLVM path, which is the default and unaffected by any of the
backend work.
`C-c C-c` a top-level form, `C-x C-e` an expression, `C-u` before either to mark a pause.
`C-c C-m` expands a macro one step and `C-u C-c C-m` to the fixpoint, into `*flan-macroexpansion*`
where `m` expands again in place. `C-c C-b` lists restarts at a break. `M-x flan-inspect-address`,
`M-x flan-allocations`, `M-x flan-leaks`. A watch keeps count, min, max, last and mean per label,
windowed to the editor's last tick.
Macros come from imported packages, qualified like a `defn`, and a session expands the buffer's own.
`vendor/raylib/modes.flan` has five `with-*` macros over raylib's begin/end pairs, used at 35 call
sites. A failed evaluation no longer kills the session — `lib/dev.ml`'s `serve` guards the whole
request and `Session.eval` commits below the checker.
## Queued, nothing blocked on a decision
1. `HANDOFF-x86-rt.md`'s seven items, item 1 first.
2. `text_codepoints_loading` and `textures_image_processing` — ordinary porting now that
`slice-from-ptr` exists.
3. Generic structs and `$n` array lengths — decided, unblocked, sections below. **Stopped once
already because it was started against the author's freeze; do not start it without asking.**
4. `any` and `drop`**stashed by the author deliberately.** Both designed, neither has a customer.
Do not schedule either.
# 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,