Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
129 lines
5.6 KiB
Plaintext
129 lines
5.6 KiB
Plaintext
;; Erlang evaluator tests — sequential expressions.
|
|
|
|
(define er-eval-test-count 0)
|
|
(define er-eval-test-pass 0)
|
|
(define er-eval-test-fails (list))
|
|
|
|
(define
|
|
eev-deep=
|
|
(fn
|
|
(a b)
|
|
(cond
|
|
(and (= (type-of a) "dict") (= (type-of b) "dict"))
|
|
(let
|
|
((ka (sort (keys a))) (kb (sort (keys b))))
|
|
(and (= ka kb) (every? (fn (k) (eev-deep= (get a k) (get b k))) ka)))
|
|
(and (= (type-of a) "list") (= (type-of b) "list"))
|
|
(and
|
|
(= (len a) (len b))
|
|
(every? (fn (i) (eev-deep= (nth a i) (nth b i))) (range 0 (len a))))
|
|
:else (= a b))))
|
|
|
|
(define
|
|
er-eval-test
|
|
(fn
|
|
(name actual expected)
|
|
(set! er-eval-test-count (+ er-eval-test-count 1))
|
|
(if
|
|
(eev-deep= actual expected)
|
|
(set! er-eval-test-pass (+ er-eval-test-pass 1))
|
|
(append! er-eval-test-fails {:actual actual :expected expected :name name}))))
|
|
|
|
(define ev erlang-eval-ast)
|
|
(define nm (fn (v) (get v :name)))
|
|
|
|
;; ── literals ──────────────────────────────────────────────────────
|
|
(er-eval-test "int" (ev "42") 42)
|
|
(er-eval-test "zero" (ev "0") 0)
|
|
(er-eval-test "float" (ev "3.14") 3.14)
|
|
(er-eval-test "string" (ev "\"hi\"") "hi")
|
|
(er-eval-test "atom" (nm (ev "ok")) "ok")
|
|
(er-eval-test "atom true" (nm (ev "true")) "true")
|
|
(er-eval-test "atom false" (nm (ev "false")) "false")
|
|
|
|
;; ── arithmetic ────────────────────────────────────────────────────
|
|
(er-eval-test "add" (ev "1 + 2") 3)
|
|
(er-eval-test "sub" (ev "5 - 3") 2)
|
|
(er-eval-test "mul" (ev "4 * 3") 12)
|
|
(er-eval-test "div-real" (ev "10 / 4") 2.5)
|
|
(er-eval-test "div-int" (ev "10 div 3") 3)
|
|
(er-eval-test "rem" (ev "10 rem 3") 1)
|
|
(er-eval-test "div-neg" (ev "-10 div 3") -3)
|
|
(er-eval-test "precedence" (ev "1 + 2 * 3") 7)
|
|
(er-eval-test "parens" (ev "(1 + 2) * 3") 9)
|
|
(er-eval-test "unary-neg" (ev "-(1 + 2)") -3)
|
|
(er-eval-test "unary-neg int" (ev "-7") -7)
|
|
|
|
;; ── comparison ────────────────────────────────────────────────────
|
|
(er-eval-test "lt true" (nm (ev "1 < 2")) "true")
|
|
(er-eval-test "gt false" (nm (ev "1 > 2")) "false")
|
|
(er-eval-test "le equal" (nm (ev "2 =< 2")) "true")
|
|
(er-eval-test "ge equal" (nm (ev "2 >= 2")) "true")
|
|
(er-eval-test "eq" (nm (ev "2 == 2")) "true")
|
|
(er-eval-test "neq" (nm (ev "1 /= 2")) "true")
|
|
(er-eval-test "exact-eq same" (nm (ev "1 =:= 1")) "true")
|
|
(er-eval-test "exact-neq int" (nm (ev "1 =:= 2")) "false")
|
|
(er-eval-test "=/= true" (nm (ev "1 =/= 2")) "true")
|
|
(er-eval-test "atom-eq" (nm (ev "ok == ok")) "true")
|
|
(er-eval-test "atom-neq" (nm (ev "ok == error")) "false")
|
|
|
|
;; ── logical ───────────────────────────────────────────────────────
|
|
(er-eval-test "and tt" (nm (ev "true and true")) "true")
|
|
(er-eval-test "and tf" (nm (ev "true and false")) "false")
|
|
(er-eval-test "or tf" (nm (ev "true or false")) "true")
|
|
(er-eval-test
|
|
"andalso short"
|
|
(nm (ev "false andalso Neverref"))
|
|
"false")
|
|
(er-eval-test
|
|
"orelse short"
|
|
(nm (ev "true orelse Neverref"))
|
|
"true")
|
|
(er-eval-test "not true" (nm (ev "not true")) "false")
|
|
(er-eval-test "not false" (nm (ev "not false")) "true")
|
|
|
|
;; ── tuples & lists ────────────────────────────────────────────────
|
|
(er-eval-test "tuple tag" (get (ev "{1, 2, 3}") :tag) "tuple")
|
|
(er-eval-test "tuple len" (len (get (ev "{1, 2, 3}") :elements)) 3)
|
|
(er-eval-test "tuple elem" (nth (get (ev "{10, 20}") :elements) 1) 20)
|
|
(er-eval-test "empty tuple" (len (get (ev "{}") :elements)) 0)
|
|
(er-eval-test "nested tuple"
|
|
(nm (nth (get (ev "{ok, error}") :elements) 0)) "ok")
|
|
(er-eval-test "nil list" (get (ev "[]") :tag) "nil")
|
|
(er-eval-test "list head" (get (ev "[1, 2, 3]") :head) 1)
|
|
(er-eval-test
|
|
"list tail tail head"
|
|
(get (get (get (ev "[1, 2, 3]") :tail) :tail) :head)
|
|
3)
|
|
|
|
;; ── list ops ──────────────────────────────────────────────────────
|
|
(er-eval-test "++ head" (get (ev "[1, 2] ++ [3]") :head) 1)
|
|
(er-eval-test "++ last"
|
|
(get (get (get (ev "[1, 2] ++ [3]") :tail) :tail) :head) 3)
|
|
|
|
;; ── block ─────────────────────────────────────────────────────────
|
|
(er-eval-test "block last wins" (ev "begin 1, 2, 3 end") 3)
|
|
(er-eval-test "bare body" (ev "1, 2, 99") 99)
|
|
|
|
;; ── match + var ───────────────────────────────────────────────────
|
|
(er-eval-test "match bind-and-use" (ev "X = 5, X + 1") 6)
|
|
(er-eval-test "match sequential" (ev "X = 1, Y = 2, X + Y") 3)
|
|
(er-eval-test
|
|
"rebind equal ok"
|
|
(ev "X = 5, X = 5, X") 5)
|
|
|
|
;; ── if ────────────────────────────────────────────────────────────
|
|
(er-eval-test "if picks first" (ev "if true -> 1; true -> 2 end") 1)
|
|
(er-eval-test
|
|
"if picks second"
|
|
(nm (ev "if 1 > 2 -> bad; true -> good end"))
|
|
"good")
|
|
(er-eval-test
|
|
"if with guard"
|
|
(ev "X = 5, if X > 0 -> 1; true -> 0 end")
|
|
1)
|
|
|
|
(define
|
|
er-eval-test-summary
|
|
(str "eval " er-eval-test-pass "/" er-eval-test-count))
|