let/let* no longer gensym variable names when they are not bound in
authorVladimir Sedach <vsedach@gmail.com>
Fri, 15 May 2009 00:38:10 +0000 (18:38 -0600)
committerVladimir Sedach <vsedach@gmail.com>
Fri, 15 May 2009 00:38:10 +0000 (18:38 -0600)
enclosing lexical scopes, resulting in prettier output ("var x = 1",
instead of "var x1 = 1") in typical usage of let.

docs/reference.lisp
src/special-forms.lisp
src/utils.lisp
t/package-system-tests.lisp
t/ps-tests.lisp
t/reference-tests.lisp

index bc60bd7..ee01716 100644 (file)
@@ -505,12 +505,12 @@ a-variable  => aVariable;
 
 (let ((a 1) (b 2))
   (psetf a b b a))
-=> var a1 = 1;
-   var b2 = 2;
-   var _js3_5 = b2;
-   var _js4_6 = a1;
-   a1 = _js3_5;
-   b2 = _js4_6;
+=> var a = 1;
+   var b = 2;
+   var _js1 = b;
+   var _js2 = a;
+   a = _js1;
+   b = _js2;
 
 ;;; The `SETQ' and `PSETQ' forms operate identically to `SETF' and
 ;;; `PSETF', but throw a compile-time error if the left-hand side form
@@ -538,9 +538,9 @@ a-variable  => aVariable;
    };
 
 (setf (color some-div) (+ 23 "em"))
-=> var _js2_3 = someDiv;
-   var _js1_4 = 23 + 'em';
-   __setf_color(_js1_4, _js2_3);
+=> var _js2 = someDiv;
+   var _js1 = 23 + 'em';
+   __setf_color(_js1, _js2);
 
 ;;; Note that temporary variables are generated to preserve evaluation
 ;;; order of the arguments as they would be in Lisp.
@@ -553,9 +553,9 @@ a-variable  => aVariable;
 => null;
 
 (setf (left some-div) (+ 123 "px"))
-=> var _js2_3 = someDiv;
-   var _js1_4 = 123 + 'px';
-   _js2_3.style.left = _js1_4;
+=> var _js2 = someDiv;
+   var _js1 = 123 + 'px';
+   _js2.style.left = _js1;
 
 (macrolet ((left (el)
              `(slot-value ,el 'offset-left)))
@@ -722,16 +722,16 @@ a-variable  => aVariable;
            (x (+ x y)))
       (+ *a* x y))))
 => var A = 4;
-   var x1 = 1;
-   var A2;
+   var x = 1;
+   var A_TMPSTACK1;
    try {
-       A2 = A;
+       A_TMPSTACK1 = A;
        A = 2;
-       var y3 = x1 + 1;
-       var x4 = x1 + y3;
-       A + x4 + y3;
+       var y = x + 1;
+       var x2 = x + y;
+       A + x2 + y;
    } finally {
-       A = A2;
+       A = A_TMPSTACK1;
    };
 
 ;;;# Iteration constructs
@@ -790,14 +790,14 @@ a-variable  => aVariable;
      (s 0 (+ s i (1+ i))))
     ((> i 10))
   ((@ document write) (+ "i: " i " s: " s "<br/>")))
-=> var i1 = 0;
-   var s2 = 0;
-   for (; i1 <= 10; ) {
-       document.write('i: ' + i1 + ' s: ' + s2 + '<br/>');
-       var _js3_5 = i1 + 1;
-       var _js4_6 = s2 + i1 + (i1 + 1);
-       i1 = _js3_5;
-       s2 = _js4_6;
+=> var i = 0;
+   var s = 0;
+   for (; i <= 10; ) {
+       document.write('i: ' + i + ' s: ' + s + '<br/>');
+       var _js1 = i + 1;
+       var _js2 = s + i + (i + 1);
+       i = _js1;
+       s = _js2;
    };
 
 ;;; compare to `DO*':
@@ -815,9 +815,9 @@ a-variable  => aVariable;
 (let ((arr (array "a" "b" "c" "d" "e")))
   (dotimes (i (@ arr length))
     ((@ document write) (+ "i: " i " arr[i]: " (aref arr i) "<br/>"))))
-=> var arr1 = ['a', 'b', 'c', 'd', 'e'];
-   for (var i = 0; i < arr1.length; i += 1) {
-       document.write('i: ' + i + ' arr[i]: ' + arr1[i] + '<br/>');
+=> var arr = ['a', 'b', 'c', 'd', 'e'];
+   for (var i = 0; i < arr.length; i += 1) {
+       document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
    };
 
 ;;; `DOTIMES' with return value:
@@ -826,12 +826,12 @@ a-variable  => aVariable;
   (alert (+ "Summation to 10 is "
             (dotimes (i 10 res)
               (incf res (1+ i))))))
-=> var res1 = 0;
+=> var res = 0;
    alert('Summation to 10 is ' + (function () {
        for (var i = 0; i < 10; i += 1) {
-           res1 += i + 1;
+           res += i + 1;
        };
-       return res1;
+       return res;
    })());
 
 ;;; `DOLIST' is like CL:DOLIST, but that it operates on numbered JS
@@ -840,9 +840,9 @@ a-variable  => aVariable;
 (let ((l (list 1 2 4 8 16 32)))
   (dolist (c l)
     ((@ document write) (+ "c: " c "<br/>"))))
-=> var l1 = [1, 2, 4, 8, 16, 32];
-   for (var c = null, _js_arrvar3 = l1, _js_idx2 = 0; _js_idx2 < _js_arrvar3.length; _js_idx2 += 1) {
-       c = _js_arrvar3[_js_idx2];
+=> var l = [1, 2, 4, 8, 16, 32];
+   for (var c = null, _js_arrvar2 = l, _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
+       c = _js_arrvar2[_js_idx1];
        document.write('c: ' + c + '<br/>');
    };
 
@@ -851,14 +851,14 @@ a-variable  => aVariable;
   (alert (+ "Sum of " l " is: "
             (dolist (c l s)
               (incf s c)))))
-=> var l1 = [1, 2, 4, 8, 16, 32];
-   var s2 = 0;
-   alert('Sum of ' + l1 + ' is: ' + (function () {
-       for (var c = null, _js_arrvar4 = l1, _js_idx3 = 0; _js_idx3 < _js_arrvar4.length; _js_idx3 += 1) {
-           c = _js_arrvar4[_js_idx3];
-           s2 += c;
+=> var l = [1, 2, 4, 8, 16, 32];
+   var s = 0;
+   alert('Sum of ' + l + ' is: ' + (function () {
+       for (var c = null, _js_arrvar2 = l, _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
+           c = _js_arrvar2[_js_idx1];
+           s += c;
        };
-       return s2;
+       return s;
    })());
 
 ;;; `FOR-IN' is translated to the JS `for...in' statement.
@@ -866,9 +866,9 @@ a-variable  => aVariable;
 (let ((obj (create :a 1 :b 2 :c 3)))
   (for-in (i obj)
     ((@ document write) (+ i ": " (aref obj i) "<br/>"))))
-=> var obj1 = { a : 1, b : 2, c : 3 };
-   for (var i in obj1) {
-       document.write(i + ': ' + obj1[i] + '<br/>');
+=> var obj = { a : 1, b : 2, c : 3 };
+   for (var i in obj) {
+       document.write(i + ': ' + obj[i] + '<br/>');
    };
 
 ;;; The `WHILE' form is transformed to the JavaScript form `while',
@@ -1017,11 +1017,11 @@ a-variable  => aVariable;
    (setf (@ element inner-h-t-m-l)
          (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
                 "Edit me"))))
-=> var disabled1 = null;
-   var authorized2 = true;
+=> var disabled = null;
+   var authorized = true;
    element.innerHTML =
    '<TEXTAREA'
-   + (disabled1 || !authorized2 ? ' DISABLED=\"' + 'disabled' + '\"' : '')
+   + (disabled || !authorized ? ' DISABLED=\"' + 'disabled' + '\"' : '')
    + '>Edit me</TEXTAREA>';
 
 ;;;# Macrology
index f47082f..6decc8f 100644 (file)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; function definition
+
+(defvar *vars-bound-in-enclosing-lexical-scopes* ())
+
 (defun compile-function-definition (args body)
-  (list (mapcar (lambda (arg) (compile-parenscript-form arg :expecting :symbol)) args)
-        (let* ((*enclosing-lexical-block-declarations* ())
-               (body (compile-parenscript-form `(progn ,@body)))
-               (var-decls (compile-parenscript-form
-                           `(progn ,@(mapcar (lambda (var) `(var ,var)) *enclosing-lexical-block-declarations*)))))
-          `(js:block ,@(cdr var-decls) ,@(cdr body)))))
+  (let ((args (mapcar (lambda (arg) (compile-parenscript-form arg :expecting :symbol)) args)))
+    (list args
+          (let* ((*enclosing-lexical-block-declarations* ())
+                 (*vars-bound-in-enclosing-lexical-scopes* (append args
+                                                                   *vars-bound-in-enclosing-lexical-scopes*))
+                 (body (compile-parenscript-form `(progn ,@body)))
+                 (var-decls (compile-parenscript-form
+                             `(progn ,@(mapcar (lambda (var) `(var ,var)) *enclosing-lexical-block-declarations*)))))
+            `(js:block ,@(cdr var-decls) ,@(cdr body))))))
 
 (define-ps-special-form %js-lambda (args &rest body)
   `(js:lambda ,@(compile-function-definition args body)))
@@ -438,11 +444,15 @@ lambda-list::=
 
 (define-ps-special-form symbol-macrolet (symbol-macros &body body)
   (with-local-macro-environment (local-macro-dict *ps-symbol-macro-env*)
-    (dolist (macro symbol-macros)
-      (destructuring-bind (name expansion)
-          macro
-        (setf (gethash name local-macro-dict) (lambda (x) (declare (ignore x)) expansion))))
-    (compile-parenscript-form `(progn ,@body) :expecting expecting)))
+    (let (local-var-bindings)
+      (dolist (macro symbol-macros)
+        (destructuring-bind (name expansion)
+            macro
+          (setf (gethash name local-macro-dict) (lambda (x) (declare (ignore x)) expansion))
+          (push name local-var-bindings)))
+      (let ((*vars-bound-in-enclosing-lexical-scopes* (append local-var-bindings
+                                                              *vars-bound-in-enclosing-lexical-scopes*)))
+        (compile-parenscript-form `(progn ,@body) :expecting expecting)))))
 
 (define-ps-special-form defmacro (name args &body body) ;; should this be a macro?
   (eval `(defpsmacro ,name ,args ,@body))
@@ -571,30 +581,44 @@ lambda-list::=
   (pushnew name *ps-special-variables*)
   `(var ,name ,@(when value-provided? (list value))))
 
-(defpsmacro let (bindings &body body)
-  (flet ((add-renamed-vars (bindings predicate)
-           (mapcar (lambda (x) (append x (list (ps-gensym (car x)))))
-                   (remove-if predicate bindings :key #'car)))
-         (var (x) (first x))
-         (val (x) (second x))
-         (renamed (x) (third x)))
-    (let* ((normalized-bindings (mapcar (lambda (x) (if (symbolp x) `(,x nil) x)) bindings))
-           (lexical-bindings (add-renamed-vars normalized-bindings #'ps-special-variable-p))
-           (dynamic-bindings (add-renamed-vars normalized-bindings (complement #'ps-special-variable-p)))
-           (renamed-body `(symbol-macrolet ,(mapcar (lambda (x) (list (var x) (renamed x)))
-                                                    lexical-bindings)
-                            ,@body)))
-    `(progn
-       ,@(mapcar (lambda (x) `(var ,(renamed x) ,(val x))) lexical-bindings)
-       ,(if dynamic-bindings
-            `(progn ,@(mapcar (lambda (x) `(var ,(renamed x))) dynamic-bindings)
-                    (try (progn (setf ,@(loop for x in dynamic-bindings append
-                                             `(,(renamed x) ,(var x)
-                                               ,(var x) ,(val x))))
-                                ,renamed-body)
-                         (:finally
-                          (setf ,@(mapcan (lambda (x) `(,(var x) ,(renamed x))) dynamic-bindings)))))
-            renamed-body)))))
+(define-ps-special-form let (bindings &body body)
+  (let* (lexical-bindings-introduced-here
+         (normalized-bindings (mapcar (lambda (x) (if (symbolp x) `(,x nil) x)) bindings))
+         (free-variables-in-binding-value-expressions (mapcan (lambda (x) (flatten (cadr x)))
+                                                              normalized-bindings)))
+    (flet ((maybe-rename-lexical-var (x)
+             (if (or (member x *vars-bound-in-enclosing-lexical-scopes*)
+                     (member x free-variables-in-binding-value-expressions))
+                 (ps-gensym x)
+                 (progn (push x lexical-bindings-introduced-here) nil)))
+           (rename (x) (first x))
+           (var (x) (second x))
+           (val (x) (third x)))
+      (let* ((lexical-bindings (loop for x in normalized-bindings
+                                  unless (ps-special-variable-p (car x))
+                                  collect (cons (maybe-rename-lexical-var (car x)) x)))
+             (dynamic-bindings (loop for x in normalized-bindings
+                                  when (ps-special-variable-p (car x))
+                                  collect (cons (ps-gensym (format nil "~A_~A" (car x) 'tmp-stack)) x)))
+             (renamed-body `(symbol-macrolet ,(loop for x in lexical-bindings
+                                                 when (rename x) collect
+                                                 `(,(var x) ,(rename x)))
+                              ,@body))
+             (*vars-bound-in-enclosing-lexical-scopes* (append lexical-bindings-introduced-here
+                                                               *vars-bound-in-enclosing-lexical-scopes*)))
+        (compile-parenscript-form
+         `(progn
+            ,@(mapcar (lambda (x) `(var ,(or (rename x) (var x)) ,(val x))) lexical-bindings)
+            ,(if dynamic-bindings
+                 `(progn ,@(mapcar (lambda (x) `(var ,(rename x))) dynamic-bindings)
+                         (try (progn (setf ,@(loop for x in dynamic-bindings append
+                                                  `(,(rename x) ,(var x)
+                                                     ,(var x) ,(val x))))
+                                     ,renamed-body)
+                              (:finally
+                               (setf ,@(mapcan (lambda (x) `(,(var x) ,(rename x))) dynamic-bindings)))))
+                 renamed-body))
+         :expecting expecting)))))
 
 (defpsmacro let* (bindings &body body)
   (if bindings
index b32d0a7..de77d42 100644 (file)
@@ -38,7 +38,7 @@
   (or (eql char #\+) (eql char #\*)))
 
 (defun special-symbol-name? (string)
-  (nth-value 1 (cl-ppcre:scan-to-strings "[\\*|\\+](.*)[\\*|\\+]([0-9]*)" string)))
+  (nth-value 1 (cl-ppcre:scan-to-strings "[\\*|\\+](.*)[\\*|\\+](.*)" string)))
 
 (defun first-uppercase-p (string)
   (and (> (length string) 1)
@@ -98,3 +98,8 @@ SOMEGLOBAL."
        `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n)))
           ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g)))
                 ,@body)))))
+
+(defun flatten (x)
+  (if (atom x)
+      (list x)
+      (mapcan #'flatten x)))
index c5c5a64..341394c 100644 (file)
@@ -63,5 +63,5 @@ foo.my_library_foo;")
 (ps-test::test-ps-js namespace-and-special-forms
   (let ((foo (create bar 1 not-a-keyword something)))
     (return (and (not foo) (+ (slot-value foo 'bar) some-other-var))))
-"var prefix_foo1 = { prefix_bar : 1, prefix_notAKeyword : prefix_something };
-return !prefix_foo1 && prefix_foo1.prefix_bar + prefix_someOtherVar;")
+"var prefix_foo = { prefix_bar : 1, prefix_notAKeyword : prefix_something };
+return !prefix_foo && prefix_foo.prefix_bar + prefix_someOtherVar;")
index a76d321..d375ddc 100644 (file)
         (setf x 4)
         (return 3))
       (setf x (+ 2 (side-effect) x 5))))
-  "var x1 = 10;
+  "var x = 10;
 function sideEffect() {
-  x1 = 4;
+  x = 4;
   return 3;
 };
-x1 = 2 + sideEffect() + x1 + 5;")
+x = 2 + sideEffect() + x + 5;")
 ;; Parenscript used to optimize incorrectly:
 ;;   var x = 10;
 ;;   function sideEffect() {
@@ -92,16 +92,16 @@ x1 = 2 + sideEffect() + x1 + 5;")
 (test-ps-js simple-slot-value
   (let ((foo (create :a 1)))
     (alert (slot-value foo 'a)))
-  "var foo1 = { a : 1 };
-   alert(foo1.a);")
+  "var foo = { a : 1 };
+   alert(foo.a);")
 
 (test-ps-js buggy-slot-value
    (let ((foo (create :a 1))
          (slot-name "a"))
     (alert (slot-value foo slot-name)))
-  " var foo1 = { a : 1 };
-    var slotName2 = 'a';
-    alert(foo1[slotName2]);
+  " var foo = { a : 1 };
+    var slotName = 'a';
+    alert(foo[slotName]);
    "); Last line was alert(foo.slotName) before bug-fix.
 
 (test-ps-js buggy-slot-value-two
@@ -182,7 +182,7 @@ x1 = 2 + sideEffect() + x1 + 5;")
                    ("uABCD" . ,(code-char #xabcd)))));; Really above ascii.
     (loop for (js-escape . lisp-char) in escapes
           for generated = (ps-doc* `(let ((x ,(format nil "hello~ahi" lisp-char)))))
-          for wanted = (format nil "var x1 = 'hello\\~ahi';" js-escape)
+          for wanted = (format nil "var x = 'hello\\~ahi';" js-escape)
           do (is (string= (normalize-js-code generated) wanted)))))
   
 (test-ps-js slot-value-setf
@@ -218,10 +218,10 @@ x1 = 2 + sideEffect() + x1 + 5;")
 (test-ps-js defsetf1
   (progn (defsetf baz (x y) (newval) `(set-baz ,x ,y ,newval))
          (setf (baz 1 2) 3))
-  "var _js2_4 = 1;
-var _js3_5 = 2;
-var _js1_6 = 3;
-setBaz(_js2_4, _js3_5, _js1_6);")
+  "var _js2 = 1;
+var _js3 = 2;
+var _js1 = 3;
+setBaz(_js2, _js3, _js1);")
 
 (test-ps-js setf-macroexpands1
   (macrolet ((baz (x y) `(aref ,x ,y 1)))
@@ -240,10 +240,10 @@ setBaz(_js2_4, _js3_5, _js1_6);")
 "function __setf_someThing(newVal, i1, i2) {
     SOMETHING[i1][i2] = newVal;
 };
-var _js2_4 = 1;
-var _js3_5 = 2;
-var _js1_6 = 'foo';
-__setf_someThing(_js1_6, _js2_4, _js3_5);")
+var _js2 = 1;
+var _js3 = 2;
+var _js1 = 'foo';
+__setf_someThing(_js1, _js2, _js3);")
 
 (test-ps-js defun-optional1
   (defun test-opt (&optional x) (return (if x "yes" "no")))
@@ -595,35 +595,44 @@ __setf_someThing(_js1_6, _js2_4, _js3_5);")
 };")
 
 (test-ps-js let-decl-in-expression
-  (defun f (x) (return (if x 1 (let* ((foo x)) foo))))
+  (defun f (x)
+    (return (if x
+                1
+                (let* ((foo x))
+                  foo))))
   "function f(x) {
-    var foo1;
-    return x ? 1 : (foo1 = x, foo1);
+    var foo;
+    return x ? 1 : (foo = x, foo);
 };")
 
 (test-ps-js special-var1
-  (progn (defvar *foo*) (let* ((*foo* 2)) (* *foo* 2)))
+  (progn (defvar *foo*)
+         (let* ((*foo* 2))
+           (* *foo* 2)))
   "var FOO;
-var FOO1;
+var FOO_TMPSTACK1;
 try {
-    FOO1 = FOO;
+    FOO_TMPSTACK1 = FOO;
     FOO = 2;
     FOO * 2;
 } finally {
-    FOO = FOO1;
+    FOO = FOO_TMPSTACK1;
 };")
 
 (test-ps-js special-var2
-  (progn (defvar *foo*) (let* ((*baz* 3) (*foo* 2)) (* *foo* 2 *baz*)))
+  (progn (defvar *foo*)
+         (let* ((*baz* 3)
+                (*foo* 2))
+           (* *foo* 2 *baz*)))
   "var FOO;
-var BAZ1 = 3;
-var FOO2;
+var BAZ = 3;
+var FOO_TMPSTACK1;
 try {
-    FOO2 = FOO;
+    FOO_TMPSTACK1 = FOO;
     FOO = 2;
-    FOO * 2 * BAZ1;
+    FOO * 2 * BAZ;
 } finally {
-    FOO = FOO2;
+    FOO = FOO_TMPSTACK1;
 };")
 
 (test-ps-js literal1
@@ -861,10 +870,10 @@ bar2(foo1(1));")
 (test-ps-js ps-js-target-version-keyword-test1
   (defun foo (x y &key bar baz))
   "function foo(x, y) {
-    var x1_3 = Array.prototype.indexOf.call(arguments, 'bar', 2);
-    var bar = -1 == x1_3 ? null : arguments[x1_3 + 1];
-    var x2_4 = Array.prototype.indexOf.call(arguments, 'baz', 2);
-    var baz = -1 == x2_4 ? null : arguments[x2_4 + 1];
+    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)
 
@@ -879,30 +888,36 @@ bar2(foo1(1));")
 (test-ps-js let1
   (let (x)
     (+ x x))
-  "var x1 = null;
-x1 + x1;")
+  "var x = null;
+x + x;")
 
 (test-ps-js let2
   (let ((x 1))
     (+ x x))
-  "var x1 = 1;
+  "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 x1 = 1;
-var y2 = 2;
-x1 + x1;")
+  "var x = 1;
+var y = 2;
+x + x;")
 
 (test-ps-js let4
   (let ((x 1)
         (y (1+ x)))
     (+ x y))
   "var x1 = 1;
-var y2 = x + 1;
-x1 + y2;")
+var y = x + 1;
+x1 + y;")
 
 (test-ps-js let5
   (let ((x 1))
@@ -910,62 +925,62 @@ x1 + y2;")
     (let ((x (+ x 5)))
       (+ x 1))
     (+ x 1))
-  "var x1 = 1;
+  "var x = 1;
+x + 1;
+var x1 = x + 5;
 x1 + 1;
-var x2 = x1 + 5;
-x2 + 1;
-x1 + 1;")
+x + 1;")
 
 (test-ps-js let6
   (let ((x 2))
     (let ((x 1)
           (y (1+ x)))
       (+ x y)))
-  "var x1 = 2;
-var x2 = 1;
-var y3 = x1 + 1;
-x2 + y3;")
+  "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 x1;
-    return (x1 = null, x1 + x1);
+    var x;
+    return (x = null, x + x);
 };")
 
 (test-ps-js let*1
   (let* ((x 1)) (+ x x))
-"var x1 = 1;
-x1 + x1;")
+"var x = 1;
+x + x;")
 
 (test-ps-js let*2
   (let* ((x 1)
          (y (+ x 2)))
     (+ x y))
-  "var x1 = 1;
-var y2 = x1 + 2;
-x1 + y2;")
+  "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 x1 = 3;
-var x2 = 1;
-var y3 = x2 + 2;
-x2 + y3;")
+  "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 x1 = 3;
-var y2 = x1 + 2;
-var x3 = 1;
-x3 + y2;")
+  "var x = 3;
+var y = x + 2;
+var x1 = 1;
+x1 + y;")
 
 (test-ps-js symbol-macrolet-var
   (symbol-macrolet ((x y))
@@ -978,13 +993,13 @@ x3 + y2;")
 
 (test-ps-js setf-let1
   (setf x (let ((a 1)) a))
-  "x = (a1 = 1, a1);")
+  "x = (a = 1, a);")
 
 (test-ps-js setf-let2
   (setf x (let ((a (foo)))
             (unless (null a)
               (1+ a))))
-  "x = (a1 = foo(), a1 != null ? a1 + 1 : null);")
+  "x = (a = foo(), a != null ? a + 1 : null);")
 
 (test-ps-js symbol-macro-env1
   (symbol-macrolet ((bar 1))
@@ -1000,5 +1015,29 @@ x3 + y2;")
 (test-ps-js lisp2-namespaces1
   (let ((list nil))
     (setf list (list 1 2 3)))
-  "var list1 = null;
-list1 = [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;
+};")
index f749d18..3f1c06a 100644 (file)
@@ -259,12 +259,12 @@ x = a + b + c;")
 (test-ps-js assignment-5
   (let ((a 1) (b 2))
   (psetf a b b a))
-  "var a1 = 1;
-var b2 = 2;
-var _js3_5 = b2;
-var _js4_6 = a1;
-a1 = _js3_5;
-b2 = _js4_6;")
+  "var a = 1;
+var b = 2;
+var _js1 = b;
+var _js2 = a;
+a = _js1;
+b = _js2;")
 
 (test-ps-js assignment-6
   (setq a 1)
@@ -279,9 +279,9 @@ b2 = _js4_6;")
 
 (test-ps-js assignment-9
   (setf (color some-div) (+ 23 "em"))
-  "var _js2_3 = someDiv;
-var _js1_4 = 23 + 'em';
-__setf_color(_js1_4, _js2_3);")
+  "var _js2 = someDiv;
+var _js1 = 23 + 'em';
+__setf_color(_js1, _js2);")
 
 (test-ps-js assignment-10
   (defsetf left (el) (offset)
@@ -290,9 +290,9 @@ __setf_color(_js1_4, _js2_3);")
 
 (test-ps-js assignment-11
   (setf (left some-div) (+ 123 "px"))
-  "var _js2_3 = someDiv;
-var _js1_4 = 123 + 'px';
-_js2_3.style.left = _js1_4;")
+  "var _js2 = someDiv;
+var _js1 = 123 + 'px';
+_js2.style.left = _js1;")
 
 (test-ps-js assignment-12
   (macrolet ((left (el)
@@ -366,16 +366,16 @@ _js2_3.style.left = _js1_4;")
            (x (+ x y)))
       (+ *a* x y))))
   "var A = 4;
-var x1 = 1;
-var A2;
+var x = 1;
+var A_TMPSTACK1;
 try {
-    A2 = A;
+    A_TMPSTACK1 = A;
     A = 2;
-    var y3 = x1 + 1;
-    var x4 = x1 + y3;
-    A + x4 + y3;
+    var y = x + 1;
+    var x2 = x + y;
+    A + x2 + y;
 } finally {
-    A = A2;
+    A = A_TMPSTACK1;
 };")
 
 (test-ps-js iteration-constructs-1
@@ -396,14 +396,14 @@ try {
      (s 0 (+ s i (1+ i))))
     ((> i 10))
   ((@ document write) (+ "i: " i " s: " s "<br/>")))
-  "var i1 = 0;
-var s2 = 0;
-for (; i1 <= 10; ) {
-    document.write('i: ' + i1 + ' s: ' + s2 + '<br/>');
-    var _js3_5 = i1 + 1;
-    var _js4_6 = s2 + i1 + (i1 + 1);
-    i1 = _js3_5;
-    s2 = _js4_6;
+  "var i = 0;
+var s = 0;
+for (; i <= 10; ) {
+    document.write('i: ' + i + ' s: ' + s + '<br/>');
+    var _js1 = i + 1;
+    var _js2 = s + i + (i + 1);
+    i = _js1;
+    s = _js2;
 };")
 
 (test-ps-js iteration-constructs-3
@@ -419,9 +419,9 @@ for (; i1 <= 10; ) {
   (let ((arr (array "a" "b" "c" "d" "e")))
   (dotimes (i (@ arr length))
     ((@ document write) (+ "i: " i " arr[i]: " (aref arr i) "<br/>"))))
-  "var arr1 = ['a', 'b', 'c', 'd', 'e'];
-for (var i = 0; i < arr1.length; i += 1) {
-    document.write('i: ' + i + ' arr[i]: ' + arr1[i] + '<br/>');
+  "var arr = ['a', 'b', 'c', 'd', 'e'];
+for (var i = 0; i < arr.length; i += 1) {
+    document.write('i: ' + i + ' arr[i]: ' + arr[i] + '<br/>');
 };")
 
 (test-ps-js iteration-constructs-5
@@ -429,21 +429,21 @@ for (var i = 0; i < arr1.length; i += 1) {
   (alert (+ "Summation to 10 is "
             (dotimes (i 10 res)
               (incf res (1+ i))))))
-  "var res1 = 0;
+  "var res = 0;
 alert('Summation to 10 is ' + (function () {
     for (var i = 0; i < 10; i += 1) {
-        res1 += i + 1;
+        res += i + 1;
     };
-    return res1;
+    return res;
 })());")
 
 (test-ps-js iteration-constructs-6
   (let ((l (list 1 2 4 8 16 32)))
   (dolist (c l)
     ((@ document write) (+ "c: " c "<br/>"))))
-  "var l1 = [1, 2, 4, 8, 16, 32];
-for (var c = null, _js_arrvar3 = l1, _js_idx2 = 0; _js_idx2 < _js_arrvar3.length; _js_idx2 += 1) {
-    c = _js_arrvar3[_js_idx2];
+  "var l = [1, 2, 4, 8, 16, 32];
+for (var c = null, _js_arrvar2 = l, _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
+    c = _js_arrvar2[_js_idx1];
     document.write('c: ' + c + '<br/>');
 };")
 
@@ -453,23 +453,23 @@ for (var c = null, _js_arrvar3 = l1, _js_idx2 = 0; _js_idx2 < _js_arrvar3.length
   (alert (+ "Sum of " l " is: "
             (dolist (c l s)
               (incf s c)))))
-  "var l1 = [1, 2, 4, 8, 16, 32];
-var s2 = 0;
-alert('Sum of ' + l1 + ' is: ' + (function () {
-    for (var c = null, _js_arrvar4 = l1, _js_idx3 = 0; _js_idx3 < _js_arrvar4.length; _js_idx3 += 1) {
-        c = _js_arrvar4[_js_idx3];
-        s2 += c;
+  "var l = [1, 2, 4, 8, 16, 32];
+var s = 0;
+alert('Sum of ' + l + ' is: ' + (function () {
+    for (var c = null, _js_arrvar2 = l, _js_idx1 = 0; _js_idx1 < _js_arrvar2.length; _js_idx1 += 1) {
+        c = _js_arrvar2[_js_idx1];
+        s += c;
     };
-    return s2;
+    return s;
 })());")
 
 (test-ps-js iteration-constructs-8
   (let ((obj (create :a 1 :b 2 :c 3)))
   (for-in (i obj)
     ((@ document write) (+ i ": " (aref obj i) "<br/>"))))
-  "var obj1 = { a : 1, b : 2, c : 3 };
-for (var i in obj1) {
-    document.write(i + ': ' + obj1[i] + '<br/>');
+  "var obj = { a : 1, b : 2, c : 3 };
+for (var i in obj) {
+    document.write(i + ': ' + obj[i] + '<br/>');
 };")
 
 (test-ps-js iteration-constructs-9
@@ -548,10 +548,10 @@ for (var i in obj1) {
    (setf (@ element inner-h-t-m-l)
          (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
                 "Edit me"))))
-  "var disabled1 = null;
-var authorized2 = true;
+  "var disabled = null;
+var authorized = true;
 element.innerHTML =
 '<TEXTAREA'
-+ (disabled1 || !authorized2 ? ' DISABLED=\"' + 'disabled' + '\"' : '')
++ (disabled || !authorized ? ' DISABLED=\"' + 'disabled' + '\"' : '')
 + '>Edit me</TEXTAREA>';")