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

51 lines
2.3 KiB
Plaintext

;;;; A program that stops with something worth looking at in the frame.
;;;;
;;;; dev-break.flan proves an editor can find out *that* a program stopped and
;;;; choose a restart; this one is about what the frame holds while it is
;;;; stopped. One local of each shape the structural printer has an arm for —
;;;; a parameter, a string, a struct, a fixed array, a bool — plus one that is
;;;; bound only *after* the error, which is the case that must come back
;;;; refused rather than rendered: its slot is storage nothing has written yet.
(import agent "vendor:agent")
(defstruct Point [x f32 y f32])
(defstruct Boom [why i32])
(defn look [n i64 label string] i64
(let [p (Point {.x 1.5 .y 2.5})
xs [10 20 30]
flag (> n 0)
;; Three bytes, for the three answers the character half has. A [u8]
;; already renders as text, so a lone byte showing only its number is
;; the one place the same data reads two ways — but only where a
;; person is inspecting. [println] of a u8 stays a number.
byte (u8 97) ; printable: 97 (\a)
gap (u8 32) ; one the reader names: 32 (\space)
ctl (u8 7)] ; no spelling: the number alone
;; A loop, for its hidden bound: [dotimes] allocates a slot nobody named,
;; and the listing must *hide* it rather than refuse it by an invented
;; name — [s6] is not a variable anyone can find in this file.
(dotimes [hop 0] (print ""))
;; And a shadowing rebind. The checker suffixes the repeat as [label~2]
;; so the debug info never claims one binding is the other; the listing
;; keeps both raw spellings, because two rows both called [label] with
;; nothing to tell them apart would be worse.
(let [label "inner"]
(restart-case
(do (error (Boom {.why 7}))
;; Never reached before the break, so [after] is a slot with nothing
;; in it: the frame records a null for it and this is what "not bound
;; yet" has to mean.
(let [after (i64 99)] after))
(carry-on [] 5)))))
(defonce ticks i64)
(defn main [] i32
(agent/start "/tmp/flan-dev-locals-fallback.sock")
(print (look 3 "hello")) (println "")
(dotimes [i 4000]
(agent/wait 5)
(set ticks (+ ticks 1)))
0)