diff --git a/NEXT.md b/NEXT.md index e7572fc..7381f57 100644 --- a/NEXT.md +++ b/NEXT.md @@ -18,8 +18,17 @@ IEEE already answers it. # Where this is — end of 2026-09-13, second handoff +**This section is the record of that evening and is no longer where the tree is.** It is kept because the +reasoning in it is still the reasoning, but read the section above this one first, and take the state below +as a snapshot: it pins `dev-loop` at `e725a5a`, and since then the arithmetic-condition lane, the +redefinition emitter, the aggregate case across the reload boundary, the two unreached guards, DWARF for +`--x86`, the cost measurements, the last two raylib ports and the `dune test` noise have all landed. The +x86 survey it quotes at 97 now reports **103 MATCH, 0 DIFFER, 0 refused by name, 38 skipped**, and of the +seven remaining items it lists from `HANDOFF-x86-rt.md`, items 1, 3, 4, 5, 6 and 7 are done — each has a +`HANDOFF-x86-*.md` of its own. + **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. +Nothing is running and nothing is half-built. ## The x86 backend is correct, and is not yet the dev backend @@ -466,13 +475,14 @@ clause tells the abstract pass what it may assume, so the body checks at the def - The clause is written as a **Clojure-style map at the head of the body**, `{:where (ordered? $t)}`, chosen by the author over a bare keyword. It disambiguates because a bare `{}` in expression position is already refused (`parse.ml:110`), so a `{}` there can be nothing else, and Clojure's `{:pre [...] :post [...]}` is the - precedent. It leaves room for further keys without new syntax. **One catch to settle first:** `{K V}` is + precedent. It leaves room for further keys without new syntax. ~~**One catch to settle first:** `{K V}` is currently a legal return type, so `(defn f [...] {string i32} {:where ...} body)` puts two braces in a row - meaning different things. That resolves itself if `{K V}` goes in favour of `(Map K V)`, which is a separate - open question in this file. -- A `where` clause over **compile-time type predicates** admits the operators the body needs. Four are wanted — - `ordered?`, `equal?`, `hashable?`, `numeric?` — against Odin's forty-one. The prelude's nine non-collapsing - functions need only the first two. + meaning different things.~~ — resolved the way this predicted: `{K V}` went in favour of `(Map K V)`, + braces in type position are refused by name, and the two-braces-in-a-row case cannot arise. +- A `where` clause over **compile-time type predicates** admits the operators the body needs. ~~Four are + wanted — `ordered?`, `equal?`, `hashable?`, `numeric?`~~ — against Odin's forty-one. Five landed: `copyable?` + is the fifth, and it has no Odin counterpart because a `$T` there never has to answer whether it moves. The + prelude's nine non-collapsing functions need only the first two. - Each instantiation checks the concrete type satisfies the predicates and refuses **that call site** if not. **This is not a type class, and the distinction is the one to keep straight.** A type class carries diff --git a/conditions.org b/conditions.org index 81de9c3..c85873b 100644 --- a/conditions.org +++ b/conditions.org @@ -102,6 +102,19 @@ the agent's socket instead. ~BoundsError~ rather than ending the process, abandoning a frame and retrying it is a real thing to do, and a non-idempotent mutation is what makes it go wrong. +- *Four conditions come from below your program*, all with ~error~: + ~StorageExhausted~ when an allocator cannot satisfy a request, ~FileError~ + when a file operation fails, ~BoundsError~ for an index or slice outside its + container, and ~ArithError~ for arithmetic with no answer — a divide or + remainder by zero, ~INT64_MIN / -1~, and a float-to-integer cast that does not + fit, each of which used to be a bare ~SIGFPE~ with no message and no location. + The first two offer a ~retry~ at the failing site, because freeing something + or supplying another path makes the same operation succeed. The last two offer + *nothing*: no handler makes index 51 valid for a length-50 array or gives a + division by zero a quotient, so there is nothing to resume into. The restart + that answers those is the one your program already established — the frame + loop's ~continue~ — and it is on the stack and reachable without anything + being pushed at the failure. - *An unknown restart name is a hard stop.* No ~find-restart~ to test with. - *So are the wrong arguments*, and for the same reason: nothing static can know what a name will find. The message names both signatures. diff --git a/lib/tast.ml b/lib/tast.ml index 1c6085b..5900d77 100644 --- a/lib/tast.ml +++ b/lib/tast.ml @@ -1,8 +1,9 @@ (** The typed IR: what the checker produces and what every backend consumes. - Three backends share this — the tree-walking interpreter, dev redefinition - and the release AOT build (plan.org, Compilation) — so everything a backend - would otherwise have to re-derive is resolved here and nowhere else: + Every backend shares this — the LLVM emitter and the hand-written x86-64 + one, each of them under dev redefinition and under the release AOT build + (plan.org, Compilation) — so everything a backend would otherwise have to + re-derive is resolved here and nowhere else: - names are gone. A local is a slot index into the frame, a global is a name, and a call names its callee directly. No environment lookup.