DEFMACRO.html -- ACL2 Version 6.3

## DEFMACRO

define a macro

    Major Section:  EVENTS

    Example Defmacros:
    (defmacro xor (x y)
      (list 'if x (list 'not y) y))

    (defmacro git (sym key)
      (list 'getprop sym key nil
            '(quote current-acl2-world)
            '(w state)))

    (defmacro one-of (x &rest rst)
      (declare (xargs :guard (symbol-listp rst)))
      (cond ((null rst) nil)
            (t (list 'or
                     (list 'eq x (list 'quote (car rst)))
                     (list* 'one-of x (cdr rst))))))

    Example Expansions:
    term                    macroexpansion

    (xor a b)              (if a (not b) b)
    (xor a (foo b))        (if a (not (foo b)) (foo b))

    (git 'car 'lemmas)     (getprop 'car 'lemmas nil
                                    'current-acl2-world
                                    (w state))

    (one-of x a b c)       (or (eq x 'a)
                               (or (eq x 'b)
                                   (or (eq x 'c) nil)))

    (one-of x 1 2 3)       ill-formed (guard violation)

    General Form:
    (defmacro name macro-args doc-string dcl ... dcl body)

where `name` is a new symbolic name (see name), `macro-args` specifies the formal parameters of the macro, and `body` is a term. The formal parameters can be specified in a much more general way than is allowed by ACL2 `defun` events; see macro-args for a description of keyword (`&key`) and optional (`&optional`) parameters as well as other so-called ``lambda-list keywords'', `&rest` and `&whole`. `Doc-string` is an optional documentation string; see doc-string. Each `dcl` is an optional declaration (see declare) except that the only `xargs` keyword permitted by `defmacro` is `:``guard`.

For compute-intensive applications see the community book `misc/defmac.lisp`, which can speed up macroexpansion by introducing an auxiliary `defun`. For more information, evaluate the form `(include-book "misc/defmac" :dir :system)` and then evaluate `:doc defmac`.

Macroexpansion occurs when a form is read in, i.e., before the evaluation or proof of that form is undertaken. To experiment with macroexpansion, see trans. When a form whose `car` is `name` arises as the form is read in, the arguments are bound as described in CLTL pp. 60 and 145, the guard is checked, and then the `body` is evaluated. The result is used in place of the original form.

In ACL2, macros do not have access to the ACL2 state `state`. (If `state` or any user-defined stobj (see stobj) is a macro argument, it is treated as an ordinary variable, bound at macro-expansion time to a piece of syntax.) This is in part a reflection of CLTL, p. 143, ``More generally, an implementation of Common Lisp has great latitude in deciding exactly when to expand macro calls with a program. ... Macros should be written in such a way as to depend as little as possible on the execution environment to produce a correct expansion.'' In ACL2, the product of macroexpansion is independent of the current environment and is determined entirely by the macro body and the functions and constants it references. It is possible, however, to define macros that produce expansions that refer to `state` or other single-threaded objects (see stobj) or variables not among the macro's arguments. See the `git` example above. For a related utility that does have access to the ACL2 state, see make-event.