add example of negative phase level (#1330)

* add example of negative phase level

* Update proc-macros.scrbl

Remove `eval:error`

* correct dashes
This commit is contained in:
Matthew Butterick 2016-08-19 06:03:19 -07:00 committed by Matthew Flatt
parent 998bfba4c4
commit 787915155f

View File

@ -522,6 +522,85 @@ identifiers in the syntax will need bindings at @deftech{phase level
binding at the run-time phase level relative to the module that binding at the run-time phase level relative to the module that
defines the macro. defines the macro.
For instance, the @racket[swap-stx] helper function in the example below
is not a syntax transformer --- it's just an ordinary function --- but it
produces syntax objects that get spliced into the result of
@racket[shell-game]. Therefore, its containing @racket[helper] submodule
needs to be imported at @racket[shell-game]'s phase 1 with
@racket[(require (for-syntax 'helper))].
But from the perspective of @racket[swap-stx], its results will ultimately
be evaluated at phase level -1, when the syntax
returned by @racket[shell-game] is evaluated. In other words, a negative phase
level is a positive phase level from the opposite direction:
@racket[shell-game]'s phase 1 is @racket[swap-stx]'s phase 0, so
@racket[shell-game]'s phase 0 is @racket[swap-stx]'s phase -1.
And that's why this example won't work --- the @racket['helper] submodule
has no bindings at phase -1.
@codeblock|{
#lang racket/base
(require (for-syntax racket/base))
(module helper racket/base
(provide swap-stx)
(define (swap-stx a-stx b-stx)
#`(let ([tmp #,a-stx])
(set! #,a-stx #,b-stx)
(set! #,b-stx tmp))))
(require (for-syntax 'helper))
(define-syntax (shell-game stx)
(syntax-case stx ()
[(_ a b c)
#`(begin
#,(swap-stx #'a #'b)
#,(swap-stx #'b #'c)
#,(swap-stx #'a #'c)
(list a b c))]))
(define x 3)
(define y 4)
(define z 5)
(shell-game x y z)
}|
To repair this example, we add @racket[(require (for-template racket/base))]
to the @racket['helper] submodule.
@codeblock|{
#lang racket/base
(require (for-syntax racket/base))
(module helper racket/base
(require (for-template racket/base)) ; binds `let` and `set!` at phase -1
(provide swap-stx)
(define (swap-stx a-stx b-stx)
#`(let ([tmp #,a-stx])
(set! #,a-stx #,b-stx)
(set! #,b-stx tmp))))
(require (for-syntax 'helper))
(define-syntax (shell-game stx)
(syntax-case stx ()
[(_ a b c)
#`(begin
#,(swap-stx #'a #'b)
#,(swap-stx #'b #'c)
#,(swap-stx #'a #'c)
(list a b c))]))
(define x 3)
(define y 4)
(define z 5)
(shell-game x y z)
(shell-game x y z)
(shell-game x y z)}|
@; ---------------------------------------- @; ----------------------------------------
@include-section["phases.scrbl"] @include-section["phases.scrbl"]