defmacro.ss: Non-Hygienic Macros
To load: (require (lib "defmacro.ss"))
(
SYNTAX
define-macro
identifier expr
)
(
SYNTAX
define-macro
)(
identifier . formals)
expr ···1
Defines a (non-hygienic) macro identifier
as a procedure that
manipulates S-expressions (as opposed to syntax objects). In the
first form, expr
must produce a procedure. In the second form,
formals
determines the formal arguments of the procedure, as in
lambda
, and the expr
s are the procedure body. In both
cases, the procedure is generated in the transformer environment, not
the normal environment (see section 12 in PLT MzScheme: Language Manual).
In a use of the macro,
(identifier expr ···)
is applied to the expression (see
section 12.2.2 in PLT MzScheme: Language Manual), and the macro procedure is applied to the
syntax-object->datum
of the resulting list. If the number of cdr
expr
s does
not match the procedure's arity (see section 3.12.1 in PLT MzScheme: Language Manual) or if
identifier
is used in a context that does not match the above
pattern, then a syntax error is reported.
After the macro procedure returns, the result is compared to the procedure's arguments. For each value that appears exactly once within the arguments (or, more precisely, within the S-expression derived from the original source syntax), if the same value appears in the result, it is replaced with a syntax object from the original expression. This heuristic substitution preserves source location information in many cases, despite the macro procedure's operation on raw S-expressions.
After substituting syntax objects for preserved values, the entire
macro result is converted to syntax with
(see section 12.2.2 in PLT MzScheme: Language Manual). The original
expression supplies the lexical context and source location for
converted elements.datum->syntax-object
(
SYNTAX
defmacro
identifier formals expr ···1
)
Same as (
.define-macro
(identifier
. formals
) expr
···1)
Important: define-macro
is still restricted by
MzScheme's phase separation rules. This means that a macro cannot
access run-time bindings because it is executed in the syntax
expansion phase. Translating code that involves
define-macro
or defmacro
from an implementation
without this restriction usually implies separating macro related
functionality into a begin-for-syntax
or a module (that will
be imported with require-for-syntax
) and properly
distinguishing syntactic information from run-time information.