mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-24 12:20:20 +02:00
psyntax: custom ellipses using 'with-ellipsis' or R7RS syntax-rules.
* module/ice-9/psyntax.scm (binding-type): Update the header comment to mention the new 'ellipsis' binding type. (macros-only-env): Preserve ellipsis bindings. (ellipsis?): Add 'r' and 'mod' as arguments. Search the lexical environment for an ellipsis binding, and use it. (gen-syntax): Adapt to the additional arguments of 'ellipsis?'. (with-ellipsis): New core syntax. (convert-pattern): Add unary 'ellipsis?' procedure as an argument. (gen-clause): Adapt to the additional arguments of 'ellipsis?'. Pass unary 'ellipsis?' procedure to 'convert-pattern'. (syntax-case): Adapt to the additional arguments of 'ellipsis?'. (syntax-local-binding): Support new 'ellipsis' binding type. (syntax-rules): Add support for a custom ellipsis identifier as the first operand, as per R7RS. Collect common code within new local procedure 'expand-syntax-rules'. * module/ice-9/psyntax-pp.scm: Regenerate. * module/ice-9/local-eval.scm (analyze-identifiers): Add support for 'ellipsis' binding type. * doc/ref/api-macros.texi (Syntax Rules): Add docs for R7RS custom ellipsis syntax. Use @dots{}. (Syntax Case): Add docs for 'with-ellipsis'. Use @dots{}. (Syntax Transformer Helpers): Update to include new 'ellipsis' binding type. * test-suite/tests/syntax.test: Add tests.
This commit is contained in:
parent
8de355d08e
commit
1624e149f7
5 changed files with 423 additions and 99 deletions
|
@ -136,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
|
||||
|
@ -363,6 +363,26 @@ Cast into this form, our @code{when} example is significantly shorter:
|
|||
(if c (begin e ...)))
|
||||
@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 per 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
|
||||
|
@ -389,7 +409,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
|
||||
|
@ -631,9 +651,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
|
||||
|
@ -681,6 +701,42 @@ 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
|
||||
|
||||
|
@ -740,8 +796,11 @@ of @code{eq?}) identifying this binding.
|
|||
A syntax transformer, either local or global. The value is the
|
||||
transformer procedure.
|
||||
@item pattern-variable
|
||||
A pattern variable, bound via syntax-case. The value is an opaque
|
||||
object, internal to the expander.
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue