Common Lisp hackery: writing fasls from non-file input
Monday, July 13th, 2009 09:08Common Lisp provides compile-file whose purposes is to convert a CL source file into an (implementation-defined) format which usually has precompiled code and is designed for faster loading into a lisp system.
compile-file takes the pathname of a textual lisp source file. But what if you want to compile some Lisp code that's not in a file already, perhaps because you translated/compiled it from some not-amenable-to-the-Lisp-reader input syntax, or because it contains unREADable literals? You can use a "universal Lisp file", which I know two ways to create (use whichever you find cleaner):
or(cl:in-package :mypackage) #.mypackage::*program*
(cl:in-package :mypackage) (macrolet ((it () *program*)) (it))
Suppose this is in "universal.lisp". Then to use it:
(defvar *program*)
(defun compile-to-file (form output-file)
(let ((*program* form))
(compile-file #p"universal.lisp"
:output-file output-file)))
This is just a minimal example; you'll also want to appropriately handle the return value from compile-file, provide an appropriate pathname to the universal file, etc. For example, here's an excerpt of the relevant code from E-on-CL, where I have used this technique to compile non-CL sources (emakers) into fasls:
(defparameter +the-asdf-system+ (asdf:find-system :e-on-cl))
(defvar *efasl-program*)
(defvar *efasl-result*)
...
(defun compile-e-to-file (expr output-file fqn-prefix opt-scope)
...
(let* (...
(*efasl-program*
`(setf *efasl-result*
(lambda (...) ...))))
(multiple-value-bind (truename warnings-p failure-p)
(compile-file (merge-pathnames
#p"lisp/universal.lisp"
(asdf:component-pathname +the-asdf-system+))
:output-file output-file
:verbose nil
:print nil)
(declare (ignore truename warnings-p))
(assert (not failure-p) () "Compilation for ~A failed." output-file))))
(defun load-compiled-e (file env)
(let ((*efasl-result* nil)
...)
(load file :verbose nil :print nil)
(funcall *efasl-result* env)))
Note that the pathname is computed relative to the ASDF system containing the universal file; also note the use of a variable *efasl-result* to simulate a "return value" from the compiled file, and the use of a lambda to provide a nonempty lexical environment, both of which are features not directly provided by the CL compiled file facility.
(no subject)
Date: 2009-07-13 16:01 (UTC)would this help?
Date: 2009-07-15 20:04 (UTC)extensions:compile-from-stream input-stream &key :error-stream :trace-stream :block-compile :entry-points :byte-compile
http://common-lisp.net/project/cmucl/doc/cmu-user/compiler.html#toc113
Re: would this help?
Date: 2009-07-19 21:40 (UTC)