Merge pull request #532 from dubek/vhdl-fix-defmacro
[jackhill/mal.git] / impls / lib / test_cascade.mal
1 ;; Iteration on evaluations interpreted as boolean values.
2
3 (load-file "../lib/load-file-once.mal")
4 (load-file-once "../lib/trivial.mal") ; gensym
5
6 ;; `(cond test1 result1 test2 result2 .. testn resultn)`
7 ;; is rewritten (in the step files) as
8 ;; `(if test1 result1 (if test2 result2 (.. (if testn resultn nil))))`
9 ;; It is common that `testn` is `"else"`, `:else`, `true` or similar.
10
11 ;; `(or x1 x2 .. xn x)`
12 ;; is almost rewritten as
13 ;; `(if x1 x1 (if x2 x2 (.. (if xn xn x))))`
14 ;; except that each argument is evaluated at most once.
15 ;; Without arguments, returns `nil`.
16 (defmacro! or (fn* [& xs]
17 (if (< (count xs) 2)
18 (first xs)
19 (let* [r (gensym)]
20 `(let* (~r ~(first xs)) (if ~r ~r (or ~@(rest xs))))))))
21
22 ;; Conjonction of predicate values (pred x1) and .. and (pred xn)
23 ;; Evaluate `pred x` for each `x` in turn. Return `false` if a result
24 ;; is `nil` or `false`, without evaluating the predicate for the
25 ;; remaining elements. If all test pass, return `true`.
26 (def! every?
27 (fn* (pred xs)
28 ;; pred : Element -> interpreted as a logical value
29 ;; xs : sequence of Elements x1 x2 .. xn
30 ;; return : boolean
31 (cond (empty? xs) true
32 (pred (first xs)) (every? pred (rest xs))
33 true false)))
34
35 ;; Disjonction of predicate values (pred x1) or .. (pred xn)
36 ;; Evaluate `(pred x)` for each `x` in turn. Return the first result
37 ;; that is neither `nil` nor `false`, without evaluating the predicate
38 ;; for the remaining elements. If all tests fail, return nil.
39 (def! some
40 (fn* (pred xs)
41 ;; pred : Element -> interpreted as a logical value
42 ;; xs : sequence of Elements x1 x2 .. xn
43 ;; return : boolean
44 (if (empty? xs)
45 nil
46 (or (pred (first xs))
47 (some pred (rest xs))))))
48
49 ;; Search for first evaluation returning `nil` or `false`.
50 ;; Rewrite `x1 x2 .. xn x` as
51 ;; (let* [r1 x1]
52 ;; (if r1 test1
53 ;; (let* [r2 x2]
54 ;; ..
55 ;; (if rn
56 ;; x
57 ;; rn) ..)
58 ;; r1))
59 ;; Without arguments, returns `true`.
60 (defmacro! and
61 (fn* (& xs)
62 ;; Arguments and the result are interpreted as boolean values.
63 (cond (empty? xs) true
64 (= 1 (count xs)) (first xs)
65 true (let* (condvar (gensym))
66 `(let* (~condvar ~(first xs))
67 (if ~condvar (and ~@(rest xs)) ~condvar))))))