(defmethod parenscript-print (form)
(let ((*indent-level* 0)
(*print-accumulator* ()))
- (if (and (listp form) (eql 'js-block (car form))) ; ignore top-level block
- (loop for (statement . remaining) on (third form) do
- (ps-print statement) (psw ";") (when remaining (psw #\Newline)))
- (ps-print form))
- (nreverse *print-accumulator*)))
+ (if (and (listp form) (eq 'js:block (car form))) ; ignore top-level block
+ (loop for (statement . remaining) on (third form) do
+ (ps-print statement) (psw ";") (when remaining (psw #\Newline)))
+ (ps-print form))
+ (nreverse *print-accumulator*)))
(defun psw (obj)
(push (if (characterp obj) (string obj) obj) *print-accumulator*))
(defun expression-precedence (expr)
(if (consp expr)
(case (car expr)
- ((js-slot-value js-aref) (op-precedence (car expr)))
- (js-assign (op-precedence '=))
+ ((js:slot-value js:aref) (op-precedence (car expr)))
+ (js:= (op-precedence 'js:=))
(js:? (op-precedence 'js:?))
- (unary-operator (op-precedence (second expr)))
+ (js:unary-operator (op-precedence (second expr)))
(operator (op-precedence (second expr)))
(otherwise 0))
0))
(defparameter *op-precedence-hash* (make-hash-table :test 'eq))
(let ((precedence 1))
- (dolist (ops '((new js-slot-value js-aref)
+ (dolist (ops '((js:new js:slot-value js:aref)
(postfix++ postfix--)
(delete void typeof ++ -- unary+ unary- ~ !)
(* / %)
(+ -)
(<< >> >>>)
- (< > <= >= js-instance-of in)
+ (< > <= >= js:instanceof js:in)
(== != === !== eql)
(&)
(^)
(\&\& and)
(\|\| or)
(js:?)
- (= *= /= %= += -= <<= >>= >>>= \&\= ^= \|= js-assign)
+ (= *= /= %= += -= <<= >>= >>>= \&\= ^= \|=)
(comma)))
(dolist (op ops)
(setf (gethash op *op-precedence-hash*) precedence))
(defun op-precedence (op)
(gethash op *op-precedence-hash*)))
-(defprinter js-literal (str)
+(defprinter js:literal (str)
(psw str))
(defun print-comma-delimited-list (ps-forms)
(loop for (form . remaining) on ps-forms do
(ps-print form) (when remaining (psw ", "))))
-(defprinter array-literal (&rest initial-contents)
+(defprinter js:array (&rest initial-contents)
(psw #\[) (print-comma-delimited-list initial-contents) (psw #\]))
-(defprinter js-aref (array indices)
- (if (>= (expression-precedence array) #.(op-precedence 'js-aref))
+(defprinter js:aref (array indices)
+ (if (>= (expression-precedence array) #.(op-precedence 'js:aref))
(parenthesize-print array)
(ps-print array))
(loop for idx in indices do
(psw #\[) (ps-print idx) (psw #\])))
-(defprinter js-variable (var)
+(defprinter js:variable (var)
(psw (js-translate-symbol var)))
;;; arithmetic operators
(defun parenthesize-print (ps-form)
(psw #\() (ps-print ps-form) (psw #\)))
-(defprinter operator (op args)
+(defprinter js:operator (op &rest args)
(loop for (arg . remaining) on args
with precedence = (op-precedence op) do
(if (>= (expression-precedence arg) precedence)
(ps-print arg))
(when remaining (psw (format nil " ~(~A~) " op)))))
-(defprinter unary-operator (op arg &key prefix space)
+(defprinter js:unary-operator (op arg &key prefix space)
(when prefix (psw (format nil "~(~a~)~:[~; ~]" op space)))
(if (> (expression-precedence arg)
(op-precedence (case op
(ps-print arg))
(unless prefix (psw (format nil "~(~a~)" op))))
-(defprinter js-funcall (fun-designator args)
- (funcall (if (member (car fun-designator) '(js-variable js-aref js-slot-value js-funcall))
+(defprinter js:funcall (fun-designator &rest args)
+ (funcall (if (member (car fun-designator) '(js:variable js:aref js:slot-value js:funcall))
#'ps-print
#'parenthesize-print)
fun-designator)
(psw #\() (print-comma-delimited-list args) (psw #\)))
-(defprinter js-block (block-type statements)
+(defprinter js:block (block-type statements)
(case block-type
(:statement
(psw #\{)
(ps-print statement) (when remaining (psw ", ")))
(psw #\)))))
-(defprinter js-lambda (args body)
+(defprinter js:lambda (args body)
(print-fun-def nil args body))
-(defprinter js-defun (name args body)
+(defprinter js:defun (name args body)
(print-fun-def name args body))
(defun print-fun-def (name args body-block)
(psw ") ")
(ps-print body-block))
-(defprinter js-object (slot-defs)
+(defprinter js:object (&rest slot-defs)
(psw "{ ")
(loop for ((slot-name . slot-value) . remaining) on slot-defs do
(if (and (listp slot-name) (eq 'quote (car slot-name)) (symbolp (second slot-name)))
(when remaining (psw ", ")))
(psw " }"))
-(defprinter js-slot-value (obj slot)
- (if (or (> (expression-precedence obj) #.(op-precedence 'js-slot-value))
+(defprinter js:slot-value (obj slot)
+ (if (or (> (expression-precedence obj) #.(op-precedence 'js:slot-value))
(numberp obj)
- (and (listp obj) (member (car obj) '(js-lambda js-object))))
+ (and (listp obj) (member (car obj) '(js:lambda js:object))))
(parenthesize-print obj)
(ps-print obj))
(if (symbolp slot)
(progn (psw #\.) (psw (js-translate-symbol slot)))
(progn (psw #\[) (ps-print slot) (psw #\]))))
-(defprinter js-cond-statement (clauses)
+(defprinter js:cond (clauses)
(loop for (test body-block) in clauses
for start = "if (" then " else if (" do
(if (equalp test "true")
(parenthesize-print else)
(ps-print else)))
-(defprinter js-assign (lhs rhs)
+(defprinter js:= (lhs rhs)
(ps-print lhs) (psw " = ") (ps-print rhs))
-(defprinter js-var (var-name &rest var-value)
+(defprinter js:var (var-name &rest var-value)
(psw "var ")
(psw (js-translate-symbol var-name))
(when var-value
(psw " = ")
(ps-print (car var-value))))
-(defprinter js-break (&optional label)
+(defprinter js:break (&optional label)
(psw "break")
(when label
(psw " ")
(psw (js-translate-symbol label))))
-(defprinter js-continue (&optional label)
+(defprinter js:continue (&optional label)
(psw "continue")
(when label
(psw " ")
(psw (js-translate-symbol label))))
;;; iteration
-(defprinter js-for (label vars tests steps body-block)
+(defprinter js:for (label vars tests steps body-block)
(when label (psw (js-translate-symbol label)) (psw ": ") (newline-and-indent))
(psw "for (")
(loop for ((var-name . var-init) . remaining) on vars
(psw ") ")
(ps-print body-block))
-(defprinter js-for-in (var object body-block)
+(defprinter js:for-in (var object body-block)
(psw "for (") (ps-print var) (psw " in ")
(if (> (expression-precedence object) (op-precedence 'in))
(parenthesize-print object)
(psw ") ")
(ps-print body-block))
-(defprinter js-while (test body-block)
+(defprinter js:while (test body-block)
(psw "while (") (ps-print test) (psw ") ")
(ps-print body-block))
-(defprinter js-with (expression body-block)
+(defprinter js:with (expression body-block)
(psw "with (") (ps-print expression) (psw ") ")
(ps-print body-block))
-(defprinter js-switch (test clauses)
+(defprinter js:switch (test clauses)
(flet ((print-body-statements (body-statements)
(incf *indent-level*)
(loop for statement in body-statements do
(newline-and-indent)
(psw #\})))
-(defprinter js-try (body-block &key catch finally)
+(defprinter js:try (body-block &key catch finally)
(psw "try ")
(ps-print body-block)
(when catch
(ps-print finally)))
;;; regex
-(defprinter js-regex (regex)
+(defprinter js:regex (regex)
(flet ((first-slash-p (string)
(and (> (length string) 0) (char= (char string 0) #\/))))
(let ((slash (unless (first-slash-p regex) "/")))
(psw (format nil (concatenate 'string slash "~A" slash) regex)))))
;;; conditional compilation
-(defprinter cc-if (test body-forms)
+(defprinter js:cc-if (test &rest body)
(psw "/*@if ")
(ps-print test)
(incf *indent-level*)
- (dolist (form body-forms)
+ (dolist (form body)
(newline-and-indent) (ps-print form) (psw #\;))
(decf *indent-level*)
(newline-and-indent)
(psw "@end @*/"))
-(defprinter js-instanceof (value type)
+(defprinter js:instanceof (value type)
(psw #\()
- (if (> (expression-precedence value) (op-precedence 'js-instance-of))
+ (if (> (expression-precedence value) (op-precedence 'js:instanceof))
(parenthesize-print value)
(ps-print value))
(psw " instanceof ")
- (if (> (expression-precedence type) (op-precedence 'js-instance-of))
+ (if (> (expression-precedence type) (op-precedence 'js:instanceof))
(parenthesize-print type)
(ps-print type))
(psw #\)))
-(defprinter js-escape (lisp-form)
- (psw `(ps1* ,lisp-form)))
+(defprinter js:escape (literal-js)
+ (psw literal-js))
;;; named statements
-(macrolet ((def-stmt-printer (&rest stmts)
- `(progn ,@(mapcar (lambda (stmt)
- `(defprinter ,(intern (format nil "JS-~a" stmt)) (expr)
- (psw (format nil "~(~a~) " ',stmt))
- (ps-print expr)))
- stmts))))
- (def-stmt-printer throw return))
+(defprinter js:throw (x)
+ (psw "throw ") (ps-print x))
+
+(defprinter js:return (x)
+ (psw "return ") (ps-print x))
-(in-package :parenscript)
+(in-package "PARENSCRIPT")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; literals
`(progn
(add-ps-literal ',name)
(define-ps-special-form ,name ()
- (list 'js-literal ,string))))
+ (list 'js:literal ,string))))
(defpsliteral this "this")
(defpsliteral t "true")
(add-ps-literal ',name)
(define-ps-special-form ,name (&optional label)
(list ',printer label)))))
- (def-for-literal break js-break)
- (def-for-literal continue js-continue))
+ (def-for-literal break js:break)
+ (def-for-literal continue js:continue))
(defpsmacro quote (x)
(typecase x
(let ((op (if (listp op) (car op) op))
(spacep (if (listp op) (second op) nil)))
`(define-ps-special-form ,op (x)
- (list 'unary-operator ',op
+ (list 'js:unary-operator ',op
(compile-parenscript-form x :expecting :expression)
:prefix t :space ,spacep))))
ops))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; statements
(define-ps-special-form return (&optional value)
- (list 'js-return (compile-parenscript-form value :expecting :expression)))
+ `(js:return ,(compile-parenscript-form value :expecting :expression)))
(define-ps-special-form throw (value)
- (list 'js-throw (compile-parenscript-form value :expecting :expression)))
+ `(js:throw ,(compile-parenscript-form value :expecting :expression)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; arrays
(define-ps-special-form array (&rest values)
- (cons 'array-literal (mapcar (lambda (form) (compile-parenscript-form form :expecting :expression))
+ `(js:array ,@(mapcar (lambda (form) (compile-parenscript-form form :expecting :expression))
values)))
(define-ps-special-form aref (array &rest coords)
- (list 'js-aref (compile-parenscript-form array :expecting :expression)
- (mapcar (lambda (form)
- (compile-parenscript-form form :expecting :expression))
- coords)))
+ `(js:aref ,(compile-parenscript-form array :expecting :expression)
+ ,(mapcar (lambda (form)
+ (compile-parenscript-form form :expecting :expression))
+ coords)))
(defpsmacro list (&rest values)
`(array ,@values))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; operators
(define-ps-special-form incf (x &optional (delta 1))
- (if (equal delta 1)
- (list 'unary-operator '++ (compile-parenscript-form x :expecting :expression) :prefix t)
- (list 'operator '+= (list (compile-parenscript-form x :expecting :expression)
- (compile-parenscript-form delta :expecting :expression)))))
+ (if (eql delta 1)
+ `(js:unary-operator js:++ ,(compile-parenscript-form x :expecting :expression) :prefix t)
+ `(js:operator js:+= ,(compile-parenscript-form x :expecting :expression)
+ ,(compile-parenscript-form delta :expecting :expression))))
(define-ps-special-form decf (x &optional (delta 1))
- (if (equal delta 1)
- (list 'unary-operator '-- (compile-parenscript-form x :expecting :expression) :prefix t)
- (list 'operator '-= (list (compile-parenscript-form x :expecting :expression)
- (compile-parenscript-form delta :expecting :expression)))))
+ (if (eql delta 1)
+ `(js:unary-operator js:-- ,(compile-parenscript-form x :expecting :expression) :prefix t)
+ `(js:operator js:-= ,(compile-parenscript-form x :expecting :expression)
+ ,(compile-parenscript-form delta :expecting :expression))))
(define-ps-special-form - (first &rest rest)
- (if (null rest)
- (list 'unary-operator '- (compile-parenscript-form first :expecting :expression) :prefix t)
- (list 'operator '- (mapcar (lambda (val) (compile-parenscript-form val :expecting :expression))
- (cons first rest)))))
+ (if rest
+ `(js:operator js:- ,@(mapcar (lambda (val) (compile-parenscript-form val :expecting :expression))
+ (cons first rest)))
+ `(js:unary-operator js:- ,(compile-parenscript-form first :expecting :expression) :prefix t)))
(define-ps-special-form not (x)
(let ((form (compile-parenscript-form x :expecting :expression))
- (not-op nil))
- (if (and (eql (first form) 'operator)
- (= (length (third form)) 2)
- (setf not-op (case (second form)
- (== '!=)
- (< '>=)
- (> '<=)
- (<= '>)
- (>= '<)
- (!= '==)
- (=== '!==)
- (!== '===)
- (t nil))))
- (list 'operator not-op (third form))
- (list 'unary-operator '! form :prefix t))))
+ inverse-op)
+ (if (and (eq (car form) 'js:operator)
+ (= (length (cddr form)) 2)
+ (setf inverse-op (case (cadr form)
+ (== '!=)
+ (< '>=)
+ (> '<=)
+ (<= '>)
+ (>= '<)
+ (!= '==)
+ (=== '!==)
+ (!== '===))))
+ `(js:operator ,inverse-op ,@(cddr form))
+ `(js:unary-operator js:! ,form :prefix t))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; control structures
(defun flatten-blocks (body)
(when body
(if (and (listp (car body))
- (eql 'js-block (caar body)))
+ (eq 'js:block (caar body)))
(append (third (car body)) (flatten-blocks (cdr body)))
(cons (car body) (flatten-blocks (cdr body))))))
(or (numberp form)
(stringp form)
(and (listp form)
- (eql 'js-literal (car form)))))
+ (eq 'js:literal (car form)))))
(define-ps-special-form progn (&rest body)
(if (and (eq expecting :expression) (= 1 (length body)))
(compile-parenscript-form (car body) :expecting :expression)
- (list 'js-block
- expecting
- (let* ((block (mapcar (lambda (form)
- (compile-parenscript-form form :expecting expecting))
- body))
- (clean-block (remove nil block))
- (flat-block (flatten-blocks clean-block))
- (reachable-block (append (remove-if #'constant-literal-form-p (butlast flat-block))
- (last flat-block))))
- reachable-block))))
+ `(js:block
+ ,expecting
+ ,(let* ((block (flatten-blocks (remove nil (mapcar (lambda (form)
+ (compile-parenscript-form form :expecting expecting))
+ body)))))
+ (append (remove-if #'constant-literal-form-p (butlast block)) (last block))))))
(define-ps-special-form cond (&rest clauses)
(ecase expecting
- (:statement (list 'js-cond-statement
- (mapcar (lambda (clause)
- (destructuring-bind (test &rest body)
- clause
- (list (compile-parenscript-form test :expecting :expression)
- (compile-parenscript-form `(progn ,@body) :expecting :statement))))
- clauses)))
+ (:statement `(js:cond ,(mapcar (lambda (clause)
+ (destructuring-bind (test &rest body)
+ clause
+ (list (compile-parenscript-form test :expecting :expression)
+ (compile-parenscript-form `(progn ,@body) :expecting :statement))))
+ clauses)))
(:expression (make-cond-clauses-into-nested-ifs clauses))))
(defun make-cond-clauses-into-nested-ifs (clauses)
`(js:? ,(compile-parenscript-form test :expecting :expression)
,(compile-parenscript-form `(progn ,@body) :expecting :expression)
,(make-cond-clauses-into-nested-ifs (cdr clauses)))))
- (compile-parenscript-form nil :expecting :expression)))
+ (compile-parenscript-form nil :expecting :expression))) ;; js:null
(define-ps-special-form if (test then &optional else)
(ecase expecting
,(compile-parenscript-form else :expecting :expression)))))
(define-ps-special-form switch (test-expr &rest clauses)
- (let ((clauses (mapcar (lambda (clause)
- (let ((val (car clause))
- (body (cdr clause)))
- (cons (if (and (symbolp val)
- (eq (ensure-ps-symbol val) 'default))
- 'default
- (compile-parenscript-form val :expecting :expression))
- (mapcar (lambda (statement) (compile-parenscript-form statement :expecting :statement))
- body))))
- clauses))
- (expr (compile-parenscript-form test-expr :expecting :expression)))
- (list 'js-switch expr clauses)))
+ `(js:switch ,(compile-parenscript-form test-expr :expecting :expression)
+ ,(loop for (val . body) in clauses collect
+ (cons (if (and (symbolp val) (eq (ensure-ps-symbol val) 'default))
+ 'default
+ (compile-parenscript-form val :expecting :expression))
+ (mapcar (lambda (x) (compile-parenscript-form x :expecting :statement))
+ body)))))
(defpsmacro case (value &rest clauses)
(labels ((make-clause (val body more)
;; the first compilation will produce a list of variables we need to declare in the function body
(compile-parenscript-form `(progn ,@body) :expecting :statement)
;; now declare and compile
- (compile-parenscript-form `(progn ,@(loop for var in *enclosing-lexical-block-declarations* collect `(var ,var))
- ,@body) :expecting :statement))))
+ (compile-parenscript-form `(progn
+ ,@(mapcar (lambda (var) `(var ,var)) *enclosing-lexical-block-declarations*)
+ ,@body)
+ :expecting :statement))))
(define-ps-special-form %js-lambda (args &rest body)
- (cons 'js-lambda (compile-function-definition args body)))
+ `(js:lambda ,@(compile-function-definition args body)))
(define-ps-special-form %js-defun (name args &rest body)
- (append (list 'js-defun name) (compile-function-definition args body)))
+ `(js:defun ,name ,@(compile-function-definition args body)))
(defun parse-function-body (body)
(let* ((docstring
(if rest?
(with-ps-gensyms (i)
`(progn (var ,rest (array))
- (dotimes (,i (- arguments.length ,(length effective-args)))
+ (dotimes (,i (- (slot-value arguments 'length) ,(length effective-args)))
(setf (aref ,rest ,i) (aref arguments (+ ,i ,(length effective-args)))))))
`(progn)))
(body-paren-forms (parse-function-body body)) ; remove documentation
(cons t (lambda (x) (declare (ignore x)) expansion)))))
(compile-parenscript-form `(progn ,@body))))
-(define-ps-special-form defmacro (name args &body body)
+(define-ps-special-form defmacro (name args &body body) ;; should this be a macro?
(eval `(defpsmacro ,name ,args ,@body))
nil)
-(define-ps-special-form define-symbol-macro (name expansion)
+(define-ps-special-form define-symbol-macro (name expansion) ;; should this be a macro?
(eval `(define-ps-symbol-macro ,name ,expansion))
nil)
(define-ps-symbol-macro {} (create))
(define-ps-special-form create (&rest arrows)
- (list 'js-object (loop for (key-expr val-expr) on arrows by #'cddr collecting
- (let ((key (compile-parenscript-form key-expr :expecting :expression)))
- (when (keywordp key)
- (setf key (list 'js-variable key)))
- (assert (or (stringp key)
- (numberp key)
- (and (listp key)
- (or (eq 'js-variable (car key))
- (eq 'quote (car key)))))
- ()
- "Slot key ~s is not one of js-variable, keyword, string or number." key)
- (cons key (compile-parenscript-form val-expr :expecting :expression))))))
+ `(js:object ,@(loop for (key-expr val-expr) on arrows by #'cddr collecting
+ (let ((key (compile-parenscript-form key-expr :expecting :expression)))
+ (when (keywordp key)
+ (setf key `(js:variable ,key)))
+ (assert (or (stringp key)
+ (numberp key)
+ (and (listp key)
+ (or (eq 'js:variable (car key))
+ (eq 'quote (car key)))))
+ ()
+ "Slot key ~s is not one of js-variable, keyword, string or number." key)
+ (cons key (compile-parenscript-form val-expr :expecting :expression))))))
(define-ps-special-form %js-slot-value (obj slot)
- (list 'js-slot-value (compile-parenscript-form obj :expecting :expression)
- (if (and (listp slot) (eq 'quote (car slot)))
- (second slot) ;; assume we're quoting a symbol
- (compile-parenscript-form slot))))
+ `(js:slot-value ,(compile-parenscript-form obj :expecting :expression)
+ ,(if (and (listp slot) (eq 'quote (car slot)))
+ (second slot) ;; assume we're quoting a symbol
+ (compile-parenscript-form slot))))
(define-ps-special-form instanceof (value type)
- (list 'js-instanceof (compile-parenscript-form value :expecting :expression)
- (compile-parenscript-form type :expecting :expression)))
+ `(js:instanceof ,(compile-parenscript-form value :expecting :expression)
+ ,(compile-parenscript-form type :expecting :expression)))
(defpsmacro slot-value (obj &rest slots)
(if (null (rest slots))
(/ '/=)
(t nil)))
-(defun smart-setf (lhs rhs)
- (if (and (listp rhs)
- (eql 'operator (car rhs))
- (member lhs (third rhs) :test #'equalp))
- (let ((args-without-first (remove lhs (third rhs) :count 1 :end 1 :test #'equalp)))
- (cond ((and (assignment-op (second rhs))
- (member (second rhs) '(+ *))
- (equalp lhs (first (third rhs))))
- (list 'operator (assignment-op (second rhs))
- (list lhs (list 'operator (second rhs) args-without-first))))
- (t (list 'js-assign lhs rhs))))
- (list 'js-assign lhs rhs)))
-
(define-ps-special-form setf1% (lhs rhs)
- (smart-setf (compile-parenscript-form lhs :expecting :expression) (compile-parenscript-form rhs :expecting :expression)))
+ (let ((lhs (compile-parenscript-form lhs :expecting :expression))
+ (rhs (compile-parenscript-form rhs :expecting :expression)))
+ (if (and (listp rhs)
+ (eq 'js:operator (car rhs))
+ (member (cadr rhs) '(+ *))
+ (equalp lhs (caddr rhs)))
+ `(js:operator ,(assignment-op (cadr rhs)) ,lhs (js:operator ,(cadr rhs) ,@(cdddr rhs)))
+ `(js:= ,lhs ,rhs))))
(defpsmacro setf (&rest args)
(flet ((process-setf-clause (place value-form)
(check-setq-args args)
`(psetf ,@args))
-(define-ps-special-form var (name &rest value)
- (append (list 'js-var name)
- (when value
- (assert (= (length value) 1) () "Wrong number of arguments to var: ~s" `(var ,name ,@value))
- (list (compile-parenscript-form (car value) :expecting :expression)))))
+(define-ps-special-form var (name &optional (value (values) value-provided?) documentation)
+ (declare (ignore documentation))
+ `(js:var ,name ,@(when value-provided?
+ (list (compile-parenscript-form value :expecting :expression)))))
-(defpsmacro defvar (name &rest value)
+(defpsmacro defvar (name &optional (value (values) value-provided?) documentation)
"Note: this must be used as a top-level form, otherwise the result will be undefined behavior."
(pushnew name *ps-special-variables*)
- (assert (or (null value) (= (length value) 1)) () "Wrong number of arguments to defvar: ~s" `(defvar ,name ,@value))
- `(var ,name ,@value))
+ `(var ,name ,@(when value-provided? (list value))))
(defun make-let-vars (bindings)
(mapcar (lambda (x) (if (listp x) (car x) x)) bindings))
init-forms))
(define-ps-special-form labeled-for (label init-forms cond-forms step-forms &rest body)
- (let ((vars (make-for-vars/inits init-forms))
- (steps (mapcar (lambda (x) (compile-parenscript-form x :expecting :expression)) step-forms))
- (tests (mapcar (lambda (x) (compile-parenscript-form x :expecting :expression)) cond-forms))
- (body (compile-parenscript-form `(progn ,@body))))
- (list 'js-for label vars tests steps body)))
+ `(js:for ,label
+ ,(make-for-vars/inits init-forms)
+ ,(mapcar (lambda (x) (compile-parenscript-form x :expecting :expression)) cond-forms)
+ ,(mapcar (lambda (x) (compile-parenscript-form x :expecting :expression)) step-forms)
+ ,(compile-parenscript-form `(progn ,@body))))
(defpsmacro for (init-forms cond-forms step-forms &body body)
`(labeled-for nil ,init-forms ,cond-forms ,step-forms ,@body))
,@body
,(do-make-iter-psteps decls)))))
-(define-ps-special-form for-in (decl &rest body)
- (list 'js-for-in
- (compile-parenscript-form (first decl) :expecting :expression)
- (compile-parenscript-form (second decl) :expecting :expression)
- (compile-parenscript-form `(progn ,@body))))
-
-(defpsmacro doeach ((var array &optional (result (values) result?)) &body body)
- "Iterates over `array'. If `var' is a symbol, binds `var' to each
-element key. If `var' is a list, it must be a list of two
-symbols, (key value), which will be bound to each successive key/value
-pair in `array'."
- (if result?
- (if (consp var)
- (destructuring-bind (key val) var
- `((lambda ()
- (let* (,val)
- (for-in ((var ,key) ,array)
- (setf ,val (aref ,array ,key))
- ,@body)
- (return ,result)))))
- `((lambda ()
- (for-in ((var ,var) ,array)
- ,@body)
- (return ,result))))
- (if (consp var)
- (destructuring-bind (key val) var
- `(progn
- (let* (,val)
- (for-in ((var ,key) ,array)
- (setf ,val (aref ,array ,key))
- ,@body))))
- `(progn
- (for-in ((var ,var) ,array) ,@body)))))
+(define-ps-special-form for-in ((var object) &rest body)
+ `(js:for-in ,(compile-parenscript-form `(var ,var) :expecting :expression)
+ ,(compile-parenscript-form object :expecting :expression)
+ ,(compile-parenscript-form `(progn ,@body))))
(define-ps-special-form while (test &rest body)
- (list 'js-while (compile-parenscript-form test :expecting :expression)
- (compile-parenscript-form `(progn ,@body))))
+ `(js:while ,(compile-parenscript-form test :expecting :expression)
+ ,(compile-parenscript-form `(progn ,@body))))
(defpsmacro dotimes ((var count &optional (result nil result?)) &rest body)
`(do* ((,var 0 (1+ ,var)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; misc
(define-ps-special-form with (expression &rest body)
- (list 'js-with (compile-parenscript-form expression :expecting :expression)
- (compile-parenscript-form `(progn ,@body))))
+ `(js:with ,(compile-parenscript-form expression :expecting :expression)
+ ,(compile-parenscript-form `(progn ,@body))))
(define-ps-special-form try (form &rest clauses)
(let ((catch (cdr (assoc :catch clauses)))
(assert (not (cdar catch)) nil "Sorry, currently only simple catch forms are supported.")
(assert (or catch finally) ()
"Try form should have either a catch or a finally clause or both.")
- (list 'js-try (compile-parenscript-form `(progn ,form))
- :catch (when catch (list (compile-parenscript-form (caar catch) :expecting :symbol)
+ `(js:try ,(compile-parenscript-form `(progn ,form))
+ :catch ,(when catch (list (compile-parenscript-form (caar catch) :expecting :symbol)
(compile-parenscript-form `(progn ,@(cdr catch)))))
- :finally (when finally (compile-parenscript-form `(progn ,@finally))))))
+ :finally ,(when finally (compile-parenscript-form `(progn ,@finally))))))
(define-ps-special-form cc-if (test &rest body)
- (list 'cc-if test (mapcar #'compile-parenscript-form body)))
+ `(js:cc-if ,test ,@(mapcar #'compile-parenscript-form body)))
(define-ps-special-form regex (regex)
- (list 'js-regex (string regex)))
+ `(js:regex ,(string regex)))
(define-ps-special-form lisp (lisp-form)
;; (ps (foo (lisp bar))) is in effect equivalent to (ps* `(foo ,bar))
;; when called from inside of ps*, lisp-form has access only to the dynamic environment (like for eval)
- (list 'js-escape lisp-form))
+ `(js:escape ,(ps1* lisp-form)))