(defun gvarname (symbol)
(declare (ignore symbol))
- (code "v" (incf *variable-counter*)))
+ (incf *variable-counter*)
+ (concat "v" (integer-to-string *variable-counter*)))
(defun translate-variable (symbol)
(awhen (lookup-in-lexenv symbol *environment* 'variable)
(if (or name docstring)
(js!selfcall*
`(var (func ,code))
- (when name `(= (get func |fname|) ,name))
- (when docstring `(= (get func |docstring|) ,docstring))
+ (when name `(= (get func "fname") ,name))
+ (when docstring `(= (get func "docstring") ,docstring))
`(return func))
- `(code ,code)))
+ code))
(defun lambda-check-argument-count
(n-required-arguments n-optional-arguments rest-p)
(defvar *literal-counter* 0)
(defun genlit ()
- (code "l" (incf *literal-counter*)))
+ (incf *literal-counter*)
+ (concat "l" (integer-to-string *literal-counter*)))
(defun dump-symbol (symbol)
#-jscl
((and (listp x) (eq (car x) 'lambda))
(compile-lambda (cadr x) (cddr x)))
((and (listp x) (eq (car x) 'named-lambda))
- ;; TODO: destructuring-bind now! Do error checking manually is
- ;; very annoying.
- (let ((name (cadr x))
- (ll (caddr x))
- (body (cdddr x)))
+ (destructuring-bind (name ll &rest body) (cdr x)
(compile-lambda ll body
:name (symbol-name name)
:block name)))
(extend-lexenv (mapcar #'make-function-binding fnames)
*environment*
'function)))
- `(code "(function("
- ,@(interleave (mapcar #'translate-function fnames) ",")
- "){"
- ,(ls-compile-block body t)
- "})(" ,@(interleave cfuncs ",") ")")))
+ `(call (function ,(mapcar #'make-symbol (mapcar #'translate-function fnames))
+ ,(ls-compile-block body t))
+ ,@cfuncs)))
(define-compilation labels (definitions &rest body)
(let* ((fnames (mapcar #'car definitions))
(extend-lexenv (mapcar #'make-function-binding fnames)
*environment*
'function)))
- (js!selfcall
- `(code ,@(mapcar (lambda (func)
- `(code "var " ,(translate-function (car func))
- " = " ,(compile-lambda (cadr func)
- `((block ,(car func) ,@(cddr func))))
- ";" ))
- definitions))
+ (js!selfcall*
+ `(progn
+ ,@(mapcar (lambda (func)
+ `(var (,(make-symbol (translate-function (car func)))
+ ,(compile-lambda (cadr func)
+ `((block ,(car func) ,@(cddr func)))))))
+ definitions))
(ls-compile-block body t))))
(cvalues (mapcar #'ls-compile (mapcar #'second bindings)))
(*environment* (extend-local-env (remove-if #'special-variable-p variables)))
(dynamic-bindings))
- `(code "(function("
- ,@(interleave
- (mapcar (lambda (x)
- (if (special-variable-p x)
- (let ((v (gvarname x)))
- (push (cons x v) dynamic-bindings)
- v)
- (translate-variable x)))
- variables)
- ",")
- "){"
- ,(let ((body (ls-compile-block body t t)))
- `(code ,(let-binding-wrapper dynamic-bindings body)))
- "})(" ,@(interleave cvalues ",") ")")))
+ `(call (function ,(mapcar (lambda (x)
+ (if (special-variable-p x)
+ (let ((v (gvarname x)))
+ (push (cons x v) dynamic-bindings)
+ (make-symbol v))
+ (make-symbol (translate-variable x))))
+ variables)
+ ,(let ((body (ls-compile-block body t t)))
+ `(code ,(let-binding-wrapper dynamic-bindings body))))
+ ,@cvalues)))
;;; Return the code to initialize BINDING, and push it extending the
`(try
,(ls-compile-block body t))
`(catch (|cf|)
- (if (and (== (get |cf| |type|) "catch")
- (== (get |cf| |id|) |id|))
+ (if (and (== (get |cf| "type") "catch")
+ (== (get |cf| "id") |id|))
,(if *multiple-value-p*
- `(return (call (get |values| |apply|)
+ `(return (call (get |values| "apply")
this
- (call |forcemv| (get |cf| |values|))))
- `(return (call (get |pv| |apply|)
+ (call |forcemv| (get |cf| "values"))))
+ `(return (call (get |pv| "apply")
this
- (call |forcemv| (get |cf| |values|)))))
+ (call |forcemv| (get |cf| "values")))))
(throw |cf|)))))
(define-compilation throw (id value)
(define-builtin characterp (x)
(js!bool
- (js!selfcall
- "var x = " x ";"
- "return (typeof(" x ") == \"string\") && (x.length == 1 || x.length == 2);")))
+ (js!selfcall*
+ `(var (x ,x))
+ `(return (and (== (typeof x) "string")
+ (or (== (get x "length") 1)
+ (== (get x "length") 2)))))))
(define-builtin char-upcase (x)
`(call |safe_char_upcase| ,x))
(== (get x "stringp") 1))))))
(define-raw-builtin funcall (func &rest args)
- (js!selfcall
- "var f = " (ls-compile func) ";"
- "return (typeof f === 'function'? f: f.fvalue)("
- `(code
- ,@(interleave (list* (if *multiple-value-p* "values" "pv")
- (integer-to-string (length args))
- (mapcar #'ls-compile args))
- ", "))
- ")"))
+ (js!selfcall*
+ `(var (f ,(ls-compile func)))
+ `(return (call (if (=== (typeof f) "function")
+ f
+ (get f "fvalue"))
+ ,@(list* (if *multiple-value-p* '|values| '|pv|)
+ (length args)
+ (mapcar #'ls-compile args))))))
(define-raw-builtin apply (func &rest args)
(if (null args)
(define-builtin storage-vector-ref (vector n)
(js!selfcall*
- `(var (x (get ,vector ,n)))
+ `(var (x (property ,vector ,n)))
`(if (=== x undefined) (throw "Out of range."))
`(return x)))
`(return r)))
(define-builtin get-internal-real-time ()
- `(call (get (new (call Date)) "getTime")))
+ `(call (get (new (call |Date|)) "getTime")))
(define-builtin values-array (array)
(if *multiple-value-p*
- `(code "values.apply(this, " ,array ")")
- `(code "pv.apply(this, " ,array ")")))
+ `(call (get |values| "apply") this ,array)
+ `(call (get |pv| "apply") this ,array)))
(define-raw-builtin values (&rest args)
(if *multiple-value-p*
- `(code "values(" ,@(interleave (mapcar #'ls-compile args) ",") ")")
- `(code "pv(" ,@(interleave (mapcar #'ls-compile args) ", ") ")")))
-
+ `(call |values| ,@(mapcar #'ls-compile args))
+ `(call |pv| ,@(mapcar #'ls-compile args))))
;;; Javascript FFI
-(define-builtin new () "{}")
+(define-builtin new ()
+ '(object))
(define-raw-builtin oget* (object key &rest keys)
- (js!selfcall
- "var tmp = (" (ls-compile object) ")[xstring(" (ls-compile key) ")];"
- `(code
- ,@(mapcar (lambda (key)
- `(code "if (tmp === undefined) return " ,(ls-compile nil) ";"
- "tmp = tmp[xstring(" ,(ls-compile key) ")];" ))
- keys))
- "return tmp === undefined? " (ls-compile nil) " : tmp;" ))
+ (js!selfcall*
+ `(progn
+ (var (tmp (property ,(ls-compile object) (call |xstring| ,(ls-compile key)))))
+ ,@(mapcar (lambda (key)
+ `(progn
+ (if (=== tmp undefined) (return ,(ls-compile nil)))
+ (= tmp (property tmp (call |xstring| ,(ls-compile key))))))
+ keys))
+ `(return (if (=== tmp undefined) ,(ls-compile nil) tmp))))
(define-raw-builtin oset* (value object key &rest keys)
(let ((keys (cons key keys)))
- (js!selfcall
- "var obj = " (ls-compile object) ";"
- `(code ,@(mapcar (lambda (key)
- `(code "obj = obj[xstring(" ,(ls-compile key) ")];"
- "if (obj === undefined) throw 'Impossible to set Javascript property.';" ))
- (butlast keys)))
- "var tmp = obj[xstring(" (ls-compile (car (last keys))) ")] = " (ls-compile value) ";"
- "return tmp === undefined? " (ls-compile nil) " : tmp;" )))
+ (js!selfcall*
+ `(progn
+ (var (obj ,(ls-compile object)))
+ ,@(mapcar (lambda (key)
+ `(progn
+ (= obj (property obj (call |xstring| ,(ls-compile key))))
+ (if (=== object undefined)
+ (throw "Impossible to set object property."))))
+ (butlast keys))
+ (var (tmp
+ (= (property obj (call |xstring| ,(ls-compile (car (last keys)))))
+ ,(ls-compile value))))
+ (return (if (=== tmp undefined)
+ ,(ls-compile nil)
+ tmp))))))
(define-raw-builtin oget (object key &rest keys)
`(call |js_to_lisp| ,(ls-compile `(oget* ,object ,key ,@keys))))
(js!bool `(in (call |xstring| ,key) ,object)))
(define-builtin map-for-in (function object)
- (js!selfcall
- "var f = " function ";"
- "var g = (typeof f === 'function' ? f : f.fvalue);"
- "var o = " object ";"
- "for (var key in o){"
- `(code "g(" ,(if *multiple-value-p* "values" "pv") ", 1, o[key]);" )
- "}"
- " return " (ls-compile nil) ";" ))
+ (js!selfcall*
+ `(var (f ,function)
+ (g (if (=== (typeof f) "function") f (get f "fvalue")))
+ (o ,object))
+ `(for-in (key o)
+ (call g ,(if *multiple-value-p* '|values| '|pv|) 1 (get o "key")))
+ `(return ,(ls-compile nil))))
(define-compilation %js-vref (var)
- `(code "js_to_lisp(" ,var ")"))
+ `(call |js_to_lisp| ,(make-symbol var)))
(define-compilation %js-vset (var val)
- `(code "(" ,var " = lisp_to_js(" ,(ls-compile val) "))"))
+ `(= ,(make-symbol var) (call |lisp_to_js| ,(ls-compile val))))
(define-setf-expander %js-vref (var)
(let ((new-value (gensym)))