flan/test/programs/prelude-macros.flan

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])
(defvar 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)