diff --git a/NEXT.md b/NEXT.md index 670ac51..249f06c 100644 --- a/NEXT.md +++ b/NEXT.md @@ -214,6 +214,49 @@ $ flan run test/programs/sand-headless.flan $ flan run sand.flan # a window, 120 fps, hold space ``` +## Decided 2026-09-12, by the author, and not yet built + +Five questions were put and answered in one sitting. Each is a decision, not a preference — build against them, and +reopen one only with a reason rather than a taste. + +**1. Assets are embedded at compile time, one file or one directory.** Odin's answer, and the reason it is the right +one here: it is a *compiler* feature, so it needs no build flags, no linker arguments and no per-target packaging, and +it works identically on desktop and web. That matters more here than it does for Odin, because `Load` gives link flags +only to directory packages — the single file doing `(rl/load-texture "brush.png")` is structurally the one file with +no link channel, which is what stopped the web lane from inventing a flag. Embedding has no such hole. Odin's +`#load` and `#load_directory` are the model (`src/parser.cpp:853`, `src/checker.cpp:3594`). emscripten's +`--preload-file` stays available later for assets that should load lazily rather than be baked in; the `@web` link +line already carries it if wanted. + +**2. Reading a file works everywhere; writing is desktop-only and signals on web.** Odin stubs its whole file API on +js/wasm — every operation returns `.Unsupported`, and `core/os/file_js.odin`'s own comment says the stubs exist only +so importing `core:os` "panics cleanly". Take the restriction and not the mechanism. **Flan has no conditional +compilation** — nothing in `parse.ml` or `check.ml` reads the target — so "isolate this code to desktop" is not +expressible in source, and a build-time refusal would therefore be unusable. A **silent no-op is worse than either**: +it is how a save file disappears with nothing said. So `barf` on web signals a condition under a restart and the +program decides. This is the language having something Odin does not; use it. Per-package target isolation, if a +whole desktop-only package is ever wanted, is the `@native`/`@wasi`/`@web` link-line tagging the web lane built. + +**3. Build the shadow stack.** plan.org:591 has specified it in the dev-build column since the beginning and nothing +has ever built it. It is the route to `(:op "backtrace")` *and* to locals, together, and it is dev-only so a shipped +game pays nothing. Chosen over the DWARF route deliberately: DWARF still owes a `!DILexicalBlock` per `Let` before +`p v` under shadowing is even honest, and that buys locals in lldb rather than in the break loop. The author's reason +is the one to keep in view — **the more a break loop can show, the less often a real debugger is needed** — which +makes this a dev-loop feature, not a debugger feature. + +**4. Conditions get a parent link, not class inheritance.** A condition type may name a parent where it is declared; +matching walks that static chain. This buys the hierarchy §1 of `spec-conditions.md` says there is none of — a +catch-all handler, "any file error" — at compile-time cost only. **It is deliberately not the class answer** that the +"Open: can a condition be a class?" section below weighs: a class condition allocates at the signal site, which is +the failure path and sometimes the thing that failed; it inverts §5's lifetime, so something must own and free it; +and it lets a condition's layout change while a handler frame stands against the old one. A parent link has none of +those costs and leaves the frozen model otherwise intact. Real inheritance stays possible later if a case demands it; +this closes nothing off. That section stays open for the record but is no longer the blocking question for +`handler-case`. + +**5. File I/O — `slurp` and `barf` — is the next stdlib work**, after `Vec`, because `slurp` returns a string whose +length is not known until the file is read and therefore cannot exist before an allocator does. + ## Blocked and unfinished Everything below was found, decided or half-built and then stopped. Each says what blocks it. Nothing here is a