Implemented implicit blocks for defun/flet/labels and for loops.
[parenscript.git] / t / ps-tests.lisp
blob7e9280af3e004ad0163c91951bf6d82048eeafd0
1 (in-package #:parenscript-test)
3 (in-suite ps-tests)
5 (test-ps-js plus-is-not-commutative
6 (setf x (+ "before" x "after"))
7 "x = 'before' + x + 'after';")
9 (test-ps-js plus-works-if-first
10 (setf x (+ x "middle" "after"))
11 "x = x + 'middle' + 'after';")
13 (test-ps-js setf-side-effects
14 (progn
15 (let ((x 10))
16 (defun side-effect()
17 (setf x 4)
19 (setf x (+ 2 (side-effect) x 5))))
20 "var x = 10;
21 function sideEffect() {
22 x = 4;
23 return 3;
25 x = 2 + sideEffect() + x + 5;")
27 (test-ps-js method-call-op-form
28 (funcall (getprop (+ "" x) 'to-string))
29 "('' + x).toString();")
31 (test-ps-js method-call-op-form-args
32 (funcall (getprop (+ "" x) 'foo) 1 2 :baz 3)
33 "('' + x).foo(1, 2, 'baz', 3);")
35 (test-ps-js method-call-string
36 ((getprop "hi" 'to-string))
37 "'hi'.toString();")
39 (test-ps-js method-call-conditional
40 ((if a x y) 1)
41 "(a ? x : y)(1);")
43 (test-ps-js method-call-variable
44 ((@ x to-string))
45 "x.toString();")
47 (test-ps-js method-call-array
48 ((@ (list 10 20) to-string))
49 "[ 10, 20 ].toString();")
51 (test-ps-js method-call-lambda-call
52 (funcall (getprop (funcall (lambda (x) x) 10) 'to-string))
53 "(function (x) { return x; })(10).toString();")
55 (test no-whitespace-before-dot
56 (let* ((str (ps* '((@ ((lambda (x) x) 10) to-string))))
57 (dot-pos (position #\. str :test #'char=))
58 (char-before (elt str (1- dot-pos)))
59 (a-parenthesis #\)))
60 (is (char= char-before a-parenthesis))))
62 (test-ps-js simple-getprop
63 (let ((foo (create a 1)))
64 (alert (getprop foo 'a)))
65 "var foo = { a : 1 };
66 alert(foo.a);")
68 (test-ps-js buggy-getprop
69 (getprop foo slot-name)
70 "foo[slotName];")
72 (test-ps-js buggy-getprop-two
73 (getprop foo (get-slot-name))
74 "foo[getSlotName()];")
76 (test-ps-js old-case-is-now-switch
77 ;; Switch was "case" before, but that was very non-lispish.
78 ;; For example, this code makes three messages and not one
79 ;; which may have been expected. This is because a switch
80 ;; statment must have a break statement for it to return
81 ;; after the alert. Otherwise it continues on the next
82 ;; clause.
83 (switch (aref blorg i)
84 (1 (alert "one"))
85 (2 (alert "two"))
86 (default (alert "default clause")))
87 "switch (blorg[i]) {
88 case 1: alert('one');
89 case 2: alert('two');
90 default: alert('default clause');
91 };")
93 (test-ps-js lisp-like-case
94 (case (aref blorg i)
95 (1 (alert "one"))
96 (2 (alert "two"))
97 (default (alert "default clause")))
98 "switch (blorg[i]) {
99 case 1:
100 alert('one');
101 break;
102 case 2:
103 alert('two');
104 break;
105 default: alert('default clause');
106 };")
109 (test-ps-js even-lispier-case
110 (case (aref blorg i)
111 ((1 2) (alert "Below three"))
112 (3 (alert "Three"))
113 (t (alert "Something else")))
114 "switch (blorg[i]) {
115 case 1:
116 case 2:
117 alert('Below three');
118 break;
119 case 3:
120 alert('Three');
121 break;
122 default: alert('Something else');
123 };")
125 (test-ps-js otherwise-case
126 (case (aref blorg i)
127 (1 (alert "one"))
128 (otherwise (alert "default clause")))
129 "switch (blorg[i]) {
130 case 1:
131 alert('one');
132 break;
133 default: alert('default clause');
134 };")
136 (test escape-sequences-in-string
137 (let ((escapes `((#\\ . #\\)
138 (#\b . #\Backspace)
139 (#\f . ,(code-char 12))
140 ("u000B" . ,(code-char #x000b));;Vertical tab, too uncommon to bother with
141 (#\n . #\Newline)
142 (#\r . #\Return)
143 (#\' . #\');;Double quote need not be quoted because parenscript strings are single quoted
144 (#\t . #\Tab)
145 ("u001F" . ,(code-char #x001f));; character below 32
146 ("u0080" . ,(code-char 128)) ;;Character over 127. Actually valid, parenscript escapes them to be sure.
147 ("uABCD" . ,(code-char #xabcd)))));; Really above ascii.
148 (loop for (js-escape . lisp-char) in escapes
149 for generated = (ps-doc* `(let ((x ,(format nil "hello~ahi" lisp-char)))))
150 for wanted = (format nil "var x = 'hello\\~ahi';" js-escape)
151 do (is (string= (normalize-js-code generated) wanted)))))
153 (test-ps-js getprop-setf
154 (setf (getprop x 'y) (+ (+ a 3) 4))
155 "x.y = a + 3 + 4;")
157 (test-ps-js getprop-conditional1
158 (getprop (if zoo foo bar) 'x)
159 "(zoo ? foo : bar).x;")
161 (test-ps-js getprop-conditional2
162 (getprop (if (not zoo) foo bar) 'x)
163 "(!zoo ? foo : bar).x;")
165 (test script-star-eval1
166 (is (string= "x = 1; y = 2;" (normalize-js-code (ps* '(setf x 1) '(setf y 2))))))
168 (test script-star-eval2
169 (is (string= "x = 1;" (normalize-js-code (ps* '(setf x 1))))))
171 (test-ps-js list-with-single-nil
172 (array nil)
173 "[null];")
175 (test-ps-js quoted-nil-is-array
176 'nil
177 "[];")
179 (test-ps-js defsetf1
180 (progn (defsetf baz (x y) (newval) `(set-baz ,x ,y ,newval))
181 (setf (baz 1 2) 3))
182 "var _js2 = 1;
183 var _js3 = 2;
184 var _js1 = 3;
185 setBaz(_js2, _js3, _js1);")
187 (test-ps-js setf-macroexpands1
188 (macrolet ((bar (x y)
189 `(aref ,x ,y 1)))
190 (setf (bar foo 2) 3))
191 "foo[2][1] = 3;")
193 (test-ps-js defsetf-short
194 (progn (defsetf baz set-baz "docstring")
195 (setf (baz 1 2 3) "foo"))
196 "setBaz(1, 2, 3, 'foo');")
198 (test-ps-js defun-setf1
199 (progn (defun (setf some-thing) (new-val i1 i2)
200 (setf (aref *some-thing* i1 i2) new-val))
201 (setf (some-thing 1 2) "foo"))
202 "function __setf_someThing(newVal, i1, i2) {
203 return SOMETHING[i1][i2] = newVal;
205 __setf_someThing('foo', 1, 2);")
207 (test-ps-js defun-optional1
208 (defun test-opt (&optional x)
209 (if x "yes" "no"))
210 "function testOpt(x) {
211 return x ? 'yes' : 'no';
212 };")
214 (test-ps-js defun-optional2
215 (defun foo (x &optional y)
216 (+ x y))
217 "function foo(x, y) {
218 return x + y;
219 };")
221 (test-ps-js defun-optional3
222 (defun blah (&optional (x 0))
224 "function blah(x) {
225 if (x === undefined) {
226 x = 0;
228 return x;
229 };")
231 (test-ps-js defun-optional4
232 (lambda (&optional (x 0 supplied?))
234 "function (x) {
235 var suppliedwhat = x !== undefined;
236 if (!suppliedwhat) {
237 x = 0;
239 return x;
240 };")
242 (test-ps-js return-nothing
243 (return)
244 "return null;")
246 (test-ps-js set-timeout
247 (set-timeout (lambda () (alert "foo")) 10)
248 "setTimeout(function () { return alert('foo'); }, 10);")
250 (test-ps-js operator-precedence
251 (* 3 (+ 4 5) 6)
252 "3 * (4 + 5) * 6;")
254 (test-ps-js operators-1
255 (in prop obj)
256 "prop in obj;")
258 (test-ps-js incf1
259 (incf foo bar)
260 "foo += bar;")
262 (test-ps-js decf1
263 (decf foo bar)
264 "foo -= bar;")
266 (test-ps-js incf2
267 (incf x 5)
268 "x += 5;")
270 (test-ps-js decf2
271 (decf y 10)
272 "y -= 10;")
274 (test-ps-js setf-conditional
275 (setf foo (if x 1 2))
276 "foo = x ? 1 : 2;")
278 (test-ps-js obj-literal-numbers
279 (create 1 "foo")
280 "{ 1 : 'foo' };")
282 (test-ps-js obj-literal-strings
283 (create "foo" 2)
284 "{ 'foo' : 2 };")
286 (test-ps-js getprop-string
287 (getprop foo "bar")
288 "foo['bar'];")
290 (test-ps-js getprop-string1
291 (getprop "bar" 'length)
292 "'bar'.length;")
294 (test-ps-js getprop-progn
295 (getprop (progn (some-fun "abc") "123") "length")
296 "(someFun('abc'), '123')['length'];")
298 (test-ps-js method-call-block
299 ((@ (progn (some-fun "abc") "123") to-string))
300 "(someFun('abc'), '123').toString();")
302 (test-ps-js create-blank
303 (create)
304 "{ };")
306 (test-ps-js blank-object-literal
308 "{ };")
310 (test-ps-js array-literal1
312 "[];")
314 (test-ps-js array-literal2
315 ([])
316 "[];")
318 (test-ps-js array-literal3
319 ([] 1 2 3)
320 "[1, 2, 3];")
322 (test-ps-js array-literal4
323 ([] 1 (2 3))
324 "[1, [2, 3]];")
326 (test-ps-js array-literal5
327 ([] (1 2) ("a" "b"))
328 "[[1, 2], ['a', 'b']];")
330 (test-ps-js defun-rest1
331 (defun foo (&rest bar)
332 (alert (aref bar 1)))
333 "function foo() {
334 var bar = [];
335 for (var i1 = 0; i1 < arguments.length - 0; i1 += 1) {
336 bar[i1] = arguments[i1 + 0];
338 return alert(bar[1]);
339 };")
341 (test-ps-js defun-rest2
342 (defun foo (baz &rest bar) (+ baz (aref bar 1)))
343 "function foo(baz) {
344 var bar = [];
345 for (var i1 = 0; i1 < arguments.length - 1; i1 += 1) {
346 bar[i1] = arguments[i1 + 1];
348 return baz + bar[1];
349 };")
351 (test-ps-js defun-keyword1
352 (defun zoo (foo bar &key baz) (+ foo bar baz))
353 "function zoo(foo, bar) {
354 var baz = null;
355 var _js2 = arguments.length;
356 for (var n1 = 2; n1 < _js2; n1 += 2) {
357 switch (arguments[n1]) {
358 case 'baz':
359 baz = arguments[n1 + 1];
362 return foo + bar + baz;
363 };")
365 (test-ps-js defun-keyword2
366 (defun zoo (&key baz) (* baz baz))
367 "function zoo() {
368 var baz = null;
369 var _js2 = arguments.length;
370 for (var n1 = 0; n1 < _js2; n1 += 2) {
371 switch (arguments[n1]) {
372 case 'baz':
373 baz = arguments[n1 + 1];
376 return baz * baz;
377 };")
379 (test-ps-js defun-keyword3
380 (defun zoo (&key baz (bar 4)) (* baz bar))
381 "function zoo() {
382 var baz = null;
383 var bar = 4;
384 var _js2 = arguments.length;
385 for (var n1 = 0; n1 < _js2; n1 += 2) {
386 switch (arguments[n1]) {
387 case 'baz':
388 baz = arguments[n1 + 1];
389 break;
390 case 'bar':
391 bar = arguments[n1 + 1];
394 return baz * bar;
395 };")
397 (test-ps-js defun-keyword4
398 (defun hello-world (&key ((:my-name-key my-name) 1))
399 my-name)
400 "function helloWorld() {
401 var myName = 1;
402 var _js2 = arguments.length;
403 for (var n1 = 0; n1 < _js2; n1 += 2) {
404 switch (arguments[n1]) {
405 case 'my-name-key':
406 myName = arguments[n1 + 1];
409 return myName;
410 };")
412 (test-ps-js defun-keyword-supplied
413 (lambda (&key (foo 1 supplied?))
414 foo)
415 "function () {
416 var suppliedwhat = null;
417 var foo = 1;
418 var _js2 = arguments.length;
419 for (var n1 = 0; n1 < _js2; n1 += 2) {
420 switch (arguments[n1]) {
421 case 'foo':
422 foo = arguments[n1 + 1];
423 suppliedwhat = true;
426 return foo;
427 };")
429 (test-ps-js keyword-funcall1
430 (func :baz 1)
431 "func('baz', 1);")
433 (test-ps-js keyword-funcall2
434 (func :baz 1 :bar foo)
435 "func('baz', 1, 'bar', foo);")
437 (test-ps-js keyword-funcall3
438 (fun a b :baz c)
439 "fun(a, b, 'baz', c);")
441 (test-ps-js cond1
442 (cond ((= x 1) 1))
443 "if (x === 1) {
445 };")
447 (test-ps-js cond2
448 (cond ((= x 1) 2)
449 ((= y (* x 4)) (foo "blah") (* x y)))
450 "if (x === 1) {
452 } else if (y === x * 4) {
453 foo('blah');
454 x * y;
455 };")
457 (test-ps-js if-exp-without-else-return
458 (return (if x 1))
459 "return x ? 1 : null;")
461 (test-ps-js progn-expression-single-statement
462 (return (progn (* x y)))
463 "return x * y;")
465 (test-ps-js cond-expression1
466 (defun foo ()
467 (cond ((< 1 2) (bar "foo") (* 4 5))))
468 "function foo() {
469 if (1 < 2) {
470 bar('foo');
471 return 4 * 5;
473 };")
475 (test-ps-js cond-expression2
476 (defun foo ()
477 (cond ((< 2 1) "foo")
478 ((= 7 7) "bar")))
479 "function foo() {
480 if (2 < 1) {
481 return 'foo';
482 } else if (7 === 7) {
483 return 'bar';
485 };")
487 (test-ps-js cond-expression-final-t-clause
488 (defun foo ()
489 (cond ((< 1 2) (bar "foo") (* 4 5))
490 ((= a b) (+ c d))
491 ((< 1 2 3 4 5) x)
492 (t "foo")))
493 "function foo() {
494 var _cmp3;
495 var _cmp2;
496 var _cmp1;
497 if (1 < 2) {
498 bar('foo');
499 return 4 * 5;
500 } else if (a === b) {
501 return c + d;
502 } else if (_cmp1 = 2, _cmp2 = 3, _cmp3 = 4, 1 < _cmp1 && _cmp1 < _cmp2 && _cmp2 < _cmp3 && _cmp3 < 5) {
503 return x;
504 } else {
505 return 'foo';
507 };")
509 (test-ps-js cond-expression-middle-t-clause ;; should this signal a warning?
510 (defun foo ()
511 (cond ((< 2 1) 5)
512 (t "foo")
513 ((< 1 2) "bar")))
514 "function foo() {
515 if (2 < 1) {
516 return 5;
517 } else {
518 return 'foo';
520 };")
522 (test-ps-js funcall-if-expression
523 (funcall (getprop document 'write)
524 (if (= *linkornot* 1)
525 (ps-html ((:a :href "#"
526 :onclick (ps-inline (transport)))
527 img))
528 img))
529 "document.write(LINKORNOT === 1 ? ['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">', img, '</A>']['join']('') : img);")
531 (test-ps-js negate-number-literal
532 (- 1)
533 "-1;")
535 (test macro-environment1
536 (is (string= (normalize-js-code (let* ((macroname (gensym)))
537 (ps* `(defmacro ,macroname (x) `(+ ,x 123))
538 `(defun test1 ()
539 (macrolet ((,macroname (x) `(aref data ,x)))
540 (when (,macroname x)
541 (setf (,macroname x) 123)))))))
542 (normalize-js-code
543 "function test1() {
544 if (data[x]) {
545 return data[x] = 123;
547 };"))))
549 (test macro-environment2
550 (is (string= (normalize-js-code (let ((outer-lexical-variable 1))
551 (defpsmacro macro-environment2-macro (x)
552 `(+ ,outer-lexical-variable ,x))
553 (ps* '(macro-environment2-macro 2))))
554 (normalize-js-code "1 + 2;"))))
556 (test-ps-js ampersand-whole-1
557 (macrolet ((foo (&whole foo bar baz)
558 (declare (ignore bar baz))
559 (format nil "~a" foo)))
560 (foo 1 2))
561 "'(FOO 1 2)';")
563 (test-ps-js keyword-consistent
565 "'x';")
567 (test-ps-js simple-symbol-macrolet
568 (symbol-macrolet ((x 1)) x)
569 "1;")
571 (test-ps-js compound-symbol-macrolet
572 (symbol-macrolet ((x 123)
573 (y (* 2 x)))
575 "2 * 123;")
577 (test-ps-js define-symbol-macro
578 (progn (define-symbol-macro tst-sym-macro 2)
579 tst-sym-macro)
580 "2;")
582 (test-ps-js define-symbol-macro1
583 (progn (define-symbol-macro tst-sym-macro1 2)
584 (foo tst-sym-macro1))
585 "foo(2);")
587 (test-ps-js expression-progn
588 (1+ (progn (foo) (if x 1 2)))
589 "(foo(), x ? 1 : 2) + 1;")
591 (test-ps-js let-decl-in-expression
592 (defun f (x)
593 (if x 1 (let* ((foo x)) foo)))
594 "function f(x) {
595 if (x) {
596 return 1;
597 } else {
598 var foo = x;
599 return foo;
601 };")
603 (test-ps-js special-var1
604 (progn (defvar *foo*)
605 (let* ((*foo* 2))
606 (* *foo* 2)))
607 "var FOO;
608 var FOO_TMPSTACK1;
609 try {
610 FOO_TMPSTACK1 = FOO;
611 FOO = 2;
612 FOO * 2;
613 } finally {
614 FOO = FOO_TMPSTACK1;
615 };")
617 (test-ps-js special-var2
618 (progn (defvar *foo*)
619 (let* ((*baz* 3)
620 (*foo* 2))
621 (* *foo* 2 *baz*)))
622 "var FOO;
623 var BAZ = 3;
624 var FOO_TMPSTACK1;
625 try {
626 FOO_TMPSTACK1 = FOO;
627 FOO = 2;
628 FOO * 2 * BAZ;
629 } finally {
630 FOO = FOO_TMPSTACK1;
631 };")
633 (test-ps-js literal1
634 (setf x undefined)
635 "x = undefined;")
637 (test-ps-js literal2
638 (aref this x)
639 "this[x];")
641 (test-ps-js setf-dec1
642 (setf x (- 1 x 2))
643 "x = 1 - x - 2;")
645 (test-ps-js setf-dec2
646 (setf x (- x 1 2))
647 "x = x - 1 - 2;")
649 (test-ps-js special-char-equals
650 blah=
651 "blahequals;")
653 (test-ps-js setf-operator-priority
654 (return (or (getprop cache id)
655 (setf (getprop cache id) ((@ document get-element-by-id) id))))
656 "return cache[id] || (cache[id] = document.getElementById(id));")
658 (test-ps-js aref-operator-priority
659 (aref (if (and x (> (length x) 0))
660 (aref x 0)
663 "(x && x.length > 0 ? x[0] : y)[z];")
665 (test-ps-js aref-operator-priority1
666 (aref (or (getprop x 'y)
667 (getprop a 'b))
669 "(x.y || a.b)[z];")
671 (test-ps-js aref-operator-priority2
672 (aref (if a b c) 0)
673 "(a ? b : c)[0];")
675 (test-ps-js negate-operator-priority
676 (- (if x y z))
677 "-(x ? y : z);")
679 (test-ps-js op-p1
680 (new (or a b))
681 "new (a || b);")
683 (test-ps-js op-p2
684 (delete (if a (or b c) d))
685 "delete (a ? b || c : d);")
687 (test-ps-js op-p3
688 (not (if (or x (not y)) z))
689 "!(x || !y ? z : null);")
691 (test-ps-js op-p4
692 (- (- (* 1 2) 3))
693 "-(1 * 2 - 3);")
695 (test-ps-js op-p5
696 (instanceof (or a b) (if x y z))
697 "((a || b) instanceof (x ? y : z));")
699 (test-ps-js op-p7
700 (or x (if (= x 0) "zero" "empty"))
701 "x || (x === 0 ? 'zero' : 'empty');")
703 (test-ps-js named-op-expression
704 (throw (if a b c))
705 "throw a ? b : c;")
707 (test-ps-js named-op-expression1
708 (typeof (or x y))
709 "typeof (x || y);")
711 (test-ps-js aref-array-expression
712 (aref (or a b c) 0)
713 "(a || b || c)[0];")
715 (test-ps-js getprop-operator
716 (getprop (or a b c) 'd)
717 "(a || b || c).d;")
719 (test-ps-js getprop-parens
720 (getprop (getprop foo 'bar) 'baz)
721 "foo.bar.baz;")
723 (test-ps-js funcall-funcall
724 ((foo))
725 "foo()();")
727 (test-ps-js expression-funcall
728 ((or (@ window eval) eval) foo nil)
729 "(window.eval || eval)(foo, null);")
731 (test-ps-js expression-funcall1
732 (((or (@ window eval) eval) foo nil))
733 "(window.eval || eval)(foo, null)();")
735 (test-ps-js expression-funcall2
736 (((or (@ window eval) eval)) foo nil)
737 "(window.eval || eval)()(foo, null);")
739 (test-ps-js who-html1
740 (who-ps-html (:span :class "ticker-symbol"
741 :ticker-symbol symbol
742 (:a :href "http://foo.com"
743 symbol)
744 (:span :class "ticker-symbol-popup")))
745 "['<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"', symbol, '\"><A HREF=\"http://foo.com\">', symbol, '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>']['join']('');")
747 (test-ps-js flet1
748 ((lambda () (flet ((foo (x)
749 (1+ x)))
750 (foo 1))))
751 "(function () {
752 var foo = function (x) {
753 return x + 1;
755 return foo(1);
756 })();")
758 (test-ps-js flet2
759 (flet ((foo (x) (1+ x))
760 (bar (y) (+ 2 y)))
761 (bar (foo 1)))
762 "var foo = function (x) {
763 return x + 1;
765 var bar = function (y) {
766 return 2 + y;
768 bar(foo(1));")
770 (test-ps-js flet3
771 (flet ((foo (x) (+ 2 x)))
772 (flet ((foo (x) (1+ x))
773 (bar (y) (+ 2 (foo y))))
774 (bar (foo 1))))
775 "var foo = function (x) {
776 return 2 + x;
778 var foo1 = function (x) {
779 return x + 1;
781 var bar = function (y) {
782 return 2 + foo(y);
784 bar(foo1(1));")
786 (test-ps-js labels1
787 ((lambda () (labels ((foo (x)
788 (if (= 0 x)
790 (+ x (foo (1- x))))))
791 (foo 3))))
792 "(function () {
793 var foo = function (x) {
794 if (0 === x) {
795 return 0;
796 } else {
797 return x + foo(x - 1);
800 return foo(3);
801 })();")
803 (test-ps-js labels2
804 (labels ((foo (x) (1+ (bar x)))
805 (bar (y) (+ 2 (foo y))))
806 (bar (foo 1)))
807 "var foo = function (x) {
808 return bar(x) + 1;
810 var bar = function (y) {
811 return 2 + foo(y);
813 bar(foo(1));")
815 (test-ps-js labels3
816 (labels ((foo (x) (1+ x))
817 (bar (y) (+ 2 (foo y))))
818 (bar (foo 1)))
819 "var foo = function (x) {
820 return x + 1;
822 var bar = function (y) {
823 return 2 + foo(y);
825 bar(foo(1));")
827 (test-ps-js for-loop-var-init-exp
828 ((lambda (x)
829 (do* ((y (if x 0 1) (1+ y))
830 (z 0 (1+ z)))
831 ((= y 3) z)))
832 true)
833 "(function (x) {
834 return (function () {
835 for (var y = x ? 0 : 1, z = 0; y !== 3; y += 1, z += 1) {
837 return z;
838 })();
839 })(true);")
841 (test-ps-js math-pi
843 "Math.PI;")
845 (test-ps-js literal-array
846 '(1 2 3)
847 "[1, 2, 3];")
849 (test-ps-js literal-array-1
850 '(1 foo 3)
851 "[1, 'foo', 3];")
853 (test ps-lisp-expands-in-lexical-environment
854 (is (string= "5;" (let ((x 5)) (ps (lisp x))))))
856 (test ps*-lisp-expands-in-null-lexical-environment
857 (signals error (let ((x 5)) (declare (ignore x)) (ps* '(lisp x)))))
859 (test ps*-lisp-expands-in-dynamic-environment
860 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps* '(+ 1 (lisp (locally (declare (special foo)) foo))))))))
862 (test ps-lisp-dynamic-environment
863 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps (+ 1 (lisp foo)))))))
865 (test-ps-js nested-if-expressions1
866 (return (if (if x y z) a b))
867 "return (x ? y : z) ? a : b;")
869 (test-ps-js nested-if-expressions2
870 (return (if x y (if z a b)))
871 "return x ? y : (z ? a : b);")
873 (test-ps-js let1
874 (let (x)
875 (+ x x))
876 "var x = null;
877 x + x;")
879 (test-ps-js let2
880 (let ((x 1))
881 (+ x x))
882 "var x = 1;
883 x + x;")
885 (test-ps-js let-x-x
886 (let ((x (1+ x)))
887 (+ x x))
888 "var x1 = x + 1;
889 x1 + x1;")
891 (test-ps-js let3
892 (let ((x 1)
893 (y 2))
894 (+ x x))
895 "var x = 1;
896 var y = 2;
897 x + x;")
899 (test-ps-js let4
900 (let ((x 1)
901 (y (1+ x)))
902 (+ x y))
903 "var x1 = 1;
904 var y = x + 1;
905 x1 + y;")
907 (test-ps-js let5
908 (let ((x 1))
909 (+ x 1)
910 (let ((x (+ x 5)))
911 (+ x 1))
912 (+ x 1))
913 "var x = 1;
914 x + 1;
915 var x1 = x + 5;
916 x1 + 1;
917 x + 1;")
919 (test-ps-js let6
920 (let ((x 2))
921 (let ((x 1)
922 (y (1+ x)))
923 (+ x y)))
924 "var x = 2;
925 var x1 = 1;
926 var y = x + 1;
927 x1 + y;")
929 (test-ps-js let-exp1
930 (lambda ()
931 (let (x)
932 (+ x x)))
933 "function () {
934 var x = null;
935 return x + x;
936 };")
938 (test-ps-js let*1
939 (let* ((x 1))
940 (+ x x))
941 "var x = 1;
942 x + x;")
944 (test-ps-js let*2
945 (let* ((x 1)
946 (y (+ x 2)))
947 (+ x y))
948 "var x = 1;
949 var y = x + 2;
950 x + y;")
952 (test-ps-js let*3
953 (let ((x 3))
954 (let* ((x 1)
955 (y (+ x 2)))
956 (+ x y)))
957 "var x = 3;
958 var x1 = 1;
959 var y = x1 + 2;
960 x1 + y;")
962 (test-ps-js let*4
963 (let ((x 3))
964 (let* ((y (+ x 2))
965 (x 1))
966 (+ x y)))
967 "var x = 3;
968 var y = x + 2;
969 var x1 = 1;
970 x1 + y;")
972 (test-ps-js symbol-macrolet-var
973 (symbol-macrolet ((x y))
974 (var x))
975 "var y;")
977 (test-ps-js setf-conditional1
978 (setf x (unless (null a) (1+ a)))
979 "x = a != null ? a + 1 : null;")
981 (test-ps-js setf-let1
982 (setf x (let ((a 1)) a))
983 "x = (a = 1, a);")
985 (test-ps-js setf-let2
986 (setf x (let ((a (foo)))
987 (unless (null a)
988 (1+ a))))
989 "x = (a = foo(), a != null ? a + 1 : null);")
991 (test-ps-js symbol-macro-env1
992 (symbol-macrolet ((bar 1))
993 (macrolet ((bar (x y) `(+ ,x ,y)))
994 (bar bar bar)))
995 "1 + 1;")
997 (test-ps-js symbol-macrolet-fun1
998 (symbol-macrolet ((baz +))
999 (baz 1 2))
1000 "baz(1, 2);")
1002 (test-ps-js lisp2-namespaces1
1003 (let ((list nil))
1004 (setf list (list 1 2 3)))
1005 "var list = null;
1006 list = [1, 2, 3];")
1008 (test-ps-js let-shadows-symbol-macrolet
1009 (symbol-macrolet ((x y))
1010 (let ((x 1))
1011 (+ x x))
1012 (+ x x))
1013 "var x1 = 1;
1014 x1 + x1;
1015 y + y;")
1017 (test-ps-js let-rename-optimization1
1018 (let ((x 1))
1019 (+ x x))
1020 "var x = 1;
1021 x + x;")
1023 (test-ps-js let-rename-optimization2
1024 (lambda (x)
1025 (let ((x (+ 1 x)))
1027 "function (x) {
1028 var x1 = 1 + x;
1029 return x1;
1030 };")
1032 (test-ps-js symbol-macro-array
1033 (symbol-macrolet ((x 1))
1034 (list x))
1035 "[1];")
1037 (test-ps-js symbol-macro-obj
1038 (symbol-macrolet ((x y))
1039 (create x 1))
1040 "{ x : 1 };")
1042 (test-ps-js symbol-macro-conditional1
1043 (symbol-macrolet ((x y))
1044 (if x x x))
1045 "if (y) {
1047 } else {
1049 };")
1051 (test-ps-js symbol-macro-conditional2
1052 (symbol-macrolet ((x y))
1053 (return (if x x x)))
1054 "return y ? y : y;")
1056 (test-ps-js flet-apply
1057 (flet ((foo () 'bar))
1058 (apply (function foo) nil))
1059 "var foo = function () {
1060 return 'bar';
1062 foo.apply(this, null);")
1064 (test-ps-js let-apply
1065 (let ((foo (lambda () 1)))
1066 (let ((foo (lambda () 2)))
1067 (apply foo nil)))
1068 "var foo = function () {
1069 return 1;
1071 var foo1 = function () {
1072 return 2;
1074 foo1.apply(this, null);")
1076 (test-ps-js flet-let
1077 (flet ((x (x) (1+ x)))
1078 (let ((x 2))
1079 (x x)))
1080 "var x = function (x) {
1081 return x + 1;
1083 var x1 = 2;
1084 x(x1);")
1086 (test-ps-js let-flet
1087 (let ((x 2))
1088 (flet ((x (x) (1+ x)))
1089 (x x)))
1090 "var x = 2;
1091 var x1 = function (x) {
1092 return x + 1;
1094 x1(x);")
1096 (test-ps-js labels-let
1097 (labels ((x (x) (1+ x)))
1098 (let ((x 2))
1099 (x x)))
1100 "var x = function (x) {
1101 return x + 1;
1103 var x1 = 2;
1104 x(x1);")
1106 (test-ps-js let-labels
1107 (let ((x 2))
1108 (labels ((x (x) (1+ x)))
1109 (x x)))
1110 "var x = 2;
1111 var x1 = function (x) {
1112 return x + 1;
1114 x1(x);")
1116 (test-ps-js macrolet-let-inteference
1117 (macrolet ((a (n) `(+ ,n 5)))
1118 (let ((a (a 1)))
1119 (let ((b (a (- a 4))))
1120 (+ a b))))
1121 "var a = 1 + 5;
1122 var b = a - 4 + 5;
1123 a + b;")
1125 (test-ps-js let-subtract-add
1126 (let ((x 1))
1127 (let ((x 2))
1128 (- x x)
1129 (- x)
1130 (decf x)
1131 (incf x)))
1132 "var x = 1;
1133 var x1 = 2;
1134 x1 - x1;
1135 -x1;
1136 --x1;
1137 ++x1;")
1139 (test-ps-js create-reserved-word
1140 (create :default 1)
1141 "{ 'default' : 1 };")
1143 (test-ps-js getprop-reserved-word
1144 (getprop foo :default)
1145 "foo['default'];")
1147 (test-ps-js getprop-reserved-word1
1148 (getprop foo 'default)
1149 "foo['default'];")
1151 (test-ps-js eval-when-ps-side
1152 (eval-when (:execute)
1154 "5;")
1156 (defvar *lisp-output* nil)
1158 (test eval-when-lisp-side ()
1159 (setf *lisp-output* 'original-value)
1160 (let ((js-output (normalize-js-code
1161 (ps-doc* `(eval-when (:compile-toplevel)
1162 (setf *lisp-output* 'it-works))))))
1163 (is (eql 'it-works *lisp-output*))
1164 (is (string= "" js-output))))
1166 (defpsmacro my-in-package (package-name)
1167 `(eval-when (:compile-toplevel)
1168 (setf *lisp-output* ,package-name)))
1170 (test eval-when-macro-expansion ()
1171 (setf *lisp-output* 'original-value)
1172 (let ((js-output (normalize-js-code
1173 (ps-doc* `(progn
1174 (my-in-package :cl-user)
1175 3)))))
1176 (declare (ignore js-output))
1177 (is (eql :cl-user *lisp-output*))))
1179 (test eval-when-macrolet-expansion ()
1180 (setf *lisp-output* 'original-value)
1181 (let ((js-output (normalize-js-code
1182 (ps-doc* `(macrolet ((my-in-package2 (package-name)
1183 `(eval-when (:compile-toplevel)
1184 (setf *lisp-output* ,package-name))))
1185 (my-in-package2 :cl-user)
1186 3)))))
1187 (declare (ignore js-output))
1188 (is (eql :cl-user *lisp-output*))))
1190 (test-ps-js getprop-keyword
1191 (getprop foo :bar)
1192 "foo['bar'];")
1194 (test-ps-js nary-comparison1
1195 (lambda () (< 1 2 3))
1196 "function () {
1197 var _cmp1;
1198 return (_cmp1 = 2, 1 < _cmp1 && _cmp1 < 3);
1199 };")
1201 (test-ps-js chain-getprop1
1202 (chain ($ "foo") (bar x z) frob (baz 5))
1203 "$('foo').bar(x, z).frob.baz(5);")
1205 (test-ps-js chain-getprop2
1206 (chain ($ "foo") bar baz)
1207 "$('foo').bar.baz;")
1209 (test-ps-js chain-getprop3
1210 (chain ($ "foo") bar (x y) baz)
1211 "$('foo').bar.x(y).baz;")
1213 (test-ps-js flet-expression
1214 (1+ (flet ((foo (x) (1+ x)))
1215 (foo 1)))
1216 "(foo = function (x) {
1217 return x + 1;
1218 }, foo(1)) + 1;")
1220 (test-ps-js return-case-break-elimination
1221 (return (case 1
1222 (0 1)
1223 (otherwise 2)))
1224 "switch (1) {
1225 case 0:
1226 return 1;
1227 default:
1228 return 2;
1229 };")
1231 (test-ps-js aplusplus
1233 "aplusplus;")
1235 (test-ps-js astarstar
1237 "astarstar;")
1239 (test-ps-js switch-return-fallthrough
1240 (return
1241 (switch x
1242 (1 (foo) break)
1243 (2 (bar))
1244 (default 4)))
1245 "switch (x) {
1246 case 1:
1247 return foo();
1248 case 2:
1249 bar();
1250 default:
1251 return 4;
1252 };")
1254 (test-ps-js return-last-case
1255 (return (case x
1256 (a 'eh)
1257 (b 'bee)))
1258 "switch (x) {
1259 case a:
1260 return 'eh';
1261 case b:
1262 return 'bee';
1263 };")
1265 (test-ps-js return-macrolet
1266 (return
1267 (macrolet ((x () 1))
1268 (case (x)
1269 (a 'eh)
1270 (b 'bee))))
1271 "switch (1) {
1272 case a:
1273 return 'eh';
1274 case b:
1275 return 'bee';
1276 };")
1278 (test-ps-js mv-bind1
1279 (multiple-value-bind (a b)
1280 (progn
1281 (returns-mv)
1282 (doesnt))
1283 (alert a)
1284 (alert b))
1285 "var prevmv2 = null;
1286 returnsMv();
1287 prevmv2 = arguments['callee']['mv'];
1288 try {
1289 arguments['callee']['mv'] = true;
1290 var a = doesnt();
1291 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1292 var b = mv1[0];
1293 alert(a);
1294 alert(b);
1295 } finally {
1296 if (undefined === prevmv2) {
1297 delete arguments['callee']['mv'];
1298 } else {
1299 arguments['callee']['mv'] = prevmv2;
1301 };")
1303 (test-ps-js mv-bind2
1304 (multiple-value-bind (a b)
1305 (let ((a 1))
1306 (returns-mv a)
1307 (doesnt b))
1308 (alert a)
1309 (alert b))
1310 "var prevmv2 = null;
1311 var a = 1;
1312 returnsMv(a);
1313 prevmv2 = arguments['callee']['mv'];
1314 try {
1315 arguments['callee']['mv'] = true;
1316 var a3 = doesnt(b);
1317 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1318 var b = mv1[0];
1319 alert(a3);
1320 alert(b);
1321 } finally {
1322 if (undefined === prevmv2) {
1323 delete arguments['callee']['mv'];
1324 } else {
1325 arguments['callee']['mv'] = prevmv2;
1327 };")
1329 (test-ps-js values0
1330 (lambda () (values))
1331 "function () {
1332 return null;
1333 };")
1335 (test-ps-js values1
1336 (values x)
1337 "x;")
1339 (test-ps-js values2
1340 (values x y)
1341 "var val1_1 = x;
1342 var valrest2 = [y];
1343 if (undefined !== arguments['callee']['caller']['mv']) {
1344 arguments['callee']['caller']['mv'] = valrest2;
1346 val1_1;")
1348 (test-ps-js values3
1349 (values x y z)
1350 "var val1_1 = x;
1351 var valrest2 = [y, z];
1352 if (undefined !== arguments['callee']['caller']['mv']) {
1353 arguments['callee']['caller']['mv'] = valrest2;
1355 val1_1;")
1357 (test-ps-js values-return
1358 (return (values x y))
1359 "var val1_1 = x;
1360 var valrest2 = [y];
1361 if (undefined !== arguments['callee']['caller']['mv']) {
1362 arguments['callee']['caller']['mv'] = valrest2;
1364 return val1_1;")
1366 (test-ps-js return-macrolet
1367 (return
1368 (symbol-macrolet ((x 2))
1369 (loop do (+ x x))))
1370 "for (; true; ) {
1371 2 + 2;
1373 return null;")
1375 (test-ps-js return-cond
1376 (return
1377 (cond ((foo? x) (loop for y in x do (foo y)))
1378 ((bar? x) x)
1379 (t 3)))
1380 "if (foowhat(x)) {
1381 var _js2 = x.length;
1382 var _js1 = 0;
1383 if (_js1 < _js2) {
1384 var y = x[_js1];
1385 while (true) {
1386 foo(y);
1387 _js1 += 1;
1388 if (_js1 >= _js2) {
1389 break;
1391 y = x[_js1];
1394 return null;
1395 } else if (barwhat(x)) {
1396 return x;
1397 } else {
1398 return 3;
1399 };")
1401 (test-ps-js switch-loop
1402 (case x
1403 (1 (dolist (a b))))
1404 "switch (x) {
1405 case 1:
1406 for (var a = null, _js_idx1 = 0; _js_idx1 < b.length; _js_idx1 += 1) {
1407 a = b[_js_idx1];
1409 };")
1411 (test-ps-js switch-folds-blocks
1412 (case x
1413 (1 (loop repeat 3 do (alert "foo"))))
1414 "switch (x) {
1415 case 1:
1416 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
1417 alert('foo');
1419 };")
1421 (test-ps-js setf-places-before-macros
1422 (progn
1423 (defsetf left (el) (offset)
1424 `(setf (@ ,el style left) ,offset))
1425 (macrolet ((left (el)
1426 `(@ ,el offset-left)))
1427 (setf (left x) 10)
1428 (left x)))
1429 "var _js2 = x;
1430 var _js1 = 10;
1431 _js2.style.left = _js1;
1432 x.offsetLeft;")
1434 (test-ps-js for-return
1435 (lambda () (dolist (arg args) (foo arg)))
1436 "function () {
1437 for (var arg = null, _js_idx1 = 0; _js_idx1 < args.length; _js_idx1 += 1) {
1438 arg = args[_js_idx1];
1439 foo(arg);
1441 };")
1443 (test-ps-js try-catch-return
1444 (return (try (foo)
1445 (:catch (e)
1446 (bar))
1447 (:finally
1448 (cleanup))))
1449 "try {
1450 return foo();
1451 } catch (e) {
1452 return bar();
1453 } finally {
1454 cleanup();
1455 };")
1457 (test-ps-js defun-setf-optional
1458 (defun (setf foo) (new-value b &optional c)
1459 (setf (aref b (or c 0)) new-value))
1460 "function __setf_foo(newValue, b, c) {
1461 return b[c || 0] = newValue;
1462 };")
1464 (test-ps-js defun-setf-rest
1465 (progn (defun (setf foo) (new-value b &rest foo)
1466 (do-something b foo new-value))
1467 (setf (foo x 1 2 3 4) 5))
1468 "function __setf_foo(newValue, b) {
1469 var foo = [];
1470 for (var i1 = 0; i1 < arguments.length - 2; i1 += 1) {
1471 foo[i1] = arguments[i1 + 2];
1473 return doSomething(b, foo, newValue);
1475 __setf_foo(5, x, 1, 2, 3, 4);")
1477 (test-ps-js return-null
1478 (return nil)
1479 "return null;")
1481 (test-ps-js implicit-return-null
1482 (lambda ()
1484 "function () {
1485 return null;
1486 };")
1488 (test-ps-js implicit-return-null
1489 (lambda ()
1490 nil)
1491 "function () {
1492 return null;
1493 };")
1495 (test-ps-js return-conditional-nested
1496 (defun blep (ss x y)
1497 (when foo?
1498 (let ((pair (bar)))
1499 (unless (null pair)
1500 (destructuring-bind (a b) pair
1501 (unless (or (null a) (null b))
1502 (let ((val (baz a b)))
1503 (unless (null val)
1504 (when (blah val)
1505 (unless (blee)
1506 t))))))))))
1507 "function blep(ss, x, y) {
1508 if (foowhat) {
1509 var pair = bar();
1510 if (pair != null) {
1511 var a = pair[0];
1512 var b = pair[1];
1513 if (!(a == null || b == null)) {
1514 var val = baz(a, b);
1515 if (val != null) {
1516 if (blah(val)) {
1517 return !blee() ? true : null;
1523 };")
1525 ;; this test needs to be rewritten when named blocks are implemented!!!!
1526 (test-ps-js return-when-returns-broken-return
1527 (lambda ()
1528 (return (when x 1))
1529 (+ 2 3))
1530 "function () {
1531 return x ? 1 : null;
1532 return 2 + 3;
1533 };")
1535 (test-ps-js return-case-conditional
1536 (return
1537 (case foo
1538 (123 (when (bar) t))
1539 (345 (blah))))
1540 "switch (foo) {
1541 case 123:
1542 return bar() ? true : null;
1543 case 345:
1544 return blah();
1545 };")
1547 (test-ps-js return-try-conditional
1548 (return
1549 (try (when x 1)
1550 (:catch (x) 2)
1551 (:finally (bar))))
1552 "try {
1553 return x ? 1 : null;
1554 } catch (x) {
1555 return 2;
1556 } finally {
1557 bar();
1558 };")
1560 (test-ps-js function-declare-special
1561 (lambda ()
1562 (declare (special *foo*))
1563 (let ((*foo* 1))
1564 (1+ *foo*)))
1565 "function () {
1566 var FOO_TMPSTACK1;
1567 try {
1568 FOO_TMPSTACK1 = FOO;
1569 FOO = 1;
1570 return FOO + 1;
1571 } finally {
1572 FOO = FOO_TMPSTACK1;
1574 };")
1576 (test-ps-js declare-special-let
1577 (let ((*foo* 123))
1578 (declare (special *foo*))
1579 (blah))
1580 "var FOO_TMPSTACK1;
1581 try {
1582 FOO_TMPSTACK1 = FOO;
1583 FOO = 123;
1584 blah();
1585 } finally {
1586 FOO = FOO_TMPSTACK1;
1587 };")
1589 (test-ps-js macro-null-toplevel
1590 (progn
1591 (defmacro macro-null-toplevel ()
1592 nil)
1593 (macro-null-toplevel))
1596 (test-ps-js define-symbol-macro-let
1597 (progn
1598 (define-symbol-macro test-symbol-macro 1)
1599 (let ((test-symbol-macro 2))
1600 (1+ test-symbol-macro))
1601 (1+ test-symbol-macro))
1602 "var testSymbolMacro1 = 2;
1603 testSymbolMacro1 + 1;
1604 1 + 1;")
1606 (test-ps-js define-symbol-macro-flet
1607 (progn
1608 (define-symbol-macro test-symbol-macro1 1)
1609 (flet ((test-symbol-macro1 () 2))
1610 (foo test-symbol-macro1)
1611 (test-symbol-macro1))
1612 (bar test-symbol-macro1))
1613 "var testSymbolMacro1_1 = function () {
1614 return 2;
1616 foo(1);
1617 testSymbolMacro1_1();
1618 bar(1);")
1620 (test compile-stream-nulls
1621 (is (string=
1623 (with-input-from-string (s "
1624 (defmacro macro-null-toplevel ()
1625 nil)
1626 (macro-null-toplevel)")
1627 (ps-compile-stream s)))))
1629 (test compile-stream1
1630 (is (string=
1631 "var testSymbolMacro1_1 = function () {
1632 return 2;
1634 foo(1);
1635 testSymbolMacro1_1();
1636 bar(1);
1638 (with-input-from-string (s "
1639 (define-symbol-macro test-symbol-macro1 1)
1640 (flet ((test-symbol-macro1 () 2))
1641 (foo test-symbol-macro1)
1642 (test-symbol-macro1))
1643 (bar test-symbol-macro1)")
1644 (ps::with-blank-compilation-environment (ps-compile-stream s))))))
1646 (test-ps-js equality-nary1
1647 (let ((x 10) (y 10) (z 10))
1648 (= x y z))
1649 "var x = 10;
1650 var y = 10;
1651 var z = 10;
1652 var _cmp1 = y;
1653 x === _cmp1 && _cmp1 === z;")
1655 (test-ps-js equality1
1656 (progn
1657 (equal a b)
1658 (eql a b)
1659 (eq a b)
1660 (= a b))
1661 "a == b;
1662 a === b;
1663 a === b;
1664 a === b;")
1666 (test-ps-js getprop-quote-reserved
1667 (getprop foo ':break)
1668 "foo['break'];")
1670 (test-ps-js defun-block-return-from
1671 (defun foo (x)
1672 (baz 4)
1673 (return-from foo x)
1674 (bar 5))
1675 "function foo(x) {
1676 baz(4);
1677 return x;
1678 return bar(5);
1679 }; ")
1681 (test-ps-js block-return-from
1682 (block scope
1683 (foo)
1684 (when (bar)
1685 (return-from scope))
1686 (blee))
1687 "scope: {
1688 foo();
1689 if (bar()) {
1690 break scope;
1692 blee();
1693 };")
1695 (test-ps-js let-funcall
1696 (let ((x foo))
1697 (funcall x)
1698 (let ((x bar))
1699 (funcall x))
1700 (funcall x))
1701 "var x = foo;
1702 x();
1703 var x1 = bar;
1704 x1();
1705 x();")
1707 (test-ps-js symbol-macrolet-funcall
1708 (symbol-macrolet ((foo bar))
1709 (funcall foo 1 2 3))
1710 "bar(1, 2, 3);")
1712 (test-ps-js times-assign
1713 (setf x (* x 1000))
1714 "x *= 1000;")
1716 (test-ps-js vector-literal
1717 #(1 2 3)
1718 "[1, 2, 3];")
1720 (test-ps-js rem1
1721 (+ 1 (rem 2 (+ 3 4)))
1722 "1 + 2 % (3 + 4);")
1724 (test-ps-js non-associative
1725 (+ (/ 1 (/ 2 3)) (- 1 (- 2 3)))
1726 "1 / (2 / 3) + 1 - (2 - 3);")
1728 (test-ps-js lambda-apply
1729 (lambda (x)
1730 (apply (lambda (y) (bar (1+ y))) x))
1731 "function (x) {
1732 return (function (y) {
1733 return bar(y + 1);
1734 }).apply(this, x);
1735 };")
1737 (test-ps-js operator-expressions-nested-let
1738 (let ((x (let ((y 1))
1739 y)))
1741 "var x = (y = 1, y); x;")
1743 (test-ps-js operator-expressions-array-nested-let
1744 (list (let ((y 1)) y) 2)
1745 "[(y = 1, y), 2];")
1747 (test-ps-js add-subtract-precedence
1748 (- x (+ y z))
1749 "x - (y + z);")
1751 (test-ps-js ps-inline-toplevel
1752 (ps-inline (foo))
1753 "'javascript:' + 'foo()';")
1755 (test-ps-js no-clause-progn-exp
1756 (setf x (progn))
1757 "x = null;")
1759 (test-ps-js no-clause-progn-return
1760 (return (progn))
1761 "return null;")
1763 (test-ps-js empty-cond-clause
1764 (setf x (cond ((foo))))
1765 "x = foo() ? null : null;")
1767 (test-ps-js empty-cond-clause1
1768 (setf x (cond ((foo) 123)
1769 ((bar))
1770 (t 456)))
1771 "x = foo() ? 123 : (bar() ? null : 456);")
1773 (test-ps-js let-no-body
1774 (return (let ((foo bar))))
1775 "var foo = bar;
1776 return null;")
1778 (test-ps-js dont-hoist-lexical-dupes
1779 (lambda ()
1780 (list (let ((foo 12)) (* foo 2))
1781 (let ((foo 13)) (* foo 3))))
1782 "function () {
1783 var foo;
1784 return [(foo = 12, foo * 2), (foo = 13, foo * 3)];
1785 };")
1787 (test-ps-js defun-comment1
1788 (defun foo (x)
1789 "BARBAR is a revolutionary new foobar.
1790 X y and x."
1791 (1+ x))
1792 "/**
1793 * BARBAR is a revolutionary new foobar.
1794 * X y and x.
1796 function foo(x) {
1797 return x + 1;
1798 };")
1800 (test-ps-js var-comment
1801 (var x 1 "foo")
1802 "/** foo */
1803 var x = 1;")
1805 (test-ps-js case-return-break-broken-return
1806 (defun foo ()
1807 (case x
1808 ("bar" (if y (return t) nil))
1809 ("baz" nil)))
1810 "function foo() {
1811 switch (x) {
1812 case 'bar':
1813 if (y) {
1814 return true;
1816 break;
1817 case 'baz':
1818 return null;
1820 };")
1822 (test-ps-js case-return-break1-broken-return
1823 (defun foo ()
1824 (case x
1825 ("bar" (if y (return t)))
1826 ("baz" nil)))
1827 "function foo() {
1828 switch (x) {
1829 case 'bar':
1830 if (y) {
1831 return true;
1833 break;
1834 case 'baz':
1835 return null;
1837 };")
1839 (test-ps-js setf-progn
1840 (setf foo (progn (bar) (baz) 3))
1841 "bar();
1842 baz();
1843 foo = 3;")
1845 ;; (test-ps-js var-progn
1846 ;; (var x (progn (foo) (bar)))
1847 ;; "foo();
1848 ;; var x = bar();")
1850 (test-ps-js implicit-return-loop
1851 (lambda ()
1852 (if baz 7
1853 (progn
1854 (loop :repeat 100 :do (bar))
1855 42)))
1856 "function () {
1857 if (baz) {
1858 return 7;
1859 } else {
1860 for (var _js1 = 0; _js1 < 100; _js1 += 1) {
1861 bar();
1863 return 42;
1865 };")
1867 ;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
1868 (test-ps-js loop-closures
1869 (dotimes (i 10) (lambda () (+ i 1)))
1870 "for (var i = 0; i < 10; i += 1) {
1871 with ({ i : i }) {
1872 function () {
1873 return i + 1;
1876 };")
1878 (test-ps-js loop-closures-let
1879 (dotimes (i 10) (let ((x (+ i 1))) (lambda () (+ i x))))
1880 "for (var i = 0; i < 10; i += 1) {
1881 with ({ x : null, i : i }) {
1882 var x = i + 1;
1883 function () {
1884 return i + x;
1887 };")
1889 (test-ps-js loop-closures-flet
1890 (dotimes (i 10) (flet ((foo (x) (+ i x))) (lambda () (foo i))))
1891 "for (var i = 0; i < 10; i += 1) {
1892 with ({ foo : null, i : i }) {
1893 var foo = function (x) {
1894 return i + x;
1896 function () {
1897 return foo(i);
1900 };")
1902 (test-ps-js while-closures-let
1903 (while (foo)
1904 (let ((x (bar)))
1905 (lambda () (+ 1 x))))
1906 "while (foo()) {
1907 with ({ x : null }) {
1908 var x = bar();
1909 function () {
1910 return 1 + x;
1913 };")
1915 (test-ps-js dotted-list-form
1916 (defun foo (a)
1917 (when a
1918 (destructuring-bind (b . c)
1920 (list b c))))
1921 "function foo(a) {
1922 if (a) {
1923 var b = bar[0];
1924 var c = bar.length > 1 ? bar.slice(1) : [];
1925 return [b, c];
1927 };")
1929 (test-ps-js return-from-loop
1930 (dolist (x '(2 1 3))
1931 (when (= x 1)
1932 (return))
1933 (chain console (log x)))
1934 "for (var x = null, _js_arrvar2 = [2, 1, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
1935 x = _js_arrvar2[_js_idx1];
1936 if (x === 1) {
1937 break;
1939 console.log(x);
1940 };")