From: David Vázquez Date: Fri, 3 May 2013 15:56:20 +0000 (+0100) Subject: Macro precompilation X-Git-Url: http://repo.macrolet.net/gitweb/?p=jscl.git;a=commitdiff_plain;h=600d6d4926d3f721ec660cf33c615d85332242ab Macro precompilation --- diff --git a/jscl.lisp b/jscl.lisp index 7a31191..78850dc 100644 --- a/jscl.lisp +++ b/jscl.lisp @@ -68,11 +68,15 @@ when (plusp (length compilation)) do (write-string compilation out))))) + (defun dump-global-environment (stream) (flet ((late-compile (form) (write-string (ls-compile-toplevel form) stream))) - ;; Set the initial global environment to be equal to the host global - ;; environment at this point of the compilation. + ;; We assume that environments have a friendly list representation + ;; for the compiler and it can be dumped. + (dolist (b (lexenv-function *environment*)) + (when (eq (binding-type b) 'macro) + (push *magic-unquote-marker* (binding-value b)))) (late-compile `(setq *environment* ',*environment*)) ;; Set some counter variable properly, so user compiled code will ;; not collide with the compiler itself. @@ -84,6 +88,7 @@ (setq *gensym-counter* ,*gensym-counter*))) (late-compile `(setq *literal-counter* ,*literal-counter*)))) + (defun bootstrap () (setq *environment* (make-lexenv)) (setq *literal-table* nil) diff --git a/src/compiler.lisp b/src/compiler.lisp index e02f253..e109404 100644 --- a/src/compiler.lisp +++ b/src/compiler.lisp @@ -537,7 +537,8 @@ (code "(" result ")"))) -;;; Literals +;;; Compilation of literals an object dumping + (defun escape-string (string) (let ((output "") (index 0) @@ -553,10 +554,19 @@ (incf index)) output)) - (defvar *literal-table* nil) (defvar *literal-counter* 0) +;;; BOOTSTRAP MAGIC: During bootstrap, we record the macro definitions +;;; as lists. Once everything is compiled, we want to dump the whole +;;; global environment to the output file to reproduce it in the +;;; run-time. However, the environment must contain expander functions +;;; rather than lists. We do not know how to dump function objects +;;; itself, so we mark the definitions with this object and the +;;; compiler will be called when this object has to be dumped. +;;; Backquote/unquote does a similar magic, but this use is exclusive. +(defvar *magic-unquote-marker* (gensym "MAGIC-UNQUOTE")) + (defun genlit () (code "l" (incf *literal-counter*))) @@ -597,7 +607,10 @@ (or (cdr (assoc sexp *literal-table*)) (let ((dumped (typecase sexp (symbol (dump-symbol sexp)) - (cons (dump-cons sexp)) + (cons + (if (eq (car sexp) *magic-unquote-marker*) + (ls-compile (cdr sexp)) + (dump-cons sexp))) (array (dump-array sexp))))) (if (and recursive (not (symbolp sexp))) dumped @@ -606,6 +619,7 @@ (toplevel-compilation (code "var " jsvar " = " dumped)) jsvar))))))) + (define-compilation quote (sexp) (literal sexp))