Five decisions, answered in one sitting, written down before they are built

This commit is contained in:
Joseph Ferano 2026-09-12 11:04:10 +07:00
parent 4a7b874050
commit d475e93b0f

43
NEXT.md
View File

@ -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