Online Book Reader

Home Category

Beautiful Code [281]

By Root 5190 0
x ()

[(_) #'#f]

[(_ e) #'e]

[(_ e1 e2 e3 ...)

#'(let ([t e1]) (if t t (or e2 e3 ...)))])))

An input or output form followed by an ellipsis in the syntax-case pattern language matches or produces zero or more forms.

Hygiene is ensured for the definitions of or in this example, so that the introduced binding for t and the introduced references to let, if, and even or are scoped properly. If we want to bend or break hygiene, we do so with the procedure datum->syntax, which produces a syntax object from an arbitrary s-expression. The identifiers within the s-expression are treated as if they appeared in the original source where the first argument, the template identifier, appeared.

We can use this fact to create a simple method syntax that implicitly binds the name this to the first (object) argument:

(define-syntax method

(lambda (x)

(syntax-case x ()

[(k (x ...) e1 e2 ...)

(with-syntax ([this (datum->syntax #'k 'this)])

#'(lambda (this x ...) e1 e2 ...))])))

By using the keyword k, extracted from the input, as the template variable, the variable this is treated as if it were present in the method form, so that:

(method (a) (f this a))

is treated as the equivalent of:

(lambda (this a) (f this a))

with no renaming to prevent the introduced binding from capturing the source-code reference.

The with-syntax form used in the definition of method creates local pattern-variable bindings. It is a simple macro written in terms of syntax-case:

(define-syntax with-syntax

(lambda (x)

(syntax-case x ()

[(_ ((p e0) ...) e1 e2 ...)

#'(syntax-case (list e0 ...) ()

[(p ...) (begin e1 e2 ...)])])))

The datum->syntax procedure can be used for arbitrary expressions, as illustrated by the following definition of include:

(define-syntax include

(lambda (x)

(define read-file

(lambda (fn k)

(let ([p (open-input-file fn)])

(let f ([x (read p)])

(if (eof-object? x)

(begin (close-input-port p) '())

(cons (datum->syntax k x) (f (read p))))))))

(syntax-case x ()

[(k filename)

(let ([fn (syntax->datum #'filename)])

(with-syntax ([(e ...) (read-file fn #'k)])

#'(begin e ...)))])))

The form (include "filename") has the effect of treating the forms within the named file as if they were present in the source code in place of the include form. In addition to using datum->syntax, include also uses its inverse operator, syntax->datum, to convert the filename subform into a string it can pass to open-input-file.

Syntactic Abstraction: The syntax-case Expander > Expansion Algorithm

25.2. Expansion Algorithm

The syntax-case expansion algorithm is essentially a lazy variant of the KFFD algorithm that operates on an abstract representation of the input expression rather than on the traditional s-expression representation. The abstract representation encapsulates both a representation of an input form and a wrap that enables the algorithm to determine the scope of all identifiers within the form. The wrap consists of marks and substitutions.

Marks are like KFFD timestamps and are added to the portions of a macro's output that are introduced by the macro.

Substitutions map identifiers to bindings with the help of a compile-time environment. Substitutions are created whenever a binding form, such as lambda, is encountered, and they are added to the wraps of the syntax objects representing the forms within the scope of the binding form's bindings. A substitution applies to an identifier only if the identifier has the same name and marks as the substituted identifier.

Expansion operates in a recursive, top-down fashion. As the expander encounters a macro call, it invokes the associated transformer on the form, marking it first with a fresh mark and then marking it again with the same mark. Like marks cancel, so only the introduced portions of the macro's output—i.e., those portions not simply copied from the input to the output—remain marked.

When a core form is encountered, a core form in the output language of the expander (in our case,

Return Main Page Previous Page Next Page

®Online Book Reader