Common Lisp the Language, 2nd Edition

Next: Environments Up: Macros Previous: Destructuring

# 8.4. Compiler Macros

X3J13 voted in June 1989 (DEFINE-COMPILER-MACRO) to add a facility for defining compiler macros that take effect only when compiling code, not when interpreting it.

The purpose of this facility is to permit selective source-code transformations only when the compiler is processing the code. When the compiler is about to compile a non-atomic form, it first calls `compiler-macroexpand-1` repeatedly until there is no more expansion (there might not be any to begin with). Then it continues its remaining processing, which may include calling `macroexpand-1` and so on.

The compiler is required to expand compiler macros. It is unspecified whether the interpreter does so. The intention is that only the compiler will do so, but the range of possible ``compiled-only'' implementation strategies precludes any firm specification.

[Macro]

    define-compiler-macro name lambda-list {declaration | doc-string}* {form}*

This is just like `defmacro` except the definition is not stored in the symbol function cell of name and is not seen by `macroexpand-1`. It is, however, seen by `compiler-macroexpand-1`. As with `defmacro`, the lambda-list may include `&environment` and `&whole` and may include destructuring. The definition is global. (There is no provision for defining local compiler macros in the way that `macrolet` defines local macros.)

A top-level call to `define-compiler-macro` in a file being compiled by `compile-file` has an effect on the compilation environment similar to that of a call to `defmacro`, except it is noticed as a compiler macro (see section 25.1).

Note that compiler macro definitions do not appear in information returned by `function-information`; they are global, and their interaction with other lexical and global definitions can be reconstructed by `compiler-macro-function`. It is up to code-walking programs to decide whether to invoke compiler macro expansion.

X3J13 voted in March 1988 (FLET-IMPLICIT-BLOCK) to specify that the body of the expander function defined by `defmacro` is implicitly enclosed in a `block` construct whose name is the same as the name of the defined macro; presumably this applies also to `define-compiler-macro`. Therefore `return-from` may be used to exit from the function.

[Function]
`compiler-macro-function` `name` `&optional` `env`

The name must be a symbol. If it has been defined as a compiler macro, then `compiler-macro-function` returns the macro expansion function; otherwise it returns `nil`. The lexical environment env may override any global definition for name by defining a local function or local macro (such as by `flet`, `labels`, or `macrolet`) in which case `nil` is returned.

`setf` may be used with `compiler-macro-function` to install a function as the expansion function for the compiler macro name, in the same manner as for `macro-function`. Storing the value `nil` removes any existing compiler macro definition. As with `macro-function`, a non-`nil` stored value must be a function of two arguments, the entire macro call and the environment. The second argument to `compiler-macro-function` must be omitted when it is used with `setf`.

[Function]
`compiler-macroexpand` `form` `&optional` `env` `
``compiler-macroexpand-1` `form` `&optional` `env`

These are just like `macroexpand` and `macroexpand-1` except that the expander function is obtained as if by a call to `compiler-macro-function` on the car of the form rather than by a call to `macro-function`. Note that `compiler-macroexpand` performs repeated expansion but `compiler-macroexpand-1` performs at most one expansion. Two values are returned, the expansion (or the original form) and a value that is true if any expansion occurred and `nil` otherwise.

There are three cases where no expansion happens:

- There is no compiler macro definition for the car of form.
- There is such a definition but there is also a `notinline` declaration, either globally or in the lexical environment env.
- A global compiler macro definition is shadowed by a local function or macro definition (such as by `flet`, `labels`, or `macrolet`).

Note that if there is no expansion, the original form is returned as the first value, and `nil` as the second value.

Any macro expansion performed by the function `compiler-macroexpand` or by the function `compiler-macroexpand-1` is carried out by calling the function that is the value of `*macroexpand-hook*`.

A compiler macro may decline to provide any expansion merely by returning the original form. This is useful when using the facility to put ``compiler optimizers'' on various function names. For example, here is a compiler macro that ``optimizes'' (one would hope) the zero-argument and one-argument cases of a function called `plus`:

    (define-compiler-macro plus (&whole form &rest args)
      (case (length args)
        (0 0)
        (1 (car args))
        (t form)))

Next: Environments Up: Macros Previous: Destructuring