Next: , Previous: Compilation Semantics, Up: Compilation


3.2.3 File Compilation

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.

3.2.3.1 Processing of Top Level Forms

Processing of top level forms in the file compiler is defined as follows:

  1. If the form is a compiler macro form (not disabled by a 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.
  2. If the form is a macro form, its macro expansion is computed and processed as a top level form in the same processing mode (compile-time-too or not-compile-time).
  3. If the form is a progn form, each of its body forms is sequentially processed as a top level form in the same processing mode.
  4. If the form is a 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.)
  5. If the form is an eval-when form, it is handled according to the next figure.

    CT LT E Mode Action New Mode
    Yes Yes Process compile-time-too
    No Yes Yes CTT Process compile-time-too
    No Yes Yes NCT Process not-compile-time
    No Yes No Process not-compile-time
    Yes No Evaluate
    No No Yes CTT Evaluate
    No No Yes NCT Discard
    No No No Discard

    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:

    Process: process the body as top level forms in the specified mode.
    Evaluate: evaluate the body in the dynamic execution context of the compiler, using the evaluation environment as the global environment and the lexical environment in which the eval-when appears.
    Discard: ignore the form.

    The New Mode column indicates the new processing mode. A dash (—) indicates the compiler remains in its current mode.

  6. Otherwise, the form is a top level form that is not one of the special cases. In compile-time-too mode, the compiler first evaluates the form in the evaluation environment and then minimally compiles it. In not-compile-time mode, the form is simply minimally compiled. All subforms are treated as non-top-level forms.

    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.

3.2.3.1.1 Processing of Defining Macros

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.

declaim define-modify-macro defsetf
defclass define-setf-expander defstruct
defconstant defmacro deftype
define-compiler-macro defpackage defvar
define-condition defparameter

Figure 3.8: Defining Macros That Affect the Compile-Time Environment

3.2.3.1.2 Constraints on Macros and Compiler Macros

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.