diff --git a/DISCUSS.md b/DISCUSS.md index df2bda4..52fc35d 100644 --- a/DISCUSS.md +++ b/DISCUSS.md @@ -182,22 +182,47 @@ ability to run new code in a stopped program. wasm cannot have this — `--dev` `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. +**Reader conditionals, decided in conversation.** A cljc-style subset is accepted, and the author chose Clojure's +inline reader conditionals over file-level target naming. Note what that changes: **this language has no conditional +compilation today**, and that absence drove a decision earlier the same day — `barf` signals on web rather than being +compiled out, precisely because "this bit is desktop-only" is not expressible. Note also that the sand-on-web work +introduced file-level target replacement for *C* sources (`foo.web.c` replaces `foo.c`), so the repo now has a +file-level precedent that this decision deliberately does not follow. Both were put; inline was chosen. + +**Also wanted, and independent of all of the above:** `#_` to discard the next form, and repeated (`#_#_`) to discard +that many following forms, as in Clojure. Reader-only, small, and useful immediately rather than whenever a JS backend +happens. + **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 -Today: `declare-c` names one C function per line, and the compiler generates the wrapper, the typedefs and the flattened -declaration. 175 of them for raylib. **No header is ever read, deliberately** — which means nothing can check that a -declaration matches the real signature, and that is written down as trusted rather than guaranteed. +Today: `declare-c` names one C function per line and the compiler generates the wrapper, the typedefs and the flattened +declaration — 175 lines for raylib. **No header is ever read, deliberately**, which means nothing verifies that a +declaration matches the real signature. That is written down as trusted rather than guaranteed. -The proposal is to read the header, prefix a namespace, and get `rl/InitWindow` for free — plus possibly automatic -kebab-casing to `rl/init-window`. +The proposal: read the header, prefix a namespace, get `rl/InitWindow` for free, possibly kebab-cased to +`rl/init-window`. -This is a large change in kind, not just in size: it means a C parser or a libclang dependency in the build, and it -trades an explicit, checkable list for an implicit surface. Worth weighing against what `declare-c` already buys, which -is that a binding is one line and the wrapper is generated. The auto-kebab-case question is separable and much smaller — -and note the FFI currently keeps C's own spelling on purpose, so the mapping would need to be reversible. +**The dependency is the crux, and this project already answered the same question once.** Zig's `@cImport` runs clang as +a *library*. That is exactly the dependency rejected in plan.org's "Why LLVM IR as text": a version-pinned C++ library +breaks routinely on upgrade, while a binary on `PATH` does not. Linking libclang walks back into it. + +**The middle path that keeps the property:** clang will dump a parsed header as JSON from the command line +(`-Xclang -ast-dump=json`). Still only `clang` on `PATH`, still no library linkage, and it yields *real* signatures +instead of hand-transcribed ones — which closes the "trusted, not guaranteed" gap that is the strongest argument for +doing this at all. + +**The design question is how much to import.** Zig imports everything a header declares. For raylib that is several +hundred functions plus every struct and macro, nearly all unused. The current 175 lines are deliberate, and the +declaration site is also the checkpoint where the compiler *refuses* a signature it cannot safely flatten — an +aggregate return, a variadic, a `string` coming back. A wholesale import removes that checkpoint, or has to reproduce +it as a filter. Generating the list from the header while keeping it explicit in the source is a third option: generate +once, commit the result, regenerate when the library moves. + +**Kebab-casing is separable and small**, with one constraint: it must be reversible, because the generated C wrapper +needs the library's own spelling. ## 7. Where `defclass` stands