\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}