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.
51 lines
2.3 KiB
Plaintext
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)
|