Fixed up bug where defuns were getting wrapped in lambdas because toplevel form check...
[parenscript.git] / t / output-tests.lisp
blobe985665d1b773f5d67fba2b84c369705988f7668
1 ;; Copying and distribution of this file, with or without
2 ;; modification, are permitted in any medium without royalty. This
3 ;; file is offered as-is, without any warranty.
5 (in-package #:ps-test)
6 (named-readtables:in-readtable :parenscript)
8 (in-suite output-tests)
10 (test-ps-js statements-and-expressions-1
11 (+ i (if 1 2 3))
12 "i + (1 ? 2 : 3);")
14 (test-ps-js statements-and-expressions-2
15 (if 1 2 3)
16 "if (1) {
18 } else {
20 };")
22 (test-ps-js symbol-conversion-1
23 !?#@%
24 "bangwhathashatpercent;")
26 (test-ps-js symbol-conversion-2
27 bla-foo-bar
28 "blaFooBar;")
30 (test-ps-js symbol-conversion-3
31 *array
32 "Array;")
34 (test-ps-js symbol-conversion-4
35 *global-array*
36 "GLOBALARRAY;")
38 (test-ps-js symbol-conversion-5
39 encodeURIComponent
40 "encodeURIComponent;")
42 (test-ps-js symbol-conversion-6
43 URI
44 "URI;")
46 (test-ps-js number-literals-1
48 "1;")
50 (test-ps-js number-literals-2
51 123.123
52 "123.123;")
54 (test-ps-js number-literals-3
55 #x10
56 "16;")
58 (test-ps-js string-literals-1
59 "foobar"
60 "'foobar';")
62 (test-ps-js string-literals-2
63 "bratzel bub"
64 "'bratzel bub';")
66 (test-ps-js string-literals-3
67 " "
68 "'\\t';")
70 (test-ps-js array-literals-1
71 (array)
72 "[ ];")
74 (test-ps-js array-literals-2
75 (array 1 2 3)
76 "[ 1, 2, 3 ];")
78 (test-ps-js array-literals-3
79 (array (array 2 3)
80 (array "foobar" "bratzel bub"))
81 "[ [ 2, 3 ], [ 'foobar', 'bratzel bub' ] ];")
83 (test-ps-js array-literals-4
84 (make-array)
85 "new Array();")
87 (test-ps-js array-literals-5
88 (make-array 1 2 3)
89 "new Array(1, 2, 3);")
91 (test-ps-js array-literals-6
92 (make-array
93 (make-array 2 3)
94 (make-array "foobar" "bratzel bub"))
95 "new Array(new Array(2, 3), new Array('foobar', 'bratzel bub'));")
97 (test-ps-js object-literals-1
98 (create foo "bar" :blorg 1)
99 "({ foo : 'bar', 'blorg' : 1 });")
101 (test-ps-js object-literals-2
102 (create foo "hihi"
103 blorg (array 1 2 3)
104 another-object (create :schtrunz 1))
105 "({ foo : 'hihi',
106 blorg : [ 1, 2, 3 ],
107 anotherObject : { 'schtrunz' : 1 } });")
109 (test-ps-js object-literals-3
110 (getprop an-object 'foo)
111 "anObject.foo;")
113 (test-ps-js object-literals-4
114 (@ an-object foo bar)
115 "anObject.foo.bar;")
117 (test-ps-js object-literals-5
118 (with-slots (a b c) this
119 (+ a b c))
120 "this.a + this.b + this.c;")
122 (test-ps-js regular-expression-literals-1
123 (regex "foobar")
124 "/foobar/;")
126 (test-ps-js regular-expression-literals-2
127 (regex "/foobar/i")
128 "/foobar/i;")
130 (test-ps-js literal-symbols-1
132 "true;")
134 (test-ps-js literal-symbols-2
135 false
136 "false;")
138 (test-ps-js literal-symbols-3
140 "false;")
142 (test-ps-js literal-symbols-4
143 (lambda () nil)
144 "(function () {
145 return null;
146 });")
148 (test-ps-js literal-symbols-5
149 undefined
150 "undefined;")
152 (test-ps-js literal-symbols-6
153 this
154 "this;")
156 (test-ps-js variables-1
157 variable
158 "variable;")
160 (test-ps-js variables-2
161 a-variable
162 "aVariable;")
164 (test-ps-js variables-3
165 *math
166 "Math;")
168 (test-ps-js function-calls-and-method-calls-1
169 (blorg 1 2)
170 "blorg(1, 2);")
172 (test-ps-js function-calls-and-method-calls-2
173 (foobar (blorg 1 2) (blabla 3 4) (array 2 3 4))
174 "foobar(blorg(1, 2), blabla(3, 4), [ 2, 3, 4 ]);")
176 (test-ps-js function-calls-and-method-calls-3
177 ((getprop this 'blorg) 1 2)
178 "this.blorg(1, 2);")
180 (test-ps-js function-calls-and-method-calls-4
181 ((aref foo i) 1 2)
182 "foo[i](1, 2);")
184 (test-ps-js function-calls-and-method-calls-5
185 ((getprop (aref foobar 1) 'blorg) nil t)
186 "foobar[1].blorg(null, true);")
188 (test-ps-js operator-expressions-1
189 (* 1 2)
190 "1 * 2;")
192 (test-ps-js operator-expressions-2
193 (= 1 2)
194 "1 === 2;")
196 (test-ps-js operator-expressions-3
197 (* 1 (+ 2 3 4) 4 (/ 6 7))
198 "1 * (2 + 3 + 4) * 4 * (6 / 7);")
200 (test-ps-js operator-expressions-4
201 (incf i)
202 "++i;")
204 (test-ps-js operator-expressions-5
205 (decf i)
206 "--i;")
208 (test-ps-js operator-expressions-6
209 (1- i)
210 "i - 1;")
212 (test-ps-js operator-expressions-7
213 (1+ i)
214 "i + 1;")
216 (test-ps-js operator-expressions-8
217 (not (< i 2))
218 "i >= 2;")
220 (test-ps-js body-forms-1
221 (progn (blorg i) (blafoo i))
222 "blorg(i);
223 blafoo(i);")
225 (test-ps-js body-forms-2
226 (+ i (progn (blorg i) (blafoo i)))
227 "i + (blorg(i), blafoo(i));")
229 (test-ps-js function-definition-1
230 (defun a-function (a b)
231 (+ a b))
232 "function aFunction(a, b) {
233 return a + b;
234 };")
236 (test-ps-js lambda-definition-2
237 (lambda (a b) (+ a b))
238 "(function (a, b) {
239 return a + b;
240 });")
242 (test-ps-js assignment-1
243 (setf a 1)
244 "a = 1;")
246 (test-ps-js assignment-2
247 (setf a 2 b 3 c 4 x (+ a b c))
248 "a = 2;
249 b = 3;
250 c = 4;
251 x = a + b + c;")
253 (test-ps-js assignment-3
254 (setf a (+ a 2 3 4 a))
255 "a = a + 2 + 3 + 4 + a;")
257 (test-ps-js assignment-4
258 (setf a (- 1 a))
259 "a = 1 - a;")
261 (test-ps-js assignment-5
262 (let ((a 1) (b 2))
263 (psetf a b b a))
264 "(function () {
265 var a = 1;
266 var b = 2;
267 var _js3 = b;
268 var _js4 = a;
269 a = _js3;
270 return b = _js4;
271 })();")
273 (test-ps-js assignment-6
274 (setq a 1)
275 "a = 1;")
277 (test-ps-js assignment-8
278 (progn
279 (defun (setf color) (new-color el)
280 (setf (getprop (getprop el 'style) 'color) new-color))
281 (setf (color some-div) (+ 23 "em")))
282 "function __setf_color(newColor, el) {
283 return el.style.color = newColor;
285 __setf_color(23 + 'em', someDiv);")
287 (test-ps-js assignment-10
288 (progn
289 (defsetf left (el) (offset)
290 `(setf (getprop (getprop ,el 'style) 'left) ,offset))
291 (setf (left some-div) (+ 123 "px")))
292 "(function () {
293 var _js2 = someDiv;
294 var _js1 = 123 + 'px';
295 return _js2.style.left = _js1;
296 })();")
298 (test-ps-js assignment-12
299 (macrolet ((left (el)
300 `(getprop ,el 'offset-left)))
301 (left some-div))
302 "someDiv.offsetLeft;")
304 (test-ps-js nil-block-return-1
305 (block nil (return) 1)
306 "(function () {
307 return null;
308 return 1;
309 })();")
311 (test-ps-js single-argument-statements-2
312 (throw "foobar")
313 "throw 'foobar';")
315 (test-ps-js single-argument-expression-1
316 (delete (new (*foobar 2 3 4)))
317 "delete new Foobar(2, 3, 4);")
319 (test-ps-js single-argument-expression-2
320 (if (= (typeof blorg) *string)
321 (alert (+ "blorg is a string: " blorg))
322 (alert "blorg is not a string"))
323 "if (typeof blorg === String) {
324 alert('blorg is a string: ' + blorg);
325 } else {
326 alert('blorg is not a string');
327 };")
329 (test-ps-js conditional-statements-1
330 (defun foo ()
331 (if ((@ blorg is-correct))
332 (progn (carry-on) (return-from foo i))
333 (alert "blorg is not correct!")))
334 "function foo() {
335 if (blorg.isCorrect()) {
336 carryOn();
337 return i;
338 } else {
339 return alert('blorg is not correct!');
341 };")
343 (test-ps-js conditional-statements-2
344 (+ i (if ((@ blorg add-one)) 1 2))
345 "i + (blorg.addOne() ? 1 : 2);")
347 (test-ps-js conditional-statements-3
348 (defun foo ()
349 (when ((@ blorg is-correct))
350 (carry-on)
351 (return-from foo i)))
352 "function foo() {
353 if (blorg.isCorrect()) {
354 carryOn();
355 return i;
357 };")
359 (test-ps-js conditional-statements-4
360 (unless ((@ blorg is-correct))
361 (alert "blorg is not correct!"))
362 "if (!blorg.isCorrect()) {
363 alert('blorg is not correct!');
364 };")
366 (test-ps-js variable-declaration-1
367 (defvar *a* (array 1 2 3))
368 "var A = [ 1, 2, 3 ];")
370 (test-ps-js variable-declaration-2
371 (progn (defvar *a* 4)
372 (let ((x 1)
373 (*a* 2))
374 (let* ((y (+ x 1))
375 (x (+ x y)))
376 (+ *a* x y))))
377 "var A = 4;
378 (function () {
379 var x = 1;
380 var A_TMPSTACK1;
381 try {
382 A_TMPSTACK1 = A;
383 A = 2;
384 var y = x + 1;
385 var x2 = x + y;
386 return A + x2 + y;
387 } finally {
388 A = A_TMPSTACK1;
390 })();")
392 (test-ps-js iteration-constructs-1
393 (do* ((a) b (c (array "a" "b" "c" "d" "e"))
394 (d 0 (1+ d))
395 (e (aref c d) (aref c d)))
396 ((or (= d (@ c length)) (string= e "x")))
397 (setf a d b e)
398 (funcall (@ document write) (+ "a: " a " b: " b "<br/>")))
399 "for (var a = null, b = null, c = ['a', 'b', 'c', 'd', 'e'], d = 0, e = c[d]; !(d === c.length || e === 'x'); d += 1, e = c[d]) {
400 a = d;
401 b = e;
402 document.write('a: ' + a + ' b: ' + b + '<br/>');
403 };")
405 (test-ps-js iteration-constructs-2
406 (do ((i 0 (1+ i))
407 (s 0 (+ s i (1+ i))))
408 ((> i 10))
409 (funcall (@ document write) (+ "i: " i " s: " s "<br/>")))
410 "(function () {
411 var i = 0;
412 var s = 0;
413 for (; i <= 10; ) {
414 document.write('i: ' + i + ' s: ' + s + '<br/>');
415 var _js1 = i + 1;
416 var _js2 = s + i + i + 1;
417 i = _js1;
418 s = _js2;
420 })();")
422 (test-ps-js iteration-constructs-3
423 (do* ((i 0 (1+ i))
424 (s 0 (+ s i (1- i))))
425 ((> i 10))
426 ((@ document write) (+ "i: " i " s: " s "<br/>")))
427 "for (var i = 0, s = 0; i <= 10; i += 1, s = s + i + (i - 1)) {
428 document.write('i: ' + i + ' s: ' + s + '<br/>');
429 };")
431 (test-ps-js iteration-constructs-4
432 (let ((arr (array "a" "b" "c" "d" "e")))
433 (dotimes (i (@ arr length))
434 ((@ document write) (+ "i: " i " arr[i]: " (aref arr i) "<br/>"))))
435 "(function () {
436 var arr = ['a', 'b', 'c', 'd', 'e'];
437 for (var i = 0; i < arr.length; i += 1) {
438 document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
440 })();")
442 (test-ps-js iteration-constructs-5
443 (let ((res 0))
444 (alert (+ "Summation to 10 is "
445 (dotimes (i 10 res)
446 (incf res (1+ i))))))
447 "(function () {
448 var res = 0;
449 return alert('Summation to 10 is ' + (function () {
450 for (var i = 0; i < 10; i += 1) {
451 res += i + 1;
453 return res;
454 })());
455 })();")
457 (test-ps-js iteration-constructs-6
458 (let ((l (list 1 2 4 8 16 32)))
459 (dolist (c l)
460 ((@ document write) (+ "c: " c "<br/>"))))
461 "(function () {
462 var l = [1, 2, 4, 8, 16, 32];
463 for (var c = null, _js_idx2 = 0; _js_idx2 < l.length; _js_idx2 += 1) {
464 c = l[_js_idx2];
465 document.write('c: ' + c + '<br/>');
467 })();")
469 (test-ps-js iteration-constructs-7
470 (let ((l '(1 2 4 8 16 32))
471 (s 0))
472 (alert (+ "Sum of " l " is: "
473 (dolist (c l s)
474 (incf s c)))))
475 "(function () {
476 var l = [1, 2, 4, 8, 16, 32];
477 var s = 0;
478 return alert('Sum of ' + l + ' is: ' + (function () {
479 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
480 c = l[_js_idx1];
481 s += c;
483 return s;
484 })());
485 })();")
487 (test-ps-js iteration-constructs-8
488 (let ((obj (create a 1 b 2 c 3)))
489 (for-in (i obj)
490 ((@ document write) (+ i ": " (aref obj i) "<br/>"))))
491 "(function () {
492 var obj = { a : 1, b : 2, c : 3 };
493 for (var i in obj) {
494 document.write(i + ': ' + obj[i] + '<br/>');
496 })();")
498 (test-ps-js iteration-constructs-9
499 (while ((@ film is-not-finished))
500 ((@ this eat) (new *popcorn)))
501 "while (film.isNotFinished()) {
502 this.eat(new Popcorn);
503 };")
505 (test-ps-js the-case-statement-1
506 (case (aref blorg i)
507 ((1 "one") (alert "one"))
508 (2 (alert "two"))
509 (t (alert "default clause")))
510 "switch (blorg[i]) {
511 case 1:
512 case 'one':
513 alert('one');
514 break;
515 case 2:
516 alert('two');
517 break;
518 default:
519 alert('default clause');
520 };")
522 (test-ps-js the-case-statement-2
523 (switch (aref blorg i)
524 (1 (alert "If I get here"))
525 (2 (alert "I also get here"))
526 (default (alert "I always get here")))
527 "switch (blorg[i]) {
528 case 1: alert('If I get here');
529 case 2: alert('I also get here');
530 default: alert('I always get here');
531 };")
533 (test-ps-js the-try-statement-1
534 (try (throw "i")
535 (:catch (error)
536 (alert (+ "an error happened: " error)))
537 (:finally
538 (alert "Leaving the try form")))
539 "try {
540 throw 'i';
541 } catch (error) {
542 alert('an error happened: ' + error);
543 } finally {
544 alert('Leaving the try form');
545 };")
547 (test-ps-js the-html-generator-1
548 (ps-html ((:a :href "foobar") "blorg"))
549 "'<A HREF=\"foobar\">blorg</A>';")
551 (test-ps-js the-html-generator-2
552 (ps-html ((:a :href (generate-a-link)) "blorg"))
553 "['<A HREF=\"', generateALink(), '\">blorg</A>']['join']('');")
555 (test-ps-js the-html-generator-3
556 (funcall (getprop document 'write)
557 (ps-html ((:a :href "#"
558 :onclick (ps-inline (transport))) "link")))
559 "document.write(['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">link</A>']['join'](''));")
561 (test-ps-js the-html-generator-4
562 (let ((disabled nil)
563 (authorized t))
564 (setf (getprop element 'inner-h-t-m-l)
565 (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
566 "Edit me"))))
567 "(function () {
568 var disabled = null;
569 var authorized = true;
570 return element.innerHTML = ['<TEXTAREA', disabled || !authorized ? [' DISABLED=\"', 'disabled', '\"']['join']('') : '', '>Edit me</TEXTAREA>']['join']('');
571 })();")
573 (test-ps-js plus-is-not-commutative
574 (setf x (+ "before" x "after"))
575 "x = 'before' + x + 'after';")
577 (test-ps-js plus-works-if-first
578 (setf x (+ x "middle" "after"))
579 "x = x + 'middle' + 'after';")
581 (test-ps-js method-call-op-form
582 (funcall (getprop (+ "" x) 'to-string))
583 "('' + x).toString();")
585 (test-ps-js method-call-op-form-args
586 (funcall (getprop (+ "" x) 'foo) 1 2 :baz 3)
587 "('' + x).foo(1, 2, 'baz', 3);")
589 (test-ps-js method-call-string
590 ((getprop "hi" 'to-string))
591 "'hi'.toString();")
593 (test-ps-js method-call-conditional
594 ((if a x y) 1)
595 "(a ? x : y)(1);")
597 (test-ps-js method-call-variable
598 ((@ x to-string))
599 "x.toString();")
601 (test-ps-js method-call-array
602 ((@ (list 10 20) to-string))
603 "[ 10, 20 ].toString();")
605 (test-ps-js method-call-lambda-call
606 (funcall (getprop (funcall (lambda (x) x) 10) 'to-string))
607 "(function (x) { return x; })(10).toString();")
609 (test no-whitespace-before-dot
610 (let* ((str (ps* '((@ ((lambda (x) x) 10) to-string))))
611 (dot-pos (position #\. str :test #'char=))
612 (char-before (elt str (1- dot-pos)))
613 (a-parenthesis #\)))
614 (is (char= char-before a-parenthesis))))
616 (test-ps-js simple-getprop
617 (let ((foo (create a 1)))
618 (alert (getprop foo 'a)))
619 "(function () {
620 var foo = { a : 1 };
621 return alert(foo.a);
622 })();")
624 (test-ps-js buggy-getprop
625 (getprop foo slot-name)
626 "foo[slotName];")
628 (test-ps-js buggy-getprop-two
629 (getprop foo (get-slot-name))
630 "foo[getSlotName()];")
632 (test-ps-js old-case-is-now-switch
633 ;; Switch was "case" before, but that was very non-lispish.
634 ;; For example, this code makes three messages and not one
635 ;; which may have been expected. This is because a switch
636 ;; statment must have a break statement for it to return
637 ;; after the alert. Otherwise it continues on the next
638 ;; clause.
639 (switch (aref blorg i)
640 (1 (alert "one"))
641 (2 (alert "two"))
642 (default (alert "default clause")))
643 "switch (blorg[i]) {
644 case 1: alert('one');
645 case 2: alert('two');
646 default: alert('default clause');
647 };")
649 (test-ps-js lisp-like-case
650 (case (aref blorg i)
651 (1 (alert "one"))
652 (2 (alert "two"))
653 (default (alert "default clause")))
654 "switch (blorg[i]) {
655 case 1:
656 alert('one');
657 break;
658 case 2:
659 alert('two');
660 break;
661 default: alert('default clause');
662 };")
665 (test-ps-js even-lispier-case
666 (case (aref blorg i)
667 ((1 2) (alert "Below three"))
668 (3 (alert "Three"))
669 (t (alert "Something else")))
670 "switch (blorg[i]) {
671 case 1:
672 case 2:
673 alert('Below three');
674 break;
675 case 3:
676 alert('Three');
677 break;
678 default: alert('Something else');
679 };")
681 (test-ps-js otherwise-case
682 (case (aref blorg i)
683 (1 (alert "one"))
684 (otherwise (alert "default clause")))
685 "switch (blorg[i]) {
686 case 1:
687 alert('one');
688 break;
689 default: alert('default clause');
690 };")
692 (test escape-sequences-in-string
693 (let ((escapes `((#\\ . #\\)
694 (#\b . #\Backspace)
695 (#\f . ,(code-char 12))
696 ("u000B" . ,(code-char #x000b));;Vertical tab, too uncommon to bother with
697 (#\n . #\Newline)
698 (#\r . #\Return)
699 (#\' . #\');;Double quote need not be quoted because parenscript strings are single quoted
700 (#\t . #\Tab)
701 ("u001F" . ,(code-char #x001f));; character below 32
702 ("u0080" . ,(code-char 128)) ;;Character over 127. Actually valid, parenscript escapes them to be sure.
703 ("uABCD" . ,(code-char #xabcd)))));; Really above ascii.
704 (loop for (js-escape . lisp-char) in escapes
705 for generated = (ps-doc* (format nil "hello~ahi" lisp-char))
706 for wanted = (format nil "'hello\\~ahi';" js-escape)
707 do (is (string= (normalize-js-code generated) wanted)))))
709 (test-ps-js getprop-setf
710 (setf (getprop x 'y) (+ (+ a 3) 4))
711 "x.y = a + 3 + 4;")
713 (test-ps-js getprop-conditional1
714 (getprop (if zoo foo bar) 'x)
715 "(zoo ? foo : bar).x;")
717 (test-ps-js getprop-conditional2
718 (getprop (if (not zoo) foo bar) 'x)
719 "(!zoo ? foo : bar).x;")
721 (test script-star-eval1
722 (is (string= "x = 1; y = 2;" (normalize-js-code (ps* '(setf x 1) '(setf y 2))))))
724 (test script-star-eval2
725 (is (string= "x = 1;" (normalize-js-code (ps* '(setf x 1))))))
727 (test-ps-js list-with-single-nil
728 (array nil)
729 "[null];")
731 (test-ps-js quoted-nil-is-array
732 'nil
733 "[];")
735 (test-ps-js defsetf1
736 (progn (defsetf baz (x y) (newval) `(set-baz ,x ,y ,newval))
737 (setf (baz 1 2) 3))
738 "(function () {
739 var _js2 = 1;
740 var _js3 = 2;
741 var _js1 = 3;
742 return setBaz(_js2, _js3, _js1);
743 })();")
745 (test-ps-js setf-macroexpands1
746 (macrolet ((bar (x y)
747 `(aref ,x ,y 1)))
748 (setf (bar foo 2) 3))
749 "foo[2][1] = 3;")
751 (test-ps-js defsetf-short
752 (progn (defsetf baz set-baz "docstring")
753 (setf (baz 1 2 3) "foo"))
754 "setBaz(1, 2, 3, 'foo');")
756 (test-ps-js defun-setf1
757 (progn (defun (setf some-thing) (new-val i1 i2)
758 (setf (aref *some-thing* i1 i2) new-val))
759 (setf (some-thing 1 2) "foo"))
760 "function __setf_someThing(newVal, i1, i2) {
761 return SOMETHING[i1][i2] = newVal;
763 __setf_someThing('foo', 1, 2);")
765 (test-ps-js defun-optional1
766 (defun test-opt (&optional x)
767 (if x "yes" "no"))
768 "function testOpt(x) {
769 return x ? 'yes' : 'no';
770 };")
772 (test-ps-js defun-optional2
773 (defun foo (x &optional y)
774 (+ x y))
775 "function foo(x, y) {
776 return x + y;
777 };")
779 (test-ps-js defun-optional3
780 (defun blah (&optional (x 0))
782 "function blah(x) {
783 if (x === undefined) {
784 x = 0;
786 return x;
787 };")
789 (test-ps-js arglist-optional4
790 (lambda (&optional (x 0 supplied?))
792 "(function (x) {
793 var suppliedwhat = x !== undefined;
794 if (!suppliedwhat) {
795 x = 0;
797 return x;
798 });")
800 (test-ps-js return-nothing
801 (defun foo () (return-from foo))
802 "function foo() {
803 return null;
804 };")
806 (test-ps-js set-timeout
807 (set-timeout (lambda () (alert "foo")) 10)
808 "setTimeout(function () { return alert('foo'); }, 10);")
810 (test-ps-js operator-precedence
811 (* 3 (+ 4 5) 6)
812 "3 * (4 + 5) * 6;")
814 (test-ps-js operators-1
815 (in prop obj)
816 "prop in obj;")
818 (test-ps-js incf1
819 (incf foo bar)
820 "foo += bar;")
822 (test-ps-js decf1
823 (decf foo bar)
824 "foo -= bar;")
826 (test-ps-js incf2
827 (incf x 5)
828 "x += 5;")
830 (test-ps-js decf2
831 (decf y 10)
832 "y -= 10;")
834 (test-ps-js setf-conditional
835 (setf foo (if x 1 2))
836 "foo = x ? 1 : 2;")
838 (test-ps-js obj-literal-numbers
839 (create 1 "foo")
840 "({ 1 : 'foo' });")
842 (test-ps-js obj-literal-strings
843 (create "foo" 2)
844 "({ 'foo' : 2 });")
846 (test-ps-js getprop-string
847 (getprop foo "bar")
848 "foo['bar'];")
850 (test-ps-js getprop-string1
851 (getprop "bar" 'length)
852 "'bar'.length;")
854 (test-ps-js getprop-progn
855 (getprop (progn (some-fun "abc") "123") "length")
856 "(someFun('abc'), '123')['length'];")
858 (test-ps-js method-call-block
859 ((@ (progn (some-fun "abc") "123") to-string))
860 "(someFun('abc'), '123').toString();")
862 (test-ps-js create-blank
863 (create)
864 "({ });")
866 (test-ps-js blank-object-literal
868 "({ });")
870 (test-ps-js array-literal1
872 "[];")
874 (test-ps-js array-literal2
875 ([])
876 "[];")
878 (test-ps-js array-literal3
879 ([] 1 2 3)
880 "[1, 2, 3];")
882 (test-ps-js array-literal4
883 ([] 1 (2 3))
884 "[1, [2, 3]];")
886 (test-ps-js array-literal5
887 ([] (1 2) ("a" "b"))
888 "[[1, 2], ['a', 'b']];")
890 (test-ps-js defun-rest1
891 (defun foo (&rest bar)
892 (alert (aref bar 1)))
893 "function foo() {
894 var bar = [];
895 for (var i1 = 0; i1 < arguments.length - 0; i1 += 1) {
896 bar[i1] = arguments[i1 + 0];
898 return alert(bar[1]);
899 };")
901 (test-ps-js defun-rest2
902 (defun foo (baz &rest bar) (+ baz (aref bar 1)))
903 "function foo(baz) {
904 var bar = [];
905 for (var i1 = 0; i1 < arguments.length - 1; i1 += 1) {
906 bar[i1] = arguments[i1 + 1];
908 return baz + bar[1];
909 };")
911 (test-ps-js defun-keyword1
912 (defun zoo (foo bar &key baz) (+ foo bar baz))
913 "function zoo(foo, bar) {
914 var _js2 = arguments.length;
915 for (var n1 = 2; n1 < _js2; n1 += 2) {
916 switch (arguments[n1]) {
917 case 'baz':
918 baz = arguments[n1 + 1];
921 var baz;
922 return foo + bar + baz;
923 };")
925 (test-ps-js defun-keyword2
926 (defun zoo (&key baz) (* baz baz))
927 "function zoo() {
928 var _js2 = arguments.length;
929 for (var n1 = 0; n1 < _js2; n1 += 2) {
930 switch (arguments[n1]) {
931 case 'baz':
932 baz = arguments[n1 + 1];
935 var baz;
936 return baz * baz;
937 };")
939 (test-ps-js defun-keyword3
940 (defun zoo (&key baz (bar 4)) (* baz bar))
941 "function zoo() {
942 var _js2 = arguments.length;
943 for (var n1 = 0; n1 < _js2; n1 += 2) {
944 switch (arguments[n1]) {
945 case 'baz':
946 baz = arguments[n1 + 1];
947 break;
948 case 'bar':
949 bar = arguments[n1 + 1];
952 var baz;
953 var bar = 'undefined' === typeof bar ? 4 : bar;
954 return baz * bar;
955 };")
957 (test-ps-js defun-keyword4
958 (defun hello-world (&key ((:my-name-key my-name) 1))
959 my-name)
960 "function helloWorld() {
961 var _js2 = arguments.length;
962 for (var n1 = 0; n1 < _js2; n1 += 2) {
963 switch (arguments[n1]) {
964 case 'my-name-key':
965 myName = arguments[n1 + 1];
968 var myName = 'undefined' === typeof myName ? 1 : myName;
969 return myName;
970 };")
972 (test-ps-js arglist-keyword-supplied
973 (lambda (&key (foo 1 supplied?))
974 foo)
975 "(function () {
976 var _js2 = arguments.length;
977 for (var n1 = 0; n1 < _js2; n1 += 2) {
978 switch (arguments[n1]) {
979 case 'foo':
980 foo = arguments[n1 + 1];
981 suppliedwhat = true;
984 var suppliedwhat;
985 var foo = 'undefined' === typeof foo ? 1 : foo;
986 return foo;
987 });")
989 (test-ps-js keyword-funcall1
990 (func :baz 1)
991 "func('baz', 1);")
993 (test-ps-js keyword-funcall2
994 (func :baz 1 :bar foo)
995 "func('baz', 1, 'bar', foo);")
997 (test-ps-js keyword-funcall3
998 (fun a b :baz c)
999 "fun(a, b, 'baz', c);")
1001 (test-ps-js cond1
1002 (cond ((= x 1) 1))
1003 "if (x === 1) {
1005 };")
1007 (test-ps-js cond2
1008 (cond ((= x 1) 2)
1009 ((= y (* x 4)) (foo "blah") (* x y)))
1010 "if (x === 1) {
1012 } else if (y === x * 4) {
1013 foo('blah');
1014 x * y;
1015 };")
1017 (test-ps-js if-exp-without-else-return
1018 (defun foo () (return-from foo (if x 1)))
1019 "function foo() {
1020 return x ? 1 : null;
1021 };")
1023 (test-ps-js progn-expression-single-statement
1024 (defun foo () (return-from foo (progn (* x y))))
1025 "function foo() {
1026 return x * y;
1027 };")
1029 (test-ps-js cond-expression1
1030 (defun foo ()
1031 (cond ((< 1 2) (bar "foo") (* 4 5))))
1032 "function foo() {
1033 if (1 < 2) {
1034 bar('foo');
1035 return 4 * 5;
1037 };")
1039 (test-ps-js cond-expression2
1040 (defun foo ()
1041 (cond ((< 2 1) "foo")
1042 ((= 7 7) "bar")))
1043 "function foo() {
1044 if (2 < 1) {
1045 return 'foo';
1046 } else if (7 === 7) {
1047 return 'bar';
1049 };")
1051 (test-ps-js cond-expression-final-t-clause
1052 (defun foo ()
1053 (cond ((< 1 2) (bar "foo") (* 4 5))
1054 ((= a b) (+ c d))
1055 ((< 1 2 3 4 5) x)
1056 (t "foo")))
1057 "function foo() {
1058 var _cmp1;
1059 var _cmp2;
1060 var _cmp3;
1061 if (1 < 2) {
1062 bar('foo');
1063 return 4 * 5;
1064 } else if (a === b) {
1065 return c + d;
1066 } else if (_cmp1 = 2, _cmp2 = 3, _cmp3 = 4, 1 < _cmp1 && _cmp1 < _cmp2 && _cmp2 < _cmp3 && _cmp3 < 5) {
1067 return x;
1068 } else {
1069 return 'foo';
1071 };")
1073 (test-ps-js cond-expression-middle-t-clause ;; should this signal a warning?
1074 (defun foo ()
1075 (cond ((< 2 1) 5)
1076 (t "foo")
1077 ((< 1 2) "bar")))
1078 "function foo() {
1079 if (2 < 1) {
1080 return 5;
1081 } else {
1082 return 'foo';
1084 };")
1086 (test-ps-js funcall-if-expression
1087 (funcall (getprop document 'write)
1088 (if (= *linkornot* 1)
1089 (ps-html ((:a :href "#"
1090 :onclick (ps-inline (transport)))
1091 img))
1092 img))
1093 "document.write(LINKORNOT === 1 ? ['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">', img, '</A>']['join']('') : img);")
1095 (test-ps-js negate-number-literal
1096 (- 1)
1097 "-1;")
1099 (test macro-environment1
1100 (is (string= (normalize-js-code (let* ((macroname (gensym)))
1101 (ps* `(defmacro ,macroname (x) `(+ ,x 123))
1102 `(defun test1 ()
1103 (macrolet ((,macroname (x) `(aref data ,x)))
1104 (when (,macroname x)
1105 (setf (,macroname x) 123)))))))
1106 (normalize-js-code
1107 "function test1() {
1108 return data[x] ? (data[x] = 123) : null;
1109 };"))))
1111 (test macro-environment2
1112 (is (string= (normalize-js-code (let ((outer-lexical-variable 1))
1113 (defpsmacro macro-environment2-macro (x)
1114 `(+ ,outer-lexical-variable ,x))
1115 (ps* '(macro-environment2-macro 2))))
1116 (normalize-js-code "1 + 2;"))))
1118 (test-ps-js ampersand-whole-1
1119 (macrolet ((foo (&whole foo bar baz)
1120 (declare (ignore bar baz))
1121 (with-standard-io-syntax (format nil "~a" foo))))
1122 (foo 1 2))
1123 "'(FOO 1 2)';")
1125 (test-ps-js keyword-consistent
1127 "'x';")
1129 (test-ps-js simple-symbol-macrolet
1130 (symbol-macrolet ((x 1)) x)
1131 "1;")
1133 (test-ps-js compound-symbol-macrolet
1134 (symbol-macrolet ((x 123)
1135 (y (* 2 x)))
1137 "2 * 123;")
1139 (test-ps-js define-symbol-macro
1140 (progn (define-symbol-macro tst-sym-macro 2)
1141 tst-sym-macro)
1142 "2;")
1144 (test-ps-js define-symbol-macro1
1145 (progn (define-symbol-macro tst-sym-macro1 2)
1146 (foo tst-sym-macro1))
1147 "foo(2);")
1149 (test-ps-js expression-progn
1150 (1+ (progn (foo) (if x 1 2)))
1151 "(foo(), x ? 1 : 2) + 1;")
1153 (test-ps-js let-decl-in-expression
1154 (defun f (x)
1155 (if x 1 (let* ((foo x)) foo)))
1156 "function f(x) {
1157 if (x) {
1158 return 1;
1159 } else {
1160 var foo = x;
1161 return foo;
1163 };")
1165 (test-ps-js special-var1
1166 (progn (defvar *foo*)
1167 (let* ((*foo* 2))
1168 (* *foo* 2)))
1169 "var FOO;
1170 (function () {
1171 var FOO_TMPSTACK1;
1172 try {
1173 FOO_TMPSTACK1 = FOO;
1174 FOO = 2;
1175 return FOO * 2;
1176 } finally {
1177 FOO = FOO_TMPSTACK1;
1179 })();")
1181 (test-ps-js special-var2
1182 (progn (defvar *foo*)
1183 (let* ((*baz* 3)
1184 (*foo* 2))
1185 (* *foo* 2 *baz*)))
1186 "var FOO;
1187 (function () {
1188 var BAZ = 3;
1189 var FOO_TMPSTACK1;
1190 try {
1191 FOO_TMPSTACK1 = FOO;
1192 FOO = 2;
1193 return FOO * 2 * BAZ;
1194 } finally {
1195 FOO = FOO_TMPSTACK1;
1197 })();")
1199 (test-ps-js literal1
1200 (setf x undefined)
1201 "x = undefined;")
1203 (test-ps-js literal2
1204 (aref this x)
1205 "this[x];")
1207 (test-ps-js setf-dec1
1208 (setf x (- 1 x 2))
1209 "x = 1 - x - 2;")
1211 (test-ps-js setf-dec2
1212 (setf x (- x 1 2))
1213 "x = x - 1 - 2;")
1215 (test-ps-js special-char-equals
1216 blah=
1217 "blahequals;")
1219 (test-ps-js setf-operator-priority
1220 (defun foo ()
1221 (or (getprop cache id)
1222 (setf (getprop cache id) ((@ document get-element-by-id) id))))
1223 "function foo() {
1224 return cache[id] || (cache[id] = document.getElementById(id));
1225 };")
1227 (test-ps-js aref-operator-priority
1228 (aref (if (and x (> (length x) 0))
1229 (aref x 0)
1232 "(x && x.length > 0 ? x[0] : y)[z];")
1234 (test-ps-js aref-operator-priority1
1235 (aref (or (getprop x 'y)
1236 (getprop a 'b))
1238 "(x.y || a.b)[z];")
1240 (test-ps-js aref-operator-priority2
1241 (aref (if a b c) 0)
1242 "(a ? b : c)[0];")
1244 (test-ps-js negate-operator-priority
1245 (- (if x y z))
1246 "-(x ? y : z);")
1248 (test-ps-js op-p1
1249 (new (or a b))
1250 "new (a || b);")
1252 (test-ps-js op-p2
1253 (delete (if a (or b c) d))
1254 "delete (a ? b || c : d);")
1256 (test-ps-js op-p3
1257 (not (if (or x (not y)) z))
1258 "!(x || !y ? z : null);")
1260 (test-ps-js op-p4
1261 (- (- (* 1 2) 3))
1262 "-(1 * 2 - 3);")
1264 (test-ps-js op-p5
1265 (instanceof (or a b) (if x y z))
1266 "((a || b) instanceof (x ? y : z));")
1268 (test-ps-js op-p7
1269 (or x (if (= x 0) "zero" "empty"))
1270 "x || (x === 0 ? 'zero' : 'empty');")
1272 (test-ps-js named-op-expression
1273 (throw (if a b c))
1274 "throw a ? b : c;")
1276 (test-ps-js named-op-expression1
1277 (typeof (or x y))
1278 "typeof (x || y);")
1280 (test-ps-js aref-array-expression
1281 (aref (or a b c) 0)
1282 "(a || b || c)[0];")
1284 (test-ps-js getprop-operator
1285 (getprop (or a b c) 'd)
1286 "(a || b || c).d;")
1288 (test-ps-js getprop-parens
1289 (getprop (getprop foo 'bar) 'baz)
1290 "foo.bar.baz;")
1292 (test-ps-js funcall-funcall
1293 ((foo))
1294 "foo()();")
1296 (test-ps-js expression-funcall
1297 ((or (@ window eval) eval) foo nil)
1298 "(window.eval || eval)(foo, null);")
1300 (test-ps-js expression-funcall1
1301 (((or (@ window eval) eval) foo nil))
1302 "(window.eval || eval)(foo, null)();")
1304 (test-ps-js expression-funcall2
1305 (((or (@ window eval) eval)) foo nil)
1306 "(window.eval || eval)()(foo, null);")
1308 (test-ps-js who-html1
1309 (who-ps-html (:span :class "ticker-symbol"
1310 :ticker-symbol symbol
1311 (:a :href "http://foo.com"
1312 symbol)
1313 (:span :class "ticker-symbol-popup")))
1314 "['<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"', symbol, '\"><A HREF=\"http://foo.com\">', symbol, '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>']['join']('');")
1316 (test-ps-js who-html2
1317 (who-ps-html (:p "t0" (:span "t1")))
1318 "'<P>t0<SPAN>t1</SPAN></P>';")
1320 (test-ps-js flet1
1321 ((lambda () (flet ((foo (x)
1322 (1+ x)))
1323 (foo 1))))
1324 "(function () {
1325 var foo = function (x) {
1326 return x + 1;
1328 return foo(1);
1329 })();")
1331 (test-ps-js flet2
1332 (flet ((foo (x) (1+ x))
1333 (bar (y) (+ 2 y)))
1334 (bar (foo 1)))
1335 "(function () {
1336 var foo = function (x) {
1337 return x + 1;
1339 var bar = function (y) {
1340 return 2 + y;
1342 return bar(foo(1));
1343 })();")
1345 (test-ps-js flet3
1346 (flet ((foo (x) (+ 2 x)))
1347 (flet ((foo (x) (1+ x))
1348 (bar (y) (+ 2 (foo y))))
1349 (bar (foo 1))))
1350 "(function () {
1351 var foo = function (x) {
1352 return 2 + x;
1354 var foo1 = function (x) {
1355 return x + 1;
1357 var bar = function (y) {
1358 return 2 + foo(y);
1360 return bar(foo1(1));
1361 })();")
1363 (test-ps-js labels1
1364 ((lambda () (labels ((foo (x)
1365 (if (= 0 x)
1367 (+ x (foo (1- x))))))
1368 (foo 3))))
1369 "(function () {
1370 var foo = function (x) {
1371 return 0 === x ? 0 : x + foo(x - 1);
1373 return foo(3);
1374 })();")
1376 (test-ps-js labels2
1377 (labels ((foo (x) (1+ (bar x)))
1378 (bar (y) (+ 2 (foo y))))
1379 (bar (foo 1)))
1380 "(function () {
1381 var foo = function (x) {
1382 return bar(x) + 1;
1384 var bar = function (y) {
1385 return 2 + foo(y);
1387 return bar(foo(1));
1388 })();")
1390 (test-ps-js labels3
1391 (labels ((foo (x) (1+ x))
1392 (bar (y) (+ 2 (foo y))))
1393 (bar (foo 1)))
1394 "(function () {
1395 var foo = function (x) {
1396 return x + 1;
1398 var bar = function (y) {
1399 return 2 + foo(y);
1401 return bar(foo(1));
1402 })();")
1404 (test-ps-js labels-lambda-list
1405 (labels ((foo (x &optional (y 0))
1406 (+ x y)))
1407 (foo 1))
1408 "(function () {
1409 var foo = function (x, y) {
1410 if (y === undefined) {
1411 y = 0;
1413 return x + y;
1415 return foo(1);
1416 })();")
1418 (test-ps-js for-loop-var-init-exp
1419 ((lambda (x)
1420 (do* ((y (if x 0 1) (1+ y))
1421 (z 0 (1+ z)))
1422 ((= y 3) z)))
1423 true)
1424 "(function (x) {
1425 return (function () {
1426 for (var y = x ? 0 : 1, z = 0; y !== 3; y += 1, z += 1) {
1428 return z;
1429 })();
1430 })(true);")
1432 (test-ps-js math-pi
1434 "Math.PI;")
1436 (test-ps-js literal-array
1437 '(1 2 3)
1438 "[1, 2, 3];")
1440 (test-ps-js literal-array-1
1441 '(1 foo 3)
1442 "[1, 'foo', 3];")
1444 (test ps-lisp-expands-in-lexical-environment
1445 (is (string= "5;" (let ((x 5)) (ps (lisp x))))))
1447 (test ps*-lisp-expands-in-null-lexical-environment ;; ccl only does a warning
1448 (signals unbound-variable (let ((x 5)) (declare (ignore x)) (ps* '(lisp x)))))
1450 (test ps*-lisp-expands-in-dynamic-environment
1451 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps* '(+ 1 (lisp (locally (declare (special foo)) foo))))))))
1453 (test ps-lisp-dynamic-environment
1454 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps (+ 1 (lisp foo)))))))
1456 (test-ps-js nested-if-expressions1
1457 (defun foo ()
1458 (return-from foo (if (if x y z) a b)))
1459 "function foo() {
1460 if (x ? y : z) {
1461 return a;
1462 } else {
1463 return b;
1465 };")
1467 (test-ps-js nested-if-expressions2
1468 (defun foo ()
1469 (if x y (if z a b)))
1470 "function foo() {
1471 if (x) {
1472 return y;
1473 } else {
1474 return z ? a : b;
1476 };")
1478 (test-ps-js let1
1479 (let (x)
1480 (+ x x))
1481 "(function () {
1482 var x = null;
1483 return x + x;
1484 })();")
1486 (test-ps-js let2
1487 (let ((x 1))
1488 (+ x x))
1489 "(function () {
1490 var x = 1;
1491 return x + x;
1492 })();")
1494 (test-ps-js let-x-x
1495 (let ((x (1+ x)))
1496 (+ x x))
1497 "(function () {
1498 var x1 = x + 1;
1499 return x1 + x1;
1500 })();")
1502 (test-ps-js let3
1503 (let ((x 1)
1504 (y 2))
1505 (+ x x))
1506 "(function () {
1507 var x = 1;
1508 var y = 2;
1509 return x + x;
1510 })();")
1512 (test-ps-js let4
1513 (let ((x 1)
1514 (y (1+ x)))
1515 (+ x y))
1516 "(function () {
1517 var x1 = 1;
1518 var y = x + 1;
1519 return x1 + y;
1520 })();")
1522 (test-ps-js let5
1523 (let ((x 1))
1524 (+ x 1)
1525 (let ((x (+ x 5)))
1526 (+ x 1))
1527 (+ x 1))
1528 "(function () {
1529 var x = 1;
1530 x + 1;
1531 var x1 = x + 5;
1532 x1 + 1;
1533 return x + 1;
1534 })();")
1536 (test-ps-js let6
1537 (let ((x 2))
1538 (let ((x 1)
1539 (y (1+ x)))
1540 (+ x y)))
1541 "(function () {
1542 var x = 2;
1543 var x1 = 1;
1544 var y = x + 1;
1545 return x1 + y;
1546 })();")
1548 (test-ps-js let-exp1
1549 (lambda ()
1550 (let (x)
1551 (+ x x)))
1552 "(function () {
1553 var x = null;
1554 return x + x;
1555 });")
1557 (test-ps-js let*1
1558 (let* ((x 1))
1559 (+ x x))
1560 "(function () {
1561 var x = 1;
1562 return x + x;
1563 })();")
1565 (test-ps-js let*2
1566 (let* ((x 1)
1567 (y (+ x 2)))
1568 (+ x y))
1569 "(function () {
1570 var x = 1;
1571 var y = x + 2;
1572 return x + y;
1573 })();")
1575 (test-ps-js let*3
1576 (let ((x 3))
1577 (let* ((x 1)
1578 (y (+ x 2)))
1579 (+ x y)))
1580 "(function () {
1581 var x = 3;
1582 var x1 = 1;
1583 var y = x1 + 2;
1584 return x1 + y;
1585 })();")
1587 (test-ps-js let*4
1588 (let ((x 3))
1589 (let* ((y (+ x 2))
1590 (x 1))
1591 (+ x y)))
1592 "(function () {
1593 var x = 3;
1594 var y = x + 2;
1595 var x1 = 1;
1596 return x1 + y;
1597 })();")
1599 (test-ps-js symbol-macrolet-var
1600 (symbol-macrolet ((x y))
1601 (var x))
1602 "var y;")
1604 (test-ps-js setf-conditional1
1605 (setf x (unless (null a) (1+ a)))
1606 "x = a != null ? a + 1 : null;")
1608 (test-ps-js setf-let1
1609 (setf x (let ((a 1)) a))
1610 "x = (function () {
1611 var a = 1;
1612 return a;
1613 })();")
1615 (test-ps-js setf-let2
1616 (setf x (let ((a (foo)))
1617 (unless (null a)
1618 (1+ a))))
1619 "x = (function () {
1620 var a = foo();
1621 return a != null ? a + 1 : null;
1622 })();")
1624 (test-ps-js symbol-macro-env1
1625 (symbol-macrolet ((bar 1))
1626 (macrolet ((bar (x y) `(+ ,x ,y)))
1627 (bar bar bar)))
1628 "1 + 1;")
1630 (test-ps-js symbol-macrolet-fun1
1631 (symbol-macrolet ((baz +))
1632 (baz 1 2))
1633 "baz(1, 2);")
1635 (test-ps-js lisp2-namespaces1
1636 (let ((list nil))
1637 (setf list (list 1 2 3)))
1638 "(function () {
1639 var list = null;
1640 return list = [1, 2, 3];
1641 })();")
1643 (test-ps-js let-shadows-symbol-macrolet
1644 (symbol-macrolet ((x y))
1645 (let ((x 1))
1646 (+ x x))
1647 (+ x x))
1648 "(function () {
1649 var x1 = 1;
1650 return x1 + x1;
1651 })();
1652 y + y;")
1654 (test-ps-js let-rename-optimization1
1655 (let ((x 1))
1656 (+ x x))
1657 "(function () {
1658 var x = 1;
1659 return x + x;
1660 })();")
1662 (test-ps-js let-rename-optimization2
1663 (lambda (x)
1664 (let ((x (+ 1 x)))
1666 "(function (x) {
1667 var x1 = 1 + x;
1668 return x1;
1669 });")
1671 (test-ps-js symbol-macro-array
1672 (symbol-macrolet ((x 1))
1673 (list x))
1674 "[1];")
1676 (test-ps-js symbol-macro-obj
1677 (symbol-macrolet ((x y))
1678 (create x 1))
1679 "({ x : 1 });")
1681 (test-ps-js symbol-macro-conditional1
1682 (symbol-macrolet ((x y))
1683 (if x x x))
1684 "if (y) {
1686 } else {
1688 };")
1690 (test-ps-js symbol-macro-conditional2
1691 (symbol-macrolet ((x y))
1692 (1+ (if x x x)))
1693 "(y ? y : y) + 1;")
1695 (test-ps-js flet-apply
1696 (flet ((foo () 'bar))
1697 (apply (function foo) nil))
1698 "(function () {
1699 var foo = function () {
1700 return 'bar';
1702 return foo.apply(this, null);
1703 })();")
1705 (test-ps-js let-apply
1706 (let ((foo (lambda () 1)))
1707 (let ((foo (lambda () 2)))
1708 (apply foo nil)))
1709 "(function () {
1710 var foo = function () {
1711 return 1;
1713 var foo1 = function () {
1714 return 2;
1716 return foo1.apply(this, null);
1717 })();")
1719 (test-ps-js flet-let
1720 (flet ((x (x) (1+ x)))
1721 (let ((x 2))
1722 (x x)))
1723 "(function () {
1724 var x = function (x) {
1725 return x + 1;
1727 var x1 = 2;
1728 return x(x1);
1729 })();")
1731 (test-ps-js let-flet
1732 (let ((x 2))
1733 (flet ((x (x) (1+ x)))
1734 (x x)))
1735 "(function () {
1736 var x = 2;
1737 var x1 = function (x) {
1738 return x + 1;
1740 return x1(x);
1741 })();")
1743 (test-ps-js labels-let
1744 (labels ((x (x) (1+ x)))
1745 (let ((x 2))
1746 (x x)))
1747 "(function () {
1748 var x = function (x) {
1749 return x + 1;
1751 var x1 = 2;
1752 return x(x1);
1753 })();")
1755 (test-ps-js let-labels
1756 (let ((x 2))
1757 (labels ((x (x) (1+ x)))
1758 (x x)))
1759 "(function () {
1760 var x = 2;
1761 var x1 = function (x) {
1762 return x + 1;
1764 return x1(x);
1765 })();")
1767 (test-ps-js macrolet-let-inteference
1768 (macrolet ((a (n) `(+ ,n 5)))
1769 (let ((a (a 1)))
1770 (let ((b (a (- a 4))))
1771 (+ a b))))
1772 "(function () {
1773 var a = 1 + 5;
1774 var b = (a - 4) + 5;
1775 return a + b;
1776 })();")
1778 (test-ps-js let-subtract-add
1779 (let ((x 1))
1780 (let ((x 2))
1781 (- x x)
1782 (- x)
1783 (decf x)
1784 (incf x)))
1785 "(function () {
1786 var x = 1;
1787 var x1 = 2;
1788 x1 - x1;
1789 -x1;
1790 --x1;
1791 return ++x1;
1792 })();")
1794 (test-ps-js create-reserved-word
1795 (create :default 1)
1796 "({ 'default' : 1 });")
1798 (test-ps-js getprop-reserved-word
1799 (getprop foo :default)
1800 "foo['default'];")
1802 (test-ps-js getprop-reserved-word1
1803 (getprop foo 'default)
1804 "foo['default'];")
1806 (test-ps-js eval-when-ps-side
1807 (eval-when (:execute)
1809 "5;")
1811 (defvar *lisp-output* nil)
1813 (test eval-when-lisp-side ()
1814 (setf *lisp-output* 'original-value)
1815 (let ((js-output (normalize-js-code
1816 (ps-doc* `(eval-when (:compile-toplevel)
1817 (setf *lisp-output* 'it-works))))))
1818 (is (eql 'it-works *lisp-output*))
1819 (is (string= "" js-output))))
1821 (defpsmacro my-in-package (package-name)
1822 `(eval-when (:compile-toplevel)
1823 (setf *lisp-output* ,package-name)))
1825 (test eval-when-macro-expansion ()
1826 (setf *lisp-output* 'original-value)
1827 (let ((js-output (normalize-js-code
1828 (ps-doc* `(progn
1829 (my-in-package :cl-user)
1830 3)))))
1831 (declare (ignore js-output))
1832 (is (eql :cl-user *lisp-output*))))
1834 (test eval-when-macrolet-expansion ()
1835 (setf *lisp-output* 'original-value)
1836 (let ((js-output (normalize-js-code
1837 (ps-doc* `(macrolet ((my-in-package2 (package-name)
1838 `(eval-when (:compile-toplevel)
1839 (setf *lisp-output* ,package-name))))
1840 (my-in-package2 :cl-user)
1841 3)))))
1842 (declare (ignore js-output))
1843 (is (eql :cl-user *lisp-output*))))
1845 (test-ps-js getprop-keyword
1846 (getprop foo :bar)
1847 "foo['bar'];")
1849 (test-ps-js nary-comparison1
1850 (lambda () (< 1 2 3))
1851 "(function () {
1852 var _cmp1;
1853 return (_cmp1 = 2, 1 < _cmp1 && _cmp1 < 3);
1854 });")
1856 (test-ps-js chain-getprop1
1857 (chain ($ "foo") (bar x z) frob (baz 5))
1858 "$('foo').bar(x, z).frob.baz(5);")
1860 (test-ps-js chain-getprop2
1861 (chain ($ "foo") bar baz)
1862 "$('foo').bar.baz;")
1864 (test-ps-js chain-getprop3
1865 (chain ($ "foo") bar (x y) baz)
1866 "$('foo').bar.x(y).baz;")
1868 (test-ps-js flet-expression
1869 (1+ (flet ((foo (x) (1+ x)))
1870 (foo 1)))
1871 "(function () {
1872 var foo = function (x) {
1873 return x + 1;
1875 return foo(1);
1876 })() + 1;")
1878 (test-ps-js flet-lambda-list
1879 (flet ((foo (x &key (y 0))
1880 (+ x y)))
1881 (foo 1 :y 2))
1882 "(function () {
1883 var foo = function (x) {
1884 var _js2 = arguments.length;
1885 for (var n1 = 1; n1 < _js2; n1 += 2) {
1886 switch (arguments[n1]) {
1887 case 'y':
1888 y = arguments[n1 + 1];
1891 var y = 'undefined' === typeof y ? 0 : y;
1892 return x + y;
1894 return foo(1, 'y', 2);
1895 })();")
1897 (test-ps-js return-case-break-elimination
1898 (defun foo ()
1899 (return-from foo
1900 (case 1
1901 (0 1)
1902 (otherwise 2))))
1903 "function foo() {
1904 switch (1) {
1905 case 0:
1906 return 1;
1907 default:
1908 return 2;
1910 };")
1912 (test-ps-js aplusplus
1914 "aplusplus;")
1916 (test-ps-js astarstar
1918 "astarstar;")
1920 (test-ps-js switch-return-fallthrough
1921 (defun foo ()
1922 (return-from foo
1923 (switch x
1924 (1 (foo) break)
1925 (2 (bar))
1926 (default 4))))
1927 "function foo() {
1928 switch (x) {
1929 case 1:
1930 return foo();
1931 case 2:
1932 bar();
1933 default:
1934 return 4;
1936 };")
1938 (test-ps-js return-last-case
1939 (defun foo ()
1940 (return-from foo
1941 (case x
1942 (a 'eh)
1943 (b 'bee))))
1944 "function foo() {
1945 switch (x) {
1946 case a:
1947 return 'eh';
1948 case b:
1949 return 'bee';
1951 };")
1953 (test-ps-js return-macrolet
1954 (defun foo ()
1955 (return-from foo
1956 (macrolet ((x () 1))
1957 (case (x)
1958 (a 'eh)
1959 (b 'bee)))))
1960 "function foo() {
1961 switch (1) {
1962 case a:
1963 return 'eh';
1964 case b:
1965 return 'bee';
1967 };")
1969 (test-ps-js mv-bind1
1970 (multiple-value-bind (a b)
1971 (progn
1972 (returns-mv)
1973 (doesnt))
1974 (alert a)
1975 (alert b))
1976 "(function () {
1977 var prevMv2 = null;
1978 returnsMv();
1979 prevMv2 = arguments['callee']['mv'];
1980 try {
1981 arguments['callee']['mv'] = true;
1982 var a = doesnt();
1983 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1984 var b = mv1[0];
1985 alert(a);
1986 return alert(b);
1987 } finally {
1988 if ('undefined' === typeof prevMv2) {
1989 delete arguments['callee']['mv'];
1990 } else {
1991 arguments['callee']['mv'] = prevMv2;
1994 })();")
1996 (test-ps-js mv-bind2
1997 (multiple-value-bind (a b)
1998 (let ((a 1))
1999 (returns-mv a)
2000 (doesnt b))
2001 (alert a)
2002 (alert b))
2003 "(function () {
2004 var prevMv2 = null;
2005 var a = 1;
2006 returnsMv(a);
2007 prevMv2 = arguments['callee']['mv'];
2008 try {
2009 arguments['callee']['mv'] = true;
2010 var a3 = doesnt(b);
2011 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
2012 var b = mv1[0];
2013 alert(a3);
2014 return alert(b);
2015 } finally {
2016 if ('undefined' === typeof prevMv2) {
2017 delete arguments['callee']['mv'];
2018 } else {
2019 arguments['callee']['mv'] = prevMv2;
2022 })();")
2024 (test-ps-js multiple-value-bind-simple
2025 (multiple-value-bind (a b) (blah)
2026 (+ a b))
2027 "(function () {
2028 var prevMv2 = null;
2029 prevMv2 = arguments['callee']['mv'];
2030 try {
2031 arguments['callee']['mv'] = true;
2032 var a = blah();
2033 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
2034 var b = mv1[0];
2035 return a + b;
2036 } finally {
2037 if ('undefined' === typeof prevMv2) {
2038 delete arguments['callee']['mv'];
2039 } else {
2040 arguments['callee']['mv'] = prevMv2;
2043 })();")
2045 (test-ps-js values0
2046 (lambda () (values))
2047 "(function () {
2048 return null;
2049 });")
2051 (test-ps-js values1
2052 (values x)
2053 "x;")
2055 (test-ps-js values2
2056 (values x y)
2057 "(function () {
2058 var val1_1 = x;
2059 var valrest2 = [y];
2060 if ('undefined' !== typeof arguments['callee']['caller']['mv']) {
2061 arguments['callee']['caller']['mv'] = valrest2;
2063 return val1_1;
2064 })();")
2066 (test-ps-js values3
2067 (values x y z)
2068 "(function () {
2069 var val1_1 = x;
2070 var valrest2 = [y, z];
2071 if ('undefined' !== typeof arguments['callee']['caller']['mv']) {
2072 arguments['callee']['caller']['mv'] = valrest2;
2074 return val1_1;
2075 })();")
2077 (test-ps-js values-return
2078 (defun foo ()
2079 (return-from foo (values x y)))
2080 "function foo() {
2081 var val1_1 = x;
2082 var valrest2 = [y];
2083 if ('undefined' !== typeof arguments['callee']['caller']['mv']) {
2084 arguments['callee']['caller']['mv'] = valrest2;
2086 return val1_1;
2087 };")
2089 (test-ps-js return-macrolet1
2090 (defun foo ()
2091 (return-from foo
2092 (symbol-macrolet ((x 2))
2093 (loop do (+ x x)))))
2094 "function foo() {
2095 for (; true; ) {
2096 2 + 2;
2098 };")
2100 (test-ps-js return-cond
2101 (defun foo ()
2102 (return-from foo
2103 (cond ((foo? x) (loop for y in x do (foo y)))
2104 ((bar? x) x)
2105 (t 3))))
2106 "function foo() {
2107 if (foowhat(x)) {
2108 var _js2 = x.length;
2109 var _js1 = 0;
2110 if (_js1 < _js2) {
2111 var y = x[_js1];
2112 while (true) {
2113 foo(y);
2114 _js1 += 1;
2115 if (_js1 >= _js2) {
2116 break;
2118 y = x[_js1];
2121 } else if (barwhat(x)) {
2122 return x;
2123 } else {
2124 return 3;
2126 };")
2128 (test-ps-js return-case
2129 (defun foo ()
2130 (return-from foo
2131 (case x
2132 (1 (loop for y in x do (foo y)))
2133 (2 x)
2134 ((t) 3))))
2135 "function foo() {
2136 switch (x) {
2137 case 1:
2138 var _js2 = x.length;
2139 var _js1 = 0;
2140 if (_js1 < _js2) {
2141 var y = x[_js1];
2142 while (true) {
2143 foo(y);
2144 _js1 += 1;
2145 if (_js1 >= _js2) {
2146 break;
2148 y = x[_js1];
2150 return;
2151 } else {
2152 return null;
2154 case 2:
2155 return x;
2156 default:
2157 return 3;
2159 };")
2161 (test-ps-js return-case1
2162 (defun foo ()
2163 (return-from foo
2164 (case x
2165 (1 (if a 1 2))
2166 (2 x)
2167 ((t) 3))))
2168 "function foo() {
2169 switch (x) {
2170 case 1:
2171 return a ? 1 : 2;
2172 case 2:
2173 return x;
2174 default:
2175 return 3;
2177 };")
2179 (test-ps-js lambda-loop-if-return
2180 (lambda ()
2181 (if a
2182 (loop for y in x do (foo y))
2184 "(function () {
2185 if (a) {
2186 var _js4 = x.length;
2187 var _js3 = 0;
2188 if (_js3 < _js4) {
2189 var y = x[_js3];
2190 while (true) {
2191 foo(y);
2192 _js3 += 1;
2193 if (_js3 >= _js4) {
2194 break;
2196 y = x[_js3];
2199 } else {
2200 return c;
2202 });")
2204 (test-ps-js lambda-loop-if-return1
2205 (defun baz ()
2206 (foo (lambda ()
2207 (if a
2208 (progn (loop for y in x do (foo y))
2209 (return-from baz))
2210 c))))
2211 "function baz() {
2212 try {
2213 return foo(function () {
2214 if (a) {
2215 var _js4 = x.length;
2216 var _js3 = 0;
2217 if (_js3 < _js4) {
2218 var y = x[_js3];
2219 while (true) {
2220 foo(y);
2221 _js3 += 1;
2222 if (_js3 >= _js4) {
2223 break;
2225 y = x[_js3];
2228 throw { 'ps-block-tag' : 'baz', 'ps-return-value' : null };
2229 } else {
2230 return c;
2233 } catch (err) {
2234 if (err && 'baz' === err['ps-block-tag']) {
2235 return err['ps-return-value'];
2236 } else {
2237 throw err;
2240 };")
2242 (test-ps-js switch-loop
2243 (case x
2244 (1 (dolist (a b))))
2245 "switch (x) {
2246 case 1:
2247 for (var a = null, _js_idx1 = 0; _js_idx1 < b.length; _js_idx1 += 1) {
2248 a = b[_js_idx1];
2250 };")
2252 (test-ps-js switch-folds-blocks
2253 (case x
2254 (1 (loop repeat 3 do (alert "foo"))))
2255 "switch (x) {
2256 case 1:
2257 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
2258 alert('foo');
2260 };")
2262 (test-ps-js setf-places-before-macros
2263 (lambda ()
2264 (defsetf left (el) (offset)
2265 `(setf (@ ,el style left) ,offset))
2266 (macrolet ((left (el)
2267 `(@ ,el offset-left)))
2268 (setf (left x) 10)
2269 (left x)))
2270 "(function () {
2271 var _js2 = x;
2272 var _js1 = 10;
2273 _js2.style.left = _js1;
2274 return x.offsetLeft;
2275 });")
2277 (test-ps-js for-return
2278 (lambda () (dolist (arg args) (foo arg)))
2279 "(function () {
2280 for (var arg = null, _js_idx1 = 0; _js_idx1 < args.length; _js_idx1 += 1) {
2281 arg = args[_js_idx1];
2282 foo(arg);
2284 });")
2286 (test-ps-js try-catch-return
2287 (defun foo ()
2288 (return-from foo
2289 (try (foo)
2290 (:catch (e)
2291 (bar))
2292 (:finally
2293 (cleanup)))))
2294 "function foo() {
2295 try {
2296 return foo();
2297 } catch (e) {
2298 return bar();
2299 } finally {
2300 cleanup();
2302 };")
2304 (test-ps-js defun-setf-optional
2305 (defun (setf foo) (new-value b &optional c)
2306 (setf (aref b (or c 0)) new-value))
2307 "function __setf_foo(newValue, b, c) {
2308 return b[c || 0] = newValue;
2309 };")
2311 (test-ps-js defun-setf-rest
2312 (progn (defun (setf foo) (new-value b &rest foo)
2313 (do-something b foo new-value))
2314 (setf (foo x 1 2 3 4) 5))
2315 "function __setf_foo(newValue, b) {
2316 var foo = [];
2317 for (var i1 = 0; i1 < arguments.length - 2; i1 += 1) {
2318 foo[i1] = arguments[i1 + 2];
2320 return doSomething(b, foo, newValue);
2322 __setf_foo(5, x, 1, 2, 3, 4);")
2324 (test-ps-js return-null
2325 (defun foo () (return-from foo nil))
2326 "function foo() {
2327 return null;
2328 };")
2330 (test-ps-js implicit-return-null
2331 (lambda ()
2333 "(function () {
2334 return null;
2335 });")
2337 (test-ps-js implicit-return-null
2338 (lambda ()
2339 nil)
2340 "(function () {
2341 return null;
2342 });")
2344 (test-ps-js return-conditional-nested
2345 (defun blep (ss x y)
2346 (when foo?
2347 (let ((pair (bar)))
2348 (unless (null pair)
2349 (destructuring-bind (a b) pair
2350 (unless (or (null a) (null b))
2351 (let ((val (baz a b)))
2352 (unless (null val)
2353 (when (blah val)
2354 (unless (blee)
2355 t))))))))))
2356 "function blep(ss, x, y) {
2357 if (foowhat) {
2358 var pair = bar();
2359 if (pair != null) {
2360 var a = pair[0];
2361 var b = pair[1];
2362 if (!(a == null || b == null)) {
2363 var val = baz(a, b);
2364 if (val != null) {
2365 if (blah(val)) {
2366 return !blee() ? true : null;
2372 };")
2374 ;; this test needs to be rewritten when named blocks are implemented!!!!
2375 (test-ps-js return-when-returns-broken-return
2376 (defun foo ()
2377 (return-from foo (when x 1))
2378 (+ 2 3))
2379 "function foo() {
2380 return x ? 1 : null;
2381 return 2 + 3;
2382 };")
2384 (test-ps-js return-case-conditional
2385 (defun foo ()
2386 (return-from foo
2387 (case foo
2388 (123 (when (bar) t))
2389 (345 (blah)))))
2390 "function foo() {
2391 switch (foo) {
2392 case 123:
2393 return bar() ? true : null;
2394 case 345:
2395 return blah();
2397 };")
2399 (test-ps-js return-try-conditional
2400 (defun foo ()
2401 (return-from foo
2402 (try (when x 1)
2403 (:catch (x) 2)
2404 (:finally (bar)))))
2405 "function foo() {
2406 try {
2407 return x ? 1 : null;
2408 } catch (x) {
2409 return 2;
2410 } finally {
2411 bar();
2413 };")
2415 (test-ps-js function-declare-special
2416 (lambda ()
2417 (declare (special *foo*))
2418 (let ((*foo* 1))
2419 (1+ *foo*)))
2420 "(function () {
2421 var FOO_TMPSTACK1;
2422 try {
2423 FOO_TMPSTACK1 = FOO;
2424 FOO = 1;
2425 return FOO + 1;
2426 } finally {
2427 FOO = FOO_TMPSTACK1;
2429 });")
2431 (test-ps-js declare-special-let
2432 (let ((*foo* 123))
2433 (declare (special *foo*))
2434 (blah))
2435 "(function () {
2436 var FOO_TMPSTACK1;
2437 try {
2438 FOO_TMPSTACK1 = FOO;
2439 FOO = 123;
2440 return blah();
2441 } finally {
2442 FOO = FOO_TMPSTACK1;
2444 })();")
2446 (test-ps-js macro-null-toplevel
2447 (progn
2448 (defmacro macro-null-toplevel ()
2449 nil)
2450 (macro-null-toplevel))
2453 (test-ps-js define-symbol-macro-let
2454 (progn
2455 (define-symbol-macro test-symbol-macro 1)
2456 (let ((test-symbol-macro 2))
2457 (1+ test-symbol-macro))
2458 (1+ test-symbol-macro))
2459 "(function () {
2460 var testSymbolMacro1 = 2;
2461 return testSymbolMacro1 + 1;
2462 })();
2463 1 + 1;")
2465 (test-ps-js define-symbol-macro-flet
2466 (progn
2467 (define-symbol-macro test-symbol-macro1 1)
2468 (flet ((test-symbol-macro1 () 2))
2469 (foo test-symbol-macro1)
2470 (test-symbol-macro1))
2471 (bar test-symbol-macro1))
2472 "(function () {
2473 var testSymbolMacro1_1 = function () {
2474 return 2;
2476 foo(1);
2477 return testSymbolMacro1_1();
2478 })();
2479 bar(1);")
2481 (test compile-stream-nulls
2482 (is (string=
2484 (with-input-from-string (s "
2485 (defmacro macro-null-toplevel ()
2486 nil)
2487 (macro-null-toplevel)")
2488 (ps-compile-stream s)))))
2490 (test compile-stream1
2491 (is (string=
2492 "(function () {
2493 var testSymbolMacro1_1 = function () {
2494 return 2;
2496 foo(1);
2497 return testSymbolMacro1_1();
2498 })();
2499 bar(1);
2501 (with-input-from-string (s "
2502 (define-symbol-macro test-symbol-macro1 1)
2503 (flet ((test-symbol-macro1 () 2))
2504 (foo test-symbol-macro1)
2505 (test-symbol-macro1))
2506 (bar test-symbol-macro1)")
2507 (ps::with-blank-compilation-environment (ps-compile-stream s))))))
2509 (test-ps-js equality-nary1
2510 (let ((x 10) (y 10) (z 10))
2511 (= x y z))
2512 "(function () {
2513 var _cmp1;
2514 var x = 10;
2515 var y = 10;
2516 var z = 10;
2517 return (_cmp1 = y, x === _cmp1 && _cmp1 === z);
2518 })();")
2520 (test-ps-js equality1
2521 (progn
2522 (equal a b)
2523 (eql a b)
2524 (eq a b)
2525 (= a b))
2526 "a == b;
2527 a === b;
2528 a === b;
2529 a === b;")
2531 (test-ps-js getprop-quote-reserved
2532 (getprop foo ':break)
2533 "foo['break'];")
2535 (test-ps-js defun-block-return-from
2536 (defun foo (x)
2537 (baz 4)
2538 (return-from foo x)
2539 (bar 5))
2540 "function foo(x) {
2541 baz(4);
2542 return x;
2543 return bar(5);
2544 }; ")
2546 (test-ps-js block-return-from
2547 (block scope
2548 (foo)
2549 (when (bar)
2550 (return-from scope))
2551 (blee))
2552 "(function () {
2553 foo();
2554 if (bar()) {
2555 return null;
2557 return blee();
2558 })();")
2560 (test-ps-js block-return-from0
2561 (defun baz ()
2562 (block scope
2563 (foo)
2564 (when (bar)
2565 (return-from scope))
2566 (blee)))
2567 "function baz() {
2568 foo();
2569 if (bar()) {
2570 return null;
2572 return blee();
2573 };")
2575 (test-ps-js block-return-from01
2576 (defun baz ()
2577 (block scope
2578 (foo)
2579 (when (bar)
2580 (return-from scope))
2581 (blee))
2583 "function baz() {
2584 scope: {
2585 foo();
2586 if (bar()) {
2587 break scope;
2589 blee();
2591 return 2;
2592 };")
2594 (test-ps-js block-return-from02
2595 (defun baz ()
2596 (block scope
2597 (foo)
2598 (when (bar)
2599 (return-from scope (foobar)))
2600 (blee))
2602 "function baz() {
2603 scope: {
2604 foo();
2605 if (bar()) {
2606 foobar();
2607 break scope;
2609 blee();
2611 return 2;
2612 };")
2614 (test-ps-js block-return-from1
2615 (lambda ()
2616 (block scope
2617 (foo)
2618 (when (bar)
2619 (return-from scope))
2620 (blee))
2621 (+ 1 2))
2622 "(function () {
2623 scope: {
2624 foo();
2625 if (bar()) {
2626 break scope;
2628 blee();
2630 return 1 + 2;
2631 });")
2633 (test-ps-js block-return-from2
2634 (lambda ()
2635 (bar 5)
2636 (block scope
2637 (foo)
2638 (when (bar)
2639 (return-from scope 6))
2640 (blee)))
2641 "(function () {
2642 bar(5);
2643 foo();
2644 if (bar()) {
2645 return 6;
2647 return blee();
2648 });")
2650 (test-ps-js let-funcall
2651 (let ((x foo))
2652 (funcall x)
2653 (let ((x bar))
2654 (funcall x))
2655 (funcall x))
2656 "(function () {
2657 var x = foo;
2658 x();
2659 var x1 = bar;
2660 x1();
2661 return x();
2662 })();")
2664 (test-ps-js symbol-macrolet-funcall
2665 (symbol-macrolet ((foo bar))
2666 (funcall foo 1 2 3))
2667 "bar(1, 2, 3);")
2669 (test-ps-js times-assign
2670 (setf x (* x 1000))
2671 "x *= 1000;")
2673 (test-ps-js vector-literal
2674 #(1 2 3)
2675 "[1, 2, 3];")
2677 (test-ps-js rem1
2678 (+ 1 (rem 2 (+ 3 4)))
2679 "1 + 2 % (3 + 4);")
2681 (test-ps-js non-associative
2682 (+ (/ 1 (/ 2 3)) (- 1 (- 2 3)))
2683 "1 / (2 / 3) + (1 - (2 - 3));")
2685 (test-ps-js lambda-apply
2686 (lambda (x)
2687 (apply (lambda (y) (bar (1+ y))) x))
2688 "(function (x) {
2689 return (function (y) {
2690 return bar(y + 1);
2691 }).apply(this, x);
2692 });")
2694 (test-ps-js operator-expressions-nested-let
2695 (let ((x (let ((y 1))
2696 y)))
2698 "(function () {
2699 var y;
2700 var x = (y = 1, y);
2701 return x;
2702 })();")
2704 (test-ps-js operator-expressions-array-nested-let
2705 (list (let ((y 1)) y) 2)
2706 "[(function () {
2707 var y = 1;
2708 return y;
2709 })(), 2];")
2711 (test-ps-js add-subtract-precedence
2712 (- x (+ y z))
2713 "x - (y + z);")
2715 (test-ps-js ps-inline-toplevel
2716 (ps-inline (foo))
2717 "'javascript:' + 'foo()';")
2719 (test-ps-js no-clause-progn-exp
2720 (setf x (progn))
2721 "x = null;")
2723 (test-ps-js no-clause-progn-return
2724 (defun foo ()
2725 (return-from foo (progn)))
2726 "function foo() {
2727 return null;
2728 };")
2730 (test-ps-js empty-cond-clause
2731 (setf x (cond ((foo))))
2732 "x = foo() ? null : null;")
2734 (test-ps-js empty-cond-clause1
2735 (setf x (cond ((foo) 123)
2736 ((bar))
2737 (t 456)))
2738 "x = foo() ? 123 : (bar() ? null : 456);")
2740 (test-ps-js let-no-body
2741 (defun foo ()
2742 (return-from foo (let ((foo bar)))))
2743 "function foo() {
2744 var foo1 = bar;
2745 return null;
2746 };")
2748 (test-ps-js rename-lexical-dupes
2749 (lambda ()
2750 (list (let ((foo 12)) (* foo 2))
2751 (let ((foo 13)) (* foo 3))))
2752 "(function () {
2753 var foo;
2754 var foo1;
2755 return [(foo = 12, foo * 2), (foo1 = 13, foo1 * 3)];
2756 });")
2758 (test-ps-js defun-comment1
2759 (defun foo (x)
2760 "BARBAR is a revolutionary new foobar.
2761 X y and x."
2762 (1+ x))
2763 "/**
2764 * BARBAR is a revolutionary new foobar.
2765 * X y and x.
2767 function foo(x) {
2768 return x + 1;
2769 };")
2771 (test-ps-js var-comment
2772 (var x 1 "foo")
2773 "/** foo */
2774 var x = 1;")
2776 (test-ps-js case-return-break-broken-return
2777 (defun foo ()
2778 (case x
2779 ("bar" (if y (return-from foo t) nil))
2780 ("baz" nil)))
2781 "function foo() {
2782 switch (x) {
2783 case 'bar':
2784 if (y) {
2785 return true;
2786 } else {
2787 return null;
2789 case 'baz':
2790 return null;
2792 };")
2794 (test-ps-js case-return-break1-broken-return
2795 (defun foo ()
2796 (case x
2797 ("bar" (if y (return-from foo t)))
2798 ("baz" nil)))
2799 "function foo() {
2800 switch (x) {
2801 case 'bar':
2802 if (y) {
2803 return true;
2804 } else {
2805 return null;
2807 case 'baz':
2808 return null;
2810 };")
2812 (test-ps-js setf-progn
2813 (setf foo (progn (bar) (baz) 3))
2814 "bar();
2815 baz();
2816 foo = 3;")
2818 (test-ps-js var-progn
2819 (var x (progn (foo) (bar)))
2820 "foo();
2821 var x = bar();")
2823 (test-ps-js implicit-return-loop
2824 (lambda ()
2825 (if baz 7
2826 (progn
2827 (loop :repeat 100 :do (bar))
2828 42)))
2829 "(function () {
2830 if (baz) {
2831 return 7;
2832 } else {
2833 for (var _js2 = 0; _js2 < 100; _js2 += 1) {
2834 bar();
2836 return 42;
2838 });")
2840 ;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
2841 (test-ps-js loop-closures
2842 (dotimes (i 10) (lambda () (+ i 1)))
2843 "for (var i = 0; i < 10; i += 1) {
2844 with ({ i : i }) {
2845 function () {
2846 return i + 1;
2849 };")
2851 (test-ps-js loop-closures-let
2852 (dotimes (i 10)
2853 (let ((x (+ i 1)))
2854 (lambda () (+ i x))))
2855 "for (var i = 0; i < 10; i += 1) {
2856 with ({ i : i, x : null }) {
2857 var x = i + 1;
2858 function () {
2859 return i + x;
2862 };")
2864 (test-ps-js loop-closures-flet
2865 (dotimes (i 10) (flet ((foo (x) (+ i x))) (lambda () (foo i))))
2866 "for (var i = 0; i < 10; i += 1) {
2867 with ({ foo : null, i : i }) {
2868 var foo = function (x) {
2869 return i + x;
2871 function () {
2872 return foo(i);
2875 };")
2877 (test-ps-js while-closures-let
2878 (while (foo)
2879 (let ((x (bar)))
2880 (lambda () (+ 1 x))))
2881 "while (foo()) {
2882 with ({ x : null }) {
2883 var x = bar();
2884 function () {
2885 return 1 + x;
2888 };")
2890 (test-ps-js dotted-list-form
2891 (defun foo (a)
2892 (when a
2893 (destructuring-bind (b . c)
2895 (list b c))))
2896 "function foo(a) {
2897 if (a) {
2898 var b = bar[0];
2899 var c = bar.length > 1 ? bar.slice(1) : [];
2900 return [b, c];
2902 };")
2904 (test-ps-js return-from-loop
2905 (dolist (x '(2 1 3))
2906 (when (= x 1)
2907 (return))
2908 (chain console (log x)))
2909 "(function () {
2910 var loopResultVar3 = null;
2911 for (var x = null, _js_arrvar2 = [2, 1, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
2912 x = _js_arrvar2[_js_idx1];
2913 if (x === 1) {
2914 loopResultVar3 = null;
2915 break;
2917 console.log(x);
2919 return loopResultVar3;
2920 })();")
2922 (test-ps-js explicit-nil-block
2923 (defun bar ()
2924 (foo 1)
2925 (block nil (return (foo 2)) (+ 1 2))
2927 "function bar() {
2928 foo(1);
2929 nilBlock: {
2930 foo(2);
2931 break nilBlock;
2932 1 + 2;
2934 return 2;
2935 };")
2937 (test-ps-js dynamic-extent-function-return
2938 (defun foo () ((lambda () (return-from foo 6))))
2939 "function foo() {
2940 try {
2941 return (function () {
2942 throw { 'ps-block-tag' : 'foo', 'ps-return-value' : 6 };
2943 })();
2944 } catch (err) {
2945 if (err && 'foo' === err['ps-block-tag']) {
2946 return err['ps-return-value'];
2947 } else {
2948 throw err;
2951 };")
2953 (test-ps-js dynamic-extent-function-return-funcall
2954 (defun foo () ((lambda () (return-from foo (if baz 6 5)))))
2955 "function foo() {
2956 try {
2957 return (function () {
2958 throw { 'ps-block-tag' : 'foo', 'ps-return-value' : baz ? 6 : 5 };
2959 })();
2960 } catch (err) {
2961 if (err && 'foo' === err['ps-block-tag']) {
2962 return err['ps-return-value'];
2963 } else {
2964 throw err;
2967 };")
2969 (test-ps-js block-dynamic-return
2970 (var foo ((lambda ()
2971 (block nil
2972 ((lambda () (return 6)))
2973 (+ 1 2)))))
2974 "var foo = (function () {
2975 try {
2976 (function () {
2977 throw { 'ps-block-tag' : 'nilBlock', 'ps-return-value' : 6 };
2978 })();
2979 return 1 + 2;
2980 } catch (err) {
2981 if (err && 'nilBlock' === err['ps-block-tag']) {
2982 return err['ps-return-value'];
2983 } else {
2984 throw err;
2987 })();")
2989 (test-ps-js block-dynamic-return1
2990 (var foo ((lambda ()
2991 (block nil
2992 ((lambda () (return 6)))
2993 (+ 1 2))
2994 (foobar 1 2))))
2995 "var foo = (function () {
2996 nilBlock: {
2997 (function () {
2998 break nilBlock;
2999 })();
3000 1 + 2;
3002 return foobar(1, 2);
3003 })();")
3005 (test-ps-js iteration-lambda-capture-no-need
3006 (dolist (x y) (lambda (x) (1+ x))) ;; there's really no need to create a 'with' scope in this case
3007 "for (var x = null, _js_idx1 = 0; _js_idx1 < y.length; _js_idx1 += 1) {
3008 with ({ x : x }) {
3009 x = y[_js_idx1];
3010 function (x) {
3011 return x + 1;
3014 };")
3016 (test-ps-js case-invert1
3017 (encodeURIComponent fooBar)
3018 "encodeURIComponent(fooBar);")
3020 (test-ps-js simple-ash
3021 (+ (ash 4 1) (ash 4 -1))
3022 "(4 << 1) + (4 >> 1);")
3024 (test-ps-js progn-nil-expression
3025 (bar (progn (foo) nil))
3026 "bar((foo(), null));")
3028 (test-ps-js other-progn-nil-exp
3029 (defun blah ()
3030 (or (foo) (progn (bar) nil)))
3031 "function blah() {
3032 return foo() || (bar(), null);
3033 };")
3035 (test-ps-js lambda-nil-return
3036 (lambda (x)
3037 (block nil
3038 (when x
3039 (return 1))
3041 "(function (x) {
3042 if (x) {
3043 return 1;
3045 return 2;
3046 });")
3048 (test-ps-js lambda-nil-return-implicit-nested
3049 (lambda (x)
3050 (block nil
3051 (if x
3052 (return 1)
3053 (dotimes (i 4)
3054 (return 1)))
3056 "(function (x) {
3057 if (x) {
3058 return 1;
3059 } else {
3060 var loopResultVar1 = null;
3061 for (var i = 0; i < 4; i += 1) {
3062 loopResultVar1 = 1;
3063 break;
3065 loopResultVar1;
3067 return 2;
3068 });")
3070 (test-ps-js lambda-nil-return-implicit-nested2
3071 (lambda (x)
3072 (block foo
3073 (if x
3074 (return-from foo 1)
3075 (dotimes (i 4)
3076 (return-from foo i)))
3078 "(function (x) {
3079 if (x) {
3080 return 1;
3081 } else {
3082 for (var i = 0; i < 4; i += 1) {
3083 return i;
3086 return 2;
3087 });")
3089 (test-ps-js throw-is-a-statement
3090 (defun blah ()
3091 (let ((result (foo)))
3092 (unless (null result)
3093 (throw result))))
3094 "function blah() {
3095 var result = foo();
3096 if (result != null) {
3097 throw result;
3099 };")
3101 (test-ps-js expressify1
3102 (defun blah ()
3103 (when (some-condition)
3104 (foo)
3105 (bar)
3106 (baz)))
3107 "function blah() {
3108 if (someCondition()) {
3109 foo();
3110 bar();
3111 return baz();
3113 };")
3115 (test-ps-js case-when-return
3116 (defun blah (a)
3117 (case a
3118 ("a" (when (foo) (return-from blah 111)))
3119 ("b" t)))
3120 "function blah(a) {
3121 switch (a) {
3122 case 'a':
3123 if (foo()) {
3124 return 111;
3125 } else {
3126 return null;
3128 case 'b':
3129 return true;
3131 };")
3133 (test-ps-js flet-return-from
3134 (defun abc ()
3135 (flet ((foo ()
3136 (return-from foo 123)))
3137 (foo)))
3138 "function abc() {
3139 var foo = function () {
3140 return 123;
3142 return foo();
3143 };")
3145 (test-ps-js flet-return-from1
3146 (flet ((foo ()
3147 (return-from foo 123)))
3148 (foo))
3149 "(function () {
3150 var foo = function () {
3151 return 123;
3153 return foo();
3154 })();")
3156 (test-ps-js lambda-docstring-declarations
3157 (lambda (x)
3158 "This is a docstring"
3159 (declare (ignore x))
3161 "(function (x) {
3162 return 2;
3163 });")
3165 (test-ps-js setf-let-exp
3166 (setf foo (let ((x (+ 1 2)))
3167 (if x 123 456)))
3168 "foo = (function () {
3169 var x = 1 + 2;
3170 return x ? 123 : 456;
3171 })();")
3173 (test-ps-js create-let-exp
3174 (create :abc (let ((x (+ 1 2)))
3175 (if x 123 456)))
3176 "({ 'abc' : (function () {
3177 var x = 1 + 2;
3178 return x ? 123 : 456;
3179 })() });")
3181 (test-ps-js eql-eql-eql-precedence
3182 (unless (equal (= 3 3) (= 3 4))
3183 (chain console (log 1)))
3184 "if ((3 === 3) != (3 === 4)) {
3185 console.log(1);
3186 };")
3188 (test-ps-js case-cond-breaks
3189 (defun blah (x)
3190 (case x
3191 (123 (cond ((foo1)
3192 (when (foo2)
3193 (when (foo3)
3194 (return-from blah nil))
3195 t))))
3196 (456 (foo7))))
3197 "function blah(x) {
3198 switch (x) {
3199 case 123:
3200 if (foo1()) {
3201 if (foo2()) {
3202 if (foo3()) {
3203 return null;
3205 return true;
3206 } else {
3207 return null;
3209 } else {
3210 return null;
3212 case 456:
3213 return foo7();
3215 };")
3217 (test-ps-js cond-double-t
3218 (lambda ()
3219 (cond (foo 1)
3220 (t 2)
3221 (t 3)))
3222 "(function () {
3223 if (foo) {
3224 return 1;
3225 } else {
3226 return 2;
3228 });")
3230 (test-ps-js let-let-funcall-lambda
3231 (let ((x 5))
3232 (let ((x 7))
3233 (funcall (lambda (x) (+ x 9)) x)))
3234 "(function () {
3235 var x = 5;
3236 var x1 = 7;
3237 return (function (x) {
3238 return x + 9;
3239 })(x1);
3240 })();")
3242 (test-ps-js let-let-lambda
3243 (let ((x 5))
3244 (let ((x 7))
3245 (lambda (x) (+ x 9))))
3246 "(function () {
3247 var x = 5;
3248 var x1 = 7;
3249 return function (x) {
3250 return x + 9;
3252 })();")
3254 (test-ps-js let-lambda
3255 (let ((x 5))
3256 (lambda (x) (+ x 9)))
3257 "(function () {
3258 var x = 5;
3259 return function (x) {
3260 return x + 9;
3262 })();")
3264 (test-ps-js symbol-macrolet-no-shadow-lambda
3265 (symbol-macrolet ((x y))
3266 (lambda (x) (+ x x)))
3267 "(function (x) {
3268 return x + x;
3269 });")
3271 (test-ps-js divide-one-arg-reciprocal
3272 (/ 2)
3273 "1 / 2;")
3275 (test-ps-js division-not-associative
3276 (/ a (* b c))
3277 "a / (b * c);")
3279 (test-ps-js divide-expressions
3280 (/ (foo) (bar))
3281 "foo() / bar();")
3283 (test-ps-js divide-expressions1
3284 (floor (1- x) y)
3285 "Math.floor((x - 1) / y);")
3287 (test-ps-js lexical-funargs-shadow1
3288 (lambda (x)
3289 (let ((x 1))
3290 (foo x))
3291 (incf x))
3292 "(function (x) {
3293 var x1 = 1;
3294 foo(x1);
3295 return ++x;
3296 });")
3298 (test-ps-js times-rem
3299 (* x (rem y z))
3300 "x * (y % z);")
3302 (test-ps-js rem-divide
3303 (/ x (rem y z))
3304 "x / (y % z);")
3306 (test-ps-js case-break-return
3307 (lambda () (case x (:foo) (:bar 1)))
3308 "(function () {
3309 switch (x) {
3310 case 'foo':
3311 return null;
3312 case 'bar':
3313 return 1;
3315 });")
3317 (test-ps-js trivial-expression-switch
3318 (foobar (case x (1 2)))
3319 "foobar((function () {
3320 switch (x) {
3321 case 1:
3322 return 2;
3324 })());")
3326 (test-ps-js trivial-expression-while
3327 (foobar (while (< 0 x) (decf x)))
3328 "foobar((function () {
3329 while (0 < x) {
3330 --x;
3332 })());")
3334 (test-ps-js funcall-block-expression-loop-lambda
3335 (foobar (loop for i from 0 to 10 do (1+ i)))
3336 "foobar((function () {
3337 for (var i = 0; i <= 10; i += 1) {
3338 i + 1;
3340 })());")
3342 (test-ps-js plus-block-expression-loop-lambda
3343 (1+ (loop for i from 0 to 10 do (1+ i)))
3344 "(function () {
3345 for (var i = 0; i <= 10; i += 1) {
3346 i + 1;
3348 })() + 1;")
3350 (test-ps-js let-closures-rename
3351 (lambda ()
3352 (let ((x 1)) (lambda () (1+ x)))
3353 (let ((x 2)) (lambda () (1+ x))))
3354 "(function () {
3355 var x = 1;
3356 function () {
3357 return x + 1;
3359 var x1 = 2;
3360 return function () {
3361 return x1 + 1;
3363 });")
3365 (test-ps-js let-closures-rename1
3366 (lambda ()
3367 (let ((x 1))
3368 (let ((y 2))
3369 (lambda () (+ x y))))
3370 (let ((x 2))
3371 (let ((y 3))
3372 (lambda () (+ x y)))))
3373 "(function () {
3374 var x = 1;
3375 var y = 2;
3376 function () {
3377 return x + y;
3379 var x1 = 2;
3380 var y2 = 3;
3381 return function () {
3382 return x1 + y2;
3384 });")
3386 (test-ps-js let-closures-rename2
3387 (defun make-closures ()
3388 (list
3389 (let ((x 1)) (lambda () (1+ x)))
3390 (let ((x 2)) (lambda () (1+ x)))))
3391 "function makeClosures() {
3392 var x;
3393 var x1;
3394 return [(x = 1, function () {
3395 return x + 1;
3396 }), (x1 = 2, function () {
3397 return x1 + 1;
3398 })];
3400 };")
3402 (test-ps-js conditional-not-used-up
3403 (lambda (bar)
3404 (when bar
3405 (let ((x 1))
3406 (1+ x))))
3407 "(function (bar) {
3408 if (bar) {
3409 var x = 1;
3410 return x + 1;
3412 });")
3414 (test-ps-js toplevel-local-scope
3415 (create "fn" (let ((x 5)) (lambda () x)))
3416 "({ 'fn' : (function () {
3417 var x = 5;
3418 return function () {
3419 return x;
3421 })() });")
3423 (test-ps-js toplevel-local-scope1
3424 (defvar foo (create "fn" (let ((x 5)) (lambda () x))))
3425 "var foo = { 'fn' : (function () {
3426 var x = 5;
3427 return function () {
3428 return x;
3430 })() };")
3432 (test-ps-js block-let
3433 (block foobar
3434 (let ((x 1))
3435 (return-from foobar x)
3437 "(function () {
3438 var x = 1;
3439 return x;
3440 return 2;
3441 })();")
3443 (test-ps-js dolist-return1
3444 (dolist (x '(5 2 3))
3445 (return (1+ x)))
3446 "(function () {
3447 var loopResultVar3 = null;
3448 for (var x = null, _js_arrvar2 = [5, 2, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
3449 x = _js_arrvar2[_js_idx1];
3450 loopResultVar3 = x + 1;
3451 break;
3453 return loopResultVar3;
3454 })();")
3456 (test-ps-js expressionize-if-macroexpand-error
3457 (progn (defmacro xbaz () `(blah))
3459 (defun foo (xbaz)
3460 (unless (blah)
3461 (cond (xbaz (blah))
3462 (t (blahblah))))))
3463 "function foo(xbaz) {
3464 if (!blah()) {
3465 if (xbaz) {
3466 return blah();
3467 } else {
3468 return blahblah();
3471 };")
3473 (test-ps-js toplevel-defun-macroexpand
3474 (progn (defmacro defun-js (name lambda-list &body body)
3475 `(defun ,name ,lambda-list ,@body))
3477 (let ((foo 0))
3478 (defun-js bar () (1+ foo))
3479 (defvar baz 2)))
3480 "var foo = 0;
3481 function bar() {
3482 return foo + 1;
3484 var baz = 2;")
3486 ;;; broken
3488 ;; (test-ps-js let-defun-toplevel
3489 ;; (progn (let ((foo 0))
3490 ;; (defun bar () foo))
3491 ;; (bar))
3492 ;; "var bar_foo1 = 0;
3493 ;; function bar() {
3494 ;; return bar_foo1;
3495 ;; };
3496 ;; bar();")
3498 ;; (test-ps-js let-defvar-toplevel
3499 ;; (progn (let ((foo 0))
3500 ;; (defvar bar (1+ foo)))
3501 ;; bar)
3502 ;; "var bar_foo1 = 0;
3503 ;; var bar = bar_foo1 + 1;
3504 ;; bar;")
3506 ;; (test-ps-js setf-side-effects
3507 ;; (progn
3508 ;; (let ((x 10))
3509 ;; (defun side-effect()
3510 ;; (setf x 4)
3511 ;; 3)
3512 ;; (setf x (+ 2 (side-effect) x 5))))
3513 ;; "var sideEffect_x1 = 10;
3514 ;; function sideEffect() {
3515 ;; sideEffect_x1 = 4;
3516 ;; return 3;
3517 ;; };
3518 ;; sideEffect_x1 = 2 + sideEffect() + x + 5;")