diff --git a/DISCUSS.md b/DISCUSS.md index 7532df2..df2bda4 100644 --- a/DISCUSS.md +++ b/DISCUSS.md @@ -154,15 +154,36 @@ See item 7. Also unresolved: the shim generates a C typedef per *named* struct, and an anonymous struct has no name to generate one from. Either anonymous structs cannot cross the FFI, or the generator learns to name them. -## 5. A performant JS transpiler +## 5. A JS backend — for web apps, not for games -Asked as a feasibility question. Bear in mind the web target already exists and ships real machine code via wasm, so this -is not the only route to a browser and the case for it needs stating: smaller artifacts, no wasm toolchain, debuggability -in browser devtools, or something else. +**The goal, stated in conversation: calling JS libraries, and eventually a hiccup-style DSL for writing web apps in +Flan.** That is a different product from the wasm target and the two do not compete — games go to wasm, web apps go to +JS. -The hard parts are the ones the wasm target got for free from clang: the memory model (Flan is pointers and explicit -layout; JS is not), the FFI, and the fact that the whole raylib layer is C. A JS backend that cannot run raylib is a -different product from the one that can. +This matters because the obvious objection does not apply. "A JS backend cannot call raylib, so the whole graphics layer +would need reimplementing on canvas" is fatal for a *game* backend and irrelevant here: web apps do not use raylib. + +**The design fork, and it should be decided first:** + +- **Linear memory** — an `ArrayBuffer` standing in for pointers and structs, with typed-array reads and writes. Fast + arithmetic, and every value is opaque bytes, so every call into a JS library marshals both ways. This is asm.js, which + wasm exists to replace, and it is precisely wrong for an interop-motivated backend. +- **Object mapping** — a Flan struct becomes a plain JS object, a `Vec` becomes a JS array. Slower for tight numeric + loops, natural for interop, readable output. **For this goal this is clearly the right one**, and performance is not + the constraint people assume: DOM work is dominated by the browser, not by arithmetic. + +**The consequence to face early: the memory model does not come along.** Object mapping means garbage collection, which +means no pointers, no manual `free`, no arena, no allocator. So this is a **dialect**, not merely a second backend — +some Flan programs will not compile to JS, and that should be named up front rather than discovered. Worth deciding +which subset is the JS-targetable one, and whether the checker enforces it per target. + +**The unexpected upside: the dev loop could work on the web.** Conditions, restarts and a break loop all need the +ability to run new code in a stopped program. wasm cannot have this — `--dev` is refused there because reload is +`dlopen` and the browser has no sockets. JS has no such problem: it evaluates new code trivially. A JS target might be +the *only* place the live dev loop and the browser coexist. + +**One dependency:** hiccup is a macro, and the macro expander is blocked on `Form` being a Flan union, which is union +values. The backend can start before that; the DSL cannot. ## 6. C interop as seamless as Zig's