Reading a header need not mean linking libclang
This commit is contained in:
parent
99db8ce73f
commit
693661c4dd
43
DISCUSS.md
43
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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user