;;;; 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") (defvar 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)