+ "this[x];")
+
+(test-ps-js setf-dec1
+ (setf x (- 1 x 2))
+ "x = 1 - x - 2;")
+
+(test-ps-js setf-dec2
+ (setf x (- x 1 2))
+ "x = x - 1 - 2;")
+
+(test-ps-js special-char-equals
+ blah=
+ "blahequals;")
+
+(test-ps-js setf-operator-priority
+ (return (or (slot-value cache id)
+ (setf (slot-value cache id) ((@ document get-element-by-id) id))))
+ "return cache[id] || (cache[id] = document.getElementById(id));")
+
+(test-ps-js aref-operator-priority
+ (aref (if (and x (> (length x) 0))
+ (aref x 0)
+ y)
+ z)
+ "(x && x.length > 0 ? x[0] : y)[z];")
+
+(test-ps-js aref-operator-priority1
+ (aref (or (slot-value x 'y)
+ (slot-value a 'b))
+ z)
+ "(x.y || a.b)[z];")
+
+(test-ps-js aref-operator-priority2
+ (aref (if a b c) 0)
+ "(a ? b : c)[0];")
+
+(test-ps-js negative-operator-priority
+ (- (if x y z))
+ "-(x ? y : z);")
+
+(test-ps-js op-p1
+ (new (or a b))
+ "new (a || b);")
+
+(test-ps-js op-p2
+ (delete (if a (or b c) d))
+ "delete (a ? b || c : d);")
+
+(test-ps-js op-p3
+ (not (if (or x (not y)) z))
+ "!(x || !y ? z : null);")
+
+(test-ps-js op-p4
+ (- (- (* 1 2) 3))
+ "-(1 * 2 - 3);")
+
+(test-ps-js op-p5
+ (instanceof (or a b) (if x y z))
+ "((a || b) instanceof (x ? y : z));")
+
+(test-ps-js op-p7
+ (or x (if (= x 0) "zero" "empty"))
+ "x || (x == 0 ? 'zero' : 'empty');")
+
+(test-ps-js named-op-expression
+ (throw (if a b c))
+ "throw a ? b : c;")
+
+(test-ps-js named-op-expression1
+ (typeof (or x y))
+ "typeof (x || y);")
+
+(test-ps-js aref-array-expression
+ (aref (or a b c) 0)
+ "(a || b || c)[0];")
+
+(test-ps-js slot-value-operator
+ (slot-value (or a b c) 'd)
+ "(a || b || c).d;")
+
+(test-ps-js slot-value-parens
+ (slot-value (slot-value foo 'bar) 'baz)
+ "foo.bar.baz;")
+
+(test-ps-js funcall-funcall
+ ((foo))
+ "foo()();")
+
+(test-ps-js expression-funcall
+ ((or (@ window eval) eval) foo nil)
+ "(window.eval || eval)(foo, null);")
+
+(test-ps-js expression-funcall1
+ (((or (@ window eval) eval) foo nil))
+ "(window.eval || eval)(foo, null)();")
+
+(test-ps-js expression-funcall2
+ (((or (@ window eval) eval)) foo nil)
+ "(window.eval || eval)()(foo, null);")
+
+(test-ps-js slot-value-object-literal
+ (slot-value (create :a 1) 'a)
+ "({ a : 1 }).a;")
+
+(test-ps-js slot-value-lambda
+ (slot-value (lambda ()) 'prototype)
+ "(function () { }).prototype;")
+
+(test-ps-js who-html1
+ (who-ps-html (:span :class "ticker-symbol"
+ :ticker-symbol symbol
+ (:a :href "http://foo.com"
+ symbol)
+ (:span :class "ticker-symbol-popup")))
+ "'<SPAN CLASS=\"ticker-symbol\" TICKER-SYMBOL=\"' + symbol + '\"><A HREF=\"http://foo.com\">' + symbol + '</A><SPAN CLASS=\"ticker-symbol-popup\"></SPAN></SPAN>';")
+
+(test-ps-js flet1
+ ((lambda () (flet ((foo (x)
+ (return (1+ x))))
+ (return (foo 1)))))
+ "(function () {
+ var foo1 = function (x) {
+ return x + 1;
+ };
+ return foo1(1);
+})();")
+
+(test-ps-js flet2
+ (flet ((foo (x) (return (1+ x)))
+ (bar (y) (return (+ 2 y))))
+ (bar (foo 1)))
+"var foo1 = function (x) {
+ return x + 1;
+};
+var bar2 = function (y) {
+ return 2 + y;
+};
+bar2(foo1(1));")
+
+(test-ps-js flet3
+ (flet ((foo (x) (return (1+ x)))
+ (bar (y) (return (+ 2 (foo y)))))
+ (bar (foo 1)))
+ "var foo1 = function (x) {
+ return x + 1;
+};
+var bar2 = function (y) {
+ return 2 + foo(y);
+};
+bar2(foo1(1));")
+
+(test-ps-js labels1
+ ((lambda () (labels ((foo (x)
+ (return (if (=== 0 x)
+ 0
+ (+ x (foo (1- x)))))))
+ (return (foo 3)))))
+ "(function () {
+ var foo1 = function (x) {
+ return 0 === x ? 0 : x + foo1(x - 1);
+ };
+ return foo1(3);
+})();")
+
+(test-ps-js labels2
+ (labels ((foo (x) (return (1+ (bar x))))
+ (bar (y) (return (+ 2 (foo y)))))
+ (bar (foo 1)))
+ "var foo1 = function (x) {
+ return bar2(x) + 1;
+};
+var bar2 = function (y) {
+ return 2 + foo1(y);
+};
+bar2(foo1(1));")
+
+(test-ps-js labels3
+ (labels ((foo (x) (return (1+ x)))
+ (bar (y) (return (+ 2 (foo y)))))
+ (bar (foo 1)))
+ "var foo1 = function (x) {
+ return x + 1;
+};
+var bar2 = function (y) {
+ return 2 + foo1(y);
+};
+bar2(foo1(1));")
+
+(test-ps-js for-loop-var-init-exp
+ ((lambda (x)
+ (return (do* ((y (if x 0 1) (1+ y))
+ (z 0 (1+ z)))
+ ((= y 3) z))))
+ true)
+ "(function (x) {
+ return (function () {
+ for (var y = x ? 0 : 1, z = 0; y != 3; y += 1, z += 1) {
+ };
+ return z;
+ })();
+})(true);")
+
+(test-ps-js math-pi
+ pi
+ "Math.PI;")
+
+(test-ps-js literal-array
+ '(1 2 3)
+ "[1, 2, 3];")
+
+(test-ps-js literal-array-1
+ '(1 foo 3)
+ "[1, 'foo', 3];")
+
+(test ps-lisp-expands-in-lexical-environment
+ (is (string= "5;" (let ((x 5)) (ps (lisp x))))))
+
+(test ps*-lisp-expands-in-null-lexical-environment
+ (signals error (let ((x 5)) (declare (ignore x)) (ps* '(lisp x)))))
+
+(test ps*-lisp-expands-in-dynamic-environment
+ (is (string= "1 + 2;" (let ((*print-level* 2)) (ps* '(+ 1 (lisp *print-level*)))))))
+
+(test ps-lisp-dynamic-environment
+ (is (string= "1 + 2;" (let ((*print-level* 2)) (ps (+ 1 (lisp *print-level*)))))))
+
+(test-ps-js ps-js-target-version-keyword-test1
+ (defun foo (x y &key bar baz))
+ "function foo(x, y) {
+ var x1 = Array.prototype.indexOf.call(arguments, 'bar', 2);
+ var bar = -1 == x1 ? null : arguments[x1 + 1];
+ var x2 = Array.prototype.indexOf.call(arguments, 'baz', 2);
+ var baz = -1 == x2 ? null : arguments[x2 + 1];
+};"
+ :js-target-version 1.6)
+
+(test-ps-js nested-if-expressions1
+ (return (if (if x y z) a b))
+ "return (x ? y : z) ? a : b;")
+
+(test-ps-js nested-if-expressions2
+ (return (if x y (if z a b)))
+ "return x ? y : (z ? a : b);")
+
+(test-ps-js let1
+ (let (x)
+ (+ x x))
+ "var x = null;
+x + x;")
+
+(test-ps-js let2
+ (let ((x 1))
+ (+ x x))
+ "var x = 1;
+x + x;")
+
+(test-ps-js let-x-x
+ (let ((x (1+ x)))
+ (+ x x))
+ "var x1 = x + 1;
+x1 + x1;")
+
+(test-ps-js let3
+ (let ((x 1)
+ (y 2))
+ (+ x x))
+ "var x = 1;
+var y = 2;
+x + x;")
+
+(test-ps-js let4
+ (let ((x 1)
+ (y (1+ x)))
+ (+ x y))
+ "var x1 = 1;
+var y = x + 1;
+x1 + y;")
+
+(test-ps-js let5
+ (let ((x 1))
+ (+ x 1)
+ (let ((x (+ x 5)))
+ (+ x 1))
+ (+ x 1))
+ "var x = 1;
+x + 1;
+var x1 = x + 5;
+x1 + 1;
+x + 1;")
+
+(test-ps-js let6
+ (let ((x 2))
+ (let ((x 1)
+ (y (1+ x)))
+ (+ x y)))
+ "var x = 2;
+var x1 = 1;
+var y = x + 1;
+x1 + y;")
+
+(test-ps-js let-exp1
+ (lambda ()
+ (return (let (x) (+ x x))))
+ "function () {
+ var x;
+ return (x = null, x + x);
+};")
+
+(test-ps-js let*1
+ (let* ((x 1)) (+ x x))
+"var x = 1;
+x + x;")
+
+(test-ps-js let*2
+ (let* ((x 1)
+ (y (+ x 2)))
+ (+ x y))
+ "var x = 1;
+var y = x + 2;
+x + y;")
+
+(test-ps-js let*3
+ (let ((x 3))
+ (let* ((x 1)
+ (y (+ x 2)))
+ (+ x y)))
+ "var x = 3;
+var x1 = 1;
+var y = x1 + 2;
+x1 + y;")
+
+(test-ps-js let*4
+ (let ((x 3))
+ (let* ((y (+ x 2))
+ (x 1))
+ (+ x y)))
+ "var x = 3;
+var y = x + 2;
+var x1 = 1;
+x1 + y;")
+
+(test-ps-js symbol-macrolet-var
+ (symbol-macrolet ((x y))
+ (var x))
+ "var y;")
+
+(test-ps-js setf-conditional1
+ (setf x (unless (null a) (1+ a)))
+ "x = a != null ? a + 1 : null;")
+
+(test-ps-js setf-let1
+ (setf x (let ((a 1)) a))
+ "x = (a = 1, a);")
+
+(test-ps-js setf-let2
+ (setf x (let ((a (foo)))
+ (unless (null a)
+ (1+ a))))
+ "x = (a = foo(), a != null ? a + 1 : null);")
+
+(test-ps-js symbol-macro-env1
+ (symbol-macrolet ((bar 1))
+ (macrolet ((bar (x y) `(+ ,x ,y)))
+ (bar bar bar)))
+ "1 + 1;")
+
+(test-ps-js symbol-macrolet-fun1
+ (symbol-macrolet ((baz +))
+ (baz 1 2))
+ "baz(1, 2);")
+
+(test-ps-js lisp2-namespaces1
+ (let ((list nil))
+ (setf list (list 1 2 3)))
+ "var list = null;
+list = [1, 2, 3];")
+
+(test-ps-js let-shadows-symbol-macrolet
+ (symbol-macrolet ((x y))
+ (let ((x 1))
+ (+ x x))
+ (+ x x))
+ "var x1 = 1;
+x1 + x1;
+y + y;")
+
+(test-ps-js let-rename-optimization1
+ (let ((x 1))
+ (+ x x))
+ "var x = 1;
+x + x;")
+
+(test-ps-js let-rename-optimization2
+ (lambda (x)
+ (let ((x (+ 1 x)))
+ (return x)))
+ "function (x) {
+ var x1 = 1 + x;
+ return x1;
+};")
+
+(test-ps-js symbol-macro-array
+ (symbol-macrolet ((x 1))
+ (list x))
+ "[1];")
+
+(test-ps-js symbol-macro-obj
+ (symbol-macrolet ((x y))
+ (create x 1))
+ "{ y : 1 };")
+
+(test-ps-js symbol-macro-conditional1
+ (symbol-macrolet ((x y))
+ (if x x x))
+ "if (y) {
+ y;
+} else {
+ y;
+};")
+
+(test-ps-js symbol-macro-conditional2
+ (symbol-macrolet ((x y))
+ (return (if x x x)))
+ "return y ? y : y;")
+
+(test-ps-js flet-apply
+ (flet ((foo () 'bar))
+ (apply (function foo) nil))
+ "var foo1 = function () {
+ 'bar';
+};
+foo1.apply(this, null);")
+
+(test-ps-js let-apply
+ (let ((foo (lambda () (return 1))))
+ (let ((foo (lambda () (return 2))))
+ (apply foo nil)))
+ "var foo = function () {
+ return 1;
+};
+var foo1 = function () {
+ return 2;
+};
+foo1.apply(this, null);")
+
+(test-ps-js flet-let
+ (flet ((x (x) (return (1+ x))))
+ (let ((x 2))
+ (x x)))
+ "var x1 = function (x) {
+ return x + 1;
+};
+var x = 2;
+x1(x);")
+
+(test-ps-js let-flet
+ (let ((x 2))
+ (flet ((x (x) (return (1+ x))))
+ (x x)))
+ "var x = 2;
+var x1 = function (x) {
+ return x + 1;
+};
+x1(x);")
+
+(test-ps-js macrolet-let-inteference
+ (macrolet ((a (n) `(+ ,n 5)))
+ (let ((a (a 1)))
+ (let ((b (a (- a 4))))
+ (+ a b))))
+ "var a = 1 + 5;
+var b = (a - 4) + 5;
+a + b;")
+
+(test-ps-js let-subtract-add
+ (let ((x 1))
+ (let ((x 2))
+ (- x x)
+ (- x)
+ (decf x)
+ (incf x)))
+ "var x = 1;
+var x1 = 2;
+x1 - x1;
+-x1;
+--x1;
+++x1;")
+
+(test-ps-js create-reserved-word
+ (create :default 1)
+ "{ 'default' : 1 };")
+
+(test-ps-js slot-value-reserved-word
+ (slot-value foo :default)
+ "foo['default'];")
+
+(test-ps-js eval-when-ps-side
+ (eval-when (:execute)
+ 5)
+ "5;")
+
+(defvar *lisp-output* nil)
+
+(test eval-when-lisp-side ()
+ (setf *lisp-output* 'original-value)
+ (let ((js-output (normalize-js-code
+ (ps-doc* `(eval-when (:compile-toplevel)
+ (setf *lisp-output* 'it-works))))))
+ (is (eql 'it-works *lisp-output*))
+ (is (string= "" js-output))))
+
+(defpsmacro my-in-package (package-name)
+ `(eval-when (:compile-toplevel)
+ (setf *lisp-output* ,package-name)))
+
+(test eval-when-macro-expansion ()
+ (setf *lisp-output* 'original-value)
+ (let ((js-output (normalize-js-code
+ (ps-doc* `(progn
+ (my-in-package :cl-user)
+ 3)))))
+ (declare (ignore js-output))
+ (is (eql :cl-user *lisp-output*))))
+
+(test eval-when-macrolet-expansion ()
+ (setf *lisp-output* 'original-value)
+ (let ((js-output (normalize-js-code
+ (ps-doc* `(macrolet ((my-in-package2 (package-name)
+ `(eval-when (:compile-toplevel)
+ (setf *lisp-output* ,package-name))))
+ (my-in-package2 :cl-user)
+ 3)))))
+ (declare (ignore js-output))
+ (is (eql :cl-user *lisp-output*))))