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