Wrap let in lambda when there is no outer lexical scope to introduce one, and avoid...
[parenscript.git] / t / output-tests.lisp
blobf2ddcf868fde8734fc0c3c1a81996e142b96d77f
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 _js1 = b;
268 var _js2 = a;
269 a = _js1;
270 return b = _js2;
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))
306 "nilBlock: {
307 break nilBlock;
308 };")
310 (test-ps-js single-argument-statements-2
311 (throw "foobar")
312 "throw 'foobar';")
314 (test-ps-js single-argument-expression-1
315 (delete (new (*foobar 2 3 4)))
316 "delete new Foobar(2, 3, 4);")
318 (test-ps-js single-argument-expression-2
319 (if (= (typeof blorg) *string)
320 (alert (+ "blorg is a string: " blorg))
321 (alert "blorg is not a string"))
322 "if (typeof blorg === String) {
323 alert('blorg is a string: ' + blorg);
324 } else {
325 alert('blorg is not a string');
326 };")
328 (test-ps-js conditional-statements-1
329 (defun foo ()
330 (if ((@ blorg is-correct))
331 (progn (carry-on) (return-from foo i))
332 (alert "blorg is not correct!")))
333 "function foo() {
334 if (blorg.isCorrect()) {
335 carryOn();
336 return i;
337 } else {
338 return alert('blorg is not correct!');
340 };")
342 (test-ps-js conditional-statements-2
343 (+ i (if ((@ blorg add-one)) 1 2))
344 "i + (blorg.addOne() ? 1 : 2);")
346 (test-ps-js conditional-statements-3
347 (defun foo ()
348 (when ((@ blorg is-correct))
349 (carry-on)
350 (return-from foo i)))
351 "function foo() {
352 if (blorg.isCorrect()) {
353 carryOn();
354 return i;
356 };")
358 (test-ps-js conditional-statements-4
359 (unless ((@ blorg is-correct))
360 (alert "blorg is not correct!"))
361 "if (!blorg.isCorrect()) {
362 alert('blorg is not correct!');
363 };")
365 (test-ps-js variable-declaration-1
366 (defvar *a* (array 1 2 3))
367 "var A = [ 1, 2, 3 ];")
369 (test-ps-js variable-declaration-2
370 (progn (defvar *a* 4)
371 (let ((x 1)
372 (*a* 2))
373 (let* ((y (+ x 1))
374 (x (+ x y)))
375 (+ *a* x y))))
376 "var A = 4;
377 (function () {
378 var x = 1;
379 var A_TMPSTACK1;
380 try {
381 A_TMPSTACK1 = A;
382 A = 2;
383 var y = x + 1;
384 var x2 = x + y;
385 return A + x2 + y;
386 } finally {
387 A = A_TMPSTACK1;
389 })();")
391 (test-ps-js iteration-constructs-1
392 (do* ((a) b (c (array "a" "b" "c" "d" "e"))
393 (d 0 (1+ d))
394 (e (aref c d) (aref c d)))
395 ((or (= d (@ c length)) (string= e "x")))
396 (setf a d b e)
397 (funcall (@ document write) (+ "a: " a " b: " b "<br/>")))
398 "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]) {
399 a = d;
400 b = e;
401 document.write('a: ' + a + ' b: ' + b + '<br/>');
402 };")
404 (test-ps-js iteration-constructs-2
405 (do ((i 0 (1+ i))
406 (s 0 (+ s i (1+ i))))
407 ((> i 10))
408 (funcall (@ document write) (+ "i: " i " s: " s "<br/>")))
409 "(function () {
410 var i = 0;
411 var s = 0;
412 for (; i <= 10; ) {
413 document.write('i: ' + i + ' s: ' + s + '<br/>');
414 var _js1 = i + 1;
415 var _js2 = s + i + i + 1;
416 i = _js1;
417 s = _js2;
419 })();")
421 (test-ps-js iteration-constructs-3
422 (do* ((i 0 (1+ i))
423 (s 0 (+ s i (1- i))))
424 ((> i 10))
425 ((@ document write) (+ "i: " i " s: " s "<br/>")))
426 "for (var i = 0, s = 0; i <= 10; i += 1, s = s + i + (i - 1)) {
427 document.write('i: ' + i + ' s: ' + s + '<br/>');
428 };")
430 (test-ps-js iteration-constructs-4
431 (let ((arr (array "a" "b" "c" "d" "e")))
432 (dotimes (i (@ arr length))
433 ((@ document write) (+ "i: " i " arr[i]: " (aref arr i) "<br/>"))))
434 "(function () {
435 var arr = ['a', 'b', 'c', 'd', 'e'];
436 for (var i = 0; i < arr.length; i += 1) {
437 document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
439 })();")
441 (test-ps-js iteration-constructs-5
442 (let ((res 0))
443 (alert (+ "Summation to 10 is "
444 (dotimes (i 10 res)
445 (incf res (1+ i))))))
446 "(function () {
447 var res = 0;
448 return alert('Summation to 10 is ' + (function () {
449 for (var i = 0; i < 10; i += 1) {
450 res += i + 1;
452 return res;
453 })());
454 })();")
456 (test-ps-js iteration-constructs-6
457 (let ((l (list 1 2 4 8 16 32)))
458 (dolist (c l)
459 ((@ document write) (+ "c: " c "<br/>"))))
460 "(function () {
461 var l = [1, 2, 4, 8, 16, 32];
462 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
463 c = l[_js_idx1];
464 document.write('c: ' + c + '<br/>');
466 })();")
468 (test-ps-js iteration-constructs-7
469 (let ((l '(1 2 4 8 16 32))
470 (s 0))
471 (alert (+ "Sum of " l " is: "
472 (dolist (c l s)
473 (incf s c)))))
474 "(function () {
475 var l = [1, 2, 4, 8, 16, 32];
476 var s = 0;
477 return alert('Sum of ' + l + ' is: ' + (function () {
478 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
479 c = l[_js_idx1];
480 s += c;
482 return s;
483 })());
484 })();")
486 (test-ps-js iteration-constructs-8
487 (let ((obj (create a 1 b 2 c 3)))
488 (for-in (i obj)
489 ((@ document write) (+ i ": " (aref obj i) "<br/>"))))
490 "(function () {
491 var obj = { a : 1, b : 2, c : 3 };
492 for (var i in obj) {
493 document.write(i + ': ' + obj[i] + '<br/>');
495 })();")
497 (test-ps-js iteration-constructs-9
498 (while ((@ film is-not-finished))
499 ((@ this eat) (new *popcorn)))
500 "while (film.isNotFinished()) {
501 this.eat(new Popcorn);
502 };")
504 (test-ps-js the-case-statement-1
505 (case (aref blorg i)
506 ((1 "one") (alert "one"))
507 (2 (alert "two"))
508 (t (alert "default clause")))
509 "switch (blorg[i]) {
510 case 1:
511 case 'one':
512 alert('one');
513 break;
514 case 2:
515 alert('two');
516 break;
517 default:
518 alert('default clause');
519 };")
521 (test-ps-js the-case-statement-2
522 (switch (aref blorg i)
523 (1 (alert "If I get here"))
524 (2 (alert "I also get here"))
525 (default (alert "I always get here")))
526 "switch (blorg[i]) {
527 case 1: alert('If I get here');
528 case 2: alert('I also get here');
529 default: alert('I always get here');
530 };")
532 (test-ps-js the-try-statement-1
533 (try (throw "i")
534 (:catch (error)
535 (alert (+ "an error happened: " error)))
536 (:finally
537 (alert "Leaving the try form")))
538 "try {
539 throw 'i';
540 } catch (error) {
541 alert('an error happened: ' + error);
542 } finally {
543 alert('Leaving the try form');
544 };")
546 (test-ps-js the-html-generator-1
547 (ps-html ((:a :href "foobar") "blorg"))
548 "'<A HREF=\"foobar\">blorg</A>';")
550 (test-ps-js the-html-generator-2
551 (ps-html ((:a :href (generate-a-link)) "blorg"))
552 "['<A HREF=\"', generateALink(), '\">blorg</A>']['join']('');")
554 (test-ps-js the-html-generator-3
555 (funcall (getprop document 'write)
556 (ps-html ((:a :href "#"
557 :onclick (ps-inline (transport))) "link")))
558 "document.write(['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">link</A>']['join'](''));")
560 (test-ps-js the-html-generator-4
561 (let ((disabled nil)
562 (authorized t))
563 (setf (getprop element 'inner-h-t-m-l)
564 (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
565 "Edit me"))))
566 "(function () {
567 var disabled = null;
568 var authorized = true;
569 return element.innerHTML = ['<TEXTAREA', disabled || !authorized ? [' DISABLED=\"', 'disabled', '\"']['join']('') : '', '>Edit me</TEXTAREA>']['join']('');
570 })();")
572 (test-ps-js plus-is-not-commutative
573 (setf x (+ "before" x "after"))
574 "x = 'before' + x + 'after';")
576 (test-ps-js plus-works-if-first
577 (setf x (+ x "middle" "after"))
578 "x = x + 'middle' + 'after';")
580 (test-ps-js setf-side-effects
581 (progn
582 (let ((x 10))
583 (defun side-effect()
584 (setf x 4)
586 (setf x (+ 2 (side-effect) x 5))))
587 "(function () {
588 var x = 10;
589 function sideEffect() {
590 x = 4;
591 return 3;
593 return x = 2 + sideEffect() + x + 5;
594 })();")
596 (test-ps-js method-call-op-form
597 (funcall (getprop (+ "" x) 'to-string))
598 "('' + x).toString();")
600 (test-ps-js method-call-op-form-args
601 (funcall (getprop (+ "" x) 'foo) 1 2 :baz 3)
602 "('' + x).foo(1, 2, 'baz', 3);")
604 (test-ps-js method-call-string
605 ((getprop "hi" 'to-string))
606 "'hi'.toString();")
608 (test-ps-js method-call-conditional
609 ((if a x y) 1)
610 "(a ? x : y)(1);")
612 (test-ps-js method-call-variable
613 ((@ x to-string))
614 "x.toString();")
616 (test-ps-js method-call-array
617 ((@ (list 10 20) to-string))
618 "[ 10, 20 ].toString();")
620 (test-ps-js method-call-lambda-call
621 (funcall (getprop (funcall (lambda (x) x) 10) 'to-string))
622 "(function (x) { return x; })(10).toString();")
624 (test no-whitespace-before-dot
625 (let* ((str (ps* '((@ ((lambda (x) x) 10) to-string))))
626 (dot-pos (position #\. str :test #'char=))
627 (char-before (elt str (1- dot-pos)))
628 (a-parenthesis #\)))
629 (is (char= char-before a-parenthesis))))
631 (test-ps-js simple-getprop
632 (let ((foo (create a 1)))
633 (alert (getprop foo 'a)))
634 "(function () {
635 var foo = { a : 1 };
636 return alert(foo.a);
637 })();")
639 (test-ps-js buggy-getprop
640 (getprop foo slot-name)
641 "foo[slotName];")
643 (test-ps-js buggy-getprop-two
644 (getprop foo (get-slot-name))
645 "foo[getSlotName()];")
647 (test-ps-js old-case-is-now-switch
648 ;; Switch was "case" before, but that was very non-lispish.
649 ;; For example, this code makes three messages and not one
650 ;; which may have been expected. This is because a switch
651 ;; statment must have a break statement for it to return
652 ;; after the alert. Otherwise it continues on the next
653 ;; clause.
654 (switch (aref blorg i)
655 (1 (alert "one"))
656 (2 (alert "two"))
657 (default (alert "default clause")))
658 "switch (blorg[i]) {
659 case 1: alert('one');
660 case 2: alert('two');
661 default: alert('default clause');
662 };")
664 (test-ps-js lisp-like-case
665 (case (aref blorg i)
666 (1 (alert "one"))
667 (2 (alert "two"))
668 (default (alert "default clause")))
669 "switch (blorg[i]) {
670 case 1:
671 alert('one');
672 break;
673 case 2:
674 alert('two');
675 break;
676 default: alert('default clause');
677 };")
680 (test-ps-js even-lispier-case
681 (case (aref blorg i)
682 ((1 2) (alert "Below three"))
683 (3 (alert "Three"))
684 (t (alert "Something else")))
685 "switch (blorg[i]) {
686 case 1:
687 case 2:
688 alert('Below three');
689 break;
690 case 3:
691 alert('Three');
692 break;
693 default: alert('Something else');
694 };")
696 (test-ps-js otherwise-case
697 (case (aref blorg i)
698 (1 (alert "one"))
699 (otherwise (alert "default clause")))
700 "switch (blorg[i]) {
701 case 1:
702 alert('one');
703 break;
704 default: alert('default clause');
705 };")
707 (test escape-sequences-in-string
708 (let ((escapes `((#\\ . #\\)
709 (#\b . #\Backspace)
710 (#\f . ,(code-char 12))
711 ("u000B" . ,(code-char #x000b));;Vertical tab, too uncommon to bother with
712 (#\n . #\Newline)
713 (#\r . #\Return)
714 (#\' . #\');;Double quote need not be quoted because parenscript strings are single quoted
715 (#\t . #\Tab)
716 ("u001F" . ,(code-char #x001f));; character below 32
717 ("u0080" . ,(code-char 128)) ;;Character over 127. Actually valid, parenscript escapes them to be sure.
718 ("uABCD" . ,(code-char #xabcd)))));; Really above ascii.
719 (loop for (js-escape . lisp-char) in escapes
720 for generated = (ps-doc* (format nil "hello~ahi" lisp-char))
721 for wanted = (format nil "'hello\\~ahi';" js-escape)
722 do (is (string= (normalize-js-code generated) wanted)))))
724 (test-ps-js getprop-setf
725 (setf (getprop x 'y) (+ (+ a 3) 4))
726 "x.y = a + 3 + 4;")
728 (test-ps-js getprop-conditional1
729 (getprop (if zoo foo bar) 'x)
730 "(zoo ? foo : bar).x;")
732 (test-ps-js getprop-conditional2
733 (getprop (if (not zoo) foo bar) 'x)
734 "(!zoo ? foo : bar).x;")
736 (test script-star-eval1
737 (is (string= "x = 1; y = 2;" (normalize-js-code (ps* '(setf x 1) '(setf y 2))))))
739 (test script-star-eval2
740 (is (string= "x = 1;" (normalize-js-code (ps* '(setf x 1))))))
742 (test-ps-js list-with-single-nil
743 (array nil)
744 "[null];")
746 (test-ps-js quoted-nil-is-array
747 'nil
748 "[];")
750 (test-ps-js defsetf1
751 (progn (defsetf baz (x y) (newval) `(set-baz ,x ,y ,newval))
752 (setf (baz 1 2) 3))
753 "(function () {
754 var _js2 = 1;
755 var _js3 = 2;
756 var _js1 = 3;
757 return setBaz(_js2, _js3, _js1);
758 })();")
760 (test-ps-js setf-macroexpands1
761 (macrolet ((bar (x y)
762 `(aref ,x ,y 1)))
763 (setf (bar foo 2) 3))
764 "foo[2][1] = 3;")
766 (test-ps-js defsetf-short
767 (progn (defsetf baz set-baz "docstring")
768 (setf (baz 1 2 3) "foo"))
769 "setBaz(1, 2, 3, 'foo');")
771 (test-ps-js defun-setf1
772 (progn (defun (setf some-thing) (new-val i1 i2)
773 (setf (aref *some-thing* i1 i2) new-val))
774 (setf (some-thing 1 2) "foo"))
775 "function __setf_someThing(newVal, i1, i2) {
776 return SOMETHING[i1][i2] = newVal;
778 __setf_someThing('foo', 1, 2);")
780 (test-ps-js defun-optional1
781 (defun test-opt (&optional x)
782 (if x "yes" "no"))
783 "function testOpt(x) {
784 return x ? 'yes' : 'no';
785 };")
787 (test-ps-js defun-optional2
788 (defun foo (x &optional y)
789 (+ x y))
790 "function foo(x, y) {
791 return x + y;
792 };")
794 (test-ps-js defun-optional3
795 (defun blah (&optional (x 0))
797 "function blah(x) {
798 if (x === undefined) {
799 x = 0;
801 return x;
802 };")
804 (test-ps-js arglist-optional4
805 (lambda (&optional (x 0 supplied?))
807 "(function (x) {
808 var suppliedwhat = x !== undefined;
809 if (!suppliedwhat) {
810 x = 0;
812 return x;
813 });")
815 (test-ps-js return-nothing
816 (defun foo () (return-from foo))
817 "function foo() {
818 return null;
819 };")
821 (test-ps-js set-timeout
822 (set-timeout (lambda () (alert "foo")) 10)
823 "setTimeout(function () { return alert('foo'); }, 10);")
825 (test-ps-js operator-precedence
826 (* 3 (+ 4 5) 6)
827 "3 * (4 + 5) * 6;")
829 (test-ps-js operators-1
830 (in prop obj)
831 "prop in obj;")
833 (test-ps-js incf1
834 (incf foo bar)
835 "foo += bar;")
837 (test-ps-js decf1
838 (decf foo bar)
839 "foo -= bar;")
841 (test-ps-js incf2
842 (incf x 5)
843 "x += 5;")
845 (test-ps-js decf2
846 (decf y 10)
847 "y -= 10;")
849 (test-ps-js setf-conditional
850 (setf foo (if x 1 2))
851 "foo = x ? 1 : 2;")
853 (test-ps-js obj-literal-numbers
854 (create 1 "foo")
855 "({ 1 : 'foo' });")
857 (test-ps-js obj-literal-strings
858 (create "foo" 2)
859 "({ 'foo' : 2 });")
861 (test-ps-js getprop-string
862 (getprop foo "bar")
863 "foo['bar'];")
865 (test-ps-js getprop-string1
866 (getprop "bar" 'length)
867 "'bar'.length;")
869 (test-ps-js getprop-progn
870 (getprop (progn (some-fun "abc") "123") "length")
871 "(someFun('abc'), '123')['length'];")
873 (test-ps-js method-call-block
874 ((@ (progn (some-fun "abc") "123") to-string))
875 "(someFun('abc'), '123').toString();")
877 (test-ps-js create-blank
878 (create)
879 "({ });")
881 (test-ps-js blank-object-literal
883 "({ });")
885 (test-ps-js array-literal1
887 "[];")
889 (test-ps-js array-literal2
890 ([])
891 "[];")
893 (test-ps-js array-literal3
894 ([] 1 2 3)
895 "[1, 2, 3];")
897 (test-ps-js array-literal4
898 ([] 1 (2 3))
899 "[1, [2, 3]];")
901 (test-ps-js array-literal5
902 ([] (1 2) ("a" "b"))
903 "[[1, 2], ['a', 'b']];")
905 (test-ps-js defun-rest1
906 (defun foo (&rest bar)
907 (alert (aref bar 1)))
908 "function foo() {
909 var bar = [];
910 for (var i1 = 0; i1 < arguments.length - 0; i1 += 1) {
911 bar[i1] = arguments[i1 + 0];
913 return alert(bar[1]);
914 };")
916 (test-ps-js defun-rest2
917 (defun foo (baz &rest bar) (+ baz (aref bar 1)))
918 "function foo(baz) {
919 var bar = [];
920 for (var i1 = 0; i1 < arguments.length - 1; i1 += 1) {
921 bar[i1] = arguments[i1 + 1];
923 return baz + bar[1];
924 };")
926 (test-ps-js defun-keyword1
927 (defun zoo (foo bar &key baz) (+ foo bar baz))
928 "function zoo(foo, bar) {
929 var _js2 = arguments.length;
930 for (var n1 = 2; n1 < _js2; n1 += 2) {
931 switch (arguments[n1]) {
932 case 'baz':
933 baz = arguments[n1 + 1];
936 var baz;
937 return foo + bar + baz;
938 };")
940 (test-ps-js defun-keyword2
941 (defun zoo (&key baz) (* baz baz))
942 "function zoo() {
943 var _js2 = arguments.length;
944 for (var n1 = 0; n1 < _js2; n1 += 2) {
945 switch (arguments[n1]) {
946 case 'baz':
947 baz = arguments[n1 + 1];
950 var baz;
951 return baz * baz;
952 };")
954 (test-ps-js defun-keyword3
955 (defun zoo (&key baz (bar 4)) (* baz bar))
956 "function zoo() {
957 var _js2 = arguments.length;
958 for (var n1 = 0; n1 < _js2; n1 += 2) {
959 switch (arguments[n1]) {
960 case 'baz':
961 baz = arguments[n1 + 1];
962 break;
963 case 'bar':
964 bar = arguments[n1 + 1];
967 var baz;
968 var bar = undefined === bar ? 4 : bar;
969 return baz * bar;
970 };")
972 (test-ps-js defun-keyword4
973 (defun hello-world (&key ((:my-name-key my-name) 1))
974 my-name)
975 "function helloWorld() {
976 var _js2 = arguments.length;
977 for (var n1 = 0; n1 < _js2; n1 += 2) {
978 switch (arguments[n1]) {
979 case 'my-name-key':
980 myName = arguments[n1 + 1];
983 var myName = undefined === myName ? 1 : myName;
984 return myName;
985 };")
987 (test-ps-js arglist-keyword-supplied
988 (lambda (&key (foo 1 supplied?))
989 foo)
990 "(function () {
991 var _js2 = arguments.length;
992 for (var n1 = 0; n1 < _js2; n1 += 2) {
993 switch (arguments[n1]) {
994 case 'foo':
995 foo = arguments[n1 + 1];
996 suppliedwhat = true;
999 var suppliedwhat;
1000 var foo = undefined === foo ? 1 : foo;
1001 return foo;
1002 });")
1004 (test-ps-js keyword-funcall1
1005 (func :baz 1)
1006 "func('baz', 1);")
1008 (test-ps-js keyword-funcall2
1009 (func :baz 1 :bar foo)
1010 "func('baz', 1, 'bar', foo);")
1012 (test-ps-js keyword-funcall3
1013 (fun a b :baz c)
1014 "fun(a, b, 'baz', c);")
1016 (test-ps-js cond1
1017 (cond ((= x 1) 1))
1018 "if (x === 1) {
1020 };")
1022 (test-ps-js cond2
1023 (cond ((= x 1) 2)
1024 ((= y (* x 4)) (foo "blah") (* x y)))
1025 "if (x === 1) {
1027 } else if (y === x * 4) {
1028 foo('blah');
1029 x * y;
1030 };")
1032 (test-ps-js if-exp-without-else-return
1033 (defun foo () (return-from foo (if x 1)))
1034 "function foo() {
1035 return x ? 1 : null;
1036 };")
1038 (test-ps-js progn-expression-single-statement
1039 (defun foo () (return-from foo (progn (* x y))))
1040 "function foo() {
1041 return x * y;
1042 };")
1044 (test-ps-js cond-expression1
1045 (defun foo ()
1046 (cond ((< 1 2) (bar "foo") (* 4 5))))
1047 "function foo() {
1048 if (1 < 2) {
1049 bar('foo');
1050 return 4 * 5;
1052 };")
1054 (test-ps-js cond-expression2
1055 (defun foo ()
1056 (cond ((< 2 1) "foo")
1057 ((= 7 7) "bar")))
1058 "function foo() {
1059 if (2 < 1) {
1060 return 'foo';
1061 } else if (7 === 7) {
1062 return 'bar';
1064 };")
1066 (test-ps-js cond-expression-final-t-clause
1067 (defun foo ()
1068 (cond ((< 1 2) (bar "foo") (* 4 5))
1069 ((= a b) (+ c d))
1070 ((< 1 2 3 4 5) x)
1071 (t "foo")))
1072 "function foo() {
1073 var _cmp1;
1074 var _cmp2;
1075 var _cmp3;
1076 if (1 < 2) {
1077 bar('foo');
1078 return 4 * 5;
1079 } else if (a === b) {
1080 return c + d;
1081 } else if (_cmp1 = 2, _cmp2 = 3, _cmp3 = 4, 1 < _cmp1 && _cmp1 < _cmp2 && _cmp2 < _cmp3 && _cmp3 < 5) {
1082 return x;
1083 } else {
1084 return 'foo';
1086 };")
1088 (test-ps-js cond-expression-middle-t-clause ;; should this signal a warning?
1089 (defun foo ()
1090 (cond ((< 2 1) 5)
1091 (t "foo")
1092 ((< 1 2) "bar")))
1093 "function foo() {
1094 if (2 < 1) {
1095 return 5;
1096 } else {
1097 return 'foo';
1099 };")
1101 (test-ps-js funcall-if-expression
1102 (funcall (getprop document 'write)
1103 (if (= *linkornot* 1)
1104 (ps-html ((:a :href "#"
1105 :onclick (ps-inline (transport)))
1106 img))
1107 img))
1108 "document.write(LINKORNOT === 1 ? ['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">', img, '</A>']['join']('') : img);")
1110 (test-ps-js negate-number-literal
1111 (- 1)
1112 "-1;")
1114 (test macro-environment1
1115 (is (string= (normalize-js-code (let* ((macroname (gensym)))
1116 (ps* `(defmacro ,macroname (x) `(+ ,x 123))
1117 `(defun test1 ()
1118 (macrolet ((,macroname (x) `(aref data ,x)))
1119 (when (,macroname x)
1120 (setf (,macroname x) 123)))))))
1121 (normalize-js-code
1122 "function test1() {
1123 return data[x] ? (data[x] = 123) : null;
1124 };"))))
1126 (test macro-environment2
1127 (is (string= (normalize-js-code (let ((outer-lexical-variable 1))
1128 (defpsmacro macro-environment2-macro (x)
1129 `(+ ,outer-lexical-variable ,x))
1130 (ps* '(macro-environment2-macro 2))))
1131 (normalize-js-code "1 + 2;"))))
1133 (test-ps-js ampersand-whole-1
1134 (macrolet ((foo (&whole foo bar baz)
1135 (declare (ignore bar baz))
1136 (with-standard-io-syntax (format nil "~a" foo))))
1137 (foo 1 2))
1138 "'(FOO 1 2)';")
1140 (test-ps-js keyword-consistent
1142 "'x';")
1144 (test-ps-js simple-symbol-macrolet
1145 (symbol-macrolet ((x 1)) x)
1146 "1;")
1148 (test-ps-js compound-symbol-macrolet
1149 (symbol-macrolet ((x 123)
1150 (y (* 2 x)))
1152 "2 * 123;")
1154 (test-ps-js define-symbol-macro
1155 (progn (define-symbol-macro tst-sym-macro 2)
1156 tst-sym-macro)
1157 "2;")
1159 (test-ps-js define-symbol-macro1
1160 (progn (define-symbol-macro tst-sym-macro1 2)
1161 (foo tst-sym-macro1))
1162 "foo(2);")
1164 (test-ps-js expression-progn
1165 (1+ (progn (foo) (if x 1 2)))
1166 "(foo(), x ? 1 : 2) + 1;")
1168 (test-ps-js let-decl-in-expression
1169 (defun f (x)
1170 (if x 1 (let* ((foo x)) foo)))
1171 "function f(x) {
1172 if (x) {
1173 return 1;
1174 } else {
1175 var foo = x;
1176 return foo;
1178 };")
1180 (test-ps-js special-var1
1181 (progn (defvar *foo*)
1182 (let* ((*foo* 2))
1183 (* *foo* 2)))
1184 "var FOO;
1185 (function () {
1186 var FOO_TMPSTACK1;
1187 try {
1188 FOO_TMPSTACK1 = FOO;
1189 FOO = 2;
1190 return FOO * 2;
1191 } finally {
1192 FOO = FOO_TMPSTACK1;
1194 })();")
1196 (test-ps-js special-var2
1197 (progn (defvar *foo*)
1198 (let* ((*baz* 3)
1199 (*foo* 2))
1200 (* *foo* 2 *baz*)))
1201 "var FOO;
1202 (function () {
1203 var BAZ = 3;
1204 var FOO_TMPSTACK1;
1205 try {
1206 FOO_TMPSTACK1 = FOO;
1207 FOO = 2;
1208 return FOO * 2 * BAZ;
1209 } finally {
1210 FOO = FOO_TMPSTACK1;
1212 })();")
1214 (test-ps-js literal1
1215 (setf x undefined)
1216 "x = undefined;")
1218 (test-ps-js literal2
1219 (aref this x)
1220 "this[x];")
1222 (test-ps-js setf-dec1
1223 (setf x (- 1 x 2))
1224 "x = 1 - x - 2;")
1226 (test-ps-js setf-dec2
1227 (setf x (- x 1 2))
1228 "x = x - 1 - 2;")
1230 (test-ps-js special-char-equals
1231 blah=
1232 "blahequals;")
1234 (test-ps-js setf-operator-priority
1235 (defun foo ()
1236 (or (getprop cache id)
1237 (setf (getprop cache id) ((@ document get-element-by-id) id))))
1238 "function foo() {
1239 return cache[id] || (cache[id] = document.getElementById(id));
1240 };")
1242 (test-ps-js aref-operator-priority
1243 (aref (if (and x (> (length x) 0))
1244 (aref x 0)
1247 "(x && x.length > 0 ? x[0] : y)[z];")
1249 (test-ps-js aref-operator-priority1
1250 (aref (or (getprop x 'y)
1251 (getprop a 'b))
1253 "(x.y || a.b)[z];")
1255 (test-ps-js aref-operator-priority2
1256 (aref (if a b c) 0)
1257 "(a ? b : c)[0];")
1259 (test-ps-js negate-operator-priority
1260 (- (if x y z))
1261 "-(x ? y : z);")
1263 (test-ps-js op-p1
1264 (new (or a b))
1265 "new (a || b);")
1267 (test-ps-js op-p2
1268 (delete (if a (or b c) d))
1269 "delete (a ? b || c : d);")
1271 (test-ps-js op-p3
1272 (not (if (or x (not y)) z))
1273 "!(x || !y ? z : null);")
1275 (test-ps-js op-p4
1276 (- (- (* 1 2) 3))
1277 "-(1 * 2 - 3);")
1279 (test-ps-js op-p5
1280 (instanceof (or a b) (if x y z))
1281 "((a || b) instanceof (x ? y : z));")
1283 (test-ps-js op-p7
1284 (or x (if (= x 0) "zero" "empty"))
1285 "x || (x === 0 ? 'zero' : 'empty');")
1287 (test-ps-js named-op-expression
1288 (throw (if a b c))
1289 "throw a ? b : c;")
1291 (test-ps-js named-op-expression1
1292 (typeof (or x y))
1293 "typeof (x || y);")
1295 (test-ps-js aref-array-expression
1296 (aref (or a b c) 0)
1297 "(a || b || c)[0];")
1299 (test-ps-js getprop-operator
1300 (getprop (or a b c) 'd)
1301 "(a || b || c).d;")
1303 (test-ps-js getprop-parens
1304 (getprop (getprop foo 'bar) 'baz)
1305 "foo.bar.baz;")
1307 (test-ps-js funcall-funcall
1308 ((foo))
1309 "foo()();")
1311 (test-ps-js expression-funcall
1312 ((or (@ window eval) eval) foo nil)
1313 "(window.eval || eval)(foo, null);")
1315 (test-ps-js expression-funcall1
1316 (((or (@ window eval) eval) foo nil))
1317 "(window.eval || eval)(foo, null)();")
1319 (test-ps-js expression-funcall2
1320 (((or (@ window eval) eval)) foo nil)
1321 "(window.eval || eval)()(foo, null);")
1323 (test-ps-js who-html1
1324 (who-ps-html (:span :class "ticker-symbol"
1325 :ticker-symbol symbol
1326 (:a :href "http://foo.com"
1327 symbol)
1328 (:span :class "ticker-symbol-popup")))
1329 "['<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"', symbol, '\"><A HREF=\"http://foo.com\">', symbol, '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>']['join']('');")
1331 (test-ps-js who-html2
1332 (who-ps-html (:p "t0" (:span "t1")))
1333 "'<P>t0<SPAN>t1</SPAN></P>';")
1335 (test-ps-js flet1
1336 ((lambda () (flet ((foo (x)
1337 (1+ x)))
1338 (foo 1))))
1339 "(function () {
1340 var foo = function (x) {
1341 return x + 1;
1343 return foo(1);
1344 })();")
1346 (test-ps-js flet2
1347 (flet ((foo (x) (1+ x))
1348 (bar (y) (+ 2 y)))
1349 (bar (foo 1)))
1350 "var foo = function (x) {
1351 return x + 1;
1353 var bar = function (y) {
1354 return 2 + y;
1356 bar(foo(1));")
1358 (test-ps-js flet3
1359 (flet ((foo (x) (+ 2 x)))
1360 (flet ((foo (x) (1+ x))
1361 (bar (y) (+ 2 (foo y))))
1362 (bar (foo 1))))
1363 "var foo = function (x) {
1364 return 2 + x;
1366 var foo1 = function (x) {
1367 return x + 1;
1369 var bar = function (y) {
1370 return 2 + foo(y);
1372 bar(foo1(1));")
1374 (test-ps-js labels1
1375 ((lambda () (labels ((foo (x)
1376 (if (= 0 x)
1378 (+ x (foo (1- x))))))
1379 (foo 3))))
1380 "(function () {
1381 var foo = function (x) {
1382 return 0 === x ? 0 : x + foo(x - 1);
1384 return foo(3);
1385 })();")
1387 (test-ps-js labels2
1388 (labels ((foo (x) (1+ (bar x)))
1389 (bar (y) (+ 2 (foo y))))
1390 (bar (foo 1)))
1391 "var foo = function (x) {
1392 return bar(x) + 1;
1394 var bar = function (y) {
1395 return 2 + foo(y);
1397 bar(foo(1));")
1399 (test-ps-js labels3
1400 (labels ((foo (x) (1+ x))
1401 (bar (y) (+ 2 (foo y))))
1402 (bar (foo 1)))
1403 "var foo = function (x) {
1404 return x + 1;
1406 var bar = function (y) {
1407 return 2 + foo(y);
1409 bar(foo(1));")
1411 (test-ps-js labels-lambda-list
1412 (labels ((foo (x &optional (y 0))
1413 (+ x y)))
1414 (foo 1))
1415 "var foo = function (x, y) {
1416 if (y === undefined) {
1417 y = 0;
1419 return x + y;
1421 foo(1);")
1423 (test-ps-js for-loop-var-init-exp
1424 ((lambda (x)
1425 (do* ((y (if x 0 1) (1+ y))
1426 (z 0 (1+ z)))
1427 ((= y 3) z)))
1428 true)
1429 "(function (x) {
1430 return (function () {
1431 for (var y = x ? 0 : 1, z = 0; y !== 3; y += 1, z += 1) {
1433 return z;
1434 })();
1435 })(true);")
1437 (test-ps-js math-pi
1439 "Math.PI;")
1441 (test-ps-js literal-array
1442 '(1 2 3)
1443 "[1, 2, 3];")
1445 (test-ps-js literal-array-1
1446 '(1 foo 3)
1447 "[1, 'foo', 3];")
1449 (test ps-lisp-expands-in-lexical-environment
1450 (is (string= "5;" (let ((x 5)) (ps (lisp x))))))
1452 (test ps*-lisp-expands-in-null-lexical-environment ;; ccl only does a warning
1453 (signals unbound-variable (let ((x 5)) (declare (ignore x)) (ps* '(lisp x)))))
1455 (test ps*-lisp-expands-in-dynamic-environment
1456 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps* '(+ 1 (lisp (locally (declare (special foo)) foo))))))))
1458 (test ps-lisp-dynamic-environment
1459 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps (+ 1 (lisp foo)))))))
1461 (test-ps-js nested-if-expressions1
1462 (defun foo ()
1463 (return-from foo (if (if x y z) a b)))
1464 "function foo() {
1465 if (x ? y : z) {
1466 return a;
1467 } else {
1468 return b;
1470 };")
1472 (test-ps-js nested-if-expressions2
1473 (defun foo ()
1474 (if x y (if z a b)))
1475 "function foo() {
1476 if (x) {
1477 return y;
1478 } else {
1479 return z ? a : b;
1481 };")
1483 (test-ps-js let1
1484 (let (x)
1485 (+ x x))
1486 "(function () {
1487 var x = null;
1488 return x + x;
1489 })();")
1491 (test-ps-js let2
1492 (let ((x 1))
1493 (+ x x))
1494 "(function () {
1495 var x = 1;
1496 return x + x;
1497 })();")
1499 (test-ps-js let-x-x
1500 (let ((x (1+ x)))
1501 (+ x x))
1502 "(function () {
1503 var x1 = x + 1;
1504 return x1 + x1;
1505 })();")
1507 (test-ps-js let3
1508 (let ((x 1)
1509 (y 2))
1510 (+ x x))
1511 "(function () {
1512 var x = 1;
1513 var y = 2;
1514 return x + x;
1515 })();")
1517 (test-ps-js let4
1518 (let ((x 1)
1519 (y (1+ x)))
1520 (+ x y))
1521 "(function () {
1522 var x1 = 1;
1523 var y = x + 1;
1524 return x1 + y;
1525 })();")
1527 (test-ps-js let5
1528 (let ((x 1))
1529 (+ x 1)
1530 (let ((x (+ x 5)))
1531 (+ x 1))
1532 (+ x 1))
1533 "(function () {
1534 var x = 1;
1535 x + 1;
1536 var x1 = x + 5;
1537 x1 + 1;
1538 return x + 1;
1539 })();")
1541 (test-ps-js let6
1542 (let ((x 2))
1543 (let ((x 1)
1544 (y (1+ x)))
1545 (+ x y)))
1546 "(function () {
1547 var x = 2;
1548 var x1 = 1;
1549 var y = x + 1;
1550 return x1 + y;
1551 })();")
1553 (test-ps-js let-exp1
1554 (lambda ()
1555 (let (x)
1556 (+ x x)))
1557 "(function () {
1558 var x = null;
1559 return x + x;
1560 });")
1562 (test-ps-js let*1
1563 (let* ((x 1))
1564 (+ x x))
1565 "(function () {
1566 var x = 1;
1567 return x + x;
1568 })();")
1570 (test-ps-js let*2
1571 (let* ((x 1)
1572 (y (+ x 2)))
1573 (+ x y))
1574 "(function () {
1575 var x = 1;
1576 var y = x + 2;
1577 return x + y;
1578 })();")
1580 (test-ps-js let*3
1581 (let ((x 3))
1582 (let* ((x 1)
1583 (y (+ x 2)))
1584 (+ x y)))
1585 "(function () {
1586 var x = 3;
1587 var x1 = 1;
1588 var y = x1 + 2;
1589 return x1 + y;
1590 })();")
1592 (test-ps-js let*4
1593 (let ((x 3))
1594 (let* ((y (+ x 2))
1595 (x 1))
1596 (+ x y)))
1597 "(function () {
1598 var x = 3;
1599 var y = x + 2;
1600 var x1 = 1;
1601 return x1 + y;
1602 })();")
1604 (test-ps-js symbol-macrolet-var
1605 (symbol-macrolet ((x y))
1606 (var x))
1607 "var y;")
1609 (test-ps-js setf-conditional1
1610 (setf x (unless (null a) (1+ a)))
1611 "x = a != null ? a + 1 : null;")
1613 (test-ps-js setf-let1
1614 (setf x (let ((a 1)) a))
1615 "x = (function () {
1616 var a = 1;
1617 return a;
1618 })();")
1620 (test-ps-js setf-let2
1621 (setf x (let ((a (foo)))
1622 (unless (null a)
1623 (1+ a))))
1624 "x = (function () {
1625 var a = foo();
1626 return a != null ? a + 1 : null;
1627 })();")
1629 (test-ps-js symbol-macro-env1
1630 (symbol-macrolet ((bar 1))
1631 (macrolet ((bar (x y) `(+ ,x ,y)))
1632 (bar bar bar)))
1633 "1 + 1;")
1635 (test-ps-js symbol-macrolet-fun1
1636 (symbol-macrolet ((baz +))
1637 (baz 1 2))
1638 "baz(1, 2);")
1640 (test-ps-js lisp2-namespaces1
1641 (let ((list nil))
1642 (setf list (list 1 2 3)))
1643 "(function () {
1644 var list = null;
1645 return list = [1, 2, 3];
1646 })();")
1648 (test-ps-js let-shadows-symbol-macrolet
1649 (symbol-macrolet ((x y))
1650 (let ((x 1))
1651 (+ x x))
1652 (+ x x))
1653 "(function () {
1654 var x1 = 1;
1655 return x1 + x1;
1656 })();
1657 y + y;")
1659 (test-ps-js let-rename-optimization1
1660 (let ((x 1))
1661 (+ x x))
1662 "(function () {
1663 var x = 1;
1664 return x + x;
1665 })();")
1667 (test-ps-js let-rename-optimization2
1668 (lambda (x)
1669 (let ((x (+ 1 x)))
1671 "(function (x) {
1672 var x1 = 1 + x;
1673 return x1;
1674 });")
1676 (test-ps-js symbol-macro-array
1677 (symbol-macrolet ((x 1))
1678 (list x))
1679 "[1];")
1681 (test-ps-js symbol-macro-obj
1682 (symbol-macrolet ((x y))
1683 (create x 1))
1684 "({ x : 1 });")
1686 (test-ps-js symbol-macro-conditional1
1687 (symbol-macrolet ((x y))
1688 (if x x x))
1689 "if (y) {
1691 } else {
1693 };")
1695 (test-ps-js symbol-macro-conditional2
1696 (symbol-macrolet ((x y))
1697 (1+ (if x x x)))
1698 "(y ? y : y) + 1;")
1700 (test-ps-js flet-apply
1701 (flet ((foo () 'bar))
1702 (apply (function foo) nil))
1703 "var foo = function () {
1704 return 'bar';
1706 foo.apply(this, null);")
1708 (test-ps-js let-apply
1709 (let ((foo (lambda () 1)))
1710 (let ((foo (lambda () 2)))
1711 (apply foo nil)))
1712 "(function () {
1713 var foo = function () {
1714 return 1;
1716 var foo1 = function () {
1717 return 2;
1719 return foo1.apply(this, null);
1720 })();")
1722 (test-ps-js flet-let
1723 (flet ((x (x) (1+ x)))
1724 (let ((x 2))
1725 (x x)))
1726 "var x = function (x) {
1727 return x + 1;
1729 var x1 = 2;
1730 x(x1);")
1732 (test-ps-js let-flet
1733 (let ((x 2))
1734 (flet ((x (x) (1+ x)))
1735 (x x)))
1736 "(function () {
1737 var x = 2;
1738 var x1 = function (x) {
1739 return x + 1;
1741 return x1(x);
1742 })();")
1744 (test-ps-js labels-let
1745 (labels ((x (x) (1+ x)))
1746 (let ((x 2))
1747 (x x)))
1748 "var x = function (x) {
1749 return x + 1;
1751 var x1 = 2;
1752 x(x1);")
1754 (test-ps-js let-labels
1755 (let ((x 2))
1756 (labels ((x (x) (1+ x)))
1757 (x x)))
1758 "(function () {
1759 var x = 2;
1760 var x1 = function (x) {
1761 return x + 1;
1763 return x1(x);
1764 })();")
1766 (test-ps-js macrolet-let-inteference
1767 (macrolet ((a (n) `(+ ,n 5)))
1768 (let ((a (a 1)))
1769 (let ((b (a (- a 4))))
1770 (+ a b))))
1771 "(function () {
1772 var a = 1 + 5;
1773 var b = (a - 4) + 5;
1774 return a + b;
1775 })();")
1777 (test-ps-js let-subtract-add
1778 (let ((x 1))
1779 (let ((x 2))
1780 (- x x)
1781 (- x)
1782 (decf x)
1783 (incf x)))
1784 "(function () {
1785 var x = 1;
1786 var x1 = 2;
1787 x1 - x1;
1788 -x1;
1789 --x1;
1790 return ++x1;
1791 })();")
1793 (test-ps-js create-reserved-word
1794 (create :default 1)
1795 "({ 'default' : 1 });")
1797 (test-ps-js getprop-reserved-word
1798 (getprop foo :default)
1799 "foo['default'];")
1801 (test-ps-js getprop-reserved-word1
1802 (getprop foo 'default)
1803 "foo['default'];")
1805 (test-ps-js eval-when-ps-side
1806 (eval-when (:execute)
1808 "5;")
1810 (defvar *lisp-output* nil)
1812 (test eval-when-lisp-side ()
1813 (setf *lisp-output* 'original-value)
1814 (let ((js-output (normalize-js-code
1815 (ps-doc* `(eval-when (:compile-toplevel)
1816 (setf *lisp-output* 'it-works))))))
1817 (is (eql 'it-works *lisp-output*))
1818 (is (string= "" js-output))))
1820 (defpsmacro my-in-package (package-name)
1821 `(eval-when (:compile-toplevel)
1822 (setf *lisp-output* ,package-name)))
1824 (test eval-when-macro-expansion ()
1825 (setf *lisp-output* 'original-value)
1826 (let ((js-output (normalize-js-code
1827 (ps-doc* `(progn
1828 (my-in-package :cl-user)
1829 3)))))
1830 (declare (ignore js-output))
1831 (is (eql :cl-user *lisp-output*))))
1833 (test eval-when-macrolet-expansion ()
1834 (setf *lisp-output* 'original-value)
1835 (let ((js-output (normalize-js-code
1836 (ps-doc* `(macrolet ((my-in-package2 (package-name)
1837 `(eval-when (:compile-toplevel)
1838 (setf *lisp-output* ,package-name))))
1839 (my-in-package2 :cl-user)
1840 3)))))
1841 (declare (ignore js-output))
1842 (is (eql :cl-user *lisp-output*))))
1844 (test-ps-js getprop-keyword
1845 (getprop foo :bar)
1846 "foo['bar'];")
1848 (test-ps-js nary-comparison1
1849 (lambda () (< 1 2 3))
1850 "(function () {
1851 var _cmp1;
1852 return (_cmp1 = 2, 1 < _cmp1 && _cmp1 < 3);
1853 });")
1855 (test-ps-js chain-getprop1
1856 (chain ($ "foo") (bar x z) frob (baz 5))
1857 "$('foo').bar(x, z).frob.baz(5);")
1859 (test-ps-js chain-getprop2
1860 (chain ($ "foo") bar baz)
1861 "$('foo').bar.baz;")
1863 (test-ps-js chain-getprop3
1864 (chain ($ "foo") bar (x y) baz)
1865 "$('foo').bar.x(y).baz;")
1867 (test-ps-js flet-expression
1868 (1+ (flet ((foo (x) (1+ x)))
1869 (foo 1)))
1870 "(foo = function (x) {
1871 return x + 1;
1872 }, foo(1)) + 1;")
1874 (test-ps-js flet-lambda-list
1875 (labels ((foo (x &key (y 0))
1876 (+ x y)))
1877 (foo 1 :y 2))
1878 "var foo = function (x) {
1879 var _js2 = arguments.length;
1880 for (var n1 = 1; n1 < _js2; n1 += 2) {
1881 switch (arguments[n1]) {
1882 case 'y':
1883 y = arguments[n1 + 1];
1886 var y = undefined === y ? 0 : y;
1887 return x + y;
1889 foo(1, 'y', 2);")
1891 (test-ps-js return-case-break-elimination
1892 (defun foo ()
1893 (return-from foo
1894 (case 1
1895 (0 1)
1896 (otherwise 2))))
1897 "function foo() {
1898 switch (1) {
1899 case 0:
1900 return 1;
1901 default:
1902 return 2;
1904 };")
1906 (test-ps-js aplusplus
1908 "aplusplus;")
1910 (test-ps-js astarstar
1912 "astarstar;")
1914 (test-ps-js switch-return-fallthrough
1915 (defun foo ()
1916 (return-from foo
1917 (switch x
1918 (1 (foo) break)
1919 (2 (bar))
1920 (default 4))))
1921 "function foo() {
1922 switch (x) {
1923 case 1:
1924 return foo();
1925 case 2:
1926 bar();
1927 default:
1928 return 4;
1930 };")
1932 (test-ps-js return-last-case
1933 (defun foo ()
1934 (return-from foo
1935 (case x
1936 (a 'eh)
1937 (b 'bee))))
1938 "function foo() {
1939 switch (x) {
1940 case a:
1941 return 'eh';
1942 case b:
1943 return 'bee';
1945 };")
1947 (test-ps-js return-macrolet
1948 (defun foo ()
1949 (return-from foo
1950 (macrolet ((x () 1))
1951 (case (x)
1952 (a 'eh)
1953 (b 'bee)))))
1954 "function foo() {
1955 switch (1) {
1956 case a:
1957 return 'eh';
1958 case b:
1959 return 'bee';
1961 };")
1963 (test-ps-js mv-bind1
1964 (multiple-value-bind (a b)
1965 (progn
1966 (returns-mv)
1967 (doesnt))
1968 (alert a)
1969 (alert b))
1970 "(function () {
1971 var prevMv2 = null;
1972 returnsMv();
1973 prevMv2 = arguments['callee']['mv'];
1974 try {
1975 arguments['callee']['mv'] = true;
1976 var a = doesnt();
1977 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1978 var b = mv1[0];
1979 alert(a);
1980 return alert(b);
1981 } finally {
1982 if (undefined === prevMv2) {
1983 delete arguments['callee']['mv'];
1984 } else {
1985 arguments['callee']['mv'] = prevMv2;
1988 })();")
1990 (test-ps-js mv-bind2
1991 (multiple-value-bind (a b)
1992 (let ((a 1))
1993 (returns-mv a)
1994 (doesnt b))
1995 (alert a)
1996 (alert b))
1997 "(function () {
1998 var prevMv2 = null;
1999 var a = 1;
2000 returnsMv(a);
2001 prevMv2 = arguments['callee']['mv'];
2002 try {
2003 arguments['callee']['mv'] = true;
2004 var a3 = doesnt(b);
2005 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
2006 var b = mv1[0];
2007 alert(a3);
2008 return alert(b);
2009 } finally {
2010 if (undefined === prevMv2) {
2011 delete arguments['callee']['mv'];
2012 } else {
2013 arguments['callee']['mv'] = prevMv2;
2016 })();")
2018 (test-ps-js multiple-value-bind-simple
2019 (multiple-value-bind (a b) (blah)
2020 (+ a b))
2021 "(function () {
2022 var prevMv2 = null;
2023 prevMv2 = arguments['callee']['mv'];
2024 try {
2025 arguments['callee']['mv'] = true;
2026 var a = blah();
2027 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
2028 var b = mv1[0];
2029 return a + b;
2030 } finally {
2031 if (undefined === prevMv2) {
2032 delete arguments['callee']['mv'];
2033 } else {
2034 arguments['callee']['mv'] = prevMv2;
2037 })();")
2039 (test-ps-js values0
2040 (lambda () (values))
2041 "(function () {
2042 return null;
2043 });")
2045 (test-ps-js values1
2046 (values x)
2047 "x;")
2049 (test-ps-js values2
2050 (values x y)
2051 "(function () {
2052 var val1_1 = x;
2053 var valrest2 = [y];
2054 if (undefined !== arguments['callee']['caller']['mv']) {
2055 arguments['callee']['caller']['mv'] = valrest2;
2057 return val1_1;
2058 })();")
2060 (test-ps-js values3
2061 (values x y z)
2062 "(function () {
2063 var val1_1 = x;
2064 var valrest2 = [y, z];
2065 if (undefined !== arguments['callee']['caller']['mv']) {
2066 arguments['callee']['caller']['mv'] = valrest2;
2068 return val1_1;
2069 })();")
2071 (test-ps-js values-return
2072 (defun foo ()
2073 (return-from foo (values x y)))
2074 "function foo() {
2075 var val1_1 = x;
2076 var valrest2 = [y];
2077 if (undefined !== arguments['callee']['caller']['mv']) {
2078 arguments['callee']['caller']['mv'] = valrest2;
2080 return val1_1;
2081 };")
2083 (test-ps-js return-macrolet
2084 (defun foo ()
2085 (return-from foo
2086 (symbol-macrolet ((x 2))
2087 (loop do (+ x x)))))
2088 "function foo() {
2089 for (; true; ) {
2090 2 + 2;
2092 return null;
2093 };")
2095 (test-ps-js return-cond
2096 (defun foo ()
2097 (return-from foo
2098 (cond ((foo? x) (loop for y in x do (foo y)))
2099 ((bar? x) x)
2100 (t 3))))
2101 "function foo() {
2102 if (foowhat(x)) {
2103 var _js2 = x.length;
2104 var _js1 = 0;
2105 if (_js1 < _js2) {
2106 var y = x[_js1];
2107 while (true) {
2108 foo(y);
2109 _js1 += 1;
2110 if (_js1 >= _js2) {
2111 break;
2113 y = x[_js1];
2116 return null;
2117 } else if (barwhat(x)) {
2118 return x;
2119 } else {
2120 return 3;
2122 };")
2124 (test-ps-js switch-loop
2125 (case x
2126 (1 (dolist (a b))))
2127 "switch (x) {
2128 case 1:
2129 for (var a = null, _js_idx1 = 0; _js_idx1 < b.length; _js_idx1 += 1) {
2130 a = b[_js_idx1];
2132 };")
2134 (test-ps-js switch-folds-blocks
2135 (case x
2136 (1 (loop repeat 3 do (alert "foo"))))
2137 "switch (x) {
2138 case 1:
2139 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
2140 alert('foo');
2142 };")
2144 (test-ps-js setf-places-before-macros
2145 (lambda ()
2146 (defsetf left (el) (offset)
2147 `(setf (@ ,el style left) ,offset))
2148 (macrolet ((left (el)
2149 `(@ ,el offset-left)))
2150 (setf (left x) 10)
2151 (left x)))
2152 "(function () {
2153 var _js2 = x;
2154 var _js1 = 10;
2155 _js2.style.left = _js1;
2156 return x.offsetLeft;
2157 });")
2159 (test-ps-js for-return
2160 (lambda () (dolist (arg args) (foo arg)))
2161 "(function () {
2162 for (var arg = null, _js_idx1 = 0; _js_idx1 < args.length; _js_idx1 += 1) {
2163 arg = args[_js_idx1];
2164 foo(arg);
2166 });")
2168 (test-ps-js try-catch-return
2169 (defun foo ()
2170 (return-from foo
2171 (try (foo)
2172 (:catch (e)
2173 (bar))
2174 (:finally
2175 (cleanup)))))
2176 "function foo() {
2177 try {
2178 return foo();
2179 } catch (e) {
2180 return bar();
2181 } finally {
2182 cleanup();
2184 };")
2186 (test-ps-js defun-setf-optional
2187 (defun (setf foo) (new-value b &optional c)
2188 (setf (aref b (or c 0)) new-value))
2189 "function __setf_foo(newValue, b, c) {
2190 return b[c || 0] = newValue;
2191 };")
2193 (test-ps-js defun-setf-rest
2194 (progn (defun (setf foo) (new-value b &rest foo)
2195 (do-something b foo new-value))
2196 (setf (foo x 1 2 3 4) 5))
2197 "function __setf_foo(newValue, b) {
2198 var foo = [];
2199 for (var i1 = 0; i1 < arguments.length - 2; i1 += 1) {
2200 foo[i1] = arguments[i1 + 2];
2202 return doSomething(b, foo, newValue);
2204 __setf_foo(5, x, 1, 2, 3, 4);")
2206 (test-ps-js return-null
2207 (defun foo () (return-from foo nil))
2208 "function foo() {
2209 return null;
2210 };")
2212 (test-ps-js implicit-return-null
2213 (lambda ()
2215 "(function () {
2216 return null;
2217 });")
2219 (test-ps-js implicit-return-null
2220 (lambda ()
2221 nil)
2222 "(function () {
2223 return null;
2224 });")
2226 (test-ps-js return-conditional-nested
2227 (defun blep (ss x y)
2228 (when foo?
2229 (let ((pair (bar)))
2230 (unless (null pair)
2231 (destructuring-bind (a b) pair
2232 (unless (or (null a) (null b))
2233 (let ((val (baz a b)))
2234 (unless (null val)
2235 (when (blah val)
2236 (unless (blee)
2237 t))))))))))
2238 "function blep(ss, x, y) {
2239 if (foowhat) {
2240 var pair = bar();
2241 if (pair != null) {
2242 var a = pair[0];
2243 var b = pair[1];
2244 if (!(a == null || b == null)) {
2245 var val = baz(a, b);
2246 if (val != null) {
2247 if (blah(val)) {
2248 return !blee() ? true : null;
2254 };")
2256 ;; this test needs to be rewritten when named blocks are implemented!!!!
2257 (test-ps-js return-when-returns-broken-return
2258 (defun foo ()
2259 (return-from foo (when x 1))
2260 (+ 2 3))
2261 "function foo() {
2262 return x ? 1 : null;
2263 return 2 + 3;
2264 };")
2266 (test-ps-js return-case-conditional
2267 (defun foo ()
2268 (return-from foo
2269 (case foo
2270 (123 (when (bar) t))
2271 (345 (blah)))))
2272 "function foo() {
2273 switch (foo) {
2274 case 123:
2275 return bar() ? true : null;
2276 break;
2277 case 345:
2278 return blah();
2280 };")
2282 (test-ps-js return-try-conditional
2283 (defun foo ()
2284 (return-from foo
2285 (try (when x 1)
2286 (:catch (x) 2)
2287 (:finally (bar)))))
2288 "function foo() {
2289 try {
2290 return x ? 1 : null;
2291 } catch (x) {
2292 return 2;
2293 } finally {
2294 bar();
2296 };")
2298 (test-ps-js function-declare-special
2299 (lambda ()
2300 (declare (special *foo*))
2301 (let ((*foo* 1))
2302 (1+ *foo*)))
2303 "(function () {
2304 var FOO_TMPSTACK1;
2305 try {
2306 FOO_TMPSTACK1 = FOO;
2307 FOO = 1;
2308 return FOO + 1;
2309 } finally {
2310 FOO = FOO_TMPSTACK1;
2312 });")
2314 (test-ps-js declare-special-let
2315 (let ((*foo* 123))
2316 (declare (special *foo*))
2317 (blah))
2318 "(function () {
2319 var FOO_TMPSTACK1;
2320 try {
2321 FOO_TMPSTACK1 = FOO;
2322 FOO = 123;
2323 return blah();
2324 } finally {
2325 FOO = FOO_TMPSTACK1;
2327 })();")
2329 (test-ps-js macro-null-toplevel
2330 (progn
2331 (defmacro macro-null-toplevel ()
2332 nil)
2333 (macro-null-toplevel))
2336 (test-ps-js define-symbol-macro-let
2337 (progn
2338 (define-symbol-macro test-symbol-macro 1)
2339 (let ((test-symbol-macro 2))
2340 (1+ test-symbol-macro))
2341 (1+ test-symbol-macro))
2342 "(function () {
2343 var testSymbolMacro1 = 2;
2344 return testSymbolMacro1 + 1;
2345 })();
2346 1 + 1;")
2348 (test-ps-js define-symbol-macro-flet
2349 (progn
2350 (define-symbol-macro test-symbol-macro1 1)
2351 (flet ((test-symbol-macro1 () 2))
2352 (foo test-symbol-macro1)
2353 (test-symbol-macro1))
2354 (bar test-symbol-macro1))
2355 "var testSymbolMacro1_1 = function () {
2356 return 2;
2358 foo(1);
2359 testSymbolMacro1_1();
2360 bar(1);")
2362 (test compile-stream-nulls
2363 (is (string=
2365 (with-input-from-string (s "
2366 (defmacro macro-null-toplevel ()
2367 nil)
2368 (macro-null-toplevel)")
2369 (ps-compile-stream s)))))
2371 (test compile-stream1
2372 (is (string=
2373 "var testSymbolMacro1_1 = function () {
2374 return 2;
2376 foo(1);
2377 testSymbolMacro1_1();
2378 bar(1);
2380 (with-input-from-string (s "
2381 (define-symbol-macro test-symbol-macro1 1)
2382 (flet ((test-symbol-macro1 () 2))
2383 (foo test-symbol-macro1)
2384 (test-symbol-macro1))
2385 (bar test-symbol-macro1)")
2386 (ps::with-blank-compilation-environment (ps-compile-stream s))))))
2388 (test-ps-js equality-nary1
2389 (let ((x 10) (y 10) (z 10))
2390 (= x y z))
2391 "(function () {
2392 var _cmp1;
2393 var x = 10;
2394 var y = 10;
2395 var z = 10;
2396 return (_cmp1 = y, x === _cmp1 && _cmp1 === z);
2397 })();")
2399 (test-ps-js equality1
2400 (progn
2401 (equal a b)
2402 (eql a b)
2403 (eq a b)
2404 (= a b))
2405 "a == b;
2406 a === b;
2407 a === b;
2408 a === b;")
2410 (test-ps-js getprop-quote-reserved
2411 (getprop foo ':break)
2412 "foo['break'];")
2414 (test-ps-js defun-block-return-from
2415 (defun foo (x)
2416 (baz 4)
2417 (return-from foo x)
2418 (bar 5))
2419 "function foo(x) {
2420 baz(4);
2421 return x;
2422 return bar(5);
2423 }; ")
2425 (test-ps-js block-return-from
2426 (block scope
2427 (foo)
2428 (when (bar)
2429 (return-from scope))
2430 (blee))
2431 "scope: {
2432 foo();
2433 if (bar()) {
2434 break scope;
2436 blee();
2437 };")
2439 (test-ps-js block-return-from1
2440 (lambda ()
2441 (block scope
2442 (foo)
2443 (when (bar)
2444 (return-from scope))
2445 (blee))
2446 (+ 1 2))
2447 "(function () {
2448 scope: {
2449 foo();
2450 if (bar()) {
2451 break scope;
2453 blee();
2455 return 1 + 2;
2456 });")
2458 (test-ps-js block-return-from2
2459 (lambda ()
2460 (bar 5)
2461 (block scope
2462 (foo)
2463 (when (bar)
2464 (return-from scope 6))
2465 (blee)))
2466 "(function () {
2467 bar(5);
2468 foo();
2469 if (bar()) {
2470 return 6;
2472 return blee();
2473 });")
2475 (test-ps-js let-funcall
2476 (let ((x foo))
2477 (funcall x)
2478 (let ((x bar))
2479 (funcall x))
2480 (funcall x))
2481 "(function () {
2482 var x = foo;
2483 x();
2484 var x1 = bar;
2485 x1();
2486 return x();
2487 })();")
2489 (test-ps-js symbol-macrolet-funcall
2490 (symbol-macrolet ((foo bar))
2491 (funcall foo 1 2 3))
2492 "bar(1, 2, 3);")
2494 (test-ps-js times-assign
2495 (setf x (* x 1000))
2496 "x *= 1000;")
2498 (test-ps-js vector-literal
2499 #(1 2 3)
2500 "[1, 2, 3];")
2502 (test-ps-js rem1
2503 (+ 1 (rem 2 (+ 3 4)))
2504 "1 + 2 % (3 + 4);")
2506 (test-ps-js non-associative
2507 (+ (/ 1 (/ 2 3)) (- 1 (- 2 3)))
2508 "1 / (2 / 3) + (1 - (2 - 3));")
2510 (test-ps-js lambda-apply
2511 (lambda (x)
2512 (apply (lambda (y) (bar (1+ y))) x))
2513 "(function (x) {
2514 return (function (y) {
2515 return bar(y + 1);
2516 }).apply(this, x);
2517 });")
2519 (test-ps-js operator-expressions-nested-let
2520 (let ((x (let ((y 1))
2521 y)))
2523 "(function () {
2524 var y;
2525 var x = (y = 1, y);
2526 return x;
2527 })();")
2529 (test-ps-js operator-expressions-array-nested-let
2530 (list (let ((y 1)) y) 2)
2531 "[(function () {
2532 var y = 1;
2533 return y;
2534 })(), 2];")
2536 (test-ps-js add-subtract-precedence
2537 (- x (+ y z))
2538 "x - (y + z);")
2540 (test-ps-js ps-inline-toplevel
2541 (ps-inline (foo))
2542 "'javascript:' + 'foo()';")
2544 (test-ps-js no-clause-progn-exp
2545 (setf x (progn))
2546 "x = null;")
2548 (test-ps-js no-clause-progn-return
2549 (defun foo ()
2550 (return-from foo (progn)))
2551 "function foo() {
2552 return null;
2553 };")
2555 (test-ps-js empty-cond-clause
2556 (setf x (cond ((foo))))
2557 "x = foo() ? null : null;")
2559 (test-ps-js empty-cond-clause1
2560 (setf x (cond ((foo) 123)
2561 ((bar))
2562 (t 456)))
2563 "x = foo() ? 123 : (bar() ? null : 456);")
2565 (test-ps-js let-no-body
2566 (defun foo ()
2567 (return-from foo (let ((foo bar)))))
2568 "function foo() {
2569 var foo1 = bar;
2570 return null;
2571 };")
2573 (test-ps-js rename-lexical-dupes
2574 (lambda ()
2575 (list (let ((foo 12)) (* foo 2))
2576 (let ((foo 13)) (* foo 3))))
2577 "(function () {
2578 var foo;
2579 var foo1;
2580 return [(foo = 12, foo * 2), (foo1 = 13, foo1 * 3)];
2581 });")
2583 (test-ps-js defun-comment1
2584 (defun foo (x)
2585 "BARBAR is a revolutionary new foobar.
2586 X y and x."
2587 (1+ x))
2588 "/**
2589 * BARBAR is a revolutionary new foobar.
2590 * X y and x.
2592 function foo(x) {
2593 return x + 1;
2594 };")
2596 (test-ps-js var-comment
2597 (var x 1 "foo")
2598 "/** foo */
2599 var x = 1;")
2601 (test-ps-js case-return-break-broken-return
2602 (defun foo ()
2603 (case x
2604 ("bar" (if y (return-from foo t) nil))
2605 ("baz" nil)))
2606 "function foo() {
2607 switch (x) {
2608 case 'bar':
2609 if (y) {
2610 return true;
2612 break;
2613 case 'baz':
2614 return null;
2616 };")
2618 (test-ps-js case-return-break1-broken-return
2619 (defun foo ()
2620 (case x
2621 ("bar" (if y (return-from foo t)))
2622 ("baz" nil)))
2623 "function foo() {
2624 switch (x) {
2625 case 'bar':
2626 if (y) {
2627 return true;
2629 break;
2630 case 'baz':
2631 return null;
2633 };")
2635 (test-ps-js setf-progn
2636 (setf foo (progn (bar) (baz) 3))
2637 "bar();
2638 baz();
2639 foo = 3;")
2641 ;; (test-ps-js var-progn
2642 ;; (var x (progn (foo) (bar)))
2643 ;; "foo();
2644 ;; var x = bar();")
2646 (test-ps-js implicit-return-loop
2647 (lambda ()
2648 (if baz 7
2649 (progn
2650 (loop :repeat 100 :do (bar))
2651 42)))
2652 "(function () {
2653 if (baz) {
2654 return 7;
2655 } else {
2656 for (var _js2 = 0; _js2 < 100; _js2 += 1) {
2657 bar();
2659 return 42;
2661 });")
2663 ;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
2664 (test-ps-js loop-closures
2665 (dotimes (i 10) (lambda () (+ i 1)))
2666 "for (var i = 0; i < 10; i += 1) {
2667 with ({ i : i }) {
2668 function () {
2669 return i + 1;
2672 };")
2674 (test-ps-js loop-closures-let
2675 (dotimes (i 10)
2676 (let ((x (+ i 1)))
2677 (lambda () (+ i x))))
2678 "for (var i = 0; i < 10; i += 1) {
2679 with ({ i : i, x : null }) {
2680 var x = i + 1;
2681 function () {
2682 return i + x;
2685 };")
2687 (test-ps-js loop-closures-flet
2688 (dotimes (i 10) (flet ((foo (x) (+ i x))) (lambda () (foo i))))
2689 "for (var i = 0; i < 10; i += 1) {
2690 with ({ foo : null, i : i }) {
2691 var foo = function (x) {
2692 return i + x;
2694 function () {
2695 return foo(i);
2698 };")
2700 (test-ps-js while-closures-let
2701 (while (foo)
2702 (let ((x (bar)))
2703 (lambda () (+ 1 x))))
2704 "while (foo()) {
2705 with ({ x : null }) {
2706 var x = bar();
2707 function () {
2708 return 1 + x;
2711 };")
2713 (test-ps-js dotted-list-form
2714 (defun foo (a)
2715 (when a
2716 (destructuring-bind (b . c)
2718 (list b c))))
2719 "function foo(a) {
2720 if (a) {
2721 var b = bar[0];
2722 var c = bar.length > 1 ? bar.slice(1) : [];
2723 return [b, c];
2725 };")
2727 (test-ps-js return-from-loop
2728 (dolist (x '(2 1 3))
2729 (when (= x 1)
2730 (return))
2731 (chain console (log x)))
2732 "for (var x = null, _js_arrvar2 = [2, 1, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
2733 x = _js_arrvar2[_js_idx1];
2734 if (x === 1) {
2735 break;
2737 console.log(x);
2738 };")
2740 (test-ps-js explicit-nil-block
2741 (block nil (return) (+ 1 2))
2742 "nilBlock: {
2743 break nilBlock;
2744 1 + 2;
2745 };")
2747 (test-ps-js dynamic-extent-function-return
2748 (defun foo () ((lambda () (return-from foo 6))))
2749 "function foo() {
2750 try {
2751 return (function () {
2752 throw { 'ps-block-tag' : 'foo', 'ps-return-value' : 6 };
2753 })();
2754 } catch (err) {
2755 if (err && 'foo' === err['ps-block-tag']) {
2756 return err['ps-return-value'];
2757 } else {
2758 throw err;
2761 };")
2763 (test-ps-js block-dynamic-return
2764 (var foo ((lambda ()
2765 (block nil
2766 ((lambda () (return 6)))
2767 (+ 1 2)))))
2768 "var foo = (function () {
2769 try {
2770 (function () {
2771 throw { 'ps-block-tag' : 'nilBlock', 'ps-return-value' : 6 };
2772 })();
2773 return 1 + 2;
2774 } catch (err) {
2775 if (err && 'nilBlock' === err['ps-block-tag']) {
2776 return err['ps-return-value'];
2777 } else {
2778 throw err;
2781 })();")
2783 (test-ps-js block-dynamic-return1
2784 (var foo ((lambda ()
2785 (block nil
2786 ((lambda () (return 6)))
2787 (+ 1 2))
2788 (foobar 1 2))))
2789 "var foo = (function () {
2790 nilBlock: {
2791 (function () {
2792 break nilBlock;
2793 })();
2794 1 + 2;
2796 return foobar(1, 2);
2797 })();")
2799 (test-ps-js iteration-lambda-capture-no-need
2800 (dolist (x y) (lambda (x) (1+ x))) ;; there's really no need to create a 'with' scope in this case
2801 "for (var x = null, _js_idx1 = 0; _js_idx1 < y.length; _js_idx1 += 1) {
2802 with ({ x : x }) {
2803 x = y[_js_idx1];
2804 function (x) {
2805 return x + 1;
2808 };")
2810 (test-ps-js case-invert1
2811 (encodeURIComponent fooBar)
2812 "encodeURIComponent(fooBar);")
2814 (test-ps-js simple-ash
2815 (+ (ash 4 1) (ash 4 -1))
2816 "(4 << 1) + (4 >> 1);")
2818 (test-ps-js progn-nil-expression
2819 (bar (progn (foo) nil))
2820 "bar((foo(), null));")
2822 (test-ps-js other-progn-nil-exp
2823 (defun blah ()
2824 (or (foo) (progn (bar) nil)))
2825 "function blah() {
2826 return foo() || (bar(), null);
2827 };")
2829 (test-ps-js lambda-nil-return
2830 (lambda (x)
2831 (block nil
2832 (when x
2833 (return 1))
2835 "(function (x) {
2836 if (x) {
2837 return 1;
2839 return 2;
2840 });")
2842 (test-ps-js lambda-nil-return-implicit-nested
2843 (lambda (x)
2844 (block nil
2845 (if x
2846 (return 1)
2847 (dotimes (i 4)
2848 (return 1)))
2850 "(function (x) {
2851 if (x) {
2852 return 1;
2853 } else {
2854 for (var i = 0; i < 4; i += 1) {
2855 break;
2858 return 2;
2859 });")
2861 (test-ps-js throw-is-a-statement
2862 (defun blah ()
2863 (let ((result (foo)))
2864 (unless (null result)
2865 (throw result))))
2866 "function blah() {
2867 var result = foo();
2868 if (result != null) {
2869 throw result;
2871 };")
2873 (test-ps-js expressify1
2874 (defun blah ()
2875 (when (some-condition)
2876 (foo)
2877 (bar)
2878 (baz)))
2879 "function blah() {
2880 if (someCondition()) {
2881 foo();
2882 bar();
2883 return baz();
2885 };")
2887 (test-ps-js case-when-return
2888 (defun blah (a)
2889 (case a
2890 ("a" (when (foo) (return-from blah 111)))
2891 ("b" t)))
2892 "function blah(a) {
2893 switch (a) {
2894 case 'a':
2895 if (foo()) {
2896 return 111;
2898 break;
2899 case 'b':
2900 return true;
2902 };")
2904 (test-ps-js flet-return-from
2905 (defun abc ()
2906 (flet ((foo ()
2907 (return-from foo 123)))
2908 (foo)))
2909 "function abc() {
2910 var foo = function () {
2911 return 123;
2913 return foo();
2914 };")
2916 (test-ps-js flet-return-from1
2917 (flet ((foo ()
2918 (return-from foo 123)))
2919 (foo))
2920 "var foo = function () {
2921 return 123;
2923 foo();")
2925 (test-ps-js lambda-docstring-declarations
2926 (lambda (x)
2927 "This is a docstring"
2928 (declare (ignore x))
2930 "(function (x) {
2931 return 2;
2932 });")
2934 (test-ps-js setf-let-exp
2935 (setf foo (let ((x (+ 1 2)))
2936 (if x 123 456)))
2937 "foo = (function () {
2938 var x = 1 + 2;
2939 return x ? 123 : 456;
2940 })();")
2942 (test-ps-js create-let-exp
2943 (create :abc (let ((x (+ 1 2)))
2944 (if x 123 456)))
2945 "({ 'abc' : (function () {
2946 var x = 1 + 2;
2947 return x ? 123 : 456;
2948 })() });")
2950 (test-ps-js eql-eql-eql-precedence
2951 (unless (equal (= 3 3) (= 3 4))
2952 (chain console (log 1)))
2953 "if ((3 === 3) != (3 === 4)) {
2954 console.log(1);
2955 };")
2957 (test-ps-js case-cond-breaks
2958 (defun blah (x)
2959 (case x
2960 (123 (cond ((foo1) (when (foo2)
2961 (when (foo3)
2962 (return-from blah nil))
2963 t))))
2964 (456 (foo7))))
2965 "function blah(x) {
2966 switch (x) {
2967 case 123:
2968 if (foo1()) {
2969 if (foo2()) {
2970 if (foo3()) {
2971 return null;
2973 return true;
2976 break;
2977 case 456:
2978 return foo7();
2980 };")
2982 (test-ps-js let-let-funcall-lambda
2983 (let ((x 5))
2984 (let ((x 7))
2985 (funcall (lambda (x) (+ x 9)) x)))
2986 "(function () {
2987 var x = 5;
2988 var x1 = 7;
2989 return (function (x) {
2990 return x + 9;
2991 })(x1);
2992 })();")
2994 (test-ps-js let-let-lambda
2995 (let ((x 5))
2996 (let ((x 7))
2997 (lambda (x) (+ x 9))))
2998 "(function () {
2999 var x = 5;
3000 var x1 = 7;
3001 return function (x) {
3002 return x + 9;
3004 })();")
3006 (test-ps-js let-lambda
3007 (let ((x 5))
3008 (lambda (x) (+ x 9)))
3009 "(function () {
3010 var x = 5;
3011 return function (x) {
3012 return x + 9;
3014 })();")
3016 (test-ps-js symbol-macrolet-no-shadow-lambda
3017 (symbol-macrolet ((x y))
3018 (lambda (x) (+ x x)))
3019 "(function (x) {
3020 return x + x;
3021 });")
3023 (test-ps-js divide-one-arg-reciprocal
3024 (/ 2)
3025 "1 / 2;")
3027 (test-ps-js division-not-associative
3028 (/ a (* b c))
3029 "a / (b * c);")
3031 (test-ps-js divide-expressions
3032 (/ (foo) (bar))
3033 "foo() / bar();")
3035 (test-ps-js divide-expressions1
3036 (floor (1- x) y)
3037 "Math.floor((x - 1) / y);")
3039 (test-ps-js lexical-funargs-shadow1
3040 (lambda (x)
3041 (let ((x 1))
3042 (foo x))
3043 (incf x))
3044 "(function (x) {
3045 var x1 = 1;
3046 foo(x1);
3047 return ++x;
3048 });")
3050 (test-ps-js times-rem
3051 (* x (rem y z))
3052 "x * (y % z);")
3054 (test-ps-js rem-divide
3055 (/ x (rem y z))
3056 "x / (y % z);")
3058 (test-ps-js case-break-return
3059 (lambda () (case x (:foo) (:bar 1)))
3060 "(function () {
3061 switch (x) {
3062 case 'foo':
3063 return null;
3064 case 'bar':
3065 return 1;
3067 });")
3069 (test-ps-js trivial-expression-switch
3070 (foobar (case x (1 2)))
3071 "foobar((function () {
3072 switch (x) {
3073 case 1:
3074 return 2;
3076 })());")
3078 (test-ps-js trivial-expression-while
3079 (foobar (while (< 0 x) (decf x)))
3080 "foobar((function () {
3081 while (0 < x) {
3082 --x;
3084 })());")
3086 (test-ps-js funcall-block-expression-loop-lambda
3087 (foobar (loop for i from 0 to 10 do (1+ i)))
3088 "foobar((function () {
3089 for (var i = 0; i <= 10; i += 1) {
3090 i + 1;
3092 return null;
3093 })());")
3095 (test-ps-js let-closures-rename
3096 (lambda ()
3097 (let ((x 1)) (lambda () (1+ x)))
3098 (let ((x 2)) (lambda () (1+ x))))
3099 "(function () {
3100 var x = 1;
3101 function () {
3102 return x + 1;
3104 var x1 = 2;
3105 return function () {
3106 return x1 + 1;
3108 });")
3110 (test-ps-js let-closures-rename1
3111 (lambda ()
3112 (let ((x 1))
3113 (let ((y 2))
3114 (lambda () (+ x y))))
3115 (let ((x 2))
3116 (let ((y 3))
3117 (lambda () (+ x y)))))
3118 "(function () {
3119 var x = 1;
3120 var y = 2;
3121 function () {
3122 return x + y;
3124 var x1 = 2;
3125 var y2 = 3;
3126 return function () {
3127 return x1 + y2;
3129 });")
3131 (test-ps-js let-closures-rename2
3132 (defun make-closures ()
3133 (list
3134 (let ((x 1)) (lambda () (1+ x)))
3135 (let ((x 2)) (lambda () (1+ x)))))
3136 "function makeClosures() {
3137 var x;
3138 var x1;
3139 return [(x = 1, function () {
3140 return x + 1;
3141 }), (x1 = 2, function () {
3142 return x1 + 1;
3143 })];
3145 };")
3147 (test-ps-js conditional-not-used-up
3148 (lambda (bar)
3149 (when bar
3150 (let ((x 1))
3151 (1+ x))))
3152 "(function (bar) {
3153 if (bar) {
3154 var x = 1;
3155 return x + 1;
3157 });")
3159 (test-ps-js toplevel-local-scope
3160 (create "fn" (let ((x 5)) (lambda () x)))
3161 "({ 'fn' : (function () {
3162 var x = 5;
3163 return function () {
3164 return x;
3166 })() });")
3168 (test-ps-js toplevel-local-scope1
3169 (defvar foo (create "fn" (let ((x 5)) (lambda () x))))
3170 "var foo = { 'fn' : (function () {
3171 var x = 5;
3172 return function () {
3173 return x;
3175 })() };")