Library (rnrs syntax-case (6))

[R6RS] The (rnrs syntax-case (6))library provides support for writing low-level macros in a high-level style, with automatic syntax checking, input destructuring, output restructuring, maintenance of lexical scoping and referential transparency (hygiene), and support for controlled identifier capture.

Syntax syntax-case expression (literal ... ) clause ...

[R6RS] Each literal must be an identifier. Each clause must take one of the following two forms.

(_pattern_ _output-expression_)

(_pattern_ _fender_ _output-expression_)

Fender and output-expression must be expressions.

Pattern is the same as syntax-rules. See (rnrs base (6)) section.

A syntax-case expression first evaluates expression. It then attempts to match the pattern from the first clause against the resulting value, which is unwrapped as necessary to perform the match. If the _pattern_matches the value and no fender is present, output-expression is evaluated and its value returned as the value of the syntax-case expression. If the pattern does not match the value, syntax-case tries the second clause, then the third, and so on. It is a syntax violation if the value does not match any of the patterns.

If the optional fender is present, it serves as an additional constraint on acceptance of a clause. If the pattern of a given clause matches the input value, the corresponding fender is evaluated. If fender evaluates to a true value, the clause is accepted; otherwise, the clause is rejected as if the pattern had failed to match the value. Fenders are logically a part of the matching process, i.e., they specify additional matching constraints beyond the basic structure of the input.

Pattern variables contained within a clause's pattern are bound to the corresponding pieces of the input value within the clause's fender (if present) and output-expression. Pattern variables can be referenced only within syntax expressions (see below). Pattern variables occupy the same name space as program variables and keywords.

If the syntax-case form is in tail context, the output-expressionsare also in tail position.

Syntax syntax template

[R6RS] A template is a pattern variable, an identifier that is not a pattern variable, a pattern datum, or one of the following.

(_subtemplate_ ...)

(_subtemplate_ ... . _template_)

#(_subtemplate_ ...)

A subtemplate is a template followed by zero or more ellipses.

The value of a syntax form is a copy of template in which the pattern variables appearing within the template are replaced with the input subforms to which they are bound. Pattern data and identifiers that are not pattern variables or ellipses are copied directly into the output. A subtemplate followed by an ellipsis expands into zero or more occurrences of the subtemplate. Pattern variables that occur in subpatterns followed by one or more ellipses may occur only in subtemplates that are followed by (at least) as many ellipses. These pattern variables are replaced in the output by the input subforms to which they are bound, distributed as specified. If a pattern variable is followed by more ellipses in the subtemplate than in the associated subpattern, the input form is replicated as necessary. The subtemplate must contain at least one pattern variable from a subpattern followed by an ellipsis, and for at least one such pattern variable, the subtemplate must be followed by exactly as many ellipses as the subpattern in which the pattern variable appears.

Function identifier? obj

[R6RS] Returns #t if obj is an identifier, i.e., a syntax object representing an identifier, and #f otherwise.

Function bound-identifier=? id1 id2

[R6RS] Id1 and id2 must be identifiers. The procedure bound-identifier=? returns #t if given arguments are exactly the same object.

The bound-identifier=? procedure can be used for detecting duplicate identifiers in a binding construct or for other preprocessing of a binding construct that requires detecting instances of the bound identifiers.

Function free-identifier=? id1 id2

[R6RS] Id1 and id2 must be identifiers. The free-identifier=?procedure returns #t if given arguments are indicating the same bindings.

Function syntax->datum syntax-object

[R6RS] Strips all syntactic information from a syntax object and returns the corresponding Scheme datum.

Function datum->syntax template-id datum

[R6RS] Template-id must be a template identifier and _datum_should be a datum value.

The datum->syntax procedure returns a syntax-object representation of datum that contains the same contextual information as template-id, with the effect that the syntax object behaves as if it were introduced into the code when template-id was introduced.

The datum->syntax procedure allows a transformer to "bend" lexical scoping rules by creating implicit identifiers that behave as if they were present in the input form, thus permitting the definition of macros that introduce visible bindings for or references to identifiers that do not appear explicitly in the input form. For example, the following defines a loop expression that uses this controlled form of identifier capture to bind the variable break to an escape procedure within the loop body.

(define-syntax loop
  (lambda (x)
    (syntax-case x ()
      [(k e ...)
           ([break (datum->syntax (syntax k) 'break)])
	   (lambda (break)
	     (let f () e ... (f))))))])))

(let ((n 3) (ls '()))
    (if (= n 0) (break ls))
    (set! ls (cons 'a ls))
    (set! n (- n 1)))) 
(a a a)

Function generate-temporaries l

[R6RS] L must be a list or syntax object representing a list-structured form. The number of temporaries generated is the number of elements in l. Each temporary is guaranteed to be unique.

NOTE: If you want to create just one temporary symbol and do not think about portability, it's better to use gensym in (sagittarius) library.

Macro with-syntax ((pattern expression) ... ) body

[R6RS] The with-syntax form is used to bind pattern variables, just as let is used to bind variables. This allows a transformer to construct its output in separate pieces, then put the pieces together.

Each pattern is identical in form to a syntax-case pattern. The value of each expression is computed and destructured according to the corresponding pattern, and pattern variables within the pattern are bound as with syntax-case to the corresponding portions of the value within body.

Macro quasisyntax template
Auxiliary Macro unsyntax
Auxiliary Macro unsyntax-splicing

[R6RS] The quasisyntax form is similar to syntax, but it allows parts of the quoted text to be evaluated, in a manner similar to the operation of quasiquote.

Within a quasisyntax template, subforms of unsyntax and unsyntax-splicing forms are evaluated, and everything else is treated as ordinary template material, as with syntax. The value of each unsyntax subform is inserted into the output in place of the unsyntaxform, while the value of each unsyntax-splicing subform is spliced into the surrounding list or vector structure. Uses of unsyntax and unsyntax-splicing are valid only within quasisyntax expressions.

A quasisyntax expression may be nested, with each quasisyntaxintroducing a new level of syntax quotation and each unsyntax or unsyntax-splicing taking away a level of quotation. An expression nested within n quasisyntax expressions must be within n unsyntax or unsyntax-splicing expressions to be evaluated.

Function syntax-violation who message form :optional subform

[R6RS] Who must be #f or a string or a symbol. Message must be a string. Form must be a syntax object or a datum value. Subform must be a syntax object or a datum value.

The syntax-violation procedure raises an exception, reporting a syntax violation. Who should describe the macro transformer that detected the exception. The message argument should describe the violation. _Form_should be the erroneous source syntax object or a datum value representing a form. The optional subform argument should be a syntax object or datum value representing a form that more precisely locates the violation.