;;;; What evaluating a [def] does to a program that is running right now. ;;;; ;;;; dev-rerun.flan is the other half of the same form: it asks what the ;;;; *next run* sees. This asks what *this* run sees, and the answer is that ;;;; a [def] is Common Lisp's [defparameter] — evaluating one assigns. The ;;;; author's report is the first global here, to the letter: a palette in a ;;;; native array, edited in a live game, with the colours expected to change ;;;; on the next frame and not on the next restart. ;;;; ;;;; One global per shape the store has to reach: a native array, a scalar, a ;;;; struct, a dyn, and one whose initialiser is a call rather than a literal. ;;;; [kept] is the control — a [defonce] whose whole contract is that ;;;; evaluating it again leaves the value alone. ;;;; ;;;; main runs for as long as any of this takes and does nothing else. Every ;;;; assertion is read back out of the program's own storage by the daemon, ;;;; because a printed line is what a run computed and the question here is ;;;; what the storage holds *now*. (import agent "vendor:agent") (defstruct Tuning [gain i32 bias i32]) (defstruct Boom [why i32]) ;; A call, so that [computed]'s initialiser is lifted for a reason other than ;; the form — and so a brand-new def evaluated into this program has ;; something to call that the process was built with. (defn twice [] i64 10) ;; What a failed initialiser is made of. The condition goes unhandled, so a ;; def whose initialiser calls this stops the program in a break loop rather ;; than storing anything. (defn blow [] i64 (error (Boom {.why 1})) 0) (def colors [4 u32] [0xE6B800FF 0xFF0000FF 0xA83232FF 0xCC6B1FFF]) (def speed i64 3) (def knobs Tuning {.gain 1 .bias 2}) ;; A map and not a dyn number: a number is an immediate word and would read ;; back the same whether or not the store reached the heap. (def label dyn {:n 1}) (def computed i64 (twice)) (defonce kept i64 7) ;; A constant nothing consumes at compile time, so it is just bytes in the ;; program's memory and a re-evaluation can publish a new value into it. It ;; was the immediate one before [def] was, which is the fact this pins. ;; ;; A float rather than an integer, and that is the whole reason it is ;; written this way: the checker folds integer constants on the way in — ;; an array length has to be a number before any type resolves — and a ;; folded one is in the shape of the running program, where no store can ;; reach it. That one is refused by name, which is a different claim. (defconst limit f64 40.0) ;; The one [def] spelling with nothing to run: [uninit] lifts no initialiser, ;; so re-evaluating this form stores nothing, and the byte main wrote stays. (def scratch [4 u8] uninit) ;; For the one case where the thunk's two halves have to be in order. A ;; module carries one [flan_reload_call], and it holds both the class ;; registrations and the def stores; a def whose initialiser constructs an ;; instance of a class the same form redefined has to see the slot list the ;; registry now holds, so the registrations go first. (defclass point [x y]) (defn main [] i32 (agent/start "/tmp/flan-dev-defstore-fallback.sock") ;; A byte of [scratch] with a value somebody chose, so that "the uninit ;; form stored nothing" is a claim about a number and not about whatever ;; the bytes happened to be. (set (at scratch 0) (u8 77)) ;; Long enough that the whole block below runs against a program that is ;; still running: every assertion here is about what a *running* program ;; holds, and a fixture that parked half way through would answer the ;; second half of them from the park instead. (dotimes [i 120000] (agent/wait 5)) 0)