fix reference (restoring some text that was lost in the reference-manual rewrite) to describe the problem with macro-introduced bindings and the top level

svn: r16205
This commit is contained in:
Matthew Flatt 2009-10-01 21:14:21 +00:00
parent f7dc640f55
commit 954e850e20
2 changed files with 119 additions and 4 deletions

View File

@ -3,6 +3,9 @@
(for-syntax mzscheme)
"mz.ss")
@(define scheme-eval (make-base-eval))
@(interaction-eval #:eval scheme-eval (require (for-syntax scheme/base)))
@;------------------------------------------------------------------------
@title[#:tag "syntax-model"]{Syntax Model}
@ -447,7 +450,7 @@ core syntactic forms are encountered:
right-hand-side expressions are also extended with the
bindings.}
@item{Definitions in @scheme[internal-definition contexts] introduce
@item{Definitions in @tech{internal-definition contexts} introduce
bindings as described in @secref["intdef-body"].}
]
@ -600,7 +603,7 @@ then expansion stops without adding the identifier.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "intdef-body"]{Internal Definitions}
An internal-definition context corresponds to a partial expansion step
An @tech{internal-definition context} corresponds to a partial expansion step
(see @secref["partial-expansion"]). A form that supports internal
definitions starts by expanding its first form in an
internal-definition context, but only partially. That is, it
@ -692,6 +695,109 @@ module is attached to a namespace through
are transitively attached, but instances are attached only at
phases at or below the namespace's @tech{base phase}.
@;------------------------------------------------------------------------
@subsection[#:tag "macro-introduced-bindings"]{Macro-Introduced Bindings}
When a top-level definition binds an identifier that originates from a
macro expansion, the definition captures only uses of the identifier
that are generated by the same expansion. This behavior is consistent
with expansion in @tech{internal-definition contexts}, where the
defined identifier turns into a fresh lexical binding.
@examples[
(define-syntax def-and-use-of-x
(syntax-rules ()
[(def-and-use-of-x val)
(code:comment @#,t{@scheme[x] below originates from this macro:})
(begin (define x val) x)]))
(define x 1)
x
(def-and-use-of-x 2)
x
(define-syntax def-and-use
(syntax-rules ()
[(def-and-use x val)
(code:comment @#,t{@scheme{x} below was provided by the macro use:})
(begin (define x val) x)]))
(def-and-use x 3)
x
]
For a top-level definition (outside of a module), the order of
evaluation affects the binding of a generated definition for a
generated identifier use. If the use precedes the definition, then
the use refers to a non-generated binding, just as if the generated
definition were not present. (No such dependency on order occurs
within a module, since a module binding covers the entire module
body.) To support the declaration of an identifier before its use,
the @scheme[define-syntaxes] form avoids binding an identifier if the
body of the @scheme[define-syntaxes] declaration produces zero
results.
@examples[
#:eval scheme-eval
(define bucket-1 0)
(define bucket-2 0)
(define-syntax def-and-set!-use-of-x
(syntax-rules ()
[(def-and-set!-use-of-x val)
(begin (set! bucket-1 x) (define x val) (set! bucket-2 x))]))
(define x 1)
(def-and-set!-use-of-x 2)
x
bucket-1
bucket-2
(define-syntax defs-and-uses/fail
(syntax-rules ()
[(def-and-use)
(begin
(code:comment @#,t{Initial reference to @scheme[even] precedes definition:})
(define (odd x) (if (zero? x) #f (even (sub1 x))))
(define (even x) (if (zero? x) #t (odd (sub1 x))))
(odd 17))]))
(defs-and-uses/fail)
(define-syntax defs-and-uses
(syntax-rules ()
[(def-and-use)
(begin
(code:comment @#,t{Declare before definition via no-values @scheme[define-syntaxes]:})
(define-syntaxes (odd even) (values))
(define (odd x) (if (zero? x) #f (even (sub1 x))))
(define (even x) (if (zero? x) #t (odd (sub1 x))))
(odd 17))]))
(defs-and-uses)
]
Macro-generated \scheme{require} and \scheme{provide}
clauses also introduce and reference generation-specific bindings:
@itemize[
@item{In @scheme[require], for a @scheme[_require-spec] of the form
@scheme[(rename-in [_orig-id _bind-id])] or @scheme[(only-in
.... [_orig-id _bind-id])], the @scheme[_bind-id] is bound only for
uses of the identifier generated by the same macro expansion as
@scheme[_bind-id]. In @scheme[require] for other
@scheme[_require-spec]s, the generator of the @scheme[_require-spec]
determines the scope of the bindings.}
@item{In @scheme[provide], for a @scheme[_provide-spec] of the form
@scheme[_id], the exported identifier is the one that binds
@scheme[_id] within the module in a generator-specific way, but the
external name is the plain @scheme[_id]. The exceptions for
@scheme[all-except-out] are similarly determined in a
generator-specific way, as is the @scheme[_orig-id] binding of a
@scheme[rename-out] form, but plain identifiers are used for the
external names. For @scheme[all-defined-out], only identifiers with
definitions having the same generator as the
@scheme[(all-defined-out)] form are exported; the external name is
the plain identifier from the definition.}
]
@;------------------------------------------------------------------------
@section[#:tag "compilation-model"]{Compilation}
@ -860,3 +966,7 @@ When an inferred name is not available, but a source location is
available, a name is constructed using the source location
information. Inferred and property-assigned names are also available
to syntax transformers, via @scheme[syntax-local-name].
@;----------------------------------------
@close-eval[scheme-eval]

View File

@ -1896,7 +1896,12 @@ expands to a definition of the first form where the @scheme[expr] is a
Like @scheme[define-syntax], but creates a @tech{transformer binding}
for each @scheme[id]. The @scheme[expr] should produce as many values
as @scheme[id]s, and each value is bound to the corresponding
@scheme[id]. }
@scheme[id].
When @scheme[expr] produces zero values for a top-level
@scheme[define-syntaxes] (i.e., not in a module or internal-definition
position), then the @scheme[id]s are effectively declared without
binding; see @secref["macro-introduced-bindings"].
@defexamples[#:eval (syntax-eval)
(define-syntaxes (foo1 foo2 foo3)
@ -1915,7 +1920,7 @@ as @scheme[id]s, and each value is bound to the corresponding
(foo1)
(foo2)
(foo3)
]
]}
@defform*[[(define-for-syntax id expr)
(define-for-syntax (head args) body ...+)]]{