WASM browser tests (web/tests/test-wasm-browser.sx): 32 tests - scope/context: push+read, default, nesting, pop reveals outer - multi-signal: effect tracks 2 signals, computed from 2 sources, unsubscribe on dependency change - reactive DOM: computed expression attrs, map rendering, component rendering, spread signal update, style attributes - conditional: if/when/cond/let/begin in render-to-dom VM HO form tests (lib/tests/test-vm.sx): +8 tests - map, filter, reduce, for-each, some, every? in vm-eval - nested map, map with closure over local 32/32 WASM (source+bytecode), 1593/1593 JS full (1 pre-existing silent). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
781 lines
21 KiB
Plaintext
781 lines
21 KiB
Plaintext
(define
|
|
vm-eval
|
|
(fn
|
|
(expr)
|
|
(let
|
|
((code (compile expr)))
|
|
(vm-execute-module (code-from-value code) {}))))
|
|
|
|
(define
|
|
vm-eval-with
|
|
(fn
|
|
(expr globals)
|
|
(let
|
|
((code (compile expr)))
|
|
(vm-execute-module (code-from-value code) globals))))
|
|
|
|
(defsuite
|
|
"vm-constants"
|
|
(deftest "number constant" (assert-equal 42 (vm-eval 42)))
|
|
(deftest "string constant" (assert-equal "hello" (vm-eval "hello")))
|
|
(deftest "boolean true" (assert-equal true (vm-eval true)))
|
|
(deftest "boolean false" (assert-equal false (vm-eval false)))
|
|
(deftest "nil constant" (assert-nil (vm-eval nil)))
|
|
(deftest "negative number" (assert-equal -7 (vm-eval -7)))
|
|
(deftest "float constant" (assert-equal 3.14 (vm-eval 3.14))))
|
|
|
|
(defsuite
|
|
"vm-arithmetic"
|
|
(deftest "addition" (assert-equal 5 (vm-eval (quote (+ 2 3)))))
|
|
(deftest "subtraction" (assert-equal 7 (vm-eval (quote (- 10 3)))))
|
|
(deftest "multiplication" (assert-equal 24 (vm-eval (quote (* 6 4)))))
|
|
(deftest "division" (assert-equal 5 (vm-eval (quote (/ 10 2)))))
|
|
(deftest
|
|
"nested arithmetic"
|
|
(assert-equal 14 (vm-eval (quote (+ (* 3 4) 2)))))
|
|
(deftest
|
|
"three-arg addition"
|
|
(assert-equal 15 (vm-eval (quote (+ 5 4 6))))))
|
|
|
|
(defsuite
|
|
"vm-comparison"
|
|
(deftest "equal numbers" (assert-equal true (vm-eval (quote (= 1 1)))))
|
|
(deftest
|
|
"unequal numbers"
|
|
(assert-equal false (vm-eval (quote (= 1 2)))))
|
|
(deftest "less than" (assert-equal true (vm-eval (quote (< 1 2)))))
|
|
(deftest "greater than" (assert-equal true (vm-eval (quote (> 5 3)))))
|
|
(deftest "not" (assert-equal true (vm-eval (quote (not false)))))
|
|
(deftest "not truthy" (assert-equal false (vm-eval (quote (not 42))))))
|
|
|
|
(defsuite
|
|
"vm-control-flow"
|
|
(deftest
|
|
"if true branch"
|
|
(assert-equal 1 (vm-eval (quote (if true 1 2)))))
|
|
(deftest
|
|
"if false branch"
|
|
(assert-equal 2 (vm-eval (quote (if false 1 2)))))
|
|
(deftest
|
|
"if without else returns nil"
|
|
(assert-nil (vm-eval (quote (if false 1)))))
|
|
(deftest
|
|
"when true evaluates body"
|
|
(assert-equal 42 (vm-eval (quote (when true 42)))))
|
|
(deftest
|
|
"when false returns nil"
|
|
(assert-nil (vm-eval (quote (when false 42)))))
|
|
(deftest
|
|
"and short-circuits on false"
|
|
(assert-equal false (vm-eval (quote (and true false 42)))))
|
|
(deftest
|
|
"and returns last truthy"
|
|
(assert-equal 3 (vm-eval (quote (and 1 2 3)))))
|
|
(deftest
|
|
"or short-circuits on true"
|
|
(assert-equal 1 (vm-eval (quote (or 1 false 2)))))
|
|
(deftest
|
|
"or returns false when all falsy"
|
|
(assert-equal false (vm-eval (quote (or false false false)))))
|
|
(deftest
|
|
"cond first match"
|
|
(assert-equal
|
|
"one"
|
|
(vm-eval (quote (cond (= 1 1) "one" (= 2 2) "two")))))
|
|
(deftest
|
|
"cond else clause"
|
|
(assert-equal
|
|
"none"
|
|
(vm-eval (quote (cond (= 1 2) "one" :else "none")))))
|
|
(deftest
|
|
"case match"
|
|
(assert-equal
|
|
"two"
|
|
(vm-eval (quote (case 2 1 "one" 2 "two" :else "other")))))
|
|
(deftest
|
|
"case else"
|
|
(assert-equal
|
|
"other"
|
|
(vm-eval (quote (case 99 1 "one" 2 "two" :else "other"))))))
|
|
|
|
(defsuite
|
|
"vm-let"
|
|
(deftest
|
|
"single binding"
|
|
(assert-equal 10 (vm-eval (quote (let ((x 10)) x)))))
|
|
(deftest
|
|
"multiple bindings"
|
|
(assert-equal 30 (vm-eval (quote (let ((x 10) (y 20)) (+ x y))))))
|
|
(deftest
|
|
"bindings are sequential"
|
|
(assert-equal 11 (vm-eval (quote (let ((x 10) (y (+ x 1))) y)))))
|
|
(deftest
|
|
"nested let"
|
|
(assert-equal
|
|
3
|
|
(vm-eval (quote (let ((x 1)) (let ((y 2)) (+ x y)))))))
|
|
(deftest
|
|
"inner let shadows outer"
|
|
(assert-equal 99 (vm-eval (quote (let ((x 1)) (let ((x 99)) x))))))
|
|
(deftest
|
|
"let body returns last expression"
|
|
(assert-equal 3 (vm-eval (quote (let ((x 1)) 1 2 3))))))
|
|
|
|
(defsuite
|
|
"vm-lambda"
|
|
(deftest
|
|
"lambda call"
|
|
(assert-equal
|
|
7
|
|
(vm-eval (quote (let ((f (fn (x) (+ x 2)))) (f 5))))))
|
|
(deftest
|
|
"lambda with multiple params"
|
|
(assert-equal
|
|
11
|
|
(vm-eval (quote (let ((add (fn (a b) (+ a b)))) (add 5 6))))))
|
|
(deftest
|
|
"higher-order: pass lambda to lambda"
|
|
(assert-equal
|
|
10
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((apply-fn (fn (f x) (f x))) (double (fn (n) (* n 2))))
|
|
(apply-fn double 5))))))
|
|
(deftest
|
|
"lambda returns lambda"
|
|
(assert-equal
|
|
15
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((make-adder (fn (n) (fn (x) (+ n x)))))
|
|
(let ((add10 (make-adder 10))) (add10 5)))))))
|
|
(deftest
|
|
"immediately invoked lambda"
|
|
(assert-equal 42 (vm-eval (quote ((fn (x) (* x 2)) 21))))))
|
|
|
|
(defsuite
|
|
"vm-closures"
|
|
(deftest
|
|
"closure captures local"
|
|
(assert-equal
|
|
10
|
|
(vm-eval (quote (let ((x 10)) (let ((f (fn () x))) (f)))))))
|
|
(deftest
|
|
"closure captures through two levels"
|
|
(assert-equal
|
|
30
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((x 10))
|
|
(let ((y 20)) (let ((f (fn () (+ x y)))) (f))))))))
|
|
(deftest
|
|
"two closures share upvalue"
|
|
(assert-equal
|
|
42
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((x 0))
|
|
(let
|
|
((set-x (fn (v) (set! x v))) (get-x (fn () x)))
|
|
(set-x 42)
|
|
(get-x)))))))
|
|
(deftest
|
|
"closure mutation visible to sibling"
|
|
(assert-equal
|
|
3
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((counter 0))
|
|
(let
|
|
((inc! (fn () (set! counter (+ counter 1)))))
|
|
(inc!)
|
|
(inc!)
|
|
(inc!)
|
|
counter)))))))
|
|
|
|
(defsuite
|
|
"vm-tco"
|
|
(deftest
|
|
"tail-recursive loop doesn't overflow"
|
|
(assert-equal
|
|
0
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((loop (fn (n) (if (<= n 0) 0 (loop (- n 1))))))
|
|
(loop 10000))))))
|
|
(deftest
|
|
"tail-recursive accumulator"
|
|
(assert-equal
|
|
5050
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((sum (fn (n acc) (if (<= n 0) acc (sum (- n 1) (+ acc n))))))
|
|
(sum 100 0)))))))
|
|
|
|
(defsuite
|
|
"vm-collections"
|
|
(deftest
|
|
"list construction"
|
|
(assert-equal (list 1 2 3) (vm-eval (quote (list 1 2 3)))))
|
|
(deftest "empty list" (assert-equal (list) (vm-eval (quote (list)))))
|
|
(deftest
|
|
"dict construction"
|
|
(let
|
|
((d (vm-eval (quote {:b 2 :a 1}))))
|
|
(assert-equal 1 (get d "a"))
|
|
(assert-equal 2 (get d "b"))))
|
|
(deftest
|
|
"list operations"
|
|
(assert-equal 1 (vm-eval (quote (first (list 1 2 3)))))
|
|
(assert-equal 3 (vm-eval (quote (len (list 1 2 3))))))
|
|
(deftest
|
|
"nested list"
|
|
(assert-equal
|
|
(list 1 (list 2 3))
|
|
(vm-eval (quote (list 1 (list 2 3)))))))
|
|
|
|
(defsuite
|
|
"vm-strings"
|
|
(deftest
|
|
"str concat"
|
|
(assert-equal "hello world" (vm-eval (quote (str "hello" " " "world")))))
|
|
(deftest
|
|
"string-length"
|
|
(assert-equal 5 (vm-eval (quote (string-length "hello")))))
|
|
(deftest
|
|
"str coerces numbers"
|
|
(assert-equal "42" (vm-eval (quote (str 42))))))
|
|
|
|
(defsuite
|
|
"vm-define"
|
|
(deftest
|
|
"top-level define"
|
|
(assert-equal 42 (vm-eval (quote (do (define x 42) x)))))
|
|
(deftest
|
|
"define function then call"
|
|
(assert-equal
|
|
10
|
|
(vm-eval (quote (do (define double (fn (n) (* n 2))) (double 5))))))
|
|
(deftest
|
|
"local define inside fn"
|
|
(assert-equal
|
|
30
|
|
(vm-eval
|
|
(quote (let ((f (fn (x) (define y (* x 2)) (+ x y)))) (f 10))))))
|
|
(deftest
|
|
"define with forward reference"
|
|
(assert-equal
|
|
120
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define fact (fn (n) (if (<= n 1) 1 (* n (fact (- n 1))))))
|
|
(fact 5)))))))
|
|
|
|
(defsuite
|
|
"vm-letrec"
|
|
(deftest
|
|
"letrec self-recursion"
|
|
(assert-equal
|
|
55
|
|
(vm-eval
|
|
(quote
|
|
(letrec
|
|
((sum-to (fn (n) (if (<= n 0) 0 (+ n (sum-to (- n 1)))))))
|
|
(sum-to 10))))))
|
|
(deftest
|
|
"letrec mutual recursion"
|
|
(assert-equal
|
|
true
|
|
(vm-eval
|
|
(quote
|
|
(letrec
|
|
((my-even? (fn (n) (if (= n 0) true (my-odd? (- n 1)))))
|
|
(my-odd? (fn (n) (if (= n 0) false (my-even? (- n 1))))))
|
|
(my-even? 10)))))))
|
|
|
|
(defsuite
|
|
"vm-quasiquote"
|
|
(deftest
|
|
"simple quasiquote"
|
|
(assert-equal
|
|
(list 1 2 3)
|
|
(vm-eval (quote (let ((x 2)) (quasiquote (1 (unquote x) 3)))))))
|
|
(deftest
|
|
"quasiquote with splice"
|
|
(assert-equal
|
|
(list 1 2 3 4)
|
|
(vm-eval
|
|
(quote
|
|
(let ((xs (list 2 3))) (quasiquote (1 (splice-unquote xs) 4))))))))
|
|
|
|
(defsuite
|
|
"vm-threading"
|
|
(deftest "thread-first" (assert-equal 7 (vm-eval (quote (-> 5 (+ 2))))))
|
|
(deftest
|
|
"thread-first chain"
|
|
(assert-equal 12 (vm-eval (quote (-> 10 (+ 5) (- 3)))))))
|
|
|
|
(defsuite
|
|
"vm-integration"
|
|
(deftest
|
|
"fibonacci"
|
|
(assert-equal
|
|
55
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
fib
|
|
(fn (n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))
|
|
(fib 10))))))
|
|
(deftest
|
|
"map via recursive define"
|
|
(assert-equal
|
|
(list 2 4 6)
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
my-map
|
|
(fn
|
|
(f lst)
|
|
(if
|
|
(empty? lst)
|
|
(list)
|
|
(cons (f (first lst)) (my-map f (rest lst))))))
|
|
(my-map (fn (x) (* x 2)) (list 1 2 3)))))))
|
|
(deftest
|
|
"filter via recursive define"
|
|
(assert-equal
|
|
(list 2 4)
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
my-filter
|
|
(fn
|
|
(pred lst)
|
|
(if
|
|
(empty? lst)
|
|
(list)
|
|
(if
|
|
(pred (first lst))
|
|
(cons (first lst) (my-filter pred (rest lst)))
|
|
(my-filter pred (rest lst))))))
|
|
(my-filter (fn (x) (even? x)) (list 1 2 3 4 5)))))))
|
|
(deftest
|
|
"reduce via recursive define"
|
|
(assert-equal
|
|
15
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
my-reduce
|
|
(fn
|
|
(f acc lst)
|
|
(if
|
|
(empty? lst)
|
|
acc
|
|
(my-reduce f (f acc (first lst)) (rest lst)))))
|
|
(my-reduce (fn (acc x) (+ acc x)) 0 (list 1 2 3 4 5)))))))
|
|
(deftest
|
|
"nested function calls"
|
|
(assert-equal
|
|
42
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define compose (fn (f g) (fn (x) (f (g x)))))
|
|
(define inc (fn (x) (+ x 1)))
|
|
(define double (fn (x) (* x 2)))
|
|
(let
|
|
((inc-then-double (compose double inc)))
|
|
(inc-then-double 20))))))))
|
|
|
|
(defsuite
|
|
"vm-recursive-mutation"
|
|
(deftest
|
|
"recursive append! to shared list"
|
|
(assert-equal
|
|
3
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
walk
|
|
(fn
|
|
(items result)
|
|
(when
|
|
(not (empty? items))
|
|
(append! result (first items))
|
|
(walk (rest items) result))))
|
|
(let
|
|
((result (list)))
|
|
(walk (list "a" "b" "c") result)
|
|
(len result)))))))
|
|
(deftest
|
|
"recursive tree walk with append!"
|
|
(assert-equal
|
|
7
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
walk-children
|
|
(fn
|
|
(items result walk-fn)
|
|
(when
|
|
(not (empty? items))
|
|
(walk-fn (first items) result)
|
|
(walk-children (rest items) result walk-fn))))
|
|
(define
|
|
walk
|
|
(fn
|
|
(expr result)
|
|
(cond
|
|
(not (list? expr))
|
|
(append! result "leaf")
|
|
(empty? expr)
|
|
nil
|
|
:else (do
|
|
(append! result "open")
|
|
(walk-children (rest expr) result walk)
|
|
(append! result "close")))))
|
|
(let
|
|
((tree (first (sx-parse "(div \"a\" (span \"b\") \"c\")")))
|
|
(result (list)))
|
|
(walk tree result)
|
|
(len result)))))))
|
|
(deftest
|
|
"recursive walk matching stepper split-tag pattern"
|
|
(assert-equal
|
|
16
|
|
(vm-eval
|
|
(quote
|
|
(do
|
|
(define
|
|
walk-each
|
|
(fn
|
|
(items result walk-fn)
|
|
(when
|
|
(not (empty? items))
|
|
(walk-fn (first items) result)
|
|
(walk-each (rest items) result walk-fn))))
|
|
(define
|
|
collect-children
|
|
(fn
|
|
(items cch)
|
|
(when
|
|
(not (empty? items))
|
|
(let
|
|
((a (first items)))
|
|
(if
|
|
(and
|
|
(list? a)
|
|
(not (empty? a))
|
|
(= (type-of (first a)) "symbol")
|
|
(starts-with? (symbol-name (first a)) "~"))
|
|
nil
|
|
(append! cch a))
|
|
(collect-children (rest items) cch)))))
|
|
(define
|
|
split-tag
|
|
(fn
|
|
(expr result)
|
|
(cond
|
|
(not (list? expr))
|
|
(append! result "leaf")
|
|
(empty? expr)
|
|
nil
|
|
(not (= (type-of (first expr)) "symbol"))
|
|
(append! result "leaf")
|
|
(is-html-tag? (symbol-name (first expr)))
|
|
(let
|
|
((cch (list)))
|
|
(collect-children (rest expr) cch)
|
|
(append! result "open")
|
|
(walk-each cch result split-tag)
|
|
(append! result "close"))
|
|
:else (append! result "expr"))))
|
|
(let
|
|
((parsed (sx-parse "(div (~cssx/tw :tokens \"text-center\")\n (h1 (~cssx/tw :tokens \"text-3xl font-bold mb-2\")\n (span (~cssx/tw :tokens \"text-rose-500\") \"the \")\n (span (~cssx/tw :tokens \"text-amber-500\") \"joy \")\n (span (~cssx/tw :tokens \"text-emerald-500\") \"of \")\n (span (~cssx/tw :tokens \"text-violet-600 text-4xl\") \"sx\")))"))
|
|
(result (list)))
|
|
(split-tag (first parsed) result)
|
|
(len result))))))))
|
|
|
|
(defsuite
|
|
"vm-nested-calls"
|
|
(deftest
|
|
"function call then continue"
|
|
(assert-equal
|
|
30
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((double (fn (x) (* x 2))))
|
|
(let ((a (double 5))) (+ a (double 10))))))))
|
|
(deftest
|
|
"three sequential function calls"
|
|
(assert-equal
|
|
60
|
|
(vm-eval
|
|
(quote (let ((f (fn (x) (* x 10)))) (+ (f 1) (f 2) (f 3)))))))
|
|
(deftest
|
|
"nested call: fn calls fn"
|
|
(assert-equal
|
|
20
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((add1 (fn (x) (+ x 1))) (double (fn (x) (* x 2))))
|
|
(double (add1 9)))))))
|
|
(deftest
|
|
"three-deep nested call"
|
|
(assert-equal
|
|
22
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((add1 (fn (x) (+ x 1)))
|
|
(double (fn (x) (* x 2)))
|
|
(inc10 (fn (x) (+ x 10))))
|
|
(inc10 (double (add1 5))))))))
|
|
(deftest
|
|
"side effect after function call"
|
|
(assert-equal
|
|
42
|
|
(vm-eval
|
|
(quote (let ((x 0) (f (fn (n) (* n 2)))) (set! x (f 21)) x)))))
|
|
(deftest
|
|
"multiple side effects after nested calls"
|
|
(assert-equal
|
|
35
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((a 0) (b 0) (f (fn (x) (+ x 10))))
|
|
(set! a (f 5))
|
|
(set! b (f 10))
|
|
(+ a b))))))
|
|
(deftest
|
|
"when body continues after function call"
|
|
(assert-equal
|
|
100
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((x 0) (f (fn (n) (* n 10))))
|
|
(when true (f 1) (set! x (f 10)))
|
|
x)))))
|
|
(deftest
|
|
"function returning closure then call"
|
|
(assert-equal
|
|
15
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((make-adder (fn (n) (fn (x) (+ n x)))))
|
|
(let
|
|
((add5 (make-adder 5)) (add10 (make-adder 10)))
|
|
(add5 (add10 0))))))))
|
|
(deftest
|
|
"for-each with side effects"
|
|
(assert-equal
|
|
6
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((sum 0))
|
|
(for-each (fn (x) (set! sum (+ sum x))) (list 1 2 3))
|
|
sum)))))
|
|
(deftest
|
|
"map then use result"
|
|
(assert-equal
|
|
20
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((doubled (map (fn (x) (* x 2)) (list 1 2 3 4))))
|
|
(reduce + 0 doubled))))))
|
|
(deftest
|
|
"function call in let binding then body"
|
|
(assert-equal
|
|
25
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((square (fn (x) (* x x))))
|
|
(let ((a (square 3)) (b (square 4))) (+ a b)))))))
|
|
(deftest
|
|
"callback from higher-order function"
|
|
(assert-equal
|
|
3
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((apply-twice (fn (f x) (f (f x)))))
|
|
(apply-twice (fn (n) (+ n 1)) 1))))))
|
|
(deftest
|
|
"do block with interleaved calls"
|
|
(assert-equal
|
|
30
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((x 0) (f (fn (n) (* n 5))))
|
|
(do
|
|
(set! x (+ x (f 1)))
|
|
(set! x (+ x (f 2)))
|
|
(set! x (+ x (f 3))))
|
|
x))))))
|
|
|
|
(defsuite
|
|
"vm-cek-bridge"
|
|
(deftest
|
|
"compiled fn calls another compiled fn"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define double (fn (x) (* x 2)))) g)
|
|
(vm-eval-with
|
|
(quote (define use-double (fn (n) (+ 1 (double n)))))
|
|
g)
|
|
(assert-equal 11 (vm-eval-with (quote (use-double 5)) g))))
|
|
(deftest
|
|
"compiled fn calls compiled fn then continues"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define helper (fn (x) (+ x 10)))) g)
|
|
(vm-eval-with
|
|
(quote (define main (fn () (let ((a (helper 5))) (+ a 100)))))
|
|
g)
|
|
(assert-equal 115 (vm-eval-with (quote (main)) g))))
|
|
(deftest
|
|
"compiled fn with side effect after nested call"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define f (fn (x) (* x 3)))) g)
|
|
(vm-eval-with
|
|
(quote
|
|
(define run (fn () (let ((x 0)) (set! x (f 7)) (+ x 1)))))
|
|
g)
|
|
(assert-equal 22 (vm-eval-with (quote (run)) g))))
|
|
(deftest
|
|
"three-deep compiled call chain"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define a (fn (x) (+ x 1)))) g)
|
|
(vm-eval-with (quote (define b (fn (x) (* (a x) 2)))) g)
|
|
(vm-eval-with (quote (define c (fn (x) (+ (b x) 100)))) g)
|
|
(assert-equal 112 (vm-eval-with (quote (c 5)) g))))
|
|
(deftest
|
|
"compiled fn with when block multiple body forms"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define f (fn (x) (* x 10)))) g)
|
|
(vm-eval-with
|
|
(quote
|
|
(define
|
|
run
|
|
(fn
|
|
()
|
|
(let
|
|
((result 0))
|
|
(when true (f 1) (set! result (f 5)))
|
|
result))))
|
|
g)
|
|
(assert-equal 50 (vm-eval-with (quote (run)) g))))
|
|
(deftest
|
|
"compiled fn for-each calling compiled fn"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define process (fn (x) (* x 2)))) g)
|
|
(vm-eval-with
|
|
(quote
|
|
(define
|
|
run
|
|
(fn
|
|
()
|
|
(let
|
|
((sum 0))
|
|
(for-each
|
|
(fn (x) (set! sum (+ sum (process x))))
|
|
(list 1 2 3))
|
|
sum))))
|
|
g)
|
|
(assert-equal 12 (vm-eval-with (quote (run)) g))))
|
|
(deftest
|
|
"compiled fn returns closure then caller continues"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define wrap (fn (x) (fn () x)))) g)
|
|
(vm-eval-with
|
|
(quote (define run (fn () (let ((f (wrap 42))) (+ (f) 8)))))
|
|
g)
|
|
(assert-equal 50 (vm-eval-with (quote (run)) g))))
|
|
(deftest
|
|
"multiple sequential calls from one compiled fn"
|
|
(let
|
|
((g (dict)))
|
|
(vm-eval-with (quote (define inc (fn (x) (+ x 1)))) g)
|
|
(vm-eval-with
|
|
(quote (define run (fn () (+ (inc 0) (inc 10) (inc 20)))))
|
|
g)
|
|
(assert-equal 33 (vm-eval-with (quote (run)) g)))))
|
|
|
|
(defsuite
|
|
"vm-ho-forms"
|
|
(deftest
|
|
"map in vm-eval"
|
|
(assert-equal
|
|
(list 2 4 6)
|
|
(vm-eval (quote (map (fn (x) (* x 2)) (list 1 2 3))))))
|
|
(deftest
|
|
"filter in vm-eval"
|
|
(assert-equal
|
|
(list 2 3 4)
|
|
(vm-eval (quote (filter (fn (x) (> x 1)) (list 1 2 3 4))))))
|
|
(deftest
|
|
"reduce in vm-eval"
|
|
(assert-equal
|
|
10
|
|
(vm-eval (quote (reduce (fn (acc x) (+ acc x)) 0 (list 1 2 3 4))))))
|
|
(deftest
|
|
"for-each with set! in vm-eval"
|
|
(assert-equal
|
|
6
|
|
(vm-eval
|
|
(quote
|
|
(let
|
|
((sum 0))
|
|
(for-each (fn (x) (set! sum (+ sum x))) (list 1 2 3))
|
|
sum)))))
|
|
(deftest
|
|
"some in vm-eval"
|
|
(assert-true
|
|
(vm-eval (quote (some (fn (x) (> x 3)) (list 1 2 3 4))))))
|
|
(deftest
|
|
"every? in vm-eval"
|
|
(assert-false
|
|
(vm-eval (quote (every? (fn (x) (> x 0)) (list 1 2 -1))))))
|
|
(deftest
|
|
"nested map in vm-eval"
|
|
(assert-equal
|
|
(list 1 4 9)
|
|
(vm-eval (quote (map (fn (x) (* x x)) (list 1 2 3))))))
|
|
(deftest
|
|
"map with closure over local"
|
|
(assert-equal
|
|
(list 11 12 13)
|
|
(vm-eval
|
|
(quote
|
|
(let ((offset 10)) (map (fn (x) (+ x offset)) (list 1 2 3))))))))
|