Fixed js-with
[clinton/parenscript.git] / src / js.lisp
index 75af024..296d704 100644 (file)
   (flet ((special-append (form elt)
           (let ((len (length form)))
             (if (and (> len 0)
-                     (member (char form (1- len))
-                             '(#\; #\, #\})))
+                      (string= (char form (1- len)) elt))
                 form
                 (concatenate 'string form elt)))))
     (cond ((stringp form)
@@ -270,10 +269,11 @@ this macro."
 (defun import-macros-from-lisp (&rest names)
   "Import the named lisp macros into the js macro expansion"
   (dolist (name names)
-    (undefine-js-compiler-macro name)
-    (setf (gethash (symbol-name name) *js-macro-toplevel*)
-          (lambda (&rest args)
-            (macroexpand `(,name ,@args))))))
+    (let ((name name))
+      (undefine-js-compiler-macro name)
+      (setf (gethash (symbol-name name) *js-macro-toplevel*)
+            (lambda (&rest args)
+              (macroexpand `(,name ,@args)))))))
 
 (defun js-expand-form (expr)
   "Expand a javascript form."
@@ -335,7 +335,7 @@ prefix)."
         ,@(loop for variable in variables
                 do (setf variable (symbol-to-js variable))
                 collect `(setf (slot-value new-context ,variable) (slot-value this ,variable)))
-        (with (new-context)
+        (with new-context
               (return ,expression))))))
 
 (defvar *var-counter* 0)
@@ -940,9 +940,28 @@ vice-versa.")
 (define-js-single-op delete)
 (define-js-single-op void)
 (define-js-single-op typeof)
-(define-js-single-op instanceof)
 (define-js-single-op new)
 
+;; TODO this may not be the best integrated implementation of
+;; instanceof into the rest of the code
+(defjsclass js-instanceof (expression)
+  ((value)
+   (type :initarg :type)))
+
+(define-js-compiler-macro instanceof (value type)
+  (make-instance 'js-instanceof
+                 :value (js-compile-to-expression value)
+                 :type (js-compile-to-expression type)))
+
+(defmethod js-to-strings ((instanceof js-instanceof) start-pos)
+  (dwim-join
+   (list (js-to-strings (value instanceof) (+ start-pos 2))
+         (list "instanceof")
+         (js-to-strings (slot-value instanceof 'type) (+ start-pos 2)))
+   (- 80 start-pos 2)
+   :white-space
+   "  "))
+
 ;;; assignment
 
 (defjsclass js-setf (expression)
@@ -1110,37 +1129,6 @@ vice-versa.")
        (let ((,var (aref ,arrvar ,idx)))
          ,@body)))))
 
-(defjsmacro map-into (function array)
-  "Call FUNCTION on each element in ARRAY, replace element with the return value."
-  ;; be friendly to both (map-into 'foo array) and (map-into foo array) calls
-  (when (and (listp function)
-             (eq 'quote (first function)))
-    (setf function (eval function)))
-  (with-unique-js-names (arrvar idx fn)
-    `((lambda ()
-        (let ((,arrvar ,array)
-              (,fn ,function))
-          (do ((,idx 0 (1+ ,idx)))
-              ((>= ,idx (slot-value ,arrvar 'length)))
-            (setf (aref ,arrvar ,idx) (,fn (aref ,arrvar ,idx)))))
-        (return ,arrvar)))))
-
-(defjsmacro map (function array)
-  "Call FUNCTION on each element in ARRAY and return the returned values in a new array."
-  ;; be friendly to both (map 'foo array) and (map foo array) calls
-  (when (and (listp function)
-             (eq 'quote (first function)))
-    (setf function (eval function)))
-  (with-unique-js-names (arrvar result idx fn)
-    `((lambda ()
-        (let ((,arrvar ,array)
-              (,fn ,function)
-              (,result (make-array (slot-value ,arrvar 'length))))
-          (do ((,idx 0 (1+ ,idx)))
-              ((>= ,idx (slot-value ,arrvar 'length)))
-            (setf (aref ,result ,idx) (,fn (aref ,arrvar ,idx)))))
-        (return ,result)))))
-
 (defmethod js-to-statement-strings ((for js-for) start-pos)
   (let* ((init (dwim-join (mapcar #'(lambda (x)
                                      (dwim-join (list (list (symbol-to-js (first (var-names x))))
@@ -1214,8 +1202,8 @@ vice-versa.")
 
 (define-js-compiler-macro with (statement &rest body)
   (make-instance 'js-with
-                :obj (js-compile-to-expression (first statement))
-                :body (js-compile-to-body (cons 'progn body) :indent "  ")))
+                 :obj (js-compile-to-expression statement)
+                 :body (js-compile-to-body (cons 'progn body) :indent "  ")))
 
 (defmethod js-to-statement-strings ((with js-with) start-pos)
   (nconc (dwim-join (list (js-to-strings (with-obj with) (+ start-pos 2)))
@@ -1325,9 +1313,14 @@ vice-versa.")
 (define-js-compiler-macro regex (regex)
   (make-instance 'regex :value (string regex)))
 
+(defun first-slash-p (string)
+  (and (> (length string) 0)
+       (eq (char string 0) '#\/)))
+
 (defmethod js-to-strings ((regex regex) start-pos)
-  (declare (ignore start-pos))
-  (list (format nil "/~A/" (value regex))))
+   (declare (ignore start-pos))
+   (let ((slash (if (first-slash-p (value regex)) nil "/")))
+     (list (format nil (concatenate 'string slash "~A" slash) (value regex)))))
 
 ;;; conditional compilation