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.
(setq *gensym-counter* ,*gensym-counter*)))
(late-compile `(setq *literal-counter* ,*literal-counter*))))
+
(defun bootstrap ()
(setq *environment* (make-lexenv))
(setq *literal-table* nil)
(code "(" result ")")))
-;;; Literals
+;;; Compilation of literals an object dumping
+
(defun escape-string (string)
(let ((output "")
(index 0)
(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*)))
(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
(toplevel-compilation (code "var " jsvar " = " dumped))
jsvar)))))))
+
(define-compilation quote (sexp)
(literal sexp))