flan/test/programs/dev-watch.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

55 lines
2.4 KiB
Plaintext

;;;; A program that pushes values into the watch table from its own loop.
;;;;
;;;; The point of the case is that this needs no compiler change: the watch
;;;; entry points are ordinary C functions, so a program reaches them through
;;;; [declare-c] the same way it reaches anything else in the runtime. That is
;;;; deliberate — a [(watch "hp" hp)] form would be an arm in the checker, and
;;;; a scalar does not need one.
;;;;
;;;; The values are written every iteration and are *not* read back from here.
;;;; What reads them is the daemon's [watch] op, over the agent, while this
;;;; program is still running — which is the whole design: the program pushes
;;;; at frame rate and the editor reads memory.
(import agent "vendor:agent")
(declare-c watch-i64 [name string x i64] i32 "flan_dev_watch_i64")
(declare-c watch-f64 [name string x f64] i32 "flan_dev_watch_f64")
(declare-c watch-str [name string s string] i32 "flan_dev_watch_str")
;; The accumulator, for a value sampled from inside a hot loop. A scalar watch
;; there shows whichever iteration happened to run last, which is the case this
;; exists for; see flan_dev.c, "A number sampled thousands of times a frame".
(declare-c watch-num-i64 [name string x i64] i32 "flan_dev_watch_num_i64")
(defonce ticks i64)
(defn loop-cells [] i32
(let [i 0]
(while (< i 8)
(watch-num-i64 "cell" (i64 (* i 3)))
(set i (+ i 1)))
i))
(defn step [] i64
(set ticks (+ ticks 1))
;; Three types, because the table stores *rendered text* and the rendering
;; is per type: an i64 and an f64 do not print the same way, and a string is
;; quoted and escaped so that a newline in one cannot become a second row.
(watch-i64 "ticks" ticks)
(watch-f64 "half" (/ (f64 ticks) 2.0))
(watch-str "label" "sand")
;; A hot inner loop, and the value *varies* across it — which is what makes
;; the row a test of the accumulator rather than of the plumbing. A slot that
;; only kept [last] would report 21 and no range; n, min and max are each
;; pinned by a different part of this loop.
(loop-cells)
ticks)
(defn main [] i32
(agent/start "/tmp/flan-dev-watch-fallback.sock")
;; A watch call costs a load and a not-taken branch until somebody opens a
;; watch buffer, so spinning here writes nothing until the test arms it.
(while (= (agent/wait 20) 0) (step))
(step)
(while (= (agent/wait 20) 0) (step))
0)