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.
104 lines
3.0 KiB
Plaintext
104 lines
3.0 KiB
Plaintext
;;;; comment, inc/dec, ++/--, and an empty body — the prelude's small macros,
|
|
;;;; asserted through a compiler that has to run them.
|
|
;;;;
|
|
;;;; These cannot be asserted in test_flan the way a special form can: a macro
|
|
;;;; is compiled into a shared object and dlopened into the compiler before
|
|
;;;; the first line below is parsed, so the only honest test of one is a
|
|
;;;; program that was built. macro-unless.flan beside this file is the same
|
|
;;;; argument for the same reason.
|
|
|
|
(defstruct Counter [hits i32 misses i32])
|
|
|
|
(defonce dyn-count dyn 5)
|
|
|
|
(defn show [label string n i32] ()
|
|
(print label)
|
|
(print " ")
|
|
(println n))
|
|
|
|
;; (comment ...) never reads its arguments, so nothing inside one has to be a
|
|
;; program. Everything in this function's comment would be a refusal written
|
|
;; anywhere else: a name nothing defines, a call at an arity it does not have,
|
|
;; a string added to a number, a field of a struct that has no such field.
|
|
;; The one rule it does obey is the reader's — delimiters balance and every
|
|
;; token is legal — because reading happens before any macro runs.
|
|
(defn commented [] i32
|
|
(comment
|
|
(no-such-function 1 2 3)
|
|
(show "too" "few")
|
|
(+ 1 "two")
|
|
(.nonexistent (Counter {}))
|
|
(defn this is not even a definition))
|
|
7)
|
|
|
|
(defn main [] i32
|
|
(println (commented))
|
|
|
|
;; inc and dec answer a number and change nothing.
|
|
(let [n 10]
|
|
(show "inc" (inc n))
|
|
(show "dec" (dec n))
|
|
(show "n unchanged" n))
|
|
|
|
;; Generic for free at every numeric type, because + and - already are.
|
|
;; Nothing below names a type twice and there is no per-type family.
|
|
(let [a (i8 1)
|
|
b (i16 1)
|
|
c 1
|
|
d (i64 1)
|
|
e (u8 1)
|
|
f (u16 1)
|
|
g (u32 1)
|
|
h (u64 1)]
|
|
(print (inc a)) (print " ")
|
|
(print (inc b)) (print " ")
|
|
(print (inc c)) (print " ")
|
|
(print (inc d)) (print " ")
|
|
(print (inc e)) (print " ")
|
|
(print (inc f)) (print " ")
|
|
(print (inc g)) (print " ")
|
|
(println (inc h)))
|
|
(let [x (f32 1.5)
|
|
y 1.5]
|
|
(print (inc x)) (print " ")
|
|
(println (dec y)))
|
|
(println (inc dyn-count))
|
|
|
|
;; ++ and -- change a place. Every place `set` takes is one: a local, a
|
|
;; field, an element, a deref.
|
|
(let [n 0]
|
|
(++ n)
|
|
(++ n)
|
|
(-- n)
|
|
(show "local" n))
|
|
|
|
(let [c (Counter {.hits 0 .misses 9})]
|
|
(++ (.hits c))
|
|
(++ (.hits c))
|
|
(-- (.misses c))
|
|
(show "field hits" (.hits c))
|
|
(show "field misses" (.misses c)))
|
|
|
|
(let [xs [10 20 30]]
|
|
(++ (at xs 1))
|
|
(-- (at xs 2))
|
|
(show "element 1" (at xs 1))
|
|
(show "element 2" (at xs 2)))
|
|
|
|
(let [n 100
|
|
p (addr n)]
|
|
(++ (deref p))
|
|
(show "through a pointer" n))
|
|
|
|
;; A body that was not written. (when test) and (unless test) are the guard
|
|
;; a program passes through while it is being written, and both expand to
|
|
;; the (do) they always would have — no branch taken, nothing printed, and
|
|
;; the form's value is () either way.
|
|
(let [n 0]
|
|
(when (= n 0))
|
|
(unless (= n 0))
|
|
(when (= n 0) (++ n))
|
|
(unless (= n 1) (++ n))
|
|
(show "after empty and written bodies" n))
|
|
0)
|