diff --git a/NEXT.md b/NEXT.md index 40a4c1e..1fc9a6e 100644 --- a/NEXT.md +++ b/NEXT.md @@ -328,15 +328,12 @@ plan.org's single line on it (831) names a `for` the language does not have and procedures passed as a runtime argument (`Map_Info`, `base/runtime/core.odin:369`). That runtime is what `spec-memory.md` specifies. - **The four questions that used to sit here are answered**, in `spec-memory.md`'s "Allocators" section, frozen along - with the rest of that file. Storage is released at exactly two points, `(free v)` and `(free-all a)`, and nothing is - released at scope exit. `drop` takes a pointer, fires only inside `free`, and a value carrying one may not be - constructed against an allocator lacking `can-free` — which is what stops an arena reset from having to run - destructors. Alignment is a property of the type, computed at the call site, passed as a parameter, and not stored in - the header. And an allocator that cannot satisfy a request signals `StorageExhausted` inside a `restart-case` - offering `retry`, so `push`, `put` and `clone` keep the result types they would otherwise have and no allocating - operation returns a `Result`. One question is left open there on purpose; it does not block the build. The order to - build the thing in is below. + **The four questions that used to sit here are answered**, in `spec-memory.md`'s "Allocators" section, which is + frozen along with the rest of that file: when storage is released, the `drop` hook, alignment, and allocation + failure. Read them there rather than in a second copy here. The one consequence the build order below turns on is + that no allocating operation returns an error — a failure signals `StorageExhausted` under a `retry` restart — so + `push` and `put` are `Unit`, `clone` returns the container, and no signature grows a `Result`. One question is left + open in that section on purpose; it does not block the build. 2. **Typed restarts — `(use-value [v T] v)`.** The author's third TODO, and the most-wanted thing across every comparative study. SBCL's report: restarts without parameters lose "the entire supply-a-value half of the standard @@ -396,9 +393,17 @@ expander last, on 6's unions. information without the round trip. 2. **`(Vec T)`**, over the type-erased runtime: `ptr + len + cap + allocator` in release, plus the generation word and the epoch in dev. `push`, `reserve`, `at`, `len`, `as-slice`, `free`, `clone`. `size_of`/`align_of` are produced at - the call site, which here is simply the concrete call site, there being no generics yet. This is what unblocks the - accumulation pattern `handler-bind` was built for — `(fn [c] (push errors c) ...)` — which conditions want today and - cannot have. + the call site, which here is simply the concrete call site, there being no generics yet. + + **`Vec` alone does not buy the accumulation pattern, and it is worth knowing that before step 2 is scoped.** + `(fn [c] (push errors c) ...)` over an enclosing `(Vec ParseError)` is the pattern `handler-bind` exists for, and it + needs two further things. Capture does not exist at all: `check.ml`'s `captured` (`:176`) consults `ctx.outer` only + to raise a better refusal — "a handler cannot see %s ... Use a global, or pass it on the condition" — and `lookup` + (`:167`) never reads `outer`. That is `spec-memory.md`'s case 2, a non-escaping `fn` capturing by value into a stack + environment, and it is unbuilt. On top of it, the same spec says a captured `Vec` or `Map` is captured **by pointer, + not moved**, and every capturable type today is a value type, so the by-value/by-pointer split has never had to + exist in a capture path. Both are their own work and neither falls out of `Vec`. Step 2 delivers a container; + accumulating into one from a handler is a separate item and should be planned as one. 3. **`StorageExhausted` and `retry`, with step 2 and not after.** `restart-case` and the transfer channel exist, so this is a compiler-emitted restart at each allocating site and little else. It goes in at the same time because the signatures depend on it: retrofitting it later adds a transfer check to every call site of every allocating @@ -445,10 +450,9 @@ expander last, on 6's unions. `base/runtime/dynamic_array_internal.odin:107` and `:128`. The two that miss: `Map_Cell_Info` is at `core.odin:351`, not `:350`; and `check.ml:1670` is the FFI `Declare` arm, not the `defer` registration — the claim it is offered for, that a top-level `defer` is checked in a scope holding only parameters and globals, is true and lives in `check_fn` - at `check.ml:1800`–`1812`. `check.ml:505` is the `defer` refusal exactly as cited. Also worth a word when that - section is next edited: Carp's `getDropFunc` is at `Memory.hs:804` and the drop-before-delete emit at `Emit.hs:1044`, - both within a couple of lines of what is written, and `docs/Drop.md` confirms the sentence they support — "`A.drop` - will be run ... when the `let` scope ends". + at `check.ml:1800`–`1812`. `check.ml:505` is the `defer` refusal exactly as cited, and the Carp citations are right: + `getDropFunc` is `Memory.hs:804`, the drop-before-delete emit is `Emit.hs:1044`, and `docs/Drop.md` says outright + that `A.drop` "will be run ... when the `let` scope ends". - ~~`web/examples/breakdemo.out` is stale and `check.sh` fails on it.~~ **Fixed.** Commit `4a6a8fa` made the break banner number its restarts and the `.out` was never repinned. Nothing had to drive the socket in the end: