The trio the author decided on 2026-09-20 is now all built: def is CL's defparameter — its initialiser runs on every daemon re-run, unguarded, so an edited initialiser repaints the same storage on C-c C-c plus re-run — defonce (Clojure's name for CL's defvar, per the author) initialises once behind the .init~once. flag, and defconst stays the image. One parse arm reads both forms; the difference is Ast.reinit, carried to Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and Check.check_global lifts every def initialiser — zero and literal included — into global/<n>, so the host's startup reaches it through the function cell and a re-evaluated def swaps it (Session's def_inits; Emit.redefinition declares the cell for a non-sibling target). The old defvar spelling is refused with the rename and both compiling spellings, and every program, test, doc and editor list is swept — except sand.flan, the author's live WIP, whose seven defvar lines are flagged in FIX.org and keep its three dependent tests red on this branch.
53 lines
2.7 KiB
OCaml
53 lines
2.7 KiB
OCaml
(* The symbol names a Flan build puts into an object, spelled once.
|
|
|
|
Both backends emit the same names — that is not a nicety, it is the link:
|
|
an [--x86] host and a redefinition module built by LLVM bind against each
|
|
other, so [@"flan.cell.<n>"] has to be byte-for-byte the same string on
|
|
both sides or the dlopen fails and the piece served nothing. The macro
|
|
loader and the daemon's disassembler look up the same names from outside
|
|
the backends entirely.
|
|
|
|
So the prefixes live here, unquoted and without a sigil. Quoting is each
|
|
backend's own — LLVM writes [@"..."], the assembler writes ["..."] — and a
|
|
Flan name holds -, ?, > and /, which is why every emitted name is quoted
|
|
at all. This module only decides *which string* is quoted.
|
|
|
|
Not here: the ABI marker itself. [Emit.abi_marker] is ["flan.abi.llvm"] and
|
|
[X86.abi_marker] is ["flan.abi.x86"], and the two must stay distinct —
|
|
a crossed pair is refused at [dlopen] precisely because the marker one
|
|
image defines is not the one the other references. Sharing that string
|
|
would delete the mechanism. The *label* a module hangs its requirement on
|
|
is the other half of that mechanism and is shared, so it is here: see
|
|
[abi_require] below. *)
|
|
|
|
(* The prefix itself. It keeps the Flan [main] from colliding with C's, and
|
|
it is what makes every Flan symbol recognisable in a disassembly. *)
|
|
let prefix = "flan."
|
|
|
|
(* A function or a global. One namespace, because the language has one: a
|
|
[defn] and a [defonce] cannot share a name, so nothing here has to keep
|
|
them apart. The compiler's own names go through this too — [.init-globals]
|
|
and [.init-data] start with a dot no reader token can produce. *)
|
|
let sym n = prefix ^ n
|
|
|
|
(* A dev build's indirection cell: a mutable global holding the address of the
|
|
function that is currently this name's body. *)
|
|
let cell n = prefix ^ "cell." ^ n
|
|
|
|
(* The two module-local caches a name the host was never built with is reached
|
|
through — one for a function, one for a global. *)
|
|
let cellptr n = prefix ^ "cellp." ^ n
|
|
let globalptr n = prefix ^ "gp." ^ n
|
|
|
|
(* A compiled macro's entry point, which the expander dlsyms by this name out
|
|
of the module [Build.macro_module] wrote. *)
|
|
let macro n = prefix ^ "macro." ^ n
|
|
|
|
(* The datum a redefinition module puts its host's ABI marker into. Nothing
|
|
outside the module names it — the relocation against the marker is the
|
|
whole of what it does — but both backends emit it, so the string is spelled
|
|
once here rather than twice, beside every other name that has to read the
|
|
same on both sides. What it *holds* is each backend's own marker, and that
|
|
pair stays distinct; see the paragraph at the top. *)
|
|
let abi_require = prefix ^ "abi.require"
|