Added more unit tests
[parenscript.git] / tests / eval-tests.lisp
blobada049559e70c0a32dc8d1173cbe063899f6d00e
1 ;;; Copyright 2011-2012 Vladimir Sedach
3 ;;; SPDX-License-Identifier: BSD-3-Clause
5 ;;; Redistribution and use in source and binary forms, with or
6 ;;; without modification, are permitted provided that the following
7 ;;; conditions are met:
9 ;;; 1. Redistributions of source code must retain the above copyright
10 ;;; notice, this list of conditions and the following disclaimer.
12 ;;; 2. Redistributions in binary form must reproduce the above
13 ;;; copyright notice, this list of conditions and the following
14 ;;; disclaimer in the documentation and/or other materials provided
15 ;;; with the distribution.
17 ;;; 3. Neither the name of the copyright holder nor the names of its
18 ;;; contributors may be used to endorse or promote products derived
19 ;;; from this software without specific prior written permission.
21 ;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
22 ;;; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 ;;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 ;;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 ;;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
26 ;;; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 ;;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28 ;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 ;;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ;;; ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 ;;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 ;;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 ;;; POSSIBILITY OF SUCH DAMAGE.
35 (in-package #:parenscript.eval-tests)
36 (named-readtables:in-readtable :parenscript)
38 #+sbcl (declaim (sb-ext:muffle-conditions sb-ext:compiler-note))
40 (fiveam:in-suite parenscript.tests::eval-tests)
42 (test-js-eval number
46 (test-js-eval float
47 (< 123.12 123.123 123.124)
50 (test-js-eval string
51 "foobar"
52 "foobar")
54 (test-js-eval statements-and-expressions-2
55 ((lambda () (if 1 2 3)))
58 (test-js-eval statements-and-expressions-1
59 ((lambda () (+ 2 (if 1 2 3))))
62 (test-js-eval empty-array
63 (array)
64 '())
66 (test-js-eval funargs-let1
67 ((lambda (x)
68 (let ((x 10))
69 (incf x))
70 (incf x))
74 (test-js-eval times-rem
75 (* 12 (rem 10 3))
76 12)
78 (test-js-eval divide-rem
79 (rem 10 (/ 12 4))
82 (test-js-eval rem-divide
83 (/ 9 (rem 11 4))
86 (test-js-eval rem-multiply
87 (* 5 (rem 4 3))
90 (test-js-eval case-return-break-null
91 ((lambda (x) (case x
92 (1)
93 (2 3)))
95 :null)
97 (test-js-eval defun-return1
98 (progn (defun bar (x) (1+ x))
99 (bar 1))
102 (test-js-eval defun-return2
103 (progn (defun bar (fn)
104 (funcall fn))
106 (defun foo ()
107 (bar (lambda () (return-from foo 123))))
109 (foo))
110 123)
112 (test-js-eval defvar
113 (progn (defvar foo 1)
114 foo)
117 (test-js-eval block-dynamic-lambda
118 ((lambda () (block nil (return 4) (+ 1 2))))
121 (test-js-eval block-dynamic-lambda1
122 ((lambda () (block nil (return 4) (+ 1 2)) 5))
125 (test-js-eval loop-sum
126 (+ 1 (loop for i from 0 to 10 sum i))
129 (test-js-eval loop-funcall-sum
130 ((lambda (x) (1+ x)) (loop for i from 0 to 10 sum i))
133 (test-js-eval loop-funcall-if-sum
134 (progn (defun one-plus (x)
135 (1+ x))
137 (one-plus (if false 1 (loop for i from 0 to 10 sum i))))
140 (test-js-eval case-return-break1-broken-return
141 (progn (defun foo (x y)
142 (case x
143 ("bar" (if y (return-from foo 1)))
144 ("baz" 2)))
145 (list (foo "bar" t) (foo "bar" nil) (foo "baz" nil)))
146 '(1 :null 2))
148 (test-js-eval funcall-loop-doing
149 ((lambda (x) x)
150 (loop for i from 0 to 10 do (1+ i)))
151 :undefined)
153 (test-js-eval block-dynamic-lambda2
154 ((lambda () (1+ (block nil (return 4) (+ 1 2)))))
157 (test-js-eval block-dynamic-setf
158 (progn (defvar foo (block nil (return 4) (+ 1 2)))
159 foo)
162 (test-js-eval block-dynamic-return1
163 (progn (defvar foo ((lambda ()
164 (block nil
165 ((lambda () (return 6)))
166 (+ 1 2)))))
167 foo)
170 (test-js-eval block-lambda-dynamic-setf
171 (progn (defvar foo (block nil ((lambda () (return 4))) (+ 1 2)))
172 foo)
175 (test-js-eval block-lambda-dynamic-lambda
176 ((lambda () (block nil ((lambda () (return 4))) (+ 1 2))))
179 (test-js-eval return-from-flet
180 (progn (defun foo ()
181 (flet ((bar () (return-from foo 42)))
182 (bar)))
183 (foo))
186 (test-js-eval plus-block
187 (1+ (block nil (return 4) (+ 1 2)))
190 (test-js-eval let-closures-rename
191 (progn (defun make-closures ()
192 (list
193 (let ((x 1)) (lambda () (1+ x)))
194 (let ((x 2)) (lambda () (1+ x)))))
196 (defvar foo (make-closures))
198 (list (funcall (aref foo 0))
199 (funcall (aref foo 1))))
200 '(2 3))
202 (test-js-eval labels-return
203 ((lambda ()
204 (labels ((bar (x)
205 (when (evenp x)
206 (return-from bar "even"))
208 (bar 9))))
211 (test-js-eval labels-return1
212 (progn (defun foo ()
213 (labels ((bar (x)
214 (when (evenp x)
215 (return-from foo "even"))
217 (bar 8)
219 (foo))
220 "even")
222 (test-js-eval labels-return2
223 (progn (defun foo ()
224 (labels ((bar (x)
225 (flet ((foo (y)
226 (when (evenp (+ x y))
227 (return-from bar "even"))))
228 (foo 4)
231 (bar 8)))
232 (foo))
233 "even")
235 (test-js-eval labels-return3
236 (progn (defun foo ()
237 (labels ((bar (x)
238 (flet ((baz (y)
239 (when (evenp (+ x y))
240 (return-from foo "even"))))
241 (baz 4)
244 (bar 8)
246 (foo))
247 "even")
249 (test-js-eval toplevel-local-scope
250 (progn (defvar foo (create "fn" (let ((x 5)) (lambda () x))))
251 (funcall (getprop foo "fn")))
254 (test-js-eval special-var2
255 (progn (defvar *foo*)
256 (let* ((*baz* 3)
257 (*foo* 2))
258 (* *foo* 2 *baz*)))
261 (test-js-eval special-var3
262 (progn (defvar *foo* 1)
263 (+ *foo* (let* ((*baz* 3)
264 (*foo* 2))
265 (* *foo* 2 *baz*))))
268 (test-js-eval let3
269 (let ((x 3)
270 (y 2))
271 (+ x x))
274 (test-js-eval operator-expressions-array-nested-let
275 (list (let ((y 1)) y) 2)
276 '(1 2))
278 (test-js-eval block-return-plus
279 (+ 1 (block foobar (return-from foobar 2) 1))
282 (test-js-eval block-return-plus1
283 (+ 1 (block foobar (+ 4 ((lambda (x) (return-from foobar x)) 2)) 1))
286 (test-js-eval block-let
287 (block foobar
288 (let ((x 1))
289 (return-from foobar x)
293 (test-js-eval block-dynamic-return
294 (block nil (return 4) (+ 1 2))
297 (test-js-eval block-lambda-dynamic-return
298 (block nil ((lambda () (return 4))) (+ 1 2))
301 (test-js-eval nil-block-return-1
302 (block nil (return 1) 2)
305 (test-js-eval dolist-return
306 (dolist (x '(5 2 3))
307 (return (1+ x)))
310 (test-js-eval let-defun-toplevel
311 (progn (let ((foo 0))
312 (defun bar () foo))
313 (bar))
316 (test-js-eval let-defvar-toplevel
317 (progn (let ((foo 0))
318 (defvar bar (1+ foo)))
319 bar)
322 (test-js-eval values-not-returned
323 (let ((x 1))
324 (setf x (+ x (values 2 (incf x))))
328 (test-js-eval equality-nary1
329 (let ((x 10) (y 10) (z 10))
330 (= x y z))
333 (test-js-eval values-not-returned1
334 (let ((x 1))
335 (incf x (+ x (values 1 (incf x))))
339 (test-js-eval incf-incf
340 (let ((x 1))
341 (incf x (incf x))
345 (test-js-eval incf-setf
346 (let ((x 1))
347 (incf x (setf x 4))
351 (test-js-eval values0
352 ((lambda () (values)))
353 :null)
355 (test-js-eval mv-return1
356 (progn (defun foo ()
357 (values 1 2 3))
358 (multiple-value-bind (a b c) (foo)
359 (list a b c)))
360 '(1 2 3))
362 (test-js-eval dynamic-extent-function-return-values
363 (progn (defun foo ()
364 ((lambda ()
365 (return-from foo (values 1 2 3)))))
366 (multiple-value-bind (a b c) (foo)
367 (list a b c)))
368 '(1 2 3))
370 (test-js-eval plus-not-associative
371 (let ((str "a")
372 (n 1))
373 (+ str (+ n 1)))
374 "a2")
376 (test-js-eval loop-return
377 (progn (defun foo ()
378 (* 10 (loop for i from 0 below 10 do
379 (when (> i 3)
380 (return i)))))
381 (foo))
384 (test-js-eval for-arr-place-in
385 (loop :for (a b) :in '((2 3) (4 5)) :sum (+ a b))
388 (test-js-eval for-obj-place-in
389 (loop :for (:a :b) :in (list (create :a 2 :b 3)
390 (create :a 4 :b 5))
391 :summing (+ a b))
394 (test-js-eval for-arr-place-=
395 (flet ((foo () '(2 3)))
396 (loop :repeat 3 :for (a b) = (foo) :sum (+ a b)))
399 (test-js-eval for-obj-place-=
400 (flet ((foo () (create :a 2 :b 3)))
401 (loop :repeat 3 :for (:a :b) = (foo) :sum (+ a b)))
404 (test-js-eval loop-until1
405 (let ((x 0))
406 (loop :doing (incf x) :until t)
410 (test-js-eval loop-until2
411 (let ((b nil) (c nil))
412 (loop :for a :in '(4 9 10) :do (setf b a) :until (> a 5))
413 (loop :for a :in '(4 9 10) :until (> a 5) :do (setf c a))
414 (list b c))
415 '(9 4))
417 (test-js-eval loop-until3
418 (let ((x 0) (y 0))
419 (loop :do (incf x) :until (= x 5)
420 :do (incf y) :until (= y 3))
421 (list x y))
422 '(3 3))
424 (test-js-eval loop-with-clause
425 (loop for i :from 0 :to 5
426 with x
427 unless (< i 3)
428 do (return (setf x i)))
431 (test-js-eval loop-append
432 (loop :for i :from 0 :below 10 :by 3 :append (list i (* i 100)))
433 '(0 0 3 300 6 600 9 900))
435 (test-js-eval loop-appending
436 (loop :for i :from 0 :below 10 :by 3 :appending (list i (* i 100)))
437 '(0 0 3 300 6 600 9 900))
439 (test-js-eval loop-maximize
440 (loop :for i :in (list 1 5 3 2) :maximize i)
443 (test-js-eval loop-maximizing
444 (loop :for i :in (list 1 5 3 7) :maximizing i)
447 (test-js-eval loop-minimize
448 (loop :for i :in (list 1 5 3 2) :minimize i)
451 (test-js-eval loop-minimizing
452 (loop :for i :in (list 3 5 3 2) :minimizing i)
455 (test-js-eval loop-for-on
456 (loop :for (a b) :on '(10 20 30 40 50 60) :by 2 :collect (list b a))
457 '((20 10) (40 30) (60 50)))
459 (test-js-eval loop-parallel-clauses-with-return
460 (loop :for i :from 0 :below 10 :for x = (* i 10)
461 :when (> i 5) :do (return x)
462 :collecting i)
465 (test-js-eval loop-extended-conditional-clauses
466 (loop for i :from 0 :to 5
467 for x := (1+ i)
468 when x
469 collect x
470 and if (oddp x)
471 collect (1+ x)
472 else
473 collect (/ x 2)
474 end)
475 '(1 2 2 1 3 4 4 2 5 6 6 3))
477 (test-js-eval loop-extended-conditional-clauses1
478 (let* ((foo 0)
479 (bar (loop for i :from 0 :to 5
480 for x := (1+ i)
481 when x
482 collect x
483 and if (oddp x)
484 collect (1+ x)
485 else
486 collect (/ x 2)
488 and do (incf foo x))))
489 (funcall (@ bar push) foo)
490 bar)
491 '(1 2 2 1 3 4 4 2 5 6 6 3 21))
493 (test-js-eval for-loop-downfrom-to
494 (loop for i :downfrom 5 :to 0
495 collect i)
496 '(5 4 3 2 1 0))
498 (test-js-eval for-loop-downfrom-above
499 (loop for i :downfrom 5 :above 0
500 collect i)
501 '(5 4 3 2 1))
503 (test-js-eval loop-conditional-return-works
504 (block nil
505 (dotimes (i 10)
506 (if (< 10 i) (return i)))
507 (return -1))
510 (test-js-eval return-from-loop
511 (let ((a 0))
512 (dolist (x '(2 1 3))
513 (when (= x 1)
514 (return))
515 (incf a))
519 (test-js-eval for-loop-var-init-exp
520 ((lambda (x)
521 (do* ((y (if x 0 1) (1+ y))
522 (z 0 (1+ z)))
523 ((= y 3) z)))
524 true)
527 (test-js-eval dolist-return1
528 (dolist (x '(5 2 3))
529 (return (1+ x)))
532 (test-js-eval lambda-nil-return-implicit-nested
533 (progn (defun foo (x)
534 (block nil
535 (if x
536 (return 1)
537 (dotimes (i 4)
538 (return 1)))
541 (list (foo t) (foo nil)))
542 '(1 2))
544 (test-js-eval case-clauses0
545 (let* ((foo :bar)
546 (bar :baz)
547 (x bar))
548 (case x
549 ((:foo) 1)
550 ((:bar :baz) 2)))
553 (test-js-eval case-clauses-false
554 (* 2 (case (= 1 2)
555 (1 1)
556 (false 3)
557 (2 5)
558 (otherwise 7)))
561 (test-js-eval case-clauses-true
562 (* 2 (case (= 2 2)
563 (1 1)
564 ((t) 3)
565 (otherwise 7)))
568 ;;; needs MV pass-through to work
569 ;; (test-js-eval multiple-value-call-twice
570 ;; (progn
571 ;; (defun foo (x &optional y z)
572 ;; (if z
573 ;; (values x y z)
574 ;; (values x y)))
576 ;; (defun bar ()
577 ;; (foo 1 2 3)
578 ;; (foo 4 5))
580 ;; (multiple-value-bind (a b c) (bar)
581 ;; (list a b c)))
582 ;; '(4 5 :undefined))
584 (test-js-eval recursive-values
585 (progn
586 (defun foo (x)
587 (if (= 0 x)
588 (values 1 2 3 4)
589 (progn
590 (foo 0)
591 23)))
593 (defun bar ()
594 (foo 1))
596 (multiple-value-bind (a b c d) (bar)
597 (list a b c d)))
598 '(23 :undefined :undefined :undefined))
600 (test-js-eval recursive-values1
601 (progn
602 (defun foo (x)
603 (if (= 0 x)
604 (values 1 2 3)
605 (baz)))
607 (defun baz (x)
608 (foo 0)
611 (defun bar ()
612 (foo 1))
614 (multiple-value-bind (a b c d) (bar)
615 (list a b c d)))
616 '(23 :undefined :undefined :undefined))
618 (test-js-eval values-nonlocal-return
619 (progn
620 (defun foo (x)
621 (if (= 0 x)
622 (values 1 2 3)
623 (progn
624 (foo 0)
625 (throw 23))))
627 (defun bar ()
628 (try (foo 1)
629 (:catch (e)
630 27)))
632 (multiple-value-bind (a b c) (bar)
633 (list a b c)))
634 '(27 :undefined :undefined))
636 (test-js-eval values-nonlocal-return1
637 (progn
638 (defun foo (x)
639 (if (= 0 x)
640 (values 1 2 3)
641 (bar 0)))
643 (defun bar (x)
644 (try
645 (if (= x 0)
646 (progn
647 (foo 0)
648 (throw 11))
649 (foo x))
650 (:catch (e)
651 27)))
653 (multiple-value-bind (a b c) (bar 1)
654 (list a b c)))
655 '(27 :undefined :undefined))
657 (test-js-eval values-nonlocal-return2
658 (progn
659 (defun foo (x)
660 (try
661 (if (= 0 x)
662 (values 1 2 3)
663 (bar))
664 (:catch (e) 27)))
666 (defun bar ()
667 (foo 0)
668 (throw 13))
670 (multiple-value-bind (a b c) (foo 1)
671 (list a b c)))
672 '(27 :undefined :undefined))
674 (test-js-eval case-symbol-macro-key
675 (symbol-macrolet ((x 1))
676 (let ((blah 1))
677 (case blah
678 (0 3)
679 (x 7)
680 (t 13))))
683 (test-js-eval symbol-macro-funcall
684 (symbol-macrolet ((bar (getprop Math 'min)))
685 (funcall bar -1 2))
688 (test-js-eval negative-mod
689 (mod -12 7)
692 (test-js-eval negative-mod1
693 (mod -12 (funcall (@ Math floor) 7.5))
696 (test-js-eval negative-mod2
697 (1+ (mod -12 7))
700 (test-js-eval negative-rem
701 (rem -12 7)
704 (test-js-eval negative-rem1
705 (rem -12 (funcall (@ Math floor) 7.5))
708 (test-js-eval-epsilon trig1
709 (sinh 3.14)
710 11.530293)
712 (test-js-eval-epsilon trig2
713 (sinh (floor 3.14))
714 10.017875)
716 (test-js-eval-epsilon trig3
717 (cosh 3.14)
718 11.573576)
720 (test-js-eval-epsilon trig4
721 (cosh (floor 3.14))
722 10.067662)
724 (test-js-eval-epsilon trig5
725 (tanh 3.14)
726 0.9962602)
728 (test-js-eval-epsilon trig6
729 (tanh (floor 3.14))
730 0.9950548)
732 (test-js-eval-epsilon trig7
733 (asinh 3.14)
734 1.8618126)
736 (test-js-eval-epsilon trig8
737 (asinh (floor 3.14))
738 1.8184465)
740 (test-js-eval-epsilon trig7
741 (acosh 3.14)
742 1.8109914)
744 (test-js-eval-epsilon trig8
745 (acosh (floor 3.14))
746 1.7627472)
748 (test-js-eval-epsilon trig7
749 (atanh 0.71)
750 0.88718385)
752 (test-js-eval-epsilon trig8
753 (atanh (expt -0.71 3))
754 -0.37448788)
756 (test-js-eval let-let
757 (let ((x (let ((y 12))
758 (+ 1 2)
759 y)))
760 (1+ x))
763 (test-js-eval let-let1
764 (let ((x (let ((y 12))
765 (dolist (x '(1 2 3))
766 (* x x))
767 y)))
768 (1+ x))
771 (test-js-eval array-init-1
772 (make-array 2 :initial-contents '(10 20))
773 '(10 20))
775 (test-js-eval array-init-2
776 (make-array 5 :initial-element 10)
777 '(10 10 10 10 10))
779 (test-js-eval dotimes-block-return
780 (1+ (dotimes (x 3) (if (= x 2) (return (+ x x)))))
783 (test-js-eval labels-factorial
784 (progn
785 (defun fac (n)
786 (labels ((f (n a)
787 (if (< n 2)
789 (f (- n 1) (* n a)))))
790 (f n 1)))
791 (fac 5))
792 120)
794 (test-js-eval destructuring-bind1
795 ((lambda (a)
796 (when a
797 (destructuring-bind (b . c)
799 (list b c))))
800 '(1 2 3))
801 '(1 (2 3)))
803 (test-js-eval defun-not-a-docstring
804 (progn
805 (defun foo ()
806 "bar")
807 (foo))
808 "bar")
810 (test-js-eval lambda-not-a-docstring
811 ((lambda () "bar"))
812 "bar")
814 (test-js-eval loop-variable-capture1
815 (let ((x (make-array 10)))
816 (dotimes (i 10) (setf (aref x i) (lambda () i)))
817 (loop for x across x sum (funcall x)))
818 100)
820 (test-js-eval loop-variable-capture2
821 (let ((x (make-array 10)))
822 (dotimes (i 10)
823 (let ((y i))
824 (setf (aref x i) (lambda () y))))
825 (loop for x across x sum (funcall x)))
828 (test-js-eval loop-variable-capture3
829 (let ((x (make-array 10)))
830 (dotimes (i 10)
831 (let ((i i))
832 (setf (aref x i) (lambda () i))))
833 (loop for x across x sum (funcall x)))
836 (test-js-eval nested-let
837 (let ((x (let ((y 94))
838 y)))
842 (test-js-eval lambda-apply
843 ((lambda (x)
844 (apply (lambda (y) (1+ y))
846 (list 6))
849 (test-js-eval subtract-associative
850 (list (- 1 2 3)
851 (- 1 (- 2 3)))
852 '(-4 2))
854 (test-js-eval logand1
855 (let ((x 4583))
856 (setf x (logand x 947))
858 419)
860 (test-js-eval cons-cdr-clause-empty
861 ((lambda () (cond (923))))
862 923)
864 (test-js-eval labels-return-from
865 (labels ((bar (x)
866 (when (evenp x)
867 (return-from bar "even"))
868 "odd"))
869 (bar 9))
870 "odd")