X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=lispstrack.lisp;h=d3771feb8eb74e2370bc53bf6180df3f190a893e;hb=34dd089e729a3980a23f26f1f601fd58069f6e27;hp=705c089c63e4f7da39b376799e74d63c9ad772f8;hpb=b41e94b86a1eda01fe890971025e9a36a32b0707;p=jscl.git diff --git a/lispstrack.lisp b/lispstrack.lisp index 705c089..d3771fe 100644 --- a/lispstrack.lisp +++ b/lispstrack.lisp @@ -77,18 +77,36 @@ (ls-compile true env fenv) (ls-compile false env fenv))) -(define-compilation lambda (args &rest body) - (let ((new-env (extend-env args env))) - (concat "(function (" - (join (mapcar (lambda (x) (lookup-variable x new-env)) - args) - ",") - "){ +;;; Return the required args of a lambda list +(defun lambda-list-required-argument (lambda-list) + (if (or (null lambda-list) (eq (car lambda-list) '&rest)) + nil + (cons (car lambda-list) (lambda-list-required-argument (cdr lambda-list))))) + +(defun lambda-list-rest-argument (lambda-list) + (second (member '&rest lambda-list))) + +(define-compilation lambda (lambda-list &rest body) + (let ((required-arguments (lambda-list-required-argument lambda-list)) + (rest-argument (lambda-list-rest-argument lambda-list))) + (let ((new-env (extend-env (cons rest-argument required-arguments) env))) + (concat "(function (" + (join (mapcar (lambda (x) (lookup-variable x new-env)) + required-arguments) + ",") + "){ " - (concat (ls-compile-block (butlast body) env fenv) - "return " (ls-compile (car (last body)) env fenv) ";") - " -})"))) + (if rest-argument + (concat "var " (lookup-variable rest-argument new-env) + " = arguments.slice(" + (prin1-to-string (length required-arguments)) "); +") + "") + + (concat (ls-compile-block (butlast body) new-env fenv) + "return " (ls-compile (car (last body)) new-env fenv) ";") + " +})")))) (define-compilation fsetq (var val) (format nil "~a = ~a" (lookup-function var fenv) (ls-compile val env fenv))) @@ -96,14 +114,29 @@ (define-compilation setq (var val) (format nil "~a = ~a" (lookup-variable var env) (ls-compile val env fenv))) -(defun lisp->js (sexp) + +;;; Literals + +(defvar *literals* '()) + +(defun literal->js (sexp) (cond + ((null sexp) "undefined") ((integerp sexp) (format nil "~a" sexp)) ((stringp sexp) (format nil "\"~a\"" sexp)) - ((listp sexp) (concat "[" (join (mapcar 'lisp->js sexp) ",") "]")))) + ((consp sexp) (concat "{car: " + (literal->js (car sexp)) + ", cdr: " + (literal->js (cdr sexp)) "}")))) + +(let ((counter 0)) + (defun literal (form) + (let ((var (format nil "l~d" (incf counter)))) + (push (cons var (literal->js form)) *literals*) + var))) (define-compilation quote (sexp) - (lisp->js sexp)) + (literal sexp)) (define-compilation debug (form) (format nil "console.log(~a)" (ls-compile form env fenv))) @@ -141,6 +174,14 @@ (define-compilation = (x y) (concat "((" (ls-compile x env fenv) ") == (" (ls-compile y env fenv) "))")) +(define-compilation cons (x y) + (concat "{car: " (ls-compile x env fenv) ", cdr: " (ls-compile y env fenv) "}")) + +(define-compilation car (x) + (concat "(" (ls-compile x env fenv) ").car")) + +(define-compilation cdr (x) + (concat "(" (ls-compile x env fenv) ").cdr")) (defmacro with-eval-when-compilation (&body body) `(setq *eval-when-compilations* @@ -182,13 +223,25 @@ (apply compiler-func env fenv (cdr sexp)) (compile-funcall (car sexp) (cdr sexp) env fenv))))))) +(defun ls-compile-toplevel (sexp) + (setq *literals* nil) + (let ((code (ls-compile sexp))) + (prog1 + (concat (join (mapcar (lambda (lit) + (concat "var " (car lit) " = " (cdr lit) "; +")) + *literals*) + "") + code) + (setq *literals* nil)))) + (defun ls-compile-file (filename output) (with-open-file (in filename) (with-open-file (out output :direction :output :if-exists :supersede) (loop for x = (read in nil) while x - for compilation = (ls-compile x) + for compilation = (ls-compile-toplevel x) when compilation do (write-line (concat compilation "; ") out)))))