Macro uses (see section 9.2) are expanded into core formsat the start of evaluation (before compilation or interpretation) by a syntax expander. The set of core forms is implementation-dependent, as is the representation of these forms in the expander’s output. If the expander encounters a syntactic abstraction, it invokes the associated transformer to expand the syntactic abstraction, then repeats the expansion process for the form returned by the transformer. If the expander encounters a core form, it recursively processes its subforms that are in expression or definition context, if any, and reconstructs the form from the expanded subforms. Information about identifier bindings is maintained during expansion to enforce lexical scoping for variables and keywords.
To handle definitions, the expander processes the initial forms in a <body> (see section 11.3) or <library body> (see section 7.1) from left to right. How the expander processes each form encountered depends upon the kind of form.
For the right-hand side of the definition of a variable, expansion is deferred until after all of the definitions have been seen. Consequently, each keyword and variable reference within the right-hand side resolves to the local binding, if any.
A definition in the sequence of forms must not define any identifier whose binding is used to determine the meaning of the undeferred portions of the definition or any definition that precedes it in the sequence of forms. For example, the bodies of the following expressions violate this restriction.
(let ()
(define define 17)
(list define))
(let-syntax ([def0 (syntax-rules ()
[(_ x) (define x 0)])])
(let ([z 3])
(def0 z)
(define def0 list)
(list z)))
(let ()
(define-syntax foo
(lambda (e)
(+ 1 2)))
(define + 2)
(foo))
The following do not violate the restriction.
(let ([x 5])
(define lambda list)
(lambda x x)) ⇒ (5 5)
(let-syntax ([def0 (syntax-rules ()
[(_ x) (define x 0)])])
(let ([z 3])
(define def0 list)
(def0 z)
(list z))) ⇒ (3)
(let ()
(define-syntax foo
(lambda (e)
(let ([+ -]) (+ 1 2))))
(define + 2)
(foo)) ⇒ -1
The implementation should treat a violation of the restriction as a syntax violation.
Note that this algorithm does not directly reprocess any form. It requires a single left-to-right pass over the definitions followed by a single pass (in any order) over the body expressions and deferred right-hand sides.
Example:
(lambda (x)
(define-syntax defun
(syntax-rules ()
[(_ x a e) (define x (lambda a e))]))
(defun even? (n) (or (= n 0) (odd? (- n 1))))
(define-syntax odd?
(syntax-rules () [(_ n) (not (even? n))]))
(odd? (if (odd? x) (* x x) x)))
In the example, the definition of defun is encountered first, and the keyword defun is associated with the transformer resulting from the expansion and evaluation of the corresponding right-hand side. A use of defun is encountered next and expands into a define form. Expansion of the right-hand side of this define form is deferred. The definition of odd? is next and results in the association of the keyword odd? with the transformer resulting from expanding and evaluating the corresponding right-hand side. A use of odd? appears next and is expanded; the resulting call to not is recognized as an expression because not is bound as a variable. At this point, the expander completes the expansion of the current expression (the call to not) and the deferred right-hand side of the even? definition; the uses of odd? appearing in these expressions are expanded using the transformer associated with the keyword odd?. The final output is the equivalent of
(lambda (x)
(letrec* ([even?
(lambda (n)
(or (= n 0)
(not (even? (- n 1)))))])
(not (even? (if (not (even? x)) (* x x) x)))))
although the structure of the output is implementation-dependent.
Because definitions and expressions can be interleaved in a <top-level body> (see chapter 8), the expander’s processing of a <top-level body> is somewhat more complicated. It behaves as described above for a <body> or <library body> with the following exceptions: When the expander finds a nondefinition, it defers its expansion and continues scanning for definitions. Once it reaches the end of the set of forms, it processes the deferred right-hand-side and body expressions, then generates the equivalent of a letrec* form from the defined variables, expanded right-hand-side expressions, and expanded body expressions. For each body expression <expression> that appears before a variable definition in the body, a dummy binding is created at the corresponding place within the set of letrec* bindings, with a fresh temporary variable on the left-hand side and the equivalent of (begin <expression> <unspecified>), where <unspecified> is a side-effect-free expression returning an unspecified value, on the right-hand side, so that left-to-right evaluation order is preserved. The begin wrapper allows <expression> to evaluate to an arbitrary number of values.