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

125 lines
4.9 KiB
Plaintext

;;;; println, one row per arm of the structural printer.
;;;;
;;;; The walk in render.ml is shared with the REPL, but until now its only
;;;; coverage was the REPL tests -- and those run a dev build, where the pieces
;;;; go to flan_dev_emit. println is the same walk with the other emitter, in
;;;; an ordinary build, so every arm needs saying again here: the two emitters
;;;; are the one thing the shared module does *not* make identical.
;;;;
;;;; Run at -O0 as well as -O2. The slice arm emits a loop over slots taken
;;;; from the enclosing function's frame, and mem2reg is exactly the pass that
;;;; would launder a slot mistake into working code.
(defstruct V [x f32 y f32])
(defstruct Blob [id i32 name string pos V tags [3 i32]])
(defenum Colour [red 0 green 1 blue 2])
;; Five deep, so the walk hits max_depth (4) and prints "..." rather than
;; descending forever. A self-containing struct is the case this cap exists
;; for; five nested ones are the same shape without needing a pointer.
(defstruct D5 [n i32])
(defstruct D4 [d D5])
(defstruct D3 [d D4])
(defstruct D2 [d D3])
(defstruct D1 [d D2])
(defonce b Blob)
(defonce col Colour)
(defonce big u64)
(defonce small u64)
(defonce arr [4 i32])
(defonce wide [10 i32])
(defonce deep D1)
(defonce n i32)
(defstruct Long [s string])
(defonce long-one Long)
(defn nothing [] () )
(defn find-it [s [i32] k i32] (Option i32)
(dotimes [i (len s)]
(when (= (at s i) k) (return (Some i))))
None)
(defn main [] i32
;; A string at top level prints raw. Anywhere else it is quoted, which the
;; Blob row below shows -- the two are the same value printed two ways on
;; purpose, and that difference is the thing most likely to be "fixed".
(println "plain string")
(println (bytes-view "plain bytes"))
(println 42)
(println -7)
(set small 5)
(println small)
;; The u64 row. Through the signed printer this reads -1, which is the one
;; way println could disagree with the REPL about a value both can hold.
(set big 0xFFFFFFFFFFFFFFFF)
(println big)
(println 3.5)
(println -0.25)
(println true)
(println false)
;; () is evaluated and *then* reported: a () expression is a call made
;; for its effect, so emitting () without running it would be a lie.
(println (nothing))
(set col :green)
(println col)
;; red is 0, which is also the zero value, so this row says the chain of
;; comparisons reaches the *first* member and does not fall through to the
;; number it is erased to.
(set col :red)
(println col)
;; A pointer is its shape and is never followed -- the only thing that could
;; make this walk cycle.
(set n 3)
(println (addr n))
(println (find-it (slice wide 0 10) 0))
(println (find-it (slice wide 0 10) 99))
(set (.id b) 7)
(set (.name b) "sandy \"quoted\"")
(set (.x (.pos b)) 1.5)
(set (.y (.pos b)) -2.0)
(set (at (.tags b) 1) 42)
(println b)
(set (at arr 2) 9)
(println arr)
;; Ten elements against a span cap of eight: eight, then "...".
(set (at wide 9) 1)
(println wide)
;; A slice's length is not known until it runs, so this is the arm that
;; emits a loop rather than unrolling.
(println (slice arr 1 4))
(set (.n (.d (.d (.d (.d deep))))) 5)
(println deep)
;; Two slice printlns in one function, and one inside a loop: the slots the
;; loop needs are allocated per *call site* at check time, not per iteration.
(dotimes [i 2]
(println (slice arr 0 2)))
(println (slice arr 2 4))
;; A nested string longer than the escape buffer. Escaping is the one
;; conversion whose output is not a bounded handful of characters, so it
;; truncates -- with an ellipsis inside the quotes, because a value that
;; prints as a shorter value is the failure nobody notices.
(set (.s long-one) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
(println long-one)
;; print is println without the newline.
(print "a")
(print "b")
(println "c")
0)