flan/test/programs/dev-macro.flan
Joseph Ferano a4c6b996ff def re-runs its initialiser, and defvar is renamed defonce
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.
2026-09-21 07:12:04 +07:00

44 lines
1.8 KiB
Plaintext

;;;; dev-loop.flan's shape, with a macro in it, and the macro is the whole
;;;; point of the file.
;;;;
;;;; [flan dev]'s merged daemon is the program and the compiler in one process,
;;;; and the compiler expands a macro by dlopening a module into *itself* --
;;;; which is now also the program's address space. The module is always built
;;;; by LLVM whatever backend the session uses, and the host is linked
;;;; -rdynamic so a redefinition module can reach its cells, so until
;;;; Build.macro_module hid the module's own Flan definitions the host's bodies
;;;; interposed them. Under --x86 that is a crossed pair and it was a SIGSEGV
;;;; during the first expansion, before the program had run a line.
;;;;
;;;; So [unless] is called twice over: once here at the top level, which is the
;;;; expansion that used to kill the daemon on its way up, and once from a body
;;;; typed in later, which is the same expansion with the program already
;;;; running beside it.
(import agent "vendor:agent")
(defonce ticks i64)
(defn parity [n i64] string
(let [out "even"]
(unless (= 0 (% n 2))
(set out "odd"))
out))
(defn step [] i64
(set ticks (+ ticks 1))
ticks)
;;; A *bounded* run of frame boundaries, where dev-loop.flan waits for a
;;; delivery and dev-repl.flan runs long enough to outlast a whole test file.
;;; This program is here to park, and it has to park whether or not the thing
;;; that was delivered to it is one [agent/wait] reports — so the clock ends
;;; it rather than the editor does. Two seconds is long enough for a client to
;;; be served twice and short enough to be well inside a watchdog.
(defn main [] i32
(agent/start "/tmp/flan-dev-macro-fallback.sock")
(println (parity (step)))
(dotimes [i 400]
(agent/wait 5))
(println (parity (step)))
0)