flan/test/programs/println-variadic.flan
Joseph Ferano a64bee6d96 Review follow-ups: a new def's image, the keyword that cannot change, and the sweep
Three defects, all from lifting every def initialiser, none of which the
suite caught:

A def typed fresh into a live session came up zero and stayed zero. The
image flan_dev_global copies on the allocation is the only value a new
global ever gets — the host's .init-globals never calls its initialiser —
and both backends chose that image with Tast.const_init, which a def's
lifted Call fails by construction. Emit.initial_image reads the constant
back out of the lifted body; the x86 twin had the same bug.

Changing a global between def and defonce was silently ineffective: the
guard lives in the startup function compiled into the host, which a reload
cannot republish. Session.compatible refuses both directions and says to
restart; editing the value stays allowed.

And global/<n> no longer leaks into the signature refusal when a def is
retyped — the global loop names the same fact in words a reader can act on.

flan check prints def, defonce or defconst off grerun; (defvar) with no
arguments names the shapes rather than offering (defonce ); the docs,
plan.org, runtime comments and valgrind.supp are swept; BUILT.md states
the release-build cost and the uninit caveat.
2026-09-21 07:19:33 +07:00

34 lines
1.3 KiB
Plaintext

;;;; print and println are variadic with Clojure's spacing: every argument
;;;; prints in order, a single space between each pair, println ending the
;;;; line. (println) alone is the newline; (print) alone is nothing.
;;;;
;;;; What the pins are for. The one-argument lines must be byte-identical to
;;;; what they printed before the forms went variadic — no trailing space is
;;;; the thing an eye cannot see in a diff, so every print line ends in a "|"
;;;; marker that would move if a space leaked. And the arguments are typed and
;;;; dyn in the same call: each gets the walk it would get alone, the typed
;;;; ones selected at check time and the dyn ones handed to the runtime, so
;;;; the interleaving on one line is what proves the two sinks share a buffer.
(defonce boxed dyn 21)
(defonce dlabel dyn "mid")
(defn main [] ()
;; println at every arity
(println) ; bare newline
(println "one") ; the old single-argument form, unchanged
(println "a" "b")
(println "x:" 5 true)
;; mixed machine types in one call
(println 1 2.5 "s" false)
;; dyn and typed in the same call, dyn in the middle
(println "pre" boxed "post")
(println dlabel 7)
;; print: zero args is nothing, and no separator ever trails
(print)
(print "|")
(print "p")
(print "|")
(print "q" "r" 3)
(println "|"))