Consider associativity when unparse Javascript expressions
authorDavid Vázquez <davazp@gmail.com>
Wed, 19 Jun 2013 04:29:37 +0000 (06:29 +0200)
committerDavid Vázquez <davazp@gmail.com>
Wed, 19 Jun 2013 04:29:37 +0000 (06:29 +0200)
experimental/codegen.lisp

index b03fdc9..a54e479 100644 (file)
          (case (length (cdr form))
            (1 `(unary- ,(cadr form)))
            (t (reduce (lambda (x y) `(- ,x ,y)) (cdr form)))))
+        ((progn comma)
+         (reduce (lambda (x y) `(comma ,x ,y)) (cdr form) :from-end t))
         (t form))
       form))
 
 ;; Initialized to any value larger than any operator precedence
 (defvar *js-operator-precedence* 1000)
 (defvar *js-operator-associativity* 'left)
+(defvar *js-operand-order* 'left)
 
 ;; Format an expression optionally wrapped with parenthesis if the
 ;; precedence rules require it.
              (cond
                ((> ,g!precedence *js-operator-precedence*))
                ((< ,g!precedence *js-operator-precedence*) nil)
+               ;; Same precedence. Let us consider associativity.
                (t
-                t)))
+                (not (eq *js-operand-order* *js-operator-associativity*)))))
             (*js-operator-precedence* ,g!precedence)
-            (*js-operator-associativity* ,associativity))
+            (*js-operator-associativity* ,associativity)
+            (*js-operand-order* 'left))
        (when ,g!parens (js-format "("))
        (progn ,@body)
        (when ,g!parens (js-format ")")))))
 
+(defun js-operator (string)
+  (js-format "~a" string)
+  (setq *js-operand-order* 'right))
+
 (defun js-operator-expression (op args)
   (let ((op1 (car args))
         (op2 (cadr args)))
     (case op
-      ;; Comma (,)
-      ((progn comma)
-       (with-operator (14 'left)
-         (js-expr (car args))
-         (dolist (operand (cdr args))
-           (let ((*js-output* t))
-             (js-format ",")
-             (js-expr operand)))))
       ;; Function call
       (call
        (js-expr (car args))
                     (cond
                       (post
                        (js-expr op1)
-                       (js-format string))
+                       (js-operator string))
                       (t
-                       (js-format string)
+                       (js-operator string)
                        (js-expr op1))))
                   (return-from js-operator-expression)))
               (%binary-op (operator string precedence associativity lvalue)
                   (when lvalue (check-lvalue op1))
                   (with-operator (precedence associativity)
                     (js-expr op1)
-                    (js-format string)
+                    (js-operator string)
                     (js-expr op2))
                   (return-from js-operator-expression))))
 
            (binary-op >>=        ">>="          13    right :lvalue t)
            (binary-op >>>=       ">>>="         13    right :lvalue t)
 
+           (binary-op comma      ","            13    right)
+           (binary-op progn      ","            13    right)
+
            (when (member op '(? if))
              (with-operator (12 'right)
                (js-expr (first args))
-               (js-format "?")
+               (js-operator "?")
                (js-expr (second args))
                (js-format ":")
                (js-expr (third args))))))))))
 
-
 (defun js-expr (form)
   (let ((form (js-expand-expr form)))
     (cond
       (t
        (js-operator-expression (car form) (cdr form))))))
 
-
 (defun js-stmt (form)
   (if (atom form)
       (progn