The function compile-file
performs compilation of
forms in a file following the rules specified in Section 3.2.2 (Compilation Semantics),
and produces an output file that can be loaded by using load
.
Normally, the top level forms appearing in a file compiled with
compile-file
are evaluated only when the resulting
compiled file is loaded, and not when the file is compiled. However,
it is typically the case that some forms in the file need to be evaluated
at compile time so the
remainder of the file can be read and compiled correctly.
The eval-when
special form can be used to control
whether a top level form is evaluated at compile time, load
time, or both. It is possible to specify any of three situations with
eval-when
, denoted by the symbols :compile-toplevel,
:load-toplevel, and :execute. For top level
eval-when
forms, :compile-toplevel specifies that the
compiler must evaluate the body at compile time, and :load-toplevel
specifies that the compiler must arrange to evaluate
the body at load time. For non-top level eval-when
forms,
:execute specifies that the body must be executed in the run-time
environment.
The behavior of this form can be more precisely understood in
terms of a model of how compile-file
processes forms in
a file to be compiled. There are two processing modes, called
“not-compile-time” and “compile-time-too”.
Successive forms are read from the file by compile-file
and processed in not-compile-time mode; in this mode,
compile-file
arranges for forms to be evaluated only at load time
and not at compile time. When compile-file
is in
compile-time-too mode, forms are evaluated both at compile time and
load time.
Processing of top level forms in the file compiler is defined as follows:
notinline
declaration),
the implementation might or might not choose to compute
the compiler macro expansion of the form and,
having performed the expansion, might or might not choose to process the result
as a top level form in the same processing mode
(compile-time-too or not-compile-time).
If it declines to obtain or use the expansion, it must process the original form.
progn
form, each of its
body forms is sequentially processed as a
top level form in the same processing mode.
locally
,
macrolet
, or symbol-macrolet
,
compile-file
establishes the appropriate bindings and processes the
body forms as top level forms with those bindings in effect
in the same processing mode. (Note that this implies that the lexical
environment in which top level forms are processed
is not necessarily the null lexical environment.)
eval-when
form, it is
handled according to the next figure.
|
Figure 3.7: EVAL-WHEN processing
Column CT indicates whether :compile-toplevel is specified. Column LT indicates whether :load-toplevel is specified. Column E indicates whether :execute is specified. Column Mode indicates the processing mode; a dash (—) indicates that the processing mode is not relevant.
The Action column specifies one of three actions:
eval-when
appears.
The New Mode column indicates the new processing mode. A dash (—) indicates the compiler remains in its current mode.
Note that top level forms are processed in the order in which they textually appear in the file and that each top level form read by the compiler is processed before the next is read. However, the order of processing (including macro expansion) of subforms that are not top level forms and the order of further compilation is unspecified as long as Common Lisp semantics are preserved.
eval-when
forms cause compile-time evaluation only at
top level. Both :compile-toplevel and :load-toplevel situation specifications
are ignored for non-top-level forms. For non-top-level forms,
an eval-when
specifying the :execute situation is treated as an implicit progn
including the forms in the body of the eval-when
form;
otherwise, the forms in the body are ignored.
Defining macros (such as defmacro
or defvar
)
appearing within a file being processed by compile-file
normally have compile-time side effects which affect how subsequent forms
in the same file are compiled. A convenient model for explaining how these
side effects happen is that the defining macro expands into one or
more eval-when
forms, and that the calls which cause the compile-time
side effects to happen appear
in the body of an (eval-when (:compile-toplevel) ...)
form.
The compile-time side effects may cause information about the definition to be stored differently than if the defining macro had been processed in the `normal' way (either interpretively or by loading the compiled file).
In particular, the information stored by the defining macros at compile time
might or might not be available to the interpreter (either during or after compilation),
or during subsequent calls to the compiler. For example,
the following code is nonportable because it assumes that the compiler
stores the macro definition of foo
where it is available to the interpreter:
(defmacro foo (x) `(car ,x)) (eval-when (:execute :compile-toplevel :load-toplevel) (print (foo '(a b c))))
A portable way to do the same thing would be to include the macro
definition inside the eval-when
form, as in:
(eval-when (:execute :compile-toplevel :load-toplevel) (defmacro foo (x) `(car ,x)) (print (foo '(a b c))))
The next figure lists macros that make definitions
available both in the compilation and run-time environments.
It is not specified whether definitions made available in the
compilation environment are available in the evaluation
environment, nor is it specified whether they are available
in subsequent compilation units or subsequent invocations of the
compiler. As with eval-when
, these compile-time side
effects happen only when the defining macros appear at
top level.
|
Figure 3.8: Defining Macros That Affect the Compile-Time Environment
Except where explicitly stated otherwise, no macro defined in the Common Lisp standard produces an expansion that could cause any of the subforms of the macro form to be treated as top level forms. If an implementation also provides a special operator definition of a Common Lisp macro, the special operator definition must be semantically equivalent in this respect.
Compiler macro expansions must also have the same top level evaluation semantics as the form which they replace. This is of concern both to conforming implementations and to conforming programs.