X-Git-Url: https://git.hcoop.net/bpt/guile.git/blobdiff_plain/729b62bd95c61b6e2992f823b469b76bdc483b0d..2d6a3144a122982d5b6a9365943f73891bdb87d3:/doc/ref/api-macros.texi diff --git a/doc/ref/api-macros.texi b/doc/ref/api-macros.texi index 7ff5bf9bc..acfbc6556 100644 --- a/doc/ref/api-macros.texi +++ b/doc/ref/api-macros.texi @@ -1,7 +1,7 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011 -@c Free Software Foundation, Inc. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011, +@c 2012, 2013, 2014 Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @node Macros @@ -38,9 +38,10 @@ languages}, or EDSLs.}. * Defining Macros:: Binding macros, globally and locally. * Syntax Rules:: Pattern-driven macros. * Syntax Case:: Procedural, hygienic macros. +* Syntax Transformer Helpers:: Helpers for use in procedural macros. * Defmacros:: Lisp-style macros. * Identifier Macros:: Identifier macros. -* Syntax Parameters:: Syntax Parameters +* Syntax Parameters:: Syntax Parameters. * Eval When:: Affecting the expand-time environment. * Internal Macros:: Macros as first-class values. @end menu @@ -80,8 +81,9 @@ source code will invoke the syntax transformer defined by @var{transformer}. One can also establish local syntactic bindings with @code{let-syntax}. -@deffn {Syntax} let-syntax ((keyword transformer) ...) exp... -Bind @var{keyword...} to @var{transformer...} while expanding @var{exp...}. +@deffn {Syntax} let-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +Bind each @var{keyword} to its corresponding @var{transformer} while +expanding @var{exp1} @var{exp2} @enddots{}. A @code{let-syntax} binding only exists at expansion-time. @@ -103,8 +105,9 @@ top-level, or locally. Just as a local @code{define} expands out to an instance of @code{letrec}, a local @code{define-syntax} expands out to @code{letrec-syntax}. -@deffn {Syntax} letrec-syntax ((keyword transformer) ...) exp... -Bind @var{keyword...} to @var{transformer...} while expanding @var{exp...}. +@deffn {Syntax} letrec-syntax ((keyword transformer) @dots{}) exp1 exp2 @dots{} +Bind each @var{keyword} to its corresponding @var{transformer} while +expanding @var{exp1} @var{exp2} @enddots{}. In the spirit of @code{letrec} versus @code{let}, an expansion produced by @var{transformer} may reference a @var{keyword} bound by the @@ -119,8 +122,8 @@ same @var{letrec-syntax}. exp) ((my-or exp rest ...) (let ((t exp)) - (if exp - exp + (if t + t (my-or rest ...))))))) (my-or #f "rockaway beach")) @result{} "rockaway beach" @@ -133,7 +136,7 @@ same @var{letrec-syntax}. @code{syntax-rules} macros are simple, pattern-driven syntax transformers, with a beauty worthy of Scheme. -@deffn {Syntax} syntax-rules literals (pattern template)... +@deffn {Syntax} syntax-rules literals (pattern template) @dots{} Create a syntax transformer that will rewrite an expression using the rules embodied in the @var{pattern} and @var{template} clauses. @end deffn @@ -212,7 +215,7 @@ including ellipsizing and tail patterns. ((_ #((var val) ...) exp exp* ...) (let ((var val) ...) exp exp* ...)))) (letv #((foo 'bar)) foo) -@result{} foo +@result{} bar @end example Literals are used to match specific datums in an expression, like the use of @@ -320,8 +323,8 @@ Consider the definition of @code{my-or} from the previous section: exp) ((my-or exp rest ...) (let ((t exp)) - (if exp - exp + (if t + t (my-or rest ...)))))) @end example @@ -360,6 +363,50 @@ Cast into this form, our @code{when} example is significantly shorter: (if c (begin e ...))) @end example +@subsubsection Reporting Syntax Errors in Macros + +@deffn {Syntax} syntax-error message [arg ...] +Report an error at macro-expansion time. @var{message} must be a string +literal, and the optional @var{arg} operands can be arbitrary expressions +providing additional information. +@end deffn + +@code{syntax-error} is intended to be used within @code{syntax-rules} +templates. For example: + +@example +(define-syntax simple-let + (syntax-rules () + ((_ (head ... ((x . y) val) . tail) + body1 body2 ...) + (syntax-error + "expected an identifier but got" + (x . y))) + ((_ ((name val) ...) body1 body2 ...) + ((lambda (name ...) body1 body2 ...) + val ...)))) +@end example + +@subsubsection Specifying a Custom Ellipsis Identifier + +When writing macros that generate macro definitions, it is convenient to +use a different ellipsis identifier at each level. Guile allows the +desired ellipsis identifier to be specified as the first operand to +@code{syntax-rules}, as specified by SRFI-46 and R7RS. For example: + +@example +(define-syntax define-quotation-macros + (syntax-rules () + ((_ (macro-name head-symbol) ...) + (begin (define-syntax macro-name + (syntax-rules ::: () + ((_ x :::) + (quote (head-symbol x :::))))) + ...)))) +(define-quotation-macros (quote-a a) (quote-b b) (quote-c c)) +(quote-a 1 2 3) @result{} (a 1 2 3) +@end example + @subsubsection Further Information For a formal definition of @code{syntax-rules} and its pattern language, see @@ -386,7 +433,7 @@ Primer for the Merely Eccentric}. @code{syntax-case} macros are procedural syntax transformers, with a power worthy of Scheme. -@deffn {Syntax} syntax-case syntax literals (pattern [guard] exp)... +@deffn {Syntax} syntax-case syntax literals (pattern [guard] exp) @dots{} Match the syntax object @var{syntax} against the given patterns, in order. If a @var{pattern} matches, return the result of evaluating the associated @var{exp}. @end deffn @@ -517,7 +564,8 @@ is impossible with @code{syntax-rules}, given the datum matching forms. But with @code{syntax-case} it is easy: @deffn {Scheme Procedure} identifier? syntax-object -Returns @code{#t} iff @var{syntax-object} is an identifier. +Returns @code{#t} if @var{syntax-object} is an identifier, or @code{#f} +otherwise. @end deffn @example @@ -627,9 +675,9 @@ variable environment, and we can do so using @code{syntax-case} itself: However there are easier ways to write this. @code{with-syntax} is often convenient: -@deffn {Syntax} with-syntax ((pat val)...) exp... +@deffn {Syntax} with-syntax ((pat val) @dots{}) exp @dots{} Bind patterns @var{pat} from their corresponding values @var{val}, within the -lexical context of @var{exp...}. +lexical context of @var{exp} @enddots{}. @example ;; better @@ -671,28 +719,192 @@ source file, one may write: (newline)))))) @end example -Finally, we should mention the following helper procedures defined by the core -of @code{syntax-case}: +Readers interested in further information on @code{syntax-case} macros should +see R. Kent Dybvig's excellent @cite{The Scheme Programming Language}, either +edition 3 or 4, in the chapter on syntax. Dybvig was the primary author of the +@code{syntax-case} system. The book itself is available online at +@uref{http://scheme.com/tspl4/}. + +@subsubsection Custom Ellipsis Identifiers for syntax-case Macros + +When writing procedural macros that generate macro definitions, it is +convenient to use a different ellipsis identifier at each level. Guile +supports this for procedural macros using the @code{with-ellipsis} +special form: + +@deffn {Syntax} with-ellipsis ellipsis body @dots{} +@var{ellipsis} must be an identifier. Evaluate @var{body} in a special +lexical environment such that all macro patterns and templates within +@var{body} will use @var{ellipsis} as the ellipsis identifier instead of +the usual three dots (@code{...}). +@end deffn + +For example: + +@example +(define-syntax define-quotation-macros + (lambda (x) + (syntax-case x () + ((_ (macro-name head-symbol) ...) + #'(begin (define-syntax macro-name + (lambda (x) + (with-ellipsis ::: + (syntax-case x () + ((_ x :::) + #'(quote (head-symbol x :::))))))) + ...))))) +(define-quotation-macros (quote-a a) (quote-b b) (quote-c c)) +(quote-a 1 2 3) @result{} (a 1 2 3) +@end example + +Note that @code{with-ellipsis} does not affect the ellipsis identifier +of the generated code, unless @code{with-ellipsis} is included around +the generated code. + +@node Syntax Transformer Helpers +@subsection Syntax Transformer Helpers + +As noted in the previous section, Guile's syntax expander operates on +syntax objects. Procedural macros consume and produce syntax objects. +This section describes some of the auxiliary helpers that procedural +macros can use to compare, generate, and query objects of this data +type. @deffn {Scheme Procedure} bound-identifier=? a b -Returns @code{#t} iff the syntax objects @var{a} and @var{b} refer to the same -lexically-bound identifier. +Return @code{#t} if the syntax objects @var{a} and @var{b} refer to the +same lexically-bound identifier, or @code{#f} otherwise. @end deffn @deffn {Scheme Procedure} free-identifier=? a b -Returns @code{#t} iff the syntax objects @var{a} and @var{b} refer to the same -free identifier. +Return @code{#t} if the syntax objects @var{a} and @var{b} refer to the +same free identifier, or @code{#f} otherwise. @end deffn @deffn {Scheme Procedure} generate-temporaries ls Return a list of temporary identifiers as long as @var{ls} is long. @end deffn -Readers interested in further information on @code{syntax-case} macros should -see R. Kent Dybvig's excellent @cite{The Scheme Programming Language}, either -edition 3 or 4, in the chapter on syntax. Dybvig was the primary author of the -@code{syntax-case} system. The book itself is available online at -@uref{http://scheme.com/tspl4/}. +@deffn {Scheme Procedure} syntax-source x +Return the source properties that correspond to the syntax object +@var{x}. @xref{Source Properties}, for more information. +@end deffn + +Guile also offers some more experimental interfaces in a separate +module. As was the case with the Large Hadron Collider, it is unclear +to our senior macrologists whether adding these interfaces will result +in awesomeness or in the destruction of Guile via the creation of a +singularity. We will preserve their functionality through the 2.0 +series, but we reserve the right to modify them in a future stable +series, to a more than usual degree. + +@example +(use-modules (system syntax)) +@end example + +@deffn {Scheme Procedure} syntax-module id +Return the name of the module whose source contains the identifier +@var{id}. +@end deffn + +@deffn {Scheme Procedure} syntax-local-binding id +Resolve the identifer @var{id}, a syntax object, within the current +lexical environment, and return two values, the binding type and a +binding value. The binding type is a symbol, which may be one of the +following: + +@table @code +@item lexical +A lexically-bound variable. The value is a unique token (in the sense +of @code{eq?}) identifying this binding. +@item macro +A syntax transformer, either local or global. The value is the +transformer procedure. +@item pattern-variable +A pattern variable, bound via @code{syntax-case}. The value is an +opaque object, internal to the expander. +@item ellipsis +An internal binding, bound via @code{with-ellipsis}. The value is the +(anti-marked) local ellipsis identifier. +@item displaced-lexical +A lexical variable that has gone out of scope. This can happen if a +badly-written procedural macro saves a syntax object, then attempts to +introduce it in a context in which it is unbound. The value is +@code{#f}. +@item global +A global binding. The value is a pair, whose head is the symbol, and +whose tail is the name of the module in which to resolve the symbol. +@item other +Some other binding, like @code{lambda} or other core bindings. The +value is @code{#f}. +@end table + +This is a very low-level procedure, with limited uses. One case in +which it is useful is to build abstractions that associate auxiliary +information with macros: + +@example +(define aux-property (make-object-property)) +(define-syntax-rule (with-aux aux value) + (let ((trans value)) + (set! (aux-property trans) aux) + trans)) +(define-syntax retrieve-aux + (lambda (x) + (syntax-case x () + ((x id) + (call-with-values (lambda () (syntax-local-binding #'id)) + (lambda (type val) + (with-syntax ((aux (datum->syntax #'here + (and (eq? type 'macro) + (aux-property val))))) + #''aux))))))) +(define-syntax foo + (with-aux 'bar + (syntax-rules () ((_) 'foo)))) +(foo) +@result{} foo +(retrieve-aux foo) +@result{} bar +@end example + +@code{syntax-local-binding} must be called within the dynamic extent of +a syntax transformer; to call it otherwise will signal an error. +@end deffn + +@deffn {Scheme Procedure} syntax-locally-bound-identifiers id +Return a list of identifiers that were visible lexically when the +identifier @var{id} was created, in order from outermost to innermost. + +This procedure is intended to be used in specialized procedural macros, +to provide a macro with the set of bound identifiers that the macro can +reference. + +As a technical implementation detail, the identifiers returned by +@code{syntax-locally-bound-identifiers} will be anti-marked, like the +syntax object that is given as input to a macro. This is to signal to +the macro expander that these bindings were present in the original +source, and do not need to be hygienically renamed, as would be the case +with other introduced identifiers. See the discussion of hygiene in +section 12.1 of the R6RS, for more information on marks. + +@example +(define (local-lexicals id) + (filter (lambda (x) + (eq? (syntax-local-binding x) 'lexical)) + (syntax-locally-bound-identifiers id))) +(define-syntax lexicals + (lambda (x) + (syntax-case x () + ((lexicals) #'(lexicals lexicals)) + ((lexicals scope) + (with-syntax (((id ...) (local-lexicals #'scope))) + #'(list (cons 'id id) ...)))))) + +(let* ((x 10) (x 20)) (lexicals)) +@result{} ((x . 10) (x . 20)) +@end example +@end deffn + @node Defmacros @subsection Lisp-style Macro Definitions @@ -807,7 +1019,7 @@ left-hand side of a @code{set!} expression, as in the following: (set! foo @var{val}) ;; expands via (foo-transformer #'(set! foo @var{val})) -;; iff foo-transformer is a "variable transformer" +;; if foo-transformer is a "variable transformer" @end example As the example notes, the transformer procedure must be explicitly @@ -865,31 +1077,32 @@ wrapping in @code{#'} syntax forms. @node Syntax Parameters @subsection Syntax Parameters -Syntax parameters@footnote{Described in the paper @cite{Keeping it Clean with -Syntax Parameters} by Barzilay, Culpepper and Flatt.} are a mechanism for rebinding a macro -definition within the dynamic extent of a macro expansion. It provides -a convenient solution to one of the most common types of unhygienic -macro: those that introduce a unhygienic binding each time the macro -is used. Examples include a @code{lambda} form with a @code{return} keyword, or -class macros that introduce a special @code{self} binding. +Syntax parameters@footnote{Described in the paper @cite{Keeping it Clean +with Syntax Parameters} by Barzilay, Culpepper and Flatt.} are a +mechanism for rebinding a macro definition within the dynamic extent of +a macro expansion. This provides a convenient solution to one of the +most common types of unhygienic macro: those that introduce a unhygienic +binding each time the macro is used. Examples include a @code{lambda} +form with a @code{return} keyword, or class macros that introduce a +special @code{self} binding. With syntax parameters, instead of introducing the binding -unhygienically each time, we instead create one binding for the -keyword, which we can then adjust later when we want the keyword to -have a different meaning. As no new bindings are introduced, hygiene -is preserved. This is similar to the dynamic binding mechanisms we -have at run-time like @ref{SRFI-39, parameters} or -@ref{Fluids and Dynamic States, fluids}, except that the dynamic -binding only occurs during macro expansion. The code after macro -expansion remains lexically scoped. +unhygienically each time, we instead create one binding for the keyword, +which we can then adjust later when we want the keyword to have a +different meaning. As no new bindings are introduced, hygiene is +preserved. This is similar to the dynamic binding mechanisms we have at +run-time (@pxref{SRFI-39, parameters}), except that the dynamic binding +only occurs during macro expansion. The code after macro expansion +remains lexically scoped. @deffn {Syntax} define-syntax-parameter keyword transformer -Binds @var{keyword} to the value obtained by evaluating @var{transformer}. The -@var{transformer} provides the default expansion for the syntax parameter, -and in the absence of @code{syntax-parameterize}, is functionally equivalent -to @code{define-syntax}. Usually, you will just want to have the @var{transformer} -throw a syntax error indicating that the @var{keyword} is supposed to be -used in conjunction with another macro, for example: +Binds @var{keyword} to the value obtained by evaluating +@var{transformer}. The @var{transformer} provides the default expansion +for the syntax parameter, and in the absence of +@code{syntax-parameterize}, is functionally equivalent to +@code{define-syntax}. Usually, you will just want to have the +@var{transformer} throw a syntax error indicating that the @var{keyword} +is supposed to be used in conjunction with another macro, for example: @example (define-syntax-parameter return (lambda (stx) @@ -899,31 +1112,30 @@ used in conjunction with another macro, for example: @deffn {Syntax} syntax-parameterize ((keyword transformer) @dots{}) exp @dots{} Adjusts @var{keyword} @dots{} to use the values obtained by evaluating -their @var{transformer} @dots{}, in the expansion of the @var{exp} @dots{} -forms. Each @var{keyword} must be bound to a -syntax-parameter. @code{syntax-parameterize} differs from -@code{let-syntax}, in that the binding is not shadowed, but adjusted, -and so uses of the keyword in the expansion of exp forms use the new -transformers. This is somewhatsimilar to how @code{parameterize} -adjusts the values of regular parameters, rather than creating new -bindings. +their @var{transformer} @dots{}, in the expansion of the @var{exp} +@dots{} forms. Each @var{keyword} must be bound to a syntax-parameter. +@code{syntax-parameterize} differs from @code{let-syntax}, in that the +binding is not shadowed, but adjusted, and so uses of the keyword in the +expansion of @var{exp} @dots{} use the new transformers. This is +somewhat similar to how @code{parameterize} adjusts the values of +regular parameters, rather than creating new bindings. @example (define-syntax lambda^ (syntax-rules () - [(lambda^ argument-list body bodies ...) + [(lambda^ argument-list body body* ...) (lambda argument-list (call-with-current-continuation (lambda (escape) - ;; in the body we adjust the 'return' keyword so that calls - ;; to 'return' are replaced with calls to the escape continuation + ;; In the body we adjust the 'return' keyword so that calls + ;; to 'return' are replaced with calls to the escape + ;; continuation. (syntax-parameterize ([return (syntax-rules () [(return vals (... ...)) (escape vals (... ...))])]) - body - bodies ...))))])) + body body* ...))))])) -;; now we can write functions that return early. Here, 'product' will +;; Now we can write functions that return early. Here, 'product' will ;; return immediately if it sees any 0 element. (define product (lambda^ (list) @@ -997,7 +1209,8 @@ for syntax-case. @deffn {Scheme Procedure} macro? obj @deffnx {C Function} scm_macro_p (obj) -Return @code{#t} iff @var{obj} is a syntax transformer. +Return @code{#t} if @var{obj} is a syntax transformer, or @code{#f} +otherwise. Note that it's a bit difficult to actually get a macro as a first-class object; simply naming it (like @code{case}) will produce a syntax error. But it is