Fixed case of cond fallthrough (thanks to Daniel Gackle for the bug report)
[parenscript.git] / t / output-tests.lisp
blob8d3b854b2f0bcfe76cc51fd5f7215024e289638e
1 ;; Copying and distribution of this file, with or without modification,
2 ;; are permitted in any medium without royalty provided the copyright
3 ;; notice and this notice are preserved. This file is offered as-is,
4 ;; without any warranty.
6 (in-package #:ps-test)
7 (named-readtables:in-readtable :parenscript)
9 (in-suite output-tests)
11 (test-ps-js statements-and-expressions-1
12 (+ i (if 1 2 3))
13 "i + (1 ? 2 : 3);")
15 (test-ps-js statements-and-expressions-2
16 (if 1 2 3)
17 "if (1) {
19 } else {
21 };")
23 (test-ps-js symbol-conversion-1
24 !?#@%
25 "bangwhathashatpercent;")
27 (test-ps-js symbol-conversion-2
28 bla-foo-bar
29 "blaFooBar;")
31 (test-ps-js symbol-conversion-3
32 *array
33 "Array;")
35 (test-ps-js symbol-conversion-4
36 *global-array*
37 "GLOBALARRAY;")
39 (test-ps-js symbol-conversion-5
40 encodeURIComponent
41 "encodeURIComponent;")
43 (test-ps-js symbol-conversion-6
44 URI
45 "URI;")
47 (test-ps-js number-literals-1
49 "1;")
51 (test-ps-js number-literals-2
52 123.123
53 "123.123;")
55 (test-ps-js number-literals-3
56 #x10
57 "16;")
59 (test-ps-js string-literals-1
60 "foobar"
61 "'foobar';")
63 (test-ps-js string-literals-2
64 "bratzel bub"
65 "'bratzel bub';")
67 (test-ps-js string-literals-3
68 " "
69 "'\\t';")
71 (test-ps-js array-literals-1
72 (array)
73 "[ ];")
75 (test-ps-js array-literals-2
76 (array 1 2 3)
77 "[ 1, 2, 3 ];")
79 (test-ps-js array-literals-3
80 (array (array 2 3)
81 (array "foobar" "bratzel bub"))
82 "[ [ 2, 3 ], [ 'foobar', 'bratzel bub' ] ];")
84 (test-ps-js array-literals-4
85 (make-array)
86 "new Array();")
88 (test-ps-js array-literals-5
89 (make-array 1 2 3)
90 "new Array(1, 2, 3);")
92 (test-ps-js array-literals-6
93 (make-array
94 (make-array 2 3)
95 (make-array "foobar" "bratzel bub"))
96 "new Array(new Array(2, 3), new Array('foobar', 'bratzel bub'));")
98 (test-ps-js object-literals-1
99 (create foo "bar" :blorg 1)
100 "{ foo : 'bar', 'blorg' : 1 };")
102 (test-ps-js object-literals-2
103 (create foo "hihi"
104 blorg (array 1 2 3)
105 another-object (create :schtrunz 1))
106 "{ foo : 'hihi',
107 blorg : [ 1, 2, 3 ],
108 anotherObject : { 'schtrunz' : 1 } };")
110 (test-ps-js object-literals-3
111 (getprop an-object 'foo)
112 "anObject.foo;")
114 (test-ps-js object-literals-4
115 (@ an-object foo bar)
116 "anObject.foo.bar;")
118 (test-ps-js object-literals-5
119 (with-slots (a b c) this
120 (+ a b c))
121 "this.a + this.b + this.c;")
123 (test-ps-js regular-expression-literals-1
124 (regex "foobar")
125 "/foobar/;")
127 (test-ps-js regular-expression-literals-2
128 (regex "/foobar/i")
129 "/foobar/i;")
131 (test-ps-js literal-symbols-1
133 "true;")
135 (test-ps-js literal-symbols-2
136 false
137 "false;")
139 (test-ps-js literal-symbols-3
141 "false;")
143 (test-ps-js literal-symbols-4
144 (lambda () nil)
145 "function () {
146 return null;
147 };")
149 (test-ps-js literal-symbols-5
150 undefined
151 "undefined;")
153 (test-ps-js literal-symbols-6
154 this
155 "this;")
157 (test-ps-js variables-1
158 variable
159 "variable;")
161 (test-ps-js variables-2
162 a-variable
163 "aVariable;")
165 (test-ps-js variables-3
166 *math
167 "Math;")
169 (test-ps-js function-calls-and-method-calls-1
170 (blorg 1 2)
171 "blorg(1, 2);")
173 (test-ps-js function-calls-and-method-calls-2
174 (foobar (blorg 1 2) (blabla 3 4) (array 2 3 4))
175 "foobar(blorg(1, 2), blabla(3, 4), [ 2, 3, 4 ]);")
177 (test-ps-js function-calls-and-method-calls-3
178 ((getprop this 'blorg) 1 2)
179 "this.blorg(1, 2);")
181 (test-ps-js function-calls-and-method-calls-4
182 ((aref foo i) 1 2)
183 "foo[i](1, 2);")
185 (test-ps-js function-calls-and-method-calls-5
186 ((getprop (aref foobar 1) 'blorg) nil t)
187 "foobar[1].blorg(null, true);")
189 (test-ps-js operator-expressions-1
190 (* 1 2)
191 "1 * 2;")
193 (test-ps-js operator-expressions-2
194 (= 1 2)
195 "1 === 2;")
197 (test-ps-js operator-expressions-3
198 (* 1 (+ 2 3 4) 4 (/ 6 7))
199 "1 * (2 + 3 + 4) * 4 * 6 / 7;")
201 (test-ps-js operator-expressions-4
202 (incf i)
203 "++i;")
205 (test-ps-js operator-expressions-5
206 (decf i)
207 "--i;")
209 (test-ps-js operator-expressions-6
210 (1- i)
211 "i - 1;")
213 (test-ps-js operator-expressions-7
214 (1+ i)
215 "i + 1;")
217 (test-ps-js operator-expressions-8
218 (not (< i 2))
219 "i >= 2;")
221 (test-ps-js body-forms-1
222 (progn (blorg i) (blafoo i))
223 "blorg(i);
224 blafoo(i);")
226 (test-ps-js body-forms-2
227 (+ i (progn (blorg i) (blafoo i)))
228 "i + (blorg(i), blafoo(i));")
230 (test-ps-js function-definition-1
231 (defun a-function (a b)
232 (+ a b))
233 "function aFunction(a, b) {
234 return a + b;
235 };")
237 (test-ps-js function-definition-2
238 (lambda (a b) (+ a b))
239 "function (a, b) {
240 return a + b;
241 };")
243 (test-ps-js assignment-1
244 (setf a 1)
245 "a = 1;")
247 (test-ps-js assignment-2
248 (setf a 2 b 3 c 4 x (+ a b c))
249 "a = 2;
250 b = 3;
251 c = 4;
252 x = a + b + c;")
254 (test-ps-js assignment-3
255 (setf a (+ a 2 3 4 a))
256 "a = a + 2 + 3 + 4 + a;")
258 (test-ps-js assignment-4
259 (setf a (- 1 a))
260 "a = 1 - a;")
262 (test-ps-js assignment-5
263 (let ((a 1) (b 2))
264 (psetf a b b a))
265 "var a = 1;
266 var b = 2;
267 var _js1 = b;
268 var _js2 = a;
269 a = _js1;
270 b = _js2;")
272 (test-ps-js assignment-6
273 (setq a 1)
274 "a = 1;")
276 (test-ps-js assignment-8
277 (progn
278 (defun (setf color) (new-color el)
279 (setf (getprop (getprop el 'style) 'color) new-color))
280 (setf (color some-div) (+ 23 "em")))
281 "function __setf_color(newColor, el) {
282 return el.style.color = newColor;
284 __setf_color(23 + 'em', someDiv);")
286 (test-ps-js assignment-10
287 (progn
288 (defsetf left (el) (offset)
289 `(setf (getprop (getprop ,el 'style) 'left) ,offset))
290 (setf (left some-div) (+ 123 "px")))
291 "var _js2 = someDiv;
292 var _js1 = 123 + 'px';
293 _js2.style.left = _js1;")
295 (test-ps-js assignment-12
296 (macrolet ((left (el)
297 `(getprop ,el 'offset-left)))
298 (left some-div))
299 "someDiv.offsetLeft;")
301 (test-ps-js nil-block-return-1
302 (block nil (return))
303 "nilBlock: {
304 break nilBlock;
305 };")
307 (test-ps-js single-argument-statements-2
308 (throw "foobar")
309 "throw 'foobar';")
311 (test-ps-js single-argument-expression-1
312 (delete (new (*foobar 2 3 4)))
313 "delete new Foobar(2, 3, 4);")
315 (test-ps-js single-argument-expression-2
316 (if (= (typeof blorg) *string)
317 (alert (+ "blorg is a string: " blorg))
318 (alert "blorg is not a string"))
319 "if (typeof blorg === String) {
320 alert('blorg is a string: ' + blorg);
321 } else {
322 alert('blorg is not a string');
323 };")
325 (test-ps-js conditional-statements-1
326 (defun foo ()
327 (if ((@ blorg is-correct))
328 (progn (carry-on) (return-from foo i))
329 (alert "blorg is not correct!")))
330 "function foo() {
331 if (blorg.isCorrect()) {
332 carryOn();
333 return i;
334 } else {
335 return alert('blorg is not correct!');
337 };")
339 (test-ps-js conditional-statements-2
340 (+ i (if ((@ blorg add-one)) 1 2))
341 "i + (blorg.addOne() ? 1 : 2);")
343 (test-ps-js conditional-statements-3
344 (defun foo ()
345 (when ((@ blorg is-correct))
346 (carry-on)
347 (return-from foo i)))
348 "function foo() {
349 if (blorg.isCorrect()) {
350 carryOn();
351 return i;
353 };")
355 (test-ps-js conditional-statements-4
356 (unless ((@ blorg is-correct))
357 (alert "blorg is not correct!"))
358 "if (!blorg.isCorrect()) {
359 alert('blorg is not correct!');
360 };")
362 (test-ps-js variable-declaration-1
363 (defvar *a* (array 1 2 3))
364 "var A = [ 1, 2, 3 ];")
366 (test-ps-js variable-declaration-2
367 (progn (defvar *a* 4)
368 (let ((x 1)
369 (*a* 2))
370 (let* ((y (+ x 1))
371 (x (+ x y)))
372 (+ *a* x y))))
373 "var A = 4;
374 var x = 1;
375 var A_TMPSTACK1;
376 try {
377 A_TMPSTACK1 = A;
378 A = 2;
379 var y = x + 1;
380 var x2 = x + y;
381 A + x2 + y;
382 } finally {
383 A = A_TMPSTACK1;
384 };")
386 (test-ps-js iteration-constructs-1
387 (do* ((a) b (c (array "a" "b" "c" "d" "e"))
388 (d 0 (1+ d))
389 (e (aref c d) (aref c d)))
390 ((or (= d (@ c length)) (string= e "x")))
391 (setf a d b e)
392 (funcall (@ document write) (+ "a: " a " b: " b "<br/>")))
393 "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]) {
394 a = d;
395 b = e;
396 document.write('a: ' + a + ' b: ' + b + '<br/>');
397 };")
399 (test-ps-js iteration-constructs-2
400 (do ((i 0 (1+ i))
401 (s 0 (+ s i (1+ i))))
402 ((> i 10))
403 (funcall (@ document write) (+ "i: " i " s: " s "<br/>")))
404 "var i = 0;
405 var s = 0;
406 for (; i <= 10; ) {
407 document.write('i: ' + i + ' s: ' + s + '<br/>');
408 var _js1 = i + 1;
409 var _js2 = s + i + i + 1;
410 i = _js1;
411 s = _js2;
412 };")
414 (test-ps-js iteration-constructs-3
415 (do* ((i 0 (1+ i))
416 (s 0 (+ s i (1- i))))
417 ((> i 10))
418 ((@ document write) (+ "i: " i " s: " s "<br/>")))
419 "for (var i = 0, s = 0; i <= 10; i += 1, s = s + i + i - 1) {
420 document.write('i: ' + i + ' s: ' + s + '<br/>');
421 };")
423 (test-ps-js iteration-constructs-4
424 (let ((arr (array "a" "b" "c" "d" "e")))
425 (dotimes (i (@ arr length))
426 ((@ document write) (+ "i: " i " arr[i]: " (aref arr i) "<br/>"))))
427 "var arr = ['a', 'b', 'c', 'd', 'e'];
428 for (var i = 0; i < arr.length; i += 1) {
429 document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
430 };")
432 (test-ps-js iteration-constructs-5
433 (let ((res 0))
434 (alert (+ "Summation to 10 is "
435 (dotimes (i 10 res)
436 (incf res (1+ i))))))
437 "var res = 0;
438 alert('Summation to 10 is ' + (function () {
439 for (var i = 0; i < 10; i += 1) {
440 res += i + 1;
442 return res;
443 })());")
445 (test-ps-js iteration-constructs-6
446 (let ((l (list 1 2 4 8 16 32)))
447 (dolist (c l)
448 ((@ document write) (+ "c: " c "<br/>"))))
449 "var l = [1, 2, 4, 8, 16, 32];
450 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
451 c = l[_js_idx1];
452 document.write('c: ' + c + '<br/>');
453 };")
455 (test-ps-js iteration-constructs-7
456 (let ((l '(1 2 4 8 16 32))
457 (s 0))
458 (alert (+ "Sum of " l " is: "
459 (dolist (c l s)
460 (incf s c)))))
461 "var l = [1, 2, 4, 8, 16, 32];
462 var s = 0;
463 alert('Sum of ' + l + ' is: ' + (function () {
464 for (var c = null, _js_idx1 = 0; _js_idx1 < l.length; _js_idx1 += 1) {
465 c = l[_js_idx1];
466 s += c;
468 return s;
469 })());")
471 (test-ps-js iteration-constructs-8
472 (let ((obj (create a 1 b 2 c 3)))
473 (for-in (i obj)
474 ((@ document write) (+ i ": " (aref obj i) "<br/>"))))
475 "var obj = { a : 1, b : 2, c : 3 };
476 for (var i in obj) {
477 document.write(i + ': ' + obj[i] + '<br/>');
478 };")
480 (test-ps-js iteration-constructs-9
481 (while ((@ film is-not-finished))
482 ((@ this eat) (new *popcorn)))
483 "while (film.isNotFinished()) {
484 this.eat(new Popcorn);
485 };")
487 (test-ps-js the-case-statement-1
488 (case (aref blorg i)
489 ((1 "one") (alert "one"))
490 (2 (alert "two"))
491 (t (alert "default clause")))
492 "switch (blorg[i]) {
493 case 1:
494 case 'one':
495 alert('one');
496 break;
497 case 2:
498 alert('two');
499 break;
500 default:
501 alert('default clause');
502 };")
504 (test-ps-js the-case-statement-2
505 (switch (aref blorg i)
506 (1 (alert "If I get here"))
507 (2 (alert "I also get here"))
508 (default (alert "I always get here")))
509 "switch (blorg[i]) {
510 case 1: alert('If I get here');
511 case 2: alert('I also get here');
512 default: alert('I always get here');
513 };")
515 (test-ps-js the-try-statement-1
516 (try (throw "i")
517 (:catch (error)
518 (alert (+ "an error happened: " error)))
519 (:finally
520 (alert "Leaving the try form")))
521 "try {
522 throw 'i';
523 } catch (error) {
524 alert('an error happened: ' + error);
525 } finally {
526 alert('Leaving the try form');
527 };")
529 (test-ps-js the-html-generator-1
530 (ps-html ((:a :href "foobar") "blorg"))
531 "'<A HREF=\"foobar\">blorg</A>';")
533 (test-ps-js the-html-generator-2
534 (ps-html ((:a :href (generate-a-link)) "blorg"))
535 "['<A HREF=\"', generateALink(), '\">blorg</A>']['join']('');")
537 (test-ps-js the-html-generator-3
538 (funcall (getprop document 'write)
539 (ps-html ((:a :href "#"
540 :onclick (ps-inline (transport))) "link")))
541 "document.write(['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">link</A>']['join'](''));")
543 (test-ps-js the-html-generator-4
544 (let ((disabled nil)
545 (authorized t))
546 (setf (getprop element 'inner-h-t-m-l)
547 (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
548 "Edit me"))))
549 "var disabled = null;
550 var authorized = true;
551 element.innerHTML = ['<TEXTAREA', disabled || !authorized ? [' DISABLED=\"', 'disabled', '\"']['join']('') : '', '>Edit me</TEXTAREA>']['join']('');")
553 (test-ps-js plus-is-not-commutative
554 (setf x (+ "before" x "after"))
555 "x = 'before' + x + 'after';")
557 (test-ps-js plus-works-if-first
558 (setf x (+ x "middle" "after"))
559 "x = x + 'middle' + 'after';")
561 (test-ps-js setf-side-effects
562 (progn
563 (let ((x 10))
564 (defun side-effect()
565 (setf x 4)
567 (setf x (+ 2 (side-effect) x 5))))
568 "var x = 10;
569 function sideEffect() {
570 x = 4;
571 return 3;
573 x = 2 + sideEffect() + x + 5;")
575 (test-ps-js method-call-op-form
576 (funcall (getprop (+ "" x) 'to-string))
577 "('' + x).toString();")
579 (test-ps-js method-call-op-form-args
580 (funcall (getprop (+ "" x) 'foo) 1 2 :baz 3)
581 "('' + x).foo(1, 2, 'baz', 3);")
583 (test-ps-js method-call-string
584 ((getprop "hi" 'to-string))
585 "'hi'.toString();")
587 (test-ps-js method-call-conditional
588 ((if a x y) 1)
589 "(a ? x : y)(1);")
591 (test-ps-js method-call-variable
592 ((@ x to-string))
593 "x.toString();")
595 (test-ps-js method-call-array
596 ((@ (list 10 20) to-string))
597 "[ 10, 20 ].toString();")
599 (test-ps-js method-call-lambda-call
600 (funcall (getprop (funcall (lambda (x) x) 10) 'to-string))
601 "(function (x) { return x; })(10).toString();")
603 (test no-whitespace-before-dot
604 (let* ((str (ps* '((@ ((lambda (x) x) 10) to-string))))
605 (dot-pos (position #\. str :test #'char=))
606 (char-before (elt str (1- dot-pos)))
607 (a-parenthesis #\)))
608 (is (char= char-before a-parenthesis))))
610 (test-ps-js simple-getprop
611 (let ((foo (create a 1)))
612 (alert (getprop foo 'a)))
613 "var foo = { a : 1 };
614 alert(foo.a);")
616 (test-ps-js buggy-getprop
617 (getprop foo slot-name)
618 "foo[slotName];")
620 (test-ps-js buggy-getprop-two
621 (getprop foo (get-slot-name))
622 "foo[getSlotName()];")
624 (test-ps-js old-case-is-now-switch
625 ;; Switch was "case" before, but that was very non-lispish.
626 ;; For example, this code makes three messages and not one
627 ;; which may have been expected. This is because a switch
628 ;; statment must have a break statement for it to return
629 ;; after the alert. Otherwise it continues on the next
630 ;; clause.
631 (switch (aref blorg i)
632 (1 (alert "one"))
633 (2 (alert "two"))
634 (default (alert "default clause")))
635 "switch (blorg[i]) {
636 case 1: alert('one');
637 case 2: alert('two');
638 default: alert('default clause');
639 };")
641 (test-ps-js lisp-like-case
642 (case (aref blorg i)
643 (1 (alert "one"))
644 (2 (alert "two"))
645 (default (alert "default clause")))
646 "switch (blorg[i]) {
647 case 1:
648 alert('one');
649 break;
650 case 2:
651 alert('two');
652 break;
653 default: alert('default clause');
654 };")
657 (test-ps-js even-lispier-case
658 (case (aref blorg i)
659 ((1 2) (alert "Below three"))
660 (3 (alert "Three"))
661 (t (alert "Something else")))
662 "switch (blorg[i]) {
663 case 1:
664 case 2:
665 alert('Below three');
666 break;
667 case 3:
668 alert('Three');
669 break;
670 default: alert('Something else');
671 };")
673 (test-ps-js otherwise-case
674 (case (aref blorg i)
675 (1 (alert "one"))
676 (otherwise (alert "default clause")))
677 "switch (blorg[i]) {
678 case 1:
679 alert('one');
680 break;
681 default: alert('default clause');
682 };")
684 (test escape-sequences-in-string
685 (let ((escapes `((#\\ . #\\)
686 (#\b . #\Backspace)
687 (#\f . ,(code-char 12))
688 ("u000B" . ,(code-char #x000b));;Vertical tab, too uncommon to bother with
689 (#\n . #\Newline)
690 (#\r . #\Return)
691 (#\' . #\');;Double quote need not be quoted because parenscript strings are single quoted
692 (#\t . #\Tab)
693 ("u001F" . ,(code-char #x001f));; character below 32
694 ("u0080" . ,(code-char 128)) ;;Character over 127. Actually valid, parenscript escapes them to be sure.
695 ("uABCD" . ,(code-char #xabcd)))));; Really above ascii.
696 (loop for (js-escape . lisp-char) in escapes
697 for generated = (ps-doc* `(let ((x ,(format nil "hello~ahi" lisp-char)))))
698 for wanted = (format nil "var x = 'hello\\~ahi';" js-escape)
699 do (is (string= (normalize-js-code generated) wanted)))))
701 (test-ps-js getprop-setf
702 (setf (getprop x 'y) (+ (+ a 3) 4))
703 "x.y = a + 3 + 4;")
705 (test-ps-js getprop-conditional1
706 (getprop (if zoo foo bar) 'x)
707 "(zoo ? foo : bar).x;")
709 (test-ps-js getprop-conditional2
710 (getprop (if (not zoo) foo bar) 'x)
711 "(!zoo ? foo : bar).x;")
713 (test script-star-eval1
714 (is (string= "x = 1; y = 2;" (normalize-js-code (ps* '(setf x 1) '(setf y 2))))))
716 (test script-star-eval2
717 (is (string= "x = 1;" (normalize-js-code (ps* '(setf x 1))))))
719 (test-ps-js list-with-single-nil
720 (array nil)
721 "[null];")
723 (test-ps-js quoted-nil-is-array
724 'nil
725 "[];")
727 (test-ps-js defsetf1
728 (progn (defsetf baz (x y) (newval) `(set-baz ,x ,y ,newval))
729 (setf (baz 1 2) 3))
730 "var _js2 = 1;
731 var _js3 = 2;
732 var _js1 = 3;
733 setBaz(_js2, _js3, _js1);")
735 (test-ps-js setf-macroexpands1
736 (macrolet ((bar (x y)
737 `(aref ,x ,y 1)))
738 (setf (bar foo 2) 3))
739 "foo[2][1] = 3;")
741 (test-ps-js defsetf-short
742 (progn (defsetf baz set-baz "docstring")
743 (setf (baz 1 2 3) "foo"))
744 "setBaz(1, 2, 3, 'foo');")
746 (test-ps-js defun-setf1
747 (progn (defun (setf some-thing) (new-val i1 i2)
748 (setf (aref *some-thing* i1 i2) new-val))
749 (setf (some-thing 1 2) "foo"))
750 "function __setf_someThing(newVal, i1, i2) {
751 return SOMETHING[i1][i2] = newVal;
753 __setf_someThing('foo', 1, 2);")
755 (test-ps-js defun-optional1
756 (defun test-opt (&optional x)
757 (if x "yes" "no"))
758 "function testOpt(x) {
759 return x ? 'yes' : 'no';
760 };")
762 (test-ps-js defun-optional2
763 (defun foo (x &optional y)
764 (+ x y))
765 "function foo(x, y) {
766 return x + y;
767 };")
769 (test-ps-js defun-optional3
770 (defun blah (&optional (x 0))
772 "function blah(x) {
773 if (x === undefined) {
774 x = 0;
776 return x;
777 };")
779 (test-ps-js defun-optional4
780 (lambda (&optional (x 0 supplied?))
782 "function (x) {
783 var suppliedwhat = x !== undefined;
784 if (!suppliedwhat) {
785 x = 0;
787 return x;
788 };")
790 (test-ps-js return-nothing
791 (defun foo () (return-from foo))
792 "function foo() {
793 return null;
794 };")
796 (test-ps-js set-timeout
797 (set-timeout (lambda () (alert "foo")) 10)
798 "setTimeout(function () { return alert('foo'); }, 10);")
800 (test-ps-js operator-precedence
801 (* 3 (+ 4 5) 6)
802 "3 * (4 + 5) * 6;")
804 (test-ps-js operators-1
805 (in prop obj)
806 "prop in obj;")
808 (test-ps-js incf1
809 (incf foo bar)
810 "foo += bar;")
812 (test-ps-js decf1
813 (decf foo bar)
814 "foo -= bar;")
816 (test-ps-js incf2
817 (incf x 5)
818 "x += 5;")
820 (test-ps-js decf2
821 (decf y 10)
822 "y -= 10;")
824 (test-ps-js setf-conditional
825 (setf foo (if x 1 2))
826 "foo = x ? 1 : 2;")
828 (test-ps-js obj-literal-numbers
829 (create 1 "foo")
830 "{ 1 : 'foo' };")
832 (test-ps-js obj-literal-strings
833 (create "foo" 2)
834 "{ 'foo' : 2 };")
836 (test-ps-js getprop-string
837 (getprop foo "bar")
838 "foo['bar'];")
840 (test-ps-js getprop-string1
841 (getprop "bar" 'length)
842 "'bar'.length;")
844 (test-ps-js getprop-progn
845 (getprop (progn (some-fun "abc") "123") "length")
846 "(someFun('abc'), '123')['length'];")
848 (test-ps-js method-call-block
849 ((@ (progn (some-fun "abc") "123") to-string))
850 "(someFun('abc'), '123').toString();")
852 (test-ps-js create-blank
853 (create)
854 "{ };")
856 (test-ps-js blank-object-literal
858 "{ };")
860 (test-ps-js array-literal1
862 "[];")
864 (test-ps-js array-literal2
865 ([])
866 "[];")
868 (test-ps-js array-literal3
869 ([] 1 2 3)
870 "[1, 2, 3];")
872 (test-ps-js array-literal4
873 ([] 1 (2 3))
874 "[1, [2, 3]];")
876 (test-ps-js array-literal5
877 ([] (1 2) ("a" "b"))
878 "[[1, 2], ['a', 'b']];")
880 (test-ps-js defun-rest1
881 (defun foo (&rest bar)
882 (alert (aref bar 1)))
883 "function foo() {
884 var bar = [];
885 for (var i1 = 0; i1 < arguments.length - 0; i1 += 1) {
886 bar[i1] = arguments[i1 + 0];
888 return alert(bar[1]);
889 };")
891 (test-ps-js defun-rest2
892 (defun foo (baz &rest bar) (+ baz (aref bar 1)))
893 "function foo(baz) {
894 var bar = [];
895 for (var i1 = 0; i1 < arguments.length - 1; i1 += 1) {
896 bar[i1] = arguments[i1 + 1];
898 return baz + bar[1];
899 };")
901 (test-ps-js defun-keyword1
902 (defun zoo (foo bar &key baz) (+ foo bar baz))
903 "function zoo(foo, bar) {
904 var _js2 = arguments.length;
905 for (var n1 = 2; n1 < _js2; n1 += 2) {
906 switch (arguments[n1]) {
907 case 'baz':
908 baz = arguments[n1 + 1];
911 var baz;
912 return foo + bar + baz;
913 };")
915 (test-ps-js defun-keyword2
916 (defun zoo (&key baz) (* baz baz))
917 "function zoo() {
918 var _js2 = arguments.length;
919 for (var n1 = 0; n1 < _js2; n1 += 2) {
920 switch (arguments[n1]) {
921 case 'baz':
922 baz = arguments[n1 + 1];
925 var baz;
926 return baz * baz;
927 };")
929 (test-ps-js defun-keyword3
930 (defun zoo (&key baz (bar 4)) (* baz bar))
931 "function zoo() {
932 var _js2 = arguments.length;
933 for (var n1 = 0; n1 < _js2; n1 += 2) {
934 switch (arguments[n1]) {
935 case 'baz':
936 baz = arguments[n1 + 1];
937 break;
938 case 'bar':
939 bar = arguments[n1 + 1];
942 var baz;
943 var bar = undefined === bar ? 4 : bar;
944 return baz * bar;
945 };")
947 (test-ps-js defun-keyword4
948 (defun hello-world (&key ((:my-name-key my-name) 1))
949 my-name)
950 "function helloWorld() {
951 var _js2 = arguments.length;
952 for (var n1 = 0; n1 < _js2; n1 += 2) {
953 switch (arguments[n1]) {
954 case 'my-name-key':
955 myName = arguments[n1 + 1];
958 var myName = undefined === myName ? 1 : myName;
959 return myName;
960 };")
962 (test-ps-js defun-keyword-supplied
963 (lambda (&key (foo 1 supplied?))
964 foo)
965 "function () {
966 var _js2 = arguments.length;
967 for (var n1 = 0; n1 < _js2; n1 += 2) {
968 switch (arguments[n1]) {
969 case 'foo':
970 foo = arguments[n1 + 1];
971 suppliedwhat = true;
974 var suppliedwhat;
975 var foo = undefined === foo ? 1 : foo;
976 return foo;
977 };")
979 (test-ps-js keyword-funcall1
980 (func :baz 1)
981 "func('baz', 1);")
983 (test-ps-js keyword-funcall2
984 (func :baz 1 :bar foo)
985 "func('baz', 1, 'bar', foo);")
987 (test-ps-js keyword-funcall3
988 (fun a b :baz c)
989 "fun(a, b, 'baz', c);")
991 (test-ps-js cond1
992 (cond ((= x 1) 1))
993 "if (x === 1) {
995 };")
997 (test-ps-js cond2
998 (cond ((= x 1) 2)
999 ((= y (* x 4)) (foo "blah") (* x y)))
1000 "if (x === 1) {
1002 } else if (y === x * 4) {
1003 foo('blah');
1004 x * y;
1005 };")
1007 (test-ps-js if-exp-without-else-return
1008 (defun foo () (return-from foo (if x 1)))
1009 "function foo() {
1010 return x ? 1 : null;
1011 };")
1013 (test-ps-js progn-expression-single-statement
1014 (defun foo () (return-from foo (progn (* x y))))
1015 "function foo() {
1016 return x * y;
1017 };")
1019 (test-ps-js cond-expression1
1020 (defun foo ()
1021 (cond ((< 1 2) (bar "foo") (* 4 5))))
1022 "function foo() {
1023 if (1 < 2) {
1024 bar('foo');
1025 return 4 * 5;
1027 };")
1029 (test-ps-js cond-expression2
1030 (defun foo ()
1031 (cond ((< 2 1) "foo")
1032 ((= 7 7) "bar")))
1033 "function foo() {
1034 if (2 < 1) {
1035 return 'foo';
1036 } else if (7 === 7) {
1037 return 'bar';
1039 };")
1041 (test-ps-js cond-expression-final-t-clause
1042 (defun foo ()
1043 (cond ((< 1 2) (bar "foo") (* 4 5))
1044 ((= a b) (+ c d))
1045 ((< 1 2 3 4 5) x)
1046 (t "foo")))
1047 "function foo() {
1048 var _cmp3;
1049 var _cmp2;
1050 var _cmp1;
1051 if (1 < 2) {
1052 bar('foo');
1053 return 4 * 5;
1054 } else if (a === b) {
1055 return c + d;
1056 } else if (_cmp1 = 2, _cmp2 = 3, _cmp3 = 4, 1 < _cmp1 && _cmp1 < _cmp2 && _cmp2 < _cmp3 && _cmp3 < 5) {
1057 return x;
1058 } else {
1059 return 'foo';
1061 };")
1063 (test-ps-js cond-expression-middle-t-clause ;; should this signal a warning?
1064 (defun foo ()
1065 (cond ((< 2 1) 5)
1066 (t "foo")
1067 ((< 1 2) "bar")))
1068 "function foo() {
1069 if (2 < 1) {
1070 return 5;
1071 } else {
1072 return 'foo';
1074 };")
1076 (test-ps-js funcall-if-expression
1077 (funcall (getprop document 'write)
1078 (if (= *linkornot* 1)
1079 (ps-html ((:a :href "#"
1080 :onclick (ps-inline (transport)))
1081 img))
1082 img))
1083 "document.write(LINKORNOT === 1 ? ['<A HREF=\"#\" ONCLICK=\"', 'javascript:' + 'transport()', '\">', img, '</A>']['join']('') : img);")
1085 (test-ps-js negate-number-literal
1086 (- 1)
1087 "-1;")
1089 (test macro-environment1
1090 (is (string= (normalize-js-code (let* ((macroname (gensym)))
1091 (ps* `(defmacro ,macroname (x) `(+ ,x 123))
1092 `(defun test1 ()
1093 (macrolet ((,macroname (x) `(aref data ,x)))
1094 (when (,macroname x)
1095 (setf (,macroname x) 123)))))))
1096 (normalize-js-code
1097 "function test1() {
1098 return data[x] ? (data[x] = 123) : null;
1099 };"))))
1101 (test macro-environment2
1102 (is (string= (normalize-js-code (let ((outer-lexical-variable 1))
1103 (defpsmacro macro-environment2-macro (x)
1104 `(+ ,outer-lexical-variable ,x))
1105 (ps* '(macro-environment2-macro 2))))
1106 (normalize-js-code "1 + 2;"))))
1108 (test-ps-js ampersand-whole-1
1109 (macrolet ((foo (&whole foo bar baz)
1110 (declare (ignore bar baz))
1111 (with-standard-io-syntax (format nil "~a" foo))))
1112 (foo 1 2))
1113 "'(FOO 1 2)';")
1115 (test-ps-js keyword-consistent
1117 "'x';")
1119 (test-ps-js simple-symbol-macrolet
1120 (symbol-macrolet ((x 1)) x)
1121 "1;")
1123 (test-ps-js compound-symbol-macrolet
1124 (symbol-macrolet ((x 123)
1125 (y (* 2 x)))
1127 "2 * 123;")
1129 (test-ps-js define-symbol-macro
1130 (progn (define-symbol-macro tst-sym-macro 2)
1131 tst-sym-macro)
1132 "2;")
1134 (test-ps-js define-symbol-macro1
1135 (progn (define-symbol-macro tst-sym-macro1 2)
1136 (foo tst-sym-macro1))
1137 "foo(2);")
1139 (test-ps-js expression-progn
1140 (1+ (progn (foo) (if x 1 2)))
1141 "(foo(), x ? 1 : 2) + 1;")
1143 (test-ps-js let-decl-in-expression
1144 (defun f (x)
1145 (if x 1 (let* ((foo x)) foo)))
1146 "function f(x) {
1147 if (x) {
1148 return 1;
1149 } else {
1150 var foo = x;
1151 return foo;
1153 };")
1155 (test-ps-js special-var1
1156 (progn (defvar *foo*)
1157 (let* ((*foo* 2))
1158 (* *foo* 2)))
1159 "var FOO;
1160 var FOO_TMPSTACK1;
1161 try {
1162 FOO_TMPSTACK1 = FOO;
1163 FOO = 2;
1164 FOO * 2;
1165 } finally {
1166 FOO = FOO_TMPSTACK1;
1167 };")
1169 (test-ps-js special-var2
1170 (progn (defvar *foo*)
1171 (let* ((*baz* 3)
1172 (*foo* 2))
1173 (* *foo* 2 *baz*)))
1174 "var FOO;
1175 var BAZ = 3;
1176 var FOO_TMPSTACK1;
1177 try {
1178 FOO_TMPSTACK1 = FOO;
1179 FOO = 2;
1180 FOO * 2 * BAZ;
1181 } finally {
1182 FOO = FOO_TMPSTACK1;
1183 };")
1185 (test-ps-js literal1
1186 (setf x undefined)
1187 "x = undefined;")
1189 (test-ps-js literal2
1190 (aref this x)
1191 "this[x];")
1193 (test-ps-js setf-dec1
1194 (setf x (- 1 x 2))
1195 "x = 1 - x - 2;")
1197 (test-ps-js setf-dec2
1198 (setf x (- x 1 2))
1199 "x = x - 1 - 2;")
1201 (test-ps-js special-char-equals
1202 blah=
1203 "blahequals;")
1205 (test-ps-js setf-operator-priority
1206 (defun foo ()
1207 (or (getprop cache id)
1208 (setf (getprop cache id) ((@ document get-element-by-id) id))))
1209 "function foo() {
1210 return cache[id] || (cache[id] = document.getElementById(id));
1211 };")
1213 (test-ps-js aref-operator-priority
1214 (aref (if (and x (> (length x) 0))
1215 (aref x 0)
1218 "(x && x.length > 0 ? x[0] : y)[z];")
1220 (test-ps-js aref-operator-priority1
1221 (aref (or (getprop x 'y)
1222 (getprop a 'b))
1224 "(x.y || a.b)[z];")
1226 (test-ps-js aref-operator-priority2
1227 (aref (if a b c) 0)
1228 "(a ? b : c)[0];")
1230 (test-ps-js negate-operator-priority
1231 (- (if x y z))
1232 "-(x ? y : z);")
1234 (test-ps-js op-p1
1235 (new (or a b))
1236 "new (a || b);")
1238 (test-ps-js op-p2
1239 (delete (if a (or b c) d))
1240 "delete (a ? b || c : d);")
1242 (test-ps-js op-p3
1243 (not (if (or x (not y)) z))
1244 "!(x || !y ? z : null);")
1246 (test-ps-js op-p4
1247 (- (- (* 1 2) 3))
1248 "-(1 * 2 - 3);")
1250 (test-ps-js op-p5
1251 (instanceof (or a b) (if x y z))
1252 "((a || b) instanceof (x ? y : z));")
1254 (test-ps-js op-p7
1255 (or x (if (= x 0) "zero" "empty"))
1256 "x || (x === 0 ? 'zero' : 'empty');")
1258 (test-ps-js named-op-expression
1259 (throw (if a b c))
1260 "throw a ? b : c;")
1262 (test-ps-js named-op-expression1
1263 (typeof (or x y))
1264 "typeof (x || y);")
1266 (test-ps-js aref-array-expression
1267 (aref (or a b c) 0)
1268 "(a || b || c)[0];")
1270 (test-ps-js getprop-operator
1271 (getprop (or a b c) 'd)
1272 "(a || b || c).d;")
1274 (test-ps-js getprop-parens
1275 (getprop (getprop foo 'bar) 'baz)
1276 "foo.bar.baz;")
1278 (test-ps-js funcall-funcall
1279 ((foo))
1280 "foo()();")
1282 (test-ps-js expression-funcall
1283 ((or (@ window eval) eval) foo nil)
1284 "(window.eval || eval)(foo, null);")
1286 (test-ps-js expression-funcall1
1287 (((or (@ window eval) eval) foo nil))
1288 "(window.eval || eval)(foo, null)();")
1290 (test-ps-js expression-funcall2
1291 (((or (@ window eval) eval)) foo nil)
1292 "(window.eval || eval)()(foo, null);")
1294 (test-ps-js who-html1
1295 (who-ps-html (:span :class "ticker-symbol"
1296 :ticker-symbol symbol
1297 (:a :href "http://foo.com"
1298 symbol)
1299 (:span :class "ticker-symbol-popup")))
1300 "['<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"', symbol, '\"><A HREF=\"http://foo.com\">', symbol, '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>']['join']('');")
1302 (test-ps-js flet1
1303 ((lambda () (flet ((foo (x)
1304 (1+ x)))
1305 (foo 1))))
1306 "(function () {
1307 var foo = function (x) {
1308 return x + 1;
1310 return foo(1);
1311 })();")
1313 (test-ps-js flet2
1314 (flet ((foo (x) (1+ x))
1315 (bar (y) (+ 2 y)))
1316 (bar (foo 1)))
1317 "var foo = function (x) {
1318 return x + 1;
1320 var bar = function (y) {
1321 return 2 + y;
1323 bar(foo(1));")
1325 (test-ps-js flet3
1326 (flet ((foo (x) (+ 2 x)))
1327 (flet ((foo (x) (1+ x))
1328 (bar (y) (+ 2 (foo y))))
1329 (bar (foo 1))))
1330 "var foo = function (x) {
1331 return 2 + x;
1333 var foo1 = function (x) {
1334 return x + 1;
1336 var bar = function (y) {
1337 return 2 + foo(y);
1339 bar(foo1(1));")
1341 (test-ps-js labels1
1342 ((lambda () (labels ((foo (x)
1343 (if (= 0 x)
1345 (+ x (foo (1- x))))))
1346 (foo 3))))
1347 "(function () {
1348 var foo = function (x) {
1349 return 0 === x ? 0 : x + foo(x - 1);
1351 return foo(3);
1352 })();")
1354 (test-ps-js labels2
1355 (labels ((foo (x) (1+ (bar x)))
1356 (bar (y) (+ 2 (foo y))))
1357 (bar (foo 1)))
1358 "var foo = function (x) {
1359 return bar(x) + 1;
1361 var bar = function (y) {
1362 return 2 + foo(y);
1364 bar(foo(1));")
1366 (test-ps-js labels3
1367 (labels ((foo (x) (1+ x))
1368 (bar (y) (+ 2 (foo y))))
1369 (bar (foo 1)))
1370 "var foo = function (x) {
1371 return x + 1;
1373 var bar = function (y) {
1374 return 2 + foo(y);
1376 bar(foo(1));")
1378 (test-ps-js labels-lambda-list
1379 (labels ((foo (x &optional (y 0))
1380 (+ x y)))
1381 (foo 1))
1382 "var foo = function (x, y) {
1383 if (y === undefined) {
1384 y = 0;
1386 return x + y;
1388 foo(1);")
1390 (test-ps-js for-loop-var-init-exp
1391 ((lambda (x)
1392 (do* ((y (if x 0 1) (1+ y))
1393 (z 0 (1+ z)))
1394 ((= y 3) z)))
1395 true)
1396 "(function (x) {
1397 return (function () {
1398 for (var y = x ? 0 : 1, z = 0; y !== 3; y += 1, z += 1) {
1400 return z;
1401 })();
1402 })(true);")
1404 (test-ps-js math-pi
1406 "Math.PI;")
1408 (test-ps-js literal-array
1409 '(1 2 3)
1410 "[1, 2, 3];")
1412 (test-ps-js literal-array-1
1413 '(1 foo 3)
1414 "[1, 'foo', 3];")
1416 (test ps-lisp-expands-in-lexical-environment
1417 (is (string= "5;" (let ((x 5)) (ps (lisp x))))))
1419 (test ps*-lisp-expands-in-null-lexical-environment
1420 (signals error (let ((x 5)) (declare (ignore x)) (ps* '(lisp x)))))
1422 (test ps*-lisp-expands-in-dynamic-environment
1423 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps* '(+ 1 (lisp (locally (declare (special foo)) foo))))))))
1425 (test ps-lisp-dynamic-environment
1426 (is (string= "1 + 2;" (let ((foo 2)) (declare (special foo)) (ps (+ 1 (lisp foo)))))))
1428 (test-ps-js nested-if-expressions1
1429 (defun foo ()
1430 (return-from foo (if (if x y z) a b)))
1431 "function foo() {
1432 return (x ? y : z) ? a : b;
1433 };")
1435 (test-ps-js nested-if-expressions2
1436 (defun foo ()
1437 (if x y (if z a b)))
1438 "function foo() {
1439 if (x) {
1440 return y;
1441 } else {
1442 return z ? a : b;
1444 };")
1446 (test-ps-js let1
1447 (let (x)
1448 (+ x x))
1449 "var x = null;
1450 x + x;")
1452 (test-ps-js let2
1453 (let ((x 1))
1454 (+ x x))
1455 "var x = 1;
1456 x + x;")
1458 (test-ps-js let-x-x
1459 (let ((x (1+ x)))
1460 (+ x x))
1461 "var x1 = x + 1;
1462 x1 + x1;")
1464 (test-ps-js let3
1465 (let ((x 1)
1466 (y 2))
1467 (+ x x))
1468 "var x = 1;
1469 var y = 2;
1470 x + x;")
1472 (test-ps-js let4
1473 (let ((x 1)
1474 (y (1+ x)))
1475 (+ x y))
1476 "var x1 = 1;
1477 var y = x + 1;
1478 x1 + y;")
1480 (test-ps-js let5
1481 (let ((x 1))
1482 (+ x 1)
1483 (let ((x (+ x 5)))
1484 (+ x 1))
1485 (+ x 1))
1486 "var x = 1;
1487 x + 1;
1488 var x1 = x + 5;
1489 x1 + 1;
1490 x + 1;")
1492 (test-ps-js let6
1493 (let ((x 2))
1494 (let ((x 1)
1495 (y (1+ x)))
1496 (+ x y)))
1497 "var x = 2;
1498 var x1 = 1;
1499 var y = x + 1;
1500 x1 + y;")
1502 (test-ps-js let-exp1
1503 (lambda ()
1504 (let (x)
1505 (+ x x)))
1506 "function () {
1507 var x = null;
1508 return x + x;
1509 };")
1511 (test-ps-js let*1
1512 (let* ((x 1))
1513 (+ x x))
1514 "var x = 1;
1515 x + x;")
1517 (test-ps-js let*2
1518 (let* ((x 1)
1519 (y (+ x 2)))
1520 (+ x y))
1521 "var x = 1;
1522 var y = x + 2;
1523 x + y;")
1525 (test-ps-js let*3
1526 (let ((x 3))
1527 (let* ((x 1)
1528 (y (+ x 2)))
1529 (+ x y)))
1530 "var x = 3;
1531 var x1 = 1;
1532 var y = x1 + 2;
1533 x1 + y;")
1535 (test-ps-js let*4
1536 (let ((x 3))
1537 (let* ((y (+ x 2))
1538 (x 1))
1539 (+ x y)))
1540 "var x = 3;
1541 var y = x + 2;
1542 var x1 = 1;
1543 x1 + y;")
1545 (test-ps-js symbol-macrolet-var
1546 (symbol-macrolet ((x y))
1547 (var x))
1548 "var y;")
1550 (test-ps-js setf-conditional1
1551 (setf x (unless (null a) (1+ a)))
1552 "x = a != null ? a + 1 : null;")
1554 (test-ps-js setf-let1
1555 (setf x (let ((a 1)) a))
1556 "x = (a = 1, a);")
1558 (test-ps-js setf-let2
1559 (setf x (let ((a (foo)))
1560 (unless (null a)
1561 (1+ a))))
1562 "x = (a = foo(), a != null ? a + 1 : null);")
1564 (test-ps-js symbol-macro-env1
1565 (symbol-macrolet ((bar 1))
1566 (macrolet ((bar (x y) `(+ ,x ,y)))
1567 (bar bar bar)))
1568 "1 + 1;")
1570 (test-ps-js symbol-macrolet-fun1
1571 (symbol-macrolet ((baz +))
1572 (baz 1 2))
1573 "baz(1, 2);")
1575 (test-ps-js lisp2-namespaces1
1576 (let ((list nil))
1577 (setf list (list 1 2 3)))
1578 "var list = null;
1579 list = [1, 2, 3];")
1581 (test-ps-js let-shadows-symbol-macrolet
1582 (symbol-macrolet ((x y))
1583 (let ((x 1))
1584 (+ x x))
1585 (+ x x))
1586 "var x1 = 1;
1587 x1 + x1;
1588 y + y;")
1590 (test-ps-js let-rename-optimization1
1591 (let ((x 1))
1592 (+ x x))
1593 "var x = 1;
1594 x + x;")
1596 (test-ps-js let-rename-optimization2
1597 (lambda (x)
1598 (let ((x (+ 1 x)))
1600 "function (x) {
1601 var x1 = 1 + x;
1602 return x1;
1603 };")
1605 (test-ps-js symbol-macro-array
1606 (symbol-macrolet ((x 1))
1607 (list x))
1608 "[1];")
1610 (test-ps-js symbol-macro-obj
1611 (symbol-macrolet ((x y))
1612 (create x 1))
1613 "{ x : 1 };")
1615 (test-ps-js symbol-macro-conditional1
1616 (symbol-macrolet ((x y))
1617 (if x x x))
1618 "if (y) {
1620 } else {
1622 };")
1624 (test-ps-js symbol-macro-conditional2
1625 (symbol-macrolet ((x y))
1626 (1+ (if x x x)))
1627 "(y ? y : y) + 1;")
1629 (test-ps-js flet-apply
1630 (flet ((foo () 'bar))
1631 (apply (function foo) nil))
1632 "var foo = function () {
1633 return 'bar';
1635 foo.apply(this, null);")
1637 (test-ps-js let-apply
1638 (let ((foo (lambda () 1)))
1639 (let ((foo (lambda () 2)))
1640 (apply foo nil)))
1641 "var foo = function () {
1642 return 1;
1644 var foo1 = function () {
1645 return 2;
1647 foo1.apply(this, null);")
1649 (test-ps-js flet-let
1650 (flet ((x (x) (1+ x)))
1651 (let ((x 2))
1652 (x x)))
1653 "var x = function (x) {
1654 return x + 1;
1656 var x1 = 2;
1657 x(x1);")
1659 (test-ps-js let-flet
1660 (let ((x 2))
1661 (flet ((x (x) (1+ x)))
1662 (x x)))
1663 "var x = 2;
1664 var x1 = function (x) {
1665 return x + 1;
1667 x1(x);")
1669 (test-ps-js labels-let
1670 (labels ((x (x) (1+ x)))
1671 (let ((x 2))
1672 (x x)))
1673 "var x = function (x) {
1674 return x + 1;
1676 var x1 = 2;
1677 x(x1);")
1679 (test-ps-js let-labels
1680 (let ((x 2))
1681 (labels ((x (x) (1+ x)))
1682 (x x)))
1683 "var x = 2;
1684 var x1 = function (x) {
1685 return x + 1;
1687 x1(x);")
1689 (test-ps-js macrolet-let-inteference
1690 (macrolet ((a (n) `(+ ,n 5)))
1691 (let ((a (a 1)))
1692 (let ((b (a (- a 4))))
1693 (+ a b))))
1694 "var a = 1 + 5;
1695 var b = a - 4 + 5;
1696 a + b;")
1698 (test-ps-js let-subtract-add
1699 (let ((x 1))
1700 (let ((x 2))
1701 (- x x)
1702 (- x)
1703 (decf x)
1704 (incf x)))
1705 "var x = 1;
1706 var x1 = 2;
1707 x1 - x1;
1708 -x1;
1709 --x1;
1710 ++x1;")
1712 (test-ps-js create-reserved-word
1713 (create :default 1)
1714 "{ 'default' : 1 };")
1716 (test-ps-js getprop-reserved-word
1717 (getprop foo :default)
1718 "foo['default'];")
1720 (test-ps-js getprop-reserved-word1
1721 (getprop foo 'default)
1722 "foo['default'];")
1724 (test-ps-js eval-when-ps-side
1725 (eval-when (:execute)
1727 "5;")
1729 (defvar *lisp-output* nil)
1731 (test eval-when-lisp-side ()
1732 (setf *lisp-output* 'original-value)
1733 (let ((js-output (normalize-js-code
1734 (ps-doc* `(eval-when (:compile-toplevel)
1735 (setf *lisp-output* 'it-works))))))
1736 (is (eql 'it-works *lisp-output*))
1737 (is (string= "" js-output))))
1739 (defpsmacro my-in-package (package-name)
1740 `(eval-when (:compile-toplevel)
1741 (setf *lisp-output* ,package-name)))
1743 (test eval-when-macro-expansion ()
1744 (setf *lisp-output* 'original-value)
1745 (let ((js-output (normalize-js-code
1746 (ps-doc* `(progn
1747 (my-in-package :cl-user)
1748 3)))))
1749 (declare (ignore js-output))
1750 (is (eql :cl-user *lisp-output*))))
1752 (test eval-when-macrolet-expansion ()
1753 (setf *lisp-output* 'original-value)
1754 (let ((js-output (normalize-js-code
1755 (ps-doc* `(macrolet ((my-in-package2 (package-name)
1756 `(eval-when (:compile-toplevel)
1757 (setf *lisp-output* ,package-name))))
1758 (my-in-package2 :cl-user)
1759 3)))))
1760 (declare (ignore js-output))
1761 (is (eql :cl-user *lisp-output*))))
1763 (test-ps-js getprop-keyword
1764 (getprop foo :bar)
1765 "foo['bar'];")
1767 (test-ps-js nary-comparison1
1768 (lambda () (< 1 2 3))
1769 "function () {
1770 var _cmp1;
1771 return (_cmp1 = 2, 1 < _cmp1 && _cmp1 < 3);
1772 };")
1774 (test-ps-js chain-getprop1
1775 (chain ($ "foo") (bar x z) frob (baz 5))
1776 "$('foo').bar(x, z).frob.baz(5);")
1778 (test-ps-js chain-getprop2
1779 (chain ($ "foo") bar baz)
1780 "$('foo').bar.baz;")
1782 (test-ps-js chain-getprop3
1783 (chain ($ "foo") bar (x y) baz)
1784 "$('foo').bar.x(y).baz;")
1786 (test-ps-js flet-expression
1787 (1+ (flet ((foo (x) (1+ x)))
1788 (foo 1)))
1789 "(foo = function (x) {
1790 return x + 1;
1791 }, foo(1)) + 1;")
1793 (test-ps-js flet-lambda-list
1794 (labels ((foo (x &key (y 0))
1795 (+ x y)))
1796 (foo 1 :y 2))
1797 "var foo = function (x) {
1798 var _js2 = arguments.length;
1799 for (var n1 = 1; n1 < _js2; n1 += 2) {
1800 switch (arguments[n1]) {
1801 case 'y':
1802 y = arguments[n1 + 1];
1805 var y = undefined === y ? 0 : y;
1806 return x + y;
1808 foo(1, 'y', 2);")
1810 (test-ps-js return-case-break-elimination
1811 (defun foo ()
1812 (return-from foo
1813 (case 1
1814 (0 1)
1815 (otherwise 2))))
1816 "function foo() {
1817 switch (1) {
1818 case 0:
1819 return 1;
1820 default:
1821 return 2;
1823 };")
1825 (test-ps-js aplusplus
1827 "aplusplus;")
1829 (test-ps-js astarstar
1831 "astarstar;")
1833 (test-ps-js switch-return-fallthrough
1834 (defun foo ()
1835 (return-from foo
1836 (switch x
1837 (1 (foo) break)
1838 (2 (bar))
1839 (default 4))))
1840 "function foo() {
1841 switch (x) {
1842 case 1:
1843 return foo();
1844 case 2:
1845 bar();
1846 default:
1847 return 4;
1849 };")
1851 (test-ps-js return-last-case
1852 (defun foo ()
1853 (return-from foo
1854 (case x
1855 (a 'eh)
1856 (b 'bee))))
1857 "function foo() {
1858 switch (x) {
1859 case a:
1860 return 'eh';
1861 case b:
1862 return 'bee';
1864 };")
1866 (test-ps-js return-macrolet
1867 (defun foo ()
1868 (return-from foo
1869 (macrolet ((x () 1))
1870 (case (x)
1871 (a 'eh)
1872 (b 'bee)))))
1873 "function foo() {
1874 switch (1) {
1875 case a:
1876 return 'eh';
1877 case b:
1878 return 'bee';
1880 };")
1882 (test-ps-js mv-bind1
1883 (multiple-value-bind (a b)
1884 (progn
1885 (returns-mv)
1886 (doesnt))
1887 (alert a)
1888 (alert b))
1889 "var prevMv2 = null;
1890 returnsMv();
1891 prevMv2 = arguments['callee']['mv'];
1892 try {
1893 arguments['callee']['mv'] = true;
1894 var a = doesnt();
1895 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1896 var b = mv1[0];
1897 alert(a);
1898 alert(b);
1899 } finally {
1900 if (undefined === prevMv2) {
1901 delete arguments['callee']['mv'];
1902 } else {
1903 arguments['callee']['mv'] = prevMv2;
1905 };")
1907 (test-ps-js mv-bind2
1908 (multiple-value-bind (a b)
1909 (let ((a 1))
1910 (returns-mv a)
1911 (doesnt b))
1912 (alert a)
1913 (alert b))
1914 "var prevMv2 = null;
1915 var a = 1;
1916 returnsMv(a);
1917 prevMv2 = arguments['callee']['mv'];
1918 try {
1919 arguments['callee']['mv'] = true;
1920 var a3 = doesnt(b);
1921 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1922 var b = mv1[0];
1923 alert(a3);
1924 alert(b);
1925 } finally {
1926 if (undefined === prevMv2) {
1927 delete arguments['callee']['mv'];
1928 } else {
1929 arguments['callee']['mv'] = prevMv2;
1931 };")
1933 (test-ps-js multiple-value-bind-simple
1934 (multiple-value-bind (a b) (blah)
1935 (+ a b))
1936 "var prevMv2 = null;
1937 prevMv2 = arguments['callee']['mv'];
1938 try {
1939 arguments['callee']['mv'] = true;
1940 var a = blah();
1941 var mv1 = typeof arguments['callee']['mv'] === 'object' ? arguments['callee']['mv'] : new Array(1);
1942 var b = mv1[0];
1943 a + b;
1944 } finally {
1945 if (undefined === prevMv2) {
1946 delete arguments['callee']['mv'];
1947 } else {
1948 arguments['callee']['mv'] = prevMv2;
1950 };")
1952 (test-ps-js values0
1953 (lambda () (values))
1954 "function () {
1955 return null;
1956 };")
1958 (test-ps-js values1
1959 (values x)
1960 "x;")
1962 (test-ps-js values2
1963 (values x y)
1964 "var val1_1 = x;
1965 var valrest2 = [y];
1966 if (undefined !== arguments['callee']['caller']['mv']) {
1967 arguments['callee']['caller']['mv'] = valrest2;
1969 val1_1;")
1971 (test-ps-js values3
1972 (values x y z)
1973 "var val1_1 = x;
1974 var valrest2 = [y, z];
1975 if (undefined !== arguments['callee']['caller']['mv']) {
1976 arguments['callee']['caller']['mv'] = valrest2;
1978 val1_1;")
1980 (test-ps-js values-return
1981 (defun foo ()
1982 (return-from foo (values x y)))
1983 "function foo() {
1984 var val1_1 = x;
1985 var valrest2 = [y];
1986 if (undefined !== arguments['callee']['caller']['mv']) {
1987 arguments['callee']['caller']['mv'] = valrest2;
1989 return val1_1;
1990 };")
1992 (test-ps-js return-macrolet
1993 (defun foo ()
1994 (return-from foo
1995 (symbol-macrolet ((x 2))
1996 (loop do (+ x x)))))
1997 "function foo() {
1998 for (; true; ) {
1999 2 + 2;
2001 return null;
2002 };")
2004 (test-ps-js return-cond
2005 (defun foo ()
2006 (return-from foo
2007 (cond ((foo? x) (loop for y in x do (foo y)))
2008 ((bar? x) x)
2009 (t 3))))
2010 "function foo() {
2011 if (foowhat(x)) {
2012 var _js2 = x.length;
2013 var _js1 = 0;
2014 if (_js1 < _js2) {
2015 var y = x[_js1];
2016 while (true) {
2017 foo(y);
2018 _js1 += 1;
2019 if (_js1 >= _js2) {
2020 break;
2022 y = x[_js1];
2025 return null;
2026 } else if (barwhat(x)) {
2027 return x;
2028 } else {
2029 return 3;
2031 };")
2033 (test-ps-js switch-loop
2034 (case x
2035 (1 (dolist (a b))))
2036 "switch (x) {
2037 case 1:
2038 for (var a = null, _js_idx1 = 0; _js_idx1 < b.length; _js_idx1 += 1) {
2039 a = b[_js_idx1];
2041 };")
2043 (test-ps-js switch-folds-blocks
2044 (case x
2045 (1 (loop repeat 3 do (alert "foo"))))
2046 "switch (x) {
2047 case 1:
2048 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
2049 alert('foo');
2051 };")
2053 (test-ps-js setf-places-before-macros
2054 (progn
2055 (defsetf left (el) (offset)
2056 `(setf (@ ,el style left) ,offset))
2057 (macrolet ((left (el)
2058 `(@ ,el offset-left)))
2059 (setf (left x) 10)
2060 (left x)))
2061 "var _js2 = x;
2062 var _js1 = 10;
2063 _js2.style.left = _js1;
2064 x.offsetLeft;")
2066 (test-ps-js for-return
2067 (lambda () (dolist (arg args) (foo arg)))
2068 "function () {
2069 for (var arg = null, _js_idx1 = 0; _js_idx1 < args.length; _js_idx1 += 1) {
2070 arg = args[_js_idx1];
2071 foo(arg);
2073 };")
2075 (test-ps-js try-catch-return
2076 (defun foo ()
2077 (return-from foo
2078 (try (foo)
2079 (:catch (e)
2080 (bar))
2081 (:finally
2082 (cleanup)))))
2083 "function foo() {
2084 try {
2085 return foo();
2086 } catch (e) {
2087 return bar();
2088 } finally {
2089 cleanup();
2091 };")
2093 (test-ps-js defun-setf-optional
2094 (defun (setf foo) (new-value b &optional c)
2095 (setf (aref b (or c 0)) new-value))
2096 "function __setf_foo(newValue, b, c) {
2097 return b[c || 0] = newValue;
2098 };")
2100 (test-ps-js defun-setf-rest
2101 (progn (defun (setf foo) (new-value b &rest foo)
2102 (do-something b foo new-value))
2103 (setf (foo x 1 2 3 4) 5))
2104 "function __setf_foo(newValue, b) {
2105 var foo = [];
2106 for (var i1 = 0; i1 < arguments.length - 2; i1 += 1) {
2107 foo[i1] = arguments[i1 + 2];
2109 return doSomething(b, foo, newValue);
2111 __setf_foo(5, x, 1, 2, 3, 4);")
2113 (test-ps-js return-null
2114 (defun foo () (return-from foo nil))
2115 "function foo() {
2116 return null;
2117 };")
2119 (test-ps-js implicit-return-null
2120 (lambda ()
2122 "function () {
2123 return null;
2124 };")
2126 (test-ps-js implicit-return-null
2127 (lambda ()
2128 nil)
2129 "function () {
2130 return null;
2131 };")
2133 (test-ps-js return-conditional-nested
2134 (defun blep (ss x y)
2135 (when foo?
2136 (let ((pair (bar)))
2137 (unless (null pair)
2138 (destructuring-bind (a b) pair
2139 (unless (or (null a) (null b))
2140 (let ((val (baz a b)))
2141 (unless (null val)
2142 (when (blah val)
2143 (unless (blee)
2144 t))))))))))
2145 "function blep(ss, x, y) {
2146 if (foowhat) {
2147 var pair = bar();
2148 if (pair != null) {
2149 var a = pair[0];
2150 var b = pair[1];
2151 if (!(a == null || b == null)) {
2152 var val = baz(a, b);
2153 if (val != null) {
2154 if (blah(val)) {
2155 return !blee() ? true : null;
2161 };")
2163 ;; this test needs to be rewritten when named blocks are implemented!!!!
2164 (test-ps-js return-when-returns-broken-return
2165 (defun foo ()
2166 (return-from foo (when x 1))
2167 (+ 2 3))
2168 "function foo() {
2169 return x ? 1 : null;
2170 return 2 + 3;
2171 };")
2173 (test-ps-js return-case-conditional
2174 (defun foo ()
2175 (return-from foo
2176 (case foo
2177 (123 (when (bar) t))
2178 (345 (blah)))))
2179 "function foo() {
2180 switch (foo) {
2181 case 123:
2182 return bar() ? true : null;
2183 break;
2184 case 345:
2185 return blah();
2187 };")
2189 (test-ps-js return-try-conditional
2190 (defun foo ()
2191 (return-from foo
2192 (try (when x 1)
2193 (:catch (x) 2)
2194 (:finally (bar)))))
2195 "function foo() {
2196 try {
2197 return x ? 1 : null;
2198 } catch (x) {
2199 return 2;
2200 } finally {
2201 bar();
2203 };")
2205 (test-ps-js function-declare-special
2206 (lambda ()
2207 (declare (special *foo*))
2208 (let ((*foo* 1))
2209 (1+ *foo*)))
2210 "function () {
2211 var FOO_TMPSTACK1;
2212 try {
2213 FOO_TMPSTACK1 = FOO;
2214 FOO = 1;
2215 return FOO + 1;
2216 } finally {
2217 FOO = FOO_TMPSTACK1;
2219 };")
2221 (test-ps-js declare-special-let
2222 (let ((*foo* 123))
2223 (declare (special *foo*))
2224 (blah))
2225 "var FOO_TMPSTACK1;
2226 try {
2227 FOO_TMPSTACK1 = FOO;
2228 FOO = 123;
2229 blah();
2230 } finally {
2231 FOO = FOO_TMPSTACK1;
2232 };")
2234 (test-ps-js macro-null-toplevel
2235 (progn
2236 (defmacro macro-null-toplevel ()
2237 nil)
2238 (macro-null-toplevel))
2241 (test-ps-js define-symbol-macro-let
2242 (progn
2243 (define-symbol-macro test-symbol-macro 1)
2244 (let ((test-symbol-macro 2))
2245 (1+ test-symbol-macro))
2246 (1+ test-symbol-macro))
2247 "var testSymbolMacro1 = 2;
2248 testSymbolMacro1 + 1;
2249 1 + 1;")
2251 (test-ps-js define-symbol-macro-flet
2252 (progn
2253 (define-symbol-macro test-symbol-macro1 1)
2254 (flet ((test-symbol-macro1 () 2))
2255 (foo test-symbol-macro1)
2256 (test-symbol-macro1))
2257 (bar test-symbol-macro1))
2258 "var testSymbolMacro1_1 = function () {
2259 return 2;
2261 foo(1);
2262 testSymbolMacro1_1();
2263 bar(1);")
2265 (test compile-stream-nulls
2266 (is (string=
2268 (with-input-from-string (s "
2269 (defmacro macro-null-toplevel ()
2270 nil)
2271 (macro-null-toplevel)")
2272 (ps-compile-stream s)))))
2274 (test compile-stream1
2275 (is (string=
2276 "var testSymbolMacro1_1 = function () {
2277 return 2;
2279 foo(1);
2280 testSymbolMacro1_1();
2281 bar(1);
2283 (with-input-from-string (s "
2284 (define-symbol-macro test-symbol-macro1 1)
2285 (flet ((test-symbol-macro1 () 2))
2286 (foo test-symbol-macro1)
2287 (test-symbol-macro1))
2288 (bar test-symbol-macro1)")
2289 (ps::with-blank-compilation-environment (ps-compile-stream s))))))
2291 (test-ps-js equality-nary1
2292 (let ((x 10) (y 10) (z 10))
2293 (= x y z))
2294 "var x = 10;
2295 var y = 10;
2296 var z = 10;
2297 var _cmp1 = y;
2298 x === _cmp1 && _cmp1 === z;")
2300 (test-ps-js equality1
2301 (progn
2302 (equal a b)
2303 (eql a b)
2304 (eq a b)
2305 (= a b))
2306 "a == b;
2307 a === b;
2308 a === b;
2309 a === b;")
2311 (test-ps-js getprop-quote-reserved
2312 (getprop foo ':break)
2313 "foo['break'];")
2315 (test-ps-js defun-block-return-from
2316 (defun foo (x)
2317 (baz 4)
2318 (return-from foo x)
2319 (bar 5))
2320 "function foo(x) {
2321 baz(4);
2322 return x;
2323 return bar(5);
2324 }; ")
2326 (test-ps-js block-return-from
2327 (block scope
2328 (foo)
2329 (when (bar)
2330 (return-from scope))
2331 (blee))
2332 "scope: {
2333 foo();
2334 if (bar()) {
2335 break scope;
2337 blee();
2338 };")
2340 (test-ps-js let-funcall
2341 (let ((x foo))
2342 (funcall x)
2343 (let ((x bar))
2344 (funcall x))
2345 (funcall x))
2346 "var x = foo;
2347 x();
2348 var x1 = bar;
2349 x1();
2350 x();")
2352 (test-ps-js symbol-macrolet-funcall
2353 (symbol-macrolet ((foo bar))
2354 (funcall foo 1 2 3))
2355 "bar(1, 2, 3);")
2357 (test-ps-js times-assign
2358 (setf x (* x 1000))
2359 "x *= 1000;")
2361 (test-ps-js vector-literal
2362 #(1 2 3)
2363 "[1, 2, 3];")
2365 (test-ps-js rem1
2366 (+ 1 (rem 2 (+ 3 4)))
2367 "1 + 2 % (3 + 4);")
2369 (test-ps-js non-associative
2370 (+ (/ 1 (/ 2 3)) (- 1 (- 2 3)))
2371 "1 / (2 / 3) + 1 - (2 - 3);")
2373 (test-ps-js lambda-apply
2374 (lambda (x)
2375 (apply (lambda (y) (bar (1+ y))) x))
2376 "function (x) {
2377 return (function (y) {
2378 return bar(y + 1);
2379 }).apply(this, x);
2380 };")
2382 (test-ps-js operator-expressions-nested-let
2383 (let ((x (let ((y 1))
2384 y)))
2386 "var x = (y = 1, y); x;")
2388 (test-ps-js operator-expressions-array-nested-let
2389 (list (let ((y 1)) y) 2)
2390 "[(y = 1, y), 2];")
2392 (test-ps-js add-subtract-precedence
2393 (- x (+ y z))
2394 "x - (y + z);")
2396 (test-ps-js ps-inline-toplevel
2397 (ps-inline (foo))
2398 "'javascript:' + 'foo()';")
2400 (test-ps-js no-clause-progn-exp
2401 (setf x (progn))
2402 "x = null;")
2404 (test-ps-js no-clause-progn-return
2405 (defun foo ()
2406 (return-from foo (progn)))
2407 "function foo() {
2408 return null;
2409 };")
2411 (test-ps-js empty-cond-clause
2412 (setf x (cond ((foo))))
2413 "x = foo() ? null : null;")
2415 (test-ps-js empty-cond-clause1
2416 (setf x (cond ((foo) 123)
2417 ((bar))
2418 (t 456)))
2419 "x = foo() ? 123 : (bar() ? null : 456);")
2421 (test-ps-js let-no-body
2422 (defun foo ()
2423 (return-from foo (let ((foo bar)))))
2424 "function foo() {
2425 var foo1 = bar;
2426 return null;
2427 };")
2429 (test-ps-js dont-hoist-lexical-dupes
2430 (lambda ()
2431 (list (let ((foo 12)) (* foo 2))
2432 (let ((foo 13)) (* foo 3))))
2433 "function () {
2434 var foo;
2435 return [(foo = 12, foo * 2), (foo = 13, foo * 3)];
2436 };")
2438 (test-ps-js defun-comment1
2439 (defun foo (x)
2440 "BARBAR is a revolutionary new foobar.
2441 X y and x."
2442 (1+ x))
2443 "/**
2444 * BARBAR is a revolutionary new foobar.
2445 * X y and x.
2447 function foo(x) {
2448 return x + 1;
2449 };")
2451 (test-ps-js var-comment
2452 (var x 1 "foo")
2453 "/** foo */
2454 var x = 1;")
2456 (test-ps-js case-return-break-broken-return
2457 (defun foo ()
2458 (case x
2459 ("bar" (if y (return-from foo t) nil))
2460 ("baz" nil)))
2461 "function foo() {
2462 switch (x) {
2463 case 'bar':
2464 if (y) {
2465 return true;
2467 break;
2468 case 'baz':
2469 return null;
2471 };")
2473 (test-ps-js case-return-break1-broken-return
2474 (defun foo ()
2475 (case x
2476 ("bar" (if y (return-from foo t)))
2477 ("baz" nil)))
2478 "function foo() {
2479 switch (x) {
2480 case 'bar':
2481 if (y) {
2482 return true;
2484 break;
2485 case 'baz':
2486 return null;
2488 };")
2490 (test-ps-js setf-progn
2491 (setf foo (progn (bar) (baz) 3))
2492 "bar();
2493 baz();
2494 foo = 3;")
2496 ;; (test-ps-js var-progn
2497 ;; (var x (progn (foo) (bar)))
2498 ;; "foo();
2499 ;; var x = bar();")
2501 (test-ps-js implicit-return-loop
2502 (lambda ()
2503 (if baz 7
2504 (progn
2505 (loop :repeat 100 :do (bar))
2506 42)))
2507 "function () {
2508 if (baz) {
2509 return 7;
2510 } else {
2511 for (var _js2 = 0; _js2 < 100; _js2 += 1) {
2512 bar();
2514 return 42;
2516 };")
2518 ;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
2519 (test-ps-js loop-closures
2520 (dotimes (i 10) (lambda () (+ i 1)))
2521 "for (var i = 0; i < 10; i += 1) {
2522 with ({ i : i }) {
2523 function () {
2524 return i + 1;
2527 };")
2529 (test-ps-js loop-closures-let
2530 (dotimes (i 10) (let ((x (+ i 1))) (lambda () (+ i x))))
2531 "for (var i = 0; i < 10; i += 1) {
2532 with ({ x : null, i : i }) {
2533 var x = i + 1;
2534 function () {
2535 return i + x;
2538 };")
2540 (test-ps-js loop-closures-flet
2541 (dotimes (i 10) (flet ((foo (x) (+ i x))) (lambda () (foo i))))
2542 "for (var i = 0; i < 10; i += 1) {
2543 with ({ foo : null, i : i }) {
2544 var foo = function (x) {
2545 return i + x;
2547 function () {
2548 return foo(i);
2551 };")
2553 (test-ps-js while-closures-let
2554 (while (foo)
2555 (let ((x (bar)))
2556 (lambda () (+ 1 x))))
2557 "while (foo()) {
2558 with ({ x : null }) {
2559 var x = bar();
2560 function () {
2561 return 1 + x;
2564 };")
2566 (test-ps-js dotted-list-form
2567 (defun foo (a)
2568 (when a
2569 (destructuring-bind (b . c)
2571 (list b c))))
2572 "function foo(a) {
2573 if (a) {
2574 var b = bar[0];
2575 var c = bar.length > 1 ? bar.slice(1) : [];
2576 return [b, c];
2578 };")
2580 (test-ps-js return-from-loop
2581 (dolist (x '(2 1 3))
2582 (when (= x 1)
2583 (return))
2584 (chain console (log x)))
2585 "for (var x = null, _js_arrvar2 = [2, 1, 3], _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
2586 x = _js_arrvar2[_js_idx1];
2587 if (x === 1) {
2588 break;
2590 console.log(x);
2591 };")
2593 (test-ps-js explicit-nil-block
2594 (block nil (return) (+ 1 2))
2595 "nilBlock: {
2596 break nilBlock;
2597 1 + 2;
2598 };")
2600 (test-ps-js dynamic-extent-function-return
2601 (defun foo () ((lambda () (return-from foo))))
2602 "function foo() {
2603 try {
2604 return (function () {
2605 throw { 'ps-block-tag' : 'foo', 'ps-return-value' : null };
2606 })();
2607 } catch (err) {
2608 if (err && 'foo' === err['ps-block-tag']) {
2609 err['ps-return-value'];
2610 } else {
2611 throw err;
2614 };")
2616 (test-ps-js block-dynamic-return
2617 (block nil ((lambda () (return))) (+ 1 2))
2618 "nilBlock: {
2619 try {
2620 (function () {
2621 throw { 'ps-block-tag' : 'nilBlock', 'ps-return-value' : null };
2622 })();
2623 1 + 2;
2624 } catch (err) {
2625 if (err && 'nilBlock' === err['ps-block-tag']) {
2626 err['ps-return-value'];
2627 } else {
2628 throw err;
2631 };")
2633 (test-ps-js iteration-lambda-capture-no-need
2634 (dolist (x y) (lambda (x) (1+ x))) ;; there's really no need to create a 'with' scope in this case
2635 "for (var x = null, _js_idx1 = 0; _js_idx1 < y.length; _js_idx1 += 1) {
2636 with ({ x : x }) {
2637 x = y[_js_idx1];
2638 function (x) {
2639 return x + 1;
2642 };")
2644 (test-ps-js case-invert1
2645 (encodeURIComponent fooBar)
2646 "encodeURIComponent(fooBar);")
2648 (test-ps-js simple-ash
2649 (+ (ash 4 1) (ash 4 -1))
2650 "(4 << 1) + (4 >> 1);")
2652 (test-ps-js progn-nil-expression
2653 (bar (progn (foo) nil))
2654 "bar((foo(), null));")
2656 (test-ps-js other-progn-nil-exp
2657 (defun blah ()
2658 (or (foo) (progn (bar) nil)))
2659 "function blah() {
2660 return foo() || (bar(), null);
2661 };")
2663 (test-ps-js lambda-nil-return
2664 (lambda (x)
2665 (block nil
2666 (when x
2667 (return 1))
2669 "function (x) {
2670 if (x) {
2671 return 1;
2673 return 2;
2674 };")
2676 (test-ps-js lambda-nil-return-implicit-nested
2677 (lambda (x)
2678 (block nil
2679 (if x
2680 (return 1)
2681 (dotimes (i 4)
2682 (return 1)))
2684 "function (x) {
2685 if (x) {
2686 return 1;
2687 } else {
2688 for (var i = 0; i < 4; i += 1) {
2689 break;
2692 return 2;
2693 };")
2695 (test-ps-js throw-is-a-statement
2696 (defun blah ()
2697 (let ((result (foo)))
2698 (unless (null result)
2699 (throw result))))
2700 "function blah() {
2701 var result = foo();
2702 if (result != null) {
2703 throw result;
2705 };")
2707 (test-ps-js expressify1
2708 (defun blah ()
2709 (when (some-condition)
2710 (foo)
2711 (bar)
2712 (baz)))
2713 "function blah() {
2714 if (someCondition()) {
2715 foo();
2716 bar();
2717 return baz();
2719 };")
2721 (test-ps-js case-when-return
2722 (defun blah (a)
2723 (case a
2724 ("a" (when (foo) (return-from blah 111)))
2725 ("b" t)))
2726 "function blah(a) {
2727 switch (a) {
2728 case 'a':
2729 if (foo()) {
2730 return 111;
2732 break;
2733 case 'b':
2734 return true;
2736 };")
2738 (test-ps-js flet-return-from
2739 (defun abc ()
2740 (flet ((foo ()
2741 (return-from foo 123)))
2742 (foo)))
2743 "function abc() {
2744 var foo = function () {
2745 return 123;
2747 return foo();
2748 };")
2750 (test-ps-js flet-return-from1
2751 (flet ((foo ()
2752 (return-from foo 123)))
2753 (foo))
2754 "var foo = function () {
2755 return 123;
2757 foo();")
2759 (test-ps-js lambda-docstring-declarations
2760 (lambda (x)
2761 "This is a docstring"
2762 (declare (ignore x))
2764 "function (x) {
2765 return 2;
2766 };")
2768 (test-ps-js setf-let-exp
2769 (setf foo (let ((x (+ 1 2)))
2770 (if x 123 456)))
2771 "foo = (x = 1 + 2, x ? 123 : 456);")
2773 (test-ps-js create-let-exp
2774 (create :abc (let ((x (+ 1 2)))
2775 (if x 123 456)))
2776 "{ 'abc' : (x = 1 + 2, x ? 123 : 456) };")
2778 (test-ps-js eql-eql-eql-precedence
2779 (unless (equal (= 3 3) (= 3 4))
2780 (chain console (log 1)))
2781 "if ((3 === 3) != (3 === 4)) {
2782 console.log(1);
2783 };")
2785 (test-ps-js case-cond-breaks
2786 (defun blah (x)
2787 (case x
2788 (123 (cond ((foo1) (when (foo2)
2789 (when (foo3)
2790 (return-from blah nil))
2791 t))))
2792 (456 (foo7))))
2793 "function blah(x) {
2794 switch (x) {
2795 case 123:
2796 if (foo1()) {
2797 if (foo2()) {
2798 if (foo3()) {
2799 return null;
2801 return true;
2804 break;
2805 case 456:
2806 return foo7();
2808 };")