This is actually a bug in slot-value; the decision that I came to was to output all keywords as strings, since that's the closest equivalent to self-evaluating identifier objects in JavaScript.
The other issue here is how we should print the symbol-names of the keywords. The answer to that is it's arbitrary, as long as keywords are treated the same in all contexts (which is why this is a bug in slot-value only, and not in the way PS treats symbols).
Daniel had made a good point in that the current 'symbol-name-to-js-string' algorithm was mangling some short symbols like :+ and :-, etc. in ugly ways. It's easier just to print the symbol-name of the symbol, rather than adding a bunch of arbitrary heuristics to 'symbol-name-to-js-string.'
Vladimir
On Sun, Jul 26, 2009 at 2:52 PM, Red Dalyreddaly@gmail.com wrote:
Dear Parenscripters,
I found an inconsistency in how symbols are translated into Javascript. The issue is similar to an earlier issue:
CL-USER> (ps:ps (let ((sym :my-function)) (slot-value object sym) (slot-value object :my-function))) "var sym = 'my-function'; object[sym]; object.myFunction;"
One would expect object[sym] and object.myFunction to evaluate to the same value, but right now they do not. This bug only affects keywords:
CL-USER> (ps:ps (let ((sym 'my-function)) (slot-value object sym) (slot-value object 'my-function))) "var sym = 'myFunction'; object[sym]; object.myFunction;"
The above output is sensible. A patch is attached to fix this issue. A few test cases have also been added to prevent future breakage.
The old DEFUN-KEYWORD4 test function failed with this patch because it expected a keyword to translate to 'my-name-key'. I patched it to expect 'myNameKey'
Best, Red
From 904be1cc2eee598491557132e8ed1569a90f27a3 Mon Sep 17 00:00:00 2001 From: Red Daly reddaly@gmail.com Date: Sun, 26 Jul 2009 20:22:54 +0000 Subject: [PATCH] Fixed eval-when special form and added tests to prevent future breakage.
src/compiler.lisp | 50 ++++++++++++++++++++++++++++---------------------- t/ps-tests.lisp | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 22 deletions(-)
diff --git a/src/compiler.lisp b/src/compiler.lisp index 4fed094..e72fb4e 100644 --- a/src/compiler.lisp +++ b/src/compiler.lisp @@ -162,17 +162,20 @@ compiled to an :expression (the default), a :statement, or a :symbol."))
(defun adjust-ps-compilation-level (form level) - (cond ((or (and (consp form) (eq 'progn (car form))) - (and (symbolp form) (eq :toplevel level))) - level) - ((eq :toplevel level) :inside-toplevel-form))) + "Given the current *ps-compilation-level*, LEVEL, and the fully macroexpanded +form, FORM, returns the new value for *ps-compilation-level*." + (cond ((or (and (consp form) (member (car form) + '(progn locally macrolet symbol-macrolet compile-file))) + (and (symbolp form) (eq :toplevel level))) + level) + ((eq :toplevel level) :inside-toplevel-form)))
(defmethod compile-parenscript-form :around (form &key expecting) (assert (if expecting (member expecting '(:expression :statement :symbol)) t)) (if (eq expecting :symbol) (compile-to-symbol form) - (let ((*ps-compilation-level* (adjust-ps-compilation-level form *ps-compilation-level*))) - (call-next-method)))) + (call-next-method)))
(defun compile-to-symbol (form) "Compiles the given Parenscript form and guarantees that the @@ -226,22 +229,25 @@ the form cannot be compiled to a symbol." (defmethod compile-parenscript-form ((form cons) &key (expecting :statement)) (multiple-value-bind (form expanded-p) (ps-macroexpand form) - (cond (expanded-p (compile-parenscript-form form :expecting expecting)) - ((ps-special-form-p form) (apply (get-ps-special-form (car form)) (cons expecting (cdr form)))) - ((op-form-p form) - `(js:operator ,(ps-convert-op-name (compile-parenscript-form (car form) :expecting :symbol)) - ,@(mapcar (lambda (form) - (compile-parenscript-form (ps-macroexpand form) :expecting :expression)) - (cdr form)))) - ((funcall-form-p form) - `(js:funcall ,(compile-parenscript-form (if (symbolp (car form))
(maybe-rename-local-function (car form)) - (ps-macroexpand (car form))) - :expecting :expression) - ,@(mapcar (lambda (arg) - (compile-parenscript-form (ps-macroexpand arg) :expecting :expression)) - (cdr form)))) - (t (error "Cannot compile ~S to a ParenScript form." form))))) + (let ((*ps-compilation-level* (if expanded-p + *ps-compilation-level* + (adjust-ps-compilation-level form *ps-compilation-level*)))) + (cond (expanded-p (compile-parenscript-form form :expecting expecting)) + ((ps-special-form-p form) (apply (get-ps-special-form (car form)) (cons expecting (cdr form)))) + ((op-form-p form) + `(js:operator ,(ps-convert-op-name (compile-parenscript-form (car form) :expecting :symbol)) + ,@(mapcar (lambda (form) + (compile-parenscript-form (ps-macroexpand form) :expecting :expression)) + (cdr form)))) + ((funcall-form-p form) + `(js:funcall ,(compile-parenscript-form (if (symbolp (car form)) + (maybe-rename-local-function (car form)) + (ps-macroexpand (car form))) + :expecting :expression) + ,@(mapcar (lambda (arg) + (compile-parenscript-form (ps-macroexpand arg) :expecting :expression)) + (cdr form)))) + (t (error "Cannot compile ~S to a ParenScript form." form))))))
(defvar *ps-gensym-counter* 0)
diff --git a/t/ps-tests.lisp b/t/ps-tests.lisp index cd9d4f2..0324c09 100644 --- a/t/ps-tests.lisp +++ b/t/ps-tests.lisp @@ -1129,3 +1129,43 @@ x1 - x1; --x1; ++x1;")
+(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*)))) + ;(is (string= "" js-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*))))
+ ;(is (string= "" js-output))))
1.5.4.3
From d6748a5cfc8c4b9300884e9e5061db19cb0407cd Mon Sep 17 00:00:00 2001 From: Red Daly reddaly@gmail.com Date: Sun, 26 Jul 2009 20:49:59 +0000 Subject: [PATCH] Fixed keyword translation inconsistency between (slot-value object :key-thing) and :key-thing.
src/printer.lisp | 2 +- src/special-forms.lisp | 2 +- t/ps-tests.lisp | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/src/printer.lisp b/src/printer.lisp index b649dae..edf74b2 100644 --- a/src/printer.lisp +++ b/src/printer.lisp @@ -43,7 +43,7 @@ arguments, defines a printer for that form using the given body."
(defmethod ps-print ((s symbol)) (assert (keywordp s)) - (ps-print (string-downcase s))) + (ps-print (symbol-to-js-string s)))
(defmethod ps-print ((compiled-form cons)) (ps-print% (car compiled-form) (cdr compiled-form))) diff --git a/src/special-forms.lisp b/src/special-forms.lisp index 802dc28..e96a6d4 100644 --- a/src/special-forms.lisp +++ b/src/special-forms.lisp @@ -34,7 +34,7 @@ (typecase x (cons `(array ,@(mapcar (lambda (x) (when x `',x)) x))) (null '(array)) - (keyword x) + (keyword (symbol-to-js-string x)) (symbol (symbol-to-js-string x)) (number x) (string x)) diff --git a/t/ps-tests.lisp b/t/ps-tests.lisp index 0324c09..540d1a6 100644 --- a/t/ps-tests.lisp +++ b/t/ps-tests.lisp @@ -455,7 +455,7 @@ __setf_someThing(_js1, _js2, _js3);") var _js2 = arguments.length; for (var n1 = 0; n1 < _js2; n1 += 2) { switch (arguments[n1]) { - case 'my-name-key': + case 'myNameKey': { myName = arguments[n1 + 1]; }; @@ -1169,3 +1169,19 @@ x1 - x1; (declare (ignore js-output)) (is (eql :cl-user *lisp-output*)))) ;(is (string= "" js-output))))
+(test-ps-js keyword-conversion1 + :alpha-omega + "'alphaOmega';")
+(test-ps-js keyword-conversion2
- (slot-value object :alpha-omega)
- "object.alphaOmega;")
+(test keyword-conversion2 () + (let ((js-output1 (normalize-js-code + (ps-doc* '(slot-value object :alpha-omega)))) + (js-output2 (normalize-js-code + (ps-doc* :alpha-omega))) + (declare (ignore js-output))
+ (is (eql :cl-user *lisp-output*))))
1.5.4.3
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel