103 lines
4.4 KiB
TeX
103 lines
4.4 KiB
TeX
\begin{schemeregion}
|
|
\section{Macro protocols}
|
|
\label{sect:protocols}
|
|
|
|
Some language extensions involve not just a single macro definition, but
|
|
a collection of collaborating macros, or one macro whose multiple uses
|
|
collaborate. Those collaborating macros need ways to share information
|
|
at expansion time.
|
|
|
|
For example, any datatype created with \scheme{define-struct} can be
|
|
recognized and destructured using \scheme{match}, as follows:
|
|
\begin{schemedisplay}
|
|
(define-struct posn (x y))
|
|
|
|
(define (dist-to-origin p)
|
|
(match p
|
|
[(struct posn (a b))
|
|
(sqrt (+ (sqr a) (sqr b)))]))
|
|
\end{schemedisplay}
|
|
The \scheme{define-struct} macro gives \scheme{match} access to the
|
|
names of \scheme{posn}'s predicate and accessor functions, and
|
|
\scheme{match} uses those names in the expansion of the pattern to
|
|
test the value, extract its contents, and bind the results to the
|
|
pattern variables \scheme{a} and \scheme{b}.
|
|
|
|
PLT Scheme provides three mechanisms for compile-time communication between macros:
|
|
static bindings, side-effects, and syntax properties. Each mechanism
|
|
fits a particular form of communication.
|
|
|
|
\subsection{Static binding}
|
|
|
|
PLT Scheme generalizes \scheme{define-syntax} to bind names to
|
|
arbitrary compile-time data. The definition of the \scheme{posn}
|
|
structure above produces something similar to the following:
|
|
\begin{schemedisplay}
|
|
(begin
|
|
(define-values (make-posn posn? posn-x posn-y) ELIDED)
|
|
(define-syntax posn
|
|
(list #'make-posn
|
|
#'posn?
|
|
(list #'posn-x #'posn-y))))
|
|
\end{schemedisplay}
|
|
Despite the use of \scheme{define-syntax}, the definition of
|
|
\scheme{posn} is not a macro, as its value is not a transformer
|
|
procedure. The static information it carries is accessible from other
|
|
macros (such as \scheme{match}) via the \scheme{syntax-local-value}
|
|
procedure.
|
|
|
|
With static binding, the availability of information is tied to the
|
|
name it is bound to. Static binding also relies on the ability to
|
|
define the name; it cannot attach information to a name that is
|
|
already bound. Still, static binding is the most common mechanism for
|
|
defining macro protocols in the PLT Scheme libraries, including
|
|
protocols for structs and component
|
|
signatures~\cite{culpepper05units}.
|
|
|
|
\subsection{Side-effects}
|
|
|
|
Side-effects are commonly used to provide implicit channels of
|
|
communication between collaborating run-time components. They are just
|
|
as capable of providing such channels at compile time for macros,
|
|
provided the programmer recognizes the difference between ephemeral
|
|
and persistent effects and uses the appropriate technique.
|
|
|
|
%%% Discuss ``idempotent'' effects, module-id=? effects
|
|
|
|
% Due to the interactions between side-effects and the compilation
|
|
% process, however, we defer the discussion of side-effects to
|
|
% Section~\ref{sect:syntax:modules}.
|
|
|
|
\subsection{Syntax properties}
|
|
|
|
\citet{dhb:sc} define a syntax datatype that extends S-expressions
|
|
with hygienic binding information and source location tracking.
|
|
PLT Scheme adds \emph{syntax properties}, key-value pairs of arbitrary
|
|
associated data, as a way of attaching information to particular
|
|
terms. By default, syntax properties are simply preserved by macros
|
|
and primitive syntactic forms, so protocols defined via syntax
|
|
properties generally do not interfere if they choose distinct
|
|
keys. Accessing information contained in syntax properties requires
|
|
only access to the term that carries the property and the key to the
|
|
property. Syntax properties are available even to observers that
|
|
cannot access the expansion environment (necessary to access static
|
|
bindings and compile-time variables).
|
|
|
|
For these reasons, syntax properties are well-suited to conveying
|
|
information from macros to code analyzers that examine programs after
|
|
they have been expanded to core Scheme.
|
|
%
|
|
For example, DrScheme's Check Syntax tool examines expanded programs to graphically
|
|
display the program's binding structure. This should work even when the reference is no longer apparent in the residual program, as with the expansion of
|
|
\scheme{match}, which uses the information bound to structure name,
|
|
although the structure name does not occur in the expansion. The
|
|
\scheme{match} macro leaves a \scheme{'disappeared-use} syntax
|
|
property on its expansion telling the Check Syntax tool to color the
|
|
occurrence of \scheme{posn} as a reference and connect it to the
|
|
corresponding definition.
|
|
|
|
Macros can introduce and examine syntax properties in their arguments
|
|
using the \scheme{syntax-property} procedure.
|
|
|
|
\end{schemeregion}
|