X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler.lisp;h=2f2043265ed4e83ca9eaa2604f576f8888f5dae3;hb=d4ade72f9e7c97217ffafb7f9ca37f12161148af;hp=c824940463d82ba800db35d107b0b7112179762b;hpb=f5ffe129c45d75d9f360d02d9b8823907b163347;p=jscl.git diff --git a/src/compiler.lisp b/src/compiler.lisp index c824940..2f20432 100644 --- a/src/compiler.lisp +++ b/src/compiler.lisp @@ -207,7 +207,7 @@ `(push (list ',name (lambda ,args (block ,name ,@body))) *compilations*)) -(define-compilation if (condition true false) +(define-compilation if (condition true &optional false) (code "(" (ls-compile condition) " !== " (ls-compile nil) " ? " (ls-compile true *multiple-value-p*) " : " (ls-compile false *multiple-value-p*) @@ -468,9 +468,12 @@ (define-compilation setq (&rest pairs) (let ((result "")) + (when (null pairs) + (return-from setq (ls-compile nil))) (while t (cond - ((null pairs) (return)) + ((null pairs) + (return)) ((null (cdr pairs)) (error "Odd pairs in SETQ")) (t @@ -725,6 +728,19 @@ ",") ")"))) +(define-compilation macrolet (definitions &rest body) + (let ((*environment* (copy-lexenv *environment*))) + (dolist (def definitions) + (destructuring-bind (name lambda-list &body body) def + (let ((binding (make-binding :name name :type 'macro :value + (let ((g!form (gensym))) + `(lambda (,g!form) + (destructuring-bind ,lambda-list ,g!form + ,@body)))))) + (push-to-lexenv binding *environment* 'function)))) + (ls-compile `(progn ,@body) *multiple-value-p*))) + + (defun special-variable-p (x) (and (claimp x 'variable 'special) t)) @@ -1236,12 +1252,6 @@ "var x = " x ";" *newline* "return (typeof(" x ") == \"string\") && (x.length == 1 || x.length == 2);"))) -(define-builtin char-to-string (x) - (js!selfcall - "var r = [" x "];" *newline* - "r.type = 'character';" - "return r")) - (define-builtin char-upcase (x) (code "safe_char_upcase(" x ")")) @@ -1252,30 +1262,7 @@ (js!bool (js!selfcall "var x = " x ";" *newline* - "return typeof(x) == 'object' && 'length' in x && x.type == 'character';"))) - -(define-builtin string-upcase (x) - (code "make_lisp_string(xstring(" x ").toUpperCase())")) - -(define-builtin string-length (x) - (code x ".length")) - -(define-raw-builtin slice (vector a &optional b) - (js!selfcall - "var vector = " (ls-compile vector) ";" *newline* - "var a = " (ls-compile a) ";" *newline* - "var b;" *newline* - (when b (code "b = " (ls-compile b) ";" *newline*)) - "return vector.slice(a,b);" *newline*)) - -(define-builtin char (string index) - (code string "[" index "]")) - -(define-builtin concat-two (string1 string2) - (js!selfcall - "var r = " string1 ".concat(" string2 ");" *newline* - "r.type = 'character';" - "return r;" *newline*)) + "return typeof(x) == 'object' && 'length' in x && x.stringp == 1;"))) (define-raw-builtin funcall (func &rest args) (js!selfcall @@ -1317,83 +1304,54 @@ (define-builtin %throw (string) (js!selfcall "throw " string ";" *newline*)) -(define-builtin new () "{}") - -(define-builtin objectp (x) - (js!bool (code "(typeof (" x ") === 'object')"))) - -(define-builtin oget (object key) - (js!selfcall - "var tmp = " "(" object ")[xstring(" key ")];" *newline* - "return tmp == undefined? " (ls-compile nil) ": tmp ;" *newline*)) - -(define-builtin oset (object key value) - (code "((" object ")[xstring(" key ")] = " value ")")) - -(define-builtin in (key object) - (js!bool (code "(xstring(" key ") in (" object "))"))) - -(define-builtin map-for-in (function object) - (js!selfcall - "var f = " function ";" *newline* - "var g = (typeof f === 'function' ? f : f.fvalue);" *newline* - "var o = " object ";" *newline* - "for (var key in o){" *newline* - (indent "g(" (if *multiple-value-p* "values" "pv") ", 1, o[key]);" *newline*) - "}" - " return " (ls-compile nil) ";" *newline*)) - (define-builtin functionp (x) (js!bool (code "(typeof " x " == 'function')"))) (define-builtin write-string (x) (code "lisp.write(" x ")")) -(define-builtin make-array (n) - (js!selfcall - "var r = [];" *newline* - "for (var i = 0; i < " n "; i++)" *newline* - (indent "r.push(" (ls-compile nil) ");" *newline*) - "return r;" *newline*)) -;;; FIXME: should take optional min-extension. -;;; FIXME: should use fill-pointer instead of the absolute end of array -(define-builtin vector-push-extend (new vector) - (js!selfcall - "var v = " vector ";" *newline* - "v.push(" new ");" *newline* - "return v;")) +;;; Storage vectors. They are used to implement arrays and (in the +;;; future) structures. -(define-builtin arrayp (x) +(define-builtin storage-vector-p (x) (js!bool (js!selfcall "var x = " x ";" *newline* "return typeof x === 'object' && 'length' in x;"))) -(define-builtin aref (array n) +(define-builtin make-storage-vector (n) (js!selfcall - "var x = " "(" array ")[" n "];" *newline* + "var r = [];" *newline* + "r.length = " n ";" *newline* + "return r;" *newline*)) + +(define-builtin storage-vector-size (x) + (code x ".length")) + +(define-builtin resize-storage-vector (vector new-size) + (code "(" vector ".length = " new-size ")")) + +(define-builtin storage-vector-ref (vector n) + (js!selfcall + "var x = " "(" vector ")[" n "];" *newline* "if (x === undefined) throw 'Out of range';" *newline* "return x;" *newline*)) -(define-builtin aset (array n value) +(define-builtin storage-vector-set (vector n value) (js!selfcall - "var x = " array ";" *newline* + "var x = " vector ";" *newline* "var i = " n ";" *newline* "if (i < 0 || i >= x.length) throw 'Out of range';" *newline* "return x[i] = " value ";" *newline*)) -(define-builtin afind (value array) - (js!selfcall - "var v = " value ";" *newline* - "var x = " array ";" *newline* - "return x.indexOf(v);" *newline*)) - -(define-builtin aresize (array new-size) +(define-builtin concatenate-storage-vector (sv1 sv2) (js!selfcall - "var x = " array ";" *newline* - "var n = " new-size ";" *newline* - "return x.length = n;" *newline*)) + "var sv1 = " sv1 ";" *newline* + "var r = sv1.concat(" sv2 ");" *newline* + "r.type = sv1.type;" *newline* + "r.stringp = sv1.stringp;" *newline* + "return r;" *newline*)) (define-builtin get-internal-real-time () "(new Date()).getTime()") @@ -1411,6 +1369,54 @@ ;;; Javascript FFI +(define-builtin new () "{}") + +(define-raw-builtin oget* (object key &rest keys) + (js!selfcall + "var tmp = (" (ls-compile object) ")[xstring(" (ls-compile key) ")];" *newline* + (mapconcat (lambda (key) + (code "if (tmp === undefined) return " (ls-compile nil) ";" *newline* + "tmp = tmp[xstring(" (ls-compile key) ")];" *newline*)) + keys) + "return tmp === undefined? " (ls-compile nil) " : tmp;" *newline*)) + +(define-raw-builtin oset* (value object key &rest keys) + (let ((keys (cons key keys))) + (js!selfcall + "var obj = " (ls-compile object) ";" *newline* + (mapconcat (lambda (key) + (code "obj = obj[xstring(" (ls-compile key) ")];" + "if (obj === undefined) throw 'Impossible to set Javascript property.';" *newline*)) + (butlast keys)) + "var tmp = obj[xstring(" (ls-compile (car (last keys))) ")] = " (ls-compile value) ";" *newline* + "return tmp === undefined? " (ls-compile nil) " : tmp;" *newline*))) + +(define-raw-builtin oget (object key &rest keys) + (code "js_to_lisp(" (ls-compile `(oget* ,object ,key ,@keys)) ")")) + +(define-raw-builtin oset (value object key &rest keys) + (ls-compile `(oset* (lisp-to-js ,value) ,object ,key ,@keys))) + +(define-builtin objectp (x) + (js!bool (code "(typeof (" x ") === 'object')"))) + +(define-builtin lisp-to-js (x) (code "lisp_to_js(" x ")")) +(define-builtin js-to-lisp (x) (code "js_to_lisp(" x ")")) + + +(define-builtin in (key object) + (js!bool (code "(xstring(" key ") in (" object "))"))) + +(define-builtin map-for-in (function object) + (js!selfcall + "var f = " function ";" *newline* + "var g = (typeof f === 'function' ? f : f.fvalue);" *newline* + "var o = " object ";" *newline* + "for (var key in o){" *newline* + (indent "g(" (if *multiple-value-p* "values" "pv") ", 1, o[key]);" *newline*) + "}" + " return " (ls-compile nil) ";" *newline*)) + (define-compilation %js-vref (var) (code "js_to_lisp(" var ")")) @@ -1479,7 +1485,7 @@ (mapcar #'ls-compile args)) ", ") ")"))) (unless (or (symbolp function) (and (consp function) - (eq (car function) 'lambda))) + (member (car function) '(lambda oget)))) (error "Bad function designator `~S'" function)) (cond ((translate-function function) @@ -1488,8 +1494,14 @@ #+jscl (eq (symbol-package function) (find-package "COMMON-LISP")) #-jscl t) (code (ls-compile `',function) ".fvalue" arglist)) + #+jscl((symbolp function) + (code (ls-compile `#',function) arglist)) + ((and (consp function) (eq (car function) 'lambda)) + (code (ls-compile `#',function) arglist)) + ((and (consp function) (eq (car function) 'oget)) + (code (ls-compile function) arglist)) (t - (code (ls-compile `#',function) arglist))))) + (error "Bad function descriptor"))))) (defun ls-compile-block (sexps &optional return-last-p decls-allowed-p) (multiple-value-bind (sexps decls)