doc work: reference on syntax objects
svn: r6882
This commit is contained in:
parent
5117dd03d9
commit
8470b61466
|
@ -192,6 +192,7 @@
|
||||||
|
|
||||||
(provide defproc defproc* defstruct defthing defparam defboolparam
|
(provide defproc defproc* defstruct defthing defparam defboolparam
|
||||||
defform defform* defform/subs defform*/subs defform/none
|
defform defform* defform/subs defform*/subs defform/none
|
||||||
|
defidform
|
||||||
specform specform/subs
|
specform specform/subs
|
||||||
specsubform specsubform/subs specspecsubform specspecsubform/subs specsubform/inline
|
specsubform specsubform/subs specspecsubform specspecsubform/subs specsubform/inline
|
||||||
schemegrammar schemegrammar*
|
schemegrammar schemegrammar*
|
||||||
|
@ -311,6 +312,15 @@
|
||||||
'(spec) (list (lambda (ignored) (schemeblock0 spec)))
|
'(spec) (list (lambda (ignored) (schemeblock0 spec)))
|
||||||
null null
|
null null
|
||||||
(lambda () (list desc ...)))]))
|
(lambda () (list desc ...)))]))
|
||||||
|
(define-syntax (defidform stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ spec-id desc ...)
|
||||||
|
#'(*defforms (quote-syntax spec-id) null
|
||||||
|
'(spec-id)
|
||||||
|
(list (lambda (x) (make-paragraph (list x))))
|
||||||
|
null
|
||||||
|
null
|
||||||
|
(lambda () (list desc ...)))]))
|
||||||
(define-syntax specsubform
|
(define-syntax specsubform
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(_ #:literals (lit ...) spec desc ...)
|
[(_ #:literals (lit ...) spec desc ...)
|
||||||
|
@ -837,7 +847,11 @@
|
||||||
(apply
|
(apply
|
||||||
append
|
append
|
||||||
(map (lambda (form)
|
(map (lambda (form)
|
||||||
(let loop ([form (cons (if kw-id (cdr form) form)
|
(let loop ([form (cons (if kw-id
|
||||||
|
(if (pair? form)
|
||||||
|
(cdr form)
|
||||||
|
null)
|
||||||
|
form)
|
||||||
subs)])
|
subs)])
|
||||||
(cond
|
(cond
|
||||||
[(symbol? form) (if (or (meta-symbol? form)
|
[(symbol? form) (if (or (meta-symbol? form)
|
||||||
|
@ -869,7 +883,10 @@
|
||||||
(eq? form (car forms))
|
(eq? form (car forms))
|
||||||
(make-target-element
|
(make-target-element
|
||||||
#f
|
#f
|
||||||
(list (to-element (make-just-context (car form) kw-id)))
|
(list (to-element (make-just-context (if (pair? form)
|
||||||
|
(car form)
|
||||||
|
form)
|
||||||
|
kw-id)))
|
||||||
(register-scheme-form-definition kw-id))))))))
|
(register-scheme-form-definition kw-id))))))))
|
||||||
forms form-procs)
|
forms form-procs)
|
||||||
(if (null? sub-procs)
|
(if (null? sub-procs)
|
||||||
|
|
|
@ -363,6 +363,7 @@
|
||||||
(let ([c (syntax-e c)])
|
(let ([c (syntax-e c)])
|
||||||
(let ([s (format "~s" c)])
|
(let ([s (format "~s" c)])
|
||||||
(if (and (symbol? c)
|
(if (and (symbol? c)
|
||||||
|
((string-length s) . > . 1)
|
||||||
(char=? (string-ref s 0) #\_))
|
(char=? (string-ref s 0) #\_))
|
||||||
(values (substring s 1) #t #f)
|
(values (substring s 1) #t #f)
|
||||||
(values s #f #f))))]
|
(values s #f #f))))]
|
||||||
|
|
15
collects/scribblings/reference/ellipses.ss
Normal file
15
collects/scribblings/reference/ellipses.ss
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
(module ellipses (lib "lang.ss" "big")
|
||||||
|
(require (lib "manual.ss" "scribble"))
|
||||||
|
|
||||||
|
(provide ellipses-defn
|
||||||
|
ellipses-id)
|
||||||
|
|
||||||
|
(define-syntax ... #'no)
|
||||||
|
|
||||||
|
(define-syntax ellipses-defn
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ . body)
|
||||||
|
(defidform (... ...) . body)]))
|
||||||
|
|
||||||
|
(define ellipses-id
|
||||||
|
(scheme ...)))
|
|
@ -1,4 +1,17 @@
|
||||||
#reader(lib "docreader.ss" "scribble")
|
#reader(lib "docreader.ss" "scribble")
|
||||||
@require["mz.ss"]
|
@require["mz.ss"]
|
||||||
|
|
||||||
@title{Macros}
|
@title[#:style 'toc]{Macros}
|
||||||
|
|
||||||
|
See @secref["mz:syntax-model"] for general information on how programs
|
||||||
|
are parsed. In particular, the subsection @secref["mz:expand-steps"]
|
||||||
|
describes how parsing triggers macros, and
|
||||||
|
@secref["mz:transformer-model"] describes how macro transformers are
|
||||||
|
called.
|
||||||
|
|
||||||
|
@local-table-of-contents[]
|
||||||
|
|
||||||
|
@include-section["stx-patterns.scrbl"]
|
||||||
|
@include-section["stx-ops.scrbl"]
|
||||||
|
@include-section["stx-comp.scrbl"]
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ language.
|
||||||
@include-section["struct.scrbl"]
|
@include-section["struct.scrbl"]
|
||||||
@include-section["control.scrbl"]
|
@include-section["control.scrbl"]
|
||||||
@include-section["concurrency.scrbl"]
|
@include-section["concurrency.scrbl"]
|
||||||
|
@include-section["macros.scrbl"]
|
||||||
@include-section["security.scrbl"]
|
@include-section["security.scrbl"]
|
||||||
@include-section["io.scrbl"]
|
@include-section["io.scrbl"]
|
||||||
@include-section["os.scrbl"]
|
@include-section["os.scrbl"]
|
||||||
|
|
138
collects/scribblings/reference/stx-comp.scrbl
Normal file
138
collects/scribblings/reference/stx-comp.scrbl
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
#reader(lib "docreader.ss" "scribble")
|
||||||
|
@require["mz.ss"]
|
||||||
|
|
||||||
|
@title[#:tag "mz:stxcmp"]{Syntax Object Bindings}
|
||||||
|
|
||||||
|
@defproc[(bound-identifier=? [a-id syntax?][b-id syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if the identifier @scheme[a-id] would bind
|
||||||
|
@scheme[b-id] (or vice-versa) if the identifiers were substituted in a
|
||||||
|
suitable expression context, @scheme[#f] otherwise.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(free-identifier=? [a-id syntax?][b-id syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[a-id] and @scheme[b-id] access the same
|
||||||
|
lexical, module, or top-level binding at @tech{phase level} 0. ``Same
|
||||||
|
module binding'' means that the identifiers refer to the same original
|
||||||
|
definition site, not necessarily the @scheme[require] or
|
||||||
|
@scheme[provide] site. Due to renaming in @scheme[require] and
|
||||||
|
@scheme[provide], the identifiers may return distinct results with
|
||||||
|
@scheme[syntax-e].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(free-transformer-identifier=? [a-id syntax?][b-id syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[a-id] and @scheme[b-id] access the same
|
||||||
|
lexical, module, or top-level binding at @tech{phase level} 1 (see
|
||||||
|
@secref["mz:id-model"]).}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(free-template-identifier=? [a-id syntax?][b-id syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[a-id] and @scheme[b-id] access the same
|
||||||
|
lexical or module binding at @tech{phase level} -1 (see
|
||||||
|
@secref["mz:id-model"]).}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(check-duplicate-identifier [ids (listof identifier?)])
|
||||||
|
(or/c identifier? false/c)]{
|
||||||
|
|
||||||
|
Compares each identifier in @scheme[ids] with every other identifier
|
||||||
|
in the list with @scheme[bound-identifier=?]. If any comparison
|
||||||
|
returns @scheme[#t], one of the duplicate identifiers is returned (the
|
||||||
|
first one in @scheme[ids] that is a duplicate), otherwise the result
|
||||||
|
is @scheme[#f].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(identifier-binding [id-stx syntax?])
|
||||||
|
(or/c (one-of 'lexical #f)
|
||||||
|
(listof (or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
(or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
boolean?))]{
|
||||||
|
|
||||||
|
Returns one of three kinds of values, depending on the binding of
|
||||||
|
@scheme[id-stx] at @tech{phase level} 0:
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{The result is @scheme['lexical] if @scheme[id-stx] has
|
||||||
|
a @tech{local binding}.
|
||||||
|
|
||||||
|
@item{The result is a list of five items when @scheme[id-stx]
|
||||||
|
has a @tech{module binding}: @scheme[(list source-mod source-id
|
||||||
|
nominal-source-mod nominal-source-id et?)].
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{@scheme[source-mod] is a module path index or symbol (see
|
||||||
|
@secref["mz:modpathidx"]) that indicates the defining module.}
|
||||||
|
|
||||||
|
@item{@scheme[source-id] is a symbol for the identifier's name
|
||||||
|
at its definition site in the source module. This can be
|
||||||
|
different from the local name returned by
|
||||||
|
@scheme[syntax->datum] for several reasons: the identifier is
|
||||||
|
renamed on import, it is renamed on export, or it is
|
||||||
|
implicitly renamed because the identifier (or its import) was
|
||||||
|
generated by a macro invocation.}
|
||||||
|
|
||||||
|
@item{@scheme[nominal-source-mod] is a module path index or
|
||||||
|
symbol (see @secref["mz:modpathidx"]) that indicates the
|
||||||
|
module @scheme[require]d into the context of @scheme[id-stx]
|
||||||
|
to provide its binding. It can be different from
|
||||||
|
@scheme[source-mod] due to a re-export in
|
||||||
|
@scheme[nominal-source-mod] of some imported identifier.}
|
||||||
|
|
||||||
|
@item{@scheme[nominal-source-id] is a symbol for the
|
||||||
|
identifier's name as exported by
|
||||||
|
@scheme[nominal-source-mod]. It can be different from
|
||||||
|
@scheme[source-id] due to a renaming @scheme[provide], even if
|
||||||
|
@scheme[source-mod] and @scheme[nominal-source-mod] are the
|
||||||
|
same.}
|
||||||
|
|
||||||
|
@item{@scheme[et?] is @scheme[#t] if the source definition is
|
||||||
|
for-syntax, @scheme[#f] otherwise.}
|
||||||
|
|
||||||
|
}}}
|
||||||
|
|
||||||
|
@item{The result is @scheme[#f] if @scheme[id-stx]
|
||||||
|
has a @tech{top-level binding}.}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
@defproc[(identifier-transformer-binding [id-stx syntax?])
|
||||||
|
(or/c (one-of 'lexical #f)
|
||||||
|
(listof (or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
(or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
boolean?))]{
|
||||||
|
|
||||||
|
Like @scheme[identifier-binding], but that the reported information is
|
||||||
|
for the identifier's binding in @tech{phase level} 1 (see
|
||||||
|
@secref["mz:id-model"]).
|
||||||
|
|
||||||
|
If the result is @scheme['lexical] for either of
|
||||||
|
@scheme[identifier-binding] or
|
||||||
|
@scheme[identifier-transformer-binding], then the result is always
|
||||||
|
@scheme['lexical] for both.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(identifier-template-binding [id-stx syntax?])
|
||||||
|
(or/c (one-of 'lexical #f)
|
||||||
|
(listof (or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
(or/c module-path-index? symbol?)
|
||||||
|
symbol?
|
||||||
|
boolean?))]{
|
||||||
|
|
||||||
|
Like @scheme[identifier-binding], but that the reported information is
|
||||||
|
for the identifier's binding in @tech{phase level} -1 (see
|
||||||
|
@secref["mz:id-model"]).
|
||||||
|
|
||||||
|
If the result is @scheme['lexical] for either of
|
||||||
|
@scheme[identifier-binding] or
|
||||||
|
@scheme[identifier-template-binding], then the result is always
|
||||||
|
@scheme['lexical] for both.}
|
206
collects/scribblings/reference/stx-ops.scrbl
Normal file
206
collects/scribblings/reference/stx-ops.scrbl
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
#reader(lib "docreader.ss" "scribble")
|
||||||
|
@require["mz.ss"]
|
||||||
|
|
||||||
|
@title[#:tag "mz:stxops"]{Syntax Object Content}
|
||||||
|
|
||||||
|
@defproc[(syntax? [v any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[v] is a @tech{syntax object}, @scheme[#f]
|
||||||
|
otherwise. See also @secref["mz:stxobj-model"].}
|
||||||
|
|
||||||
|
@defproc[(syntax-source [stx syntax?]) any]{
|
||||||
|
|
||||||
|
Returns the source for the syntax object @scheme[stx], or @scheme[#f]
|
||||||
|
if none is known. The source is represented by an arbitrary value
|
||||||
|
(e.g., one passed to @scheme[read-syntax]), but it is typically a file
|
||||||
|
path string. See also @secref["mz:compilation"].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-line [stx syntax?])
|
||||||
|
(or/c positive-exact-integer?
|
||||||
|
false/c)]{
|
||||||
|
|
||||||
|
Returns the line number (positive exact integer) for the start of the
|
||||||
|
syntax object in its source, or @scheme[#f] if the line number or
|
||||||
|
source is unknown. The result is @scheme[#f] if and only if
|
||||||
|
@scheme[(syntax-column stx)] produces @scheme[#f]. See also
|
||||||
|
@secref["mz:linecol"] and @secref["mz:compilation"].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-column [stx syntax?])
|
||||||
|
(or/c nonnegative-exact-integer?
|
||||||
|
false/c)]{
|
||||||
|
|
||||||
|
Returns the column number (non-negative exact integer) for the start
|
||||||
|
of the syntax object in its source, or @scheme[#f] if the source
|
||||||
|
column is unknown. The result is @scheme[#f] if and only if
|
||||||
|
@scheme[(syntax-line stx)] produces @scheme[#f]. See also
|
||||||
|
@secref["mz:linecol"] and @secref["mz:compilation"].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-position [stx syntax?])
|
||||||
|
(or/c positive-exact-integer?
|
||||||
|
false/c)]{
|
||||||
|
|
||||||
|
Returns the character position (positive exact integer) for the start
|
||||||
|
of the syntax object in its source, or @scheme[#f] if the source
|
||||||
|
position is unknown. See also @secref["mz:linecol"] and
|
||||||
|
@secref["mz:compilation"].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-span [stx syntax?])
|
||||||
|
(or/c nonnegative-exact-integer?
|
||||||
|
false/c)]{
|
||||||
|
|
||||||
|
Returns the span (non-negative exact integer) in characters of the
|
||||||
|
syntax object in its source, or @scheme[#f] if the span is
|
||||||
|
unknown. See also @secref["mz:compilation"].}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-original? [stx syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[stx] has the property that
|
||||||
|
@scheme[read-syntax] and @scheme[read-honu-syntax] attach to the
|
||||||
|
syntax objects that they generate (see @secref["mz:stxprops"]), and if
|
||||||
|
@scheme[stx]'s lexical information does not indicate that the object
|
||||||
|
was introduced by a syntax transformer (see
|
||||||
|
@secref["mz:stxscope"]). The result is @scheme[#f] otherwise. This
|
||||||
|
predicate can be used to distinguish syntax objects in an expanded
|
||||||
|
expression that were directly present in the original expression, as
|
||||||
|
opposed to syntax objects inserted by macros.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-source-module [stx syntax?])
|
||||||
|
(or/c module-path-index? symbol?)]{
|
||||||
|
|
||||||
|
Returns a module path index or symbol (see @secref["mz:modpathidx"])
|
||||||
|
for the module whose source contains @scheme[stx], or @scheme[#f] if
|
||||||
|
@scheme[stx] has no source module.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax-e [stx syntax?]) any]{
|
||||||
|
|
||||||
|
Unwraps the immediate datum structure from a syntax object,
|
||||||
|
leaving nested syntax structure (if any) in place. The result of
|
||||||
|
@scheme[(syntax-e @scheme[stx])] is one of the following:
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{a symbol}
|
||||||
|
|
||||||
|
@item{a @tech{syntax pair} (described below)}
|
||||||
|
|
||||||
|
@item{the empty list}
|
||||||
|
|
||||||
|
@item{a vector containing syntax objects}
|
||||||
|
|
||||||
|
@item{some other kind of datum---usually a number, boolean, or string}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
A @deftech{syntax pair} is a pair containing a syntax object as its
|
||||||
|
first element, and either the empty list, a syntax pair, or a syntax
|
||||||
|
object as its second element.
|
||||||
|
|
||||||
|
A syntax object that is the result of @scheme[read-syntax] reflects
|
||||||
|
the use of delimited @litchar{.} in the input by creating a syntax
|
||||||
|
object for every pair of parentheses in the source, and by creating a
|
||||||
|
pair-valued syntax object @italic{only} for parentheses in the
|
||||||
|
source. See @secref["mz:parse-pair"] for more information.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax->list [stx syntax?])
|
||||||
|
(or/c list? false/c)]{
|
||||||
|
|
||||||
|
Returns an immutable list of syntax objects or @scheme[#f]. The result
|
||||||
|
is a list of syntax objects when @scheme[(syntax->datum stx)]
|
||||||
|
would produce a list. In other words, @tech{syntax pairs} in
|
||||||
|
@scheme[(syntax-e @scheme[stx])] are flattened.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(syntax->datum [stx syntax?]) any]{
|
||||||
|
|
||||||
|
Returns a datum by stripping the lexical and source-location
|
||||||
|
information from @scheme[stx]. Graph structure is preserved by the
|
||||||
|
conversion.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(datum->syntax [ctxt (or/c syntax? false/c)]
|
||||||
|
[v any/c]
|
||||||
|
[srcloc (or/c syntax? false/c
|
||||||
|
(list/c any/c
|
||||||
|
(or/c positive-exact-integer? false/c)
|
||||||
|
(or/c nonnegative-exact-integer? false/c)
|
||||||
|
(or/c nonnegative-exact-integer? false/c)
|
||||||
|
(or/c positive-exact-integer? false/c)))]
|
||||||
|
[prop (or/c syntax? false/c) #f]
|
||||||
|
[cert (or/c syntax? false/c) #f])
|
||||||
|
syntax?]{
|
||||||
|
|
||||||
|
Converts the @tech{datum} @scheme[v] to a @tech{syntax object}, using
|
||||||
|
syntax objects already in @scheme[v] in the result. Converted objects
|
||||||
|
in @scheme[v] are given the lexical context information of
|
||||||
|
@scheme[ctxt] and the source-location information of
|
||||||
|
@scheme[srcloc]. If @scheme[v] is not already a syntax object, then
|
||||||
|
the resulting immediate syntax object it is given the properties (see
|
||||||
|
@secref["mz:stxprops"]) of @scheme[prop] and the inactive certificates
|
||||||
|
(see @secref["mz:stxprotect"]) of @scheme[cert]. Any of
|
||||||
|
@scheme[ctxt], @scheme[srcloc], @scheme[prop], or @scheme[cert] can be
|
||||||
|
@scheme[#f], in which case the resulting syntax has no lexical
|
||||||
|
context, source information, new properties, and/or certificates.
|
||||||
|
|
||||||
|
If @scheme[srcloc] is not @scheme[#f]
|
||||||
|
or a syntax object, it must be a list of five elements:
|
||||||
|
|
||||||
|
@schemeblock[
|
||||||
|
(list source-name line column position span)
|
||||||
|
]
|
||||||
|
|
||||||
|
where @scheme[source-name-v] is an arbitrary value for the source
|
||||||
|
name; @scheme[line] is an integer for the source line, or @scheme[#f];
|
||||||
|
@scheme[column] is an integer for the source column, or @scheme[#f];
|
||||||
|
@scheme[position] is an integer for the source position, or
|
||||||
|
@scheme[#f]; and @scheme[span] is an integer for the source span, or
|
||||||
|
@scheme[#f]. The @scheme[line] and @scheme[column] values must both be
|
||||||
|
numbers or both be @scheme[#f], otherwise the
|
||||||
|
@exnraise[exn:fail:contract].
|
||||||
|
|
||||||
|
Graph structure is preserved by the conversion of @scheme[v] to a
|
||||||
|
syntax object, but graph structure that is distributed among distinct
|
||||||
|
syntax objects in @scheme[v] may be hidden from future applications of
|
||||||
|
@scheme[syntax->datum] and @scheme[syntax-graph?] to the new
|
||||||
|
syntax object.}
|
||||||
|
|
||||||
|
@defproc[(syntax-graph? [stx syntax?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[stx] might be preservably shared within
|
||||||
|
a syntax object created by @scheme[read-syntax],
|
||||||
|
@scheme[read-honu-syntax], or @scheme[datum->syntax]. In general,
|
||||||
|
sharing detection is approximate---@scheme[datum->syntax] can
|
||||||
|
construct syntax objects with sharing that is hidden from
|
||||||
|
@scheme[syntax-graph?]---but @scheme[syntax-graph?] reliably returns
|
||||||
|
@scheme[#t] for at least one syntax object in a cyclic
|
||||||
|
structure. Meanwhile, deconstructing a syntax object with procedures
|
||||||
|
such as @scheme[syntax-e] and comparing the results with @scheme[eq?]
|
||||||
|
can also fail to detect sharing (even cycles), due to the way lexical
|
||||||
|
information is lazily propagated; only @scheme[syntax->datum] reliably
|
||||||
|
exposes sharing in a way that can be detected with @scheme[eq?].}
|
||||||
|
|
||||||
|
@defproc[(identifier? [v any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @scheme[#t] if @scheme[v] is a syntax object and
|
||||||
|
@scheme[(syntax-e stx)] produces a symbol.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(generate-temporaries [stx-pair (or syntax? list?)])
|
||||||
|
(listof identifier?)]{
|
||||||
|
|
||||||
|
Returns a list of identifiers that are distinct from all other
|
||||||
|
identifiers. The list contains as many identifiers as
|
||||||
|
@scheme[stx-pair] contains elements. The @scheme[stx-pair] argument
|
||||||
|
must be a syntax pair that can be flattened into a list. The elements
|
||||||
|
of @scheme[stx-pair] can be anything, but string, symbol, and
|
||||||
|
identifier elements will be embedded in the corresponding generated
|
||||||
|
name (useful for debugging purposes). The generated identifiers are
|
||||||
|
built with interned symbols (not @scheme[gensym]s), so the limitations
|
||||||
|
described in @secref["mz:compilation"] do not apply.}
|
375
collects/scribblings/reference/stx-patterns.scrbl
Normal file
375
collects/scribblings/reference/stx-patterns.scrbl
Normal file
|
@ -0,0 +1,375 @@
|
||||||
|
#reader(lib "docreader.ss" "scribble")
|
||||||
|
@require["mz.ss"]
|
||||||
|
@require["ellipses.ss"]
|
||||||
|
|
||||||
|
@title{Pattern-Based Syntax Matching}
|
||||||
|
|
||||||
|
@defform/subs[(syntax-case stx-expr (literal-id ...)
|
||||||
|
clause ...)
|
||||||
|
([clause [pattern result-expr]
|
||||||
|
[pattern fender-expr result-expr]]
|
||||||
|
[pattern _
|
||||||
|
id
|
||||||
|
(pattern ...)
|
||||||
|
(pattern ...+ . pattern)
|
||||||
|
(pattern ... pattern ellipses pattern ...)
|
||||||
|
(pattern ... pattern ellipses pattern ... . pattern)
|
||||||
|
(code:line #,(tt "#")(pattern ...))
|
||||||
|
(code:line #,(tt "#")(pattern ... pattern ellipses pattern ...))
|
||||||
|
(ellipses stat-pattern)
|
||||||
|
const]
|
||||||
|
[stat-pattern id
|
||||||
|
(stat-pattern ...)
|
||||||
|
(stat-pattern ...+ . stat-pattern)
|
||||||
|
(code:line #,(tt "#")(stat-pattern ...))
|
||||||
|
const]
|
||||||
|
[ellipses #,ellipses-id])]{
|
||||||
|
|
||||||
|
Finds the first @scheme[pattern] that matches the syntax object
|
||||||
|
produced by @scheme[stx-expr], and for which the corresponding
|
||||||
|
@scheme[fender-expr] (if any) produces a true value; the result is from
|
||||||
|
the corresponding @scheme[result-expr], which is in tail position for
|
||||||
|
the @scheme[syntax-case] form. If no @scheme[clause] matches, then the
|
||||||
|
@exnraise[exn:fail:syntax].
|
||||||
|
|
||||||
|
A syntax object matches a @scheme[pattern] as follows:
|
||||||
|
|
||||||
|
@specsubform[_]{
|
||||||
|
|
||||||
|
A @scheme[_] pattern (i.e., an identifier with the same binding as
|
||||||
|
@scheme[_]) matches any syntax object.}
|
||||||
|
|
||||||
|
@specsubform[id]{
|
||||||
|
|
||||||
|
An @scheme[id] matches any syntax object when it is not bound to
|
||||||
|
@|ellipses-id| or @scheme[_] and does not have the same binding as
|
||||||
|
any @scheme[literal-id]. The @scheme[id] is further bound as
|
||||||
|
@deftech{pattern variable} for the corresponding @scheme[fender-expr]
|
||||||
|
(if any) and @scheme[result-expr]. A pattern-variable binding is a
|
||||||
|
transformer binding; the pattern variable can be reference only
|
||||||
|
through forms like @scheme[syntax]. The binding's value is the syntax
|
||||||
|
object that matched the pattern with a @deftech{depth marker} of
|
||||||
|
@math{0}.
|
||||||
|
|
||||||
|
An @scheme[id] that has the same binding as a @scheme[literal-id]
|
||||||
|
matches a syntax object that is an identifier with the same binding
|
||||||
|
in the sense of @scheme[free-identifier=?]. The match does not
|
||||||
|
introduce any @tech{pattern variables}.}
|
||||||
|
|
||||||
|
@specsubform[(pattern ...)]{
|
||||||
|
|
||||||
|
A @scheme[(pattern ...)] pattern matches a syntax object whose datum
|
||||||
|
form (i.e., without lexical information) is a list with as many
|
||||||
|
elements as sub-@scheme[pattern]s in the pattern, and where each
|
||||||
|
syntax object that corresponding to an element of the list matches
|
||||||
|
the corresponding sub-@scheme[pattern].
|
||||||
|
|
||||||
|
Any @tech{pattern variables} bound by the sub-@scheme[pattern]s are
|
||||||
|
bound by the complete pattern; the bindings must all be distinct.}
|
||||||
|
|
||||||
|
@specsubform[(pattern ...+ . pattern)]{
|
||||||
|
|
||||||
|
The last @scheme[pattern] must not be a @scheme[(pattern ...)],
|
||||||
|
@scheme[(pattern ...+ . pattern)], @scheme[(pattern ... pattern
|
||||||
|
ellipses pattern ...)], or @scheme[(pattern ... pattern ellipses
|
||||||
|
pattern ... . pattern)] form.
|
||||||
|
|
||||||
|
Like the previous kind of pattern, but matches syntax objects that
|
||||||
|
are not necessarily lists; for @math{n} sub-@scheme[pattern]s before
|
||||||
|
the last sub-@scheme[pattern], the syntax object's datum must be a
|
||||||
|
pair such that @math{n-1} @scheme[cdr]s produce pairs. The last
|
||||||
|
sub-@scheme[pattern] is matched against the syntax object
|
||||||
|
corresponding to the @math{n}th @scheme[cdr] (or the
|
||||||
|
@scheme[datum->syntax] coercion of the datum using the nearest
|
||||||
|
enclosing syntax object's lexical context and source location).}
|
||||||
|
|
||||||
|
@specsubform[(pattern ... pattern ellipses pattern ...)]{
|
||||||
|
|
||||||
|
Like the @scheme[(pattern ...)] kind of pattern, but matching a
|
||||||
|
syntax object with any number (zero or more) elements that match the
|
||||||
|
sub-@scheme[pattern] followed by @scheme[ellipses] in the
|
||||||
|
corresponding position relative to other sub-@scheme[pattern]s.
|
||||||
|
|
||||||
|
For each pattern variable bound by the sub-@scheme[pattern] followed
|
||||||
|
by @scheme[ellipses], the larger pattern binds the same pattern
|
||||||
|
variable to a list of values, one for each element of the syntax
|
||||||
|
object matched to the sub-@scheme[pattern], with an incremented
|
||||||
|
@tech{depth marker}. (The sub-@scheme[pattern] itself may contain
|
||||||
|
@scheme[ellipses], leading to a pattern variables bound to lists of
|
||||||
|
lists of syntax objects with a @tech{depth marker} of @math{2}, and
|
||||||
|
so on.)}
|
||||||
|
|
||||||
|
@specsubform[(pattern ... pattern ellipses pattern ... . pattern)]{
|
||||||
|
|
||||||
|
Like the previous kind of pattern, but with a final
|
||||||
|
sub-@scheme[pattern] as for @scheme[(pattern ...+ . pattern)]. The
|
||||||
|
final @scheme[pattern] never matches a syntax object whose datum is a
|
||||||
|
list.}
|
||||||
|
|
||||||
|
@specsubform[(code:line #,(tt "#")(pattern ...))]{
|
||||||
|
|
||||||
|
Like a @scheme[(pattern ...)] pattern, but matching a vector syntax object
|
||||||
|
whose elements match the corresponding sub-@scheme[pattern]s.}
|
||||||
|
|
||||||
|
@specsubform[(code:line #,(tt "#")(pattern ... pattern ellipses pattern ...))]{
|
||||||
|
|
||||||
|
Like a @scheme[(pattern ... pattern ellipses pattern ...)] pattern,
|
||||||
|
but matching a vector syntax object whose elements match the
|
||||||
|
corresponding sub-@scheme[pattern]s.}
|
||||||
|
|
||||||
|
@specsubform[(ellipses stat-pattern)]{
|
||||||
|
|
||||||
|
Matches the same as @scheme[stat-pattern], which is like a @scheme[pattern],
|
||||||
|
but identifiers with the binding @scheme[...] are treated the same as
|
||||||
|
other @scheme[id]s.}
|
||||||
|
|
||||||
|
@specsubform[const]{
|
||||||
|
|
||||||
|
A @scheme[const] is any datum that does not match one of the
|
||||||
|
preceeding forms; a syntax object matches a @scheme[const] pattern
|
||||||
|
when its datum is @scheme[equal?] to the @scheme[quote]d
|
||||||
|
@scheme[const].}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@defform[(syntax-case* stx-expr (literal-id ...) id-compare-expr
|
||||||
|
clause ...)]{
|
||||||
|
|
||||||
|
Like @scheme[syntax-case], but @scheme[id-compare-expr] must produce a
|
||||||
|
procedure that accepts two arguments. A @scheme[literal-id] in a
|
||||||
|
@scheme[_pattern] matches an identifier for which the procedure
|
||||||
|
returns true when given the identifier to match (as the first argument)
|
||||||
|
and the identifier in the @scheme[_pattern] (as the second argument).
|
||||||
|
|
||||||
|
In other words, @scheme[syntax-case] is like @scheme[syntax-case*] with
|
||||||
|
an @scheme[id-compare-expr] that produces @scheme[free-identifier=?].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(with-syntax ([pattern stx-expr] ...)
|
||||||
|
body ...+)]{
|
||||||
|
|
||||||
|
Similar to @scheme[syntax-case], in that it matches a @scheme[pattern]
|
||||||
|
to a syntax object. Unlike @scheme[syntax-case], all @scheme[pattern]s
|
||||||
|
are matched, each to the result of a corresponding @scheme[stx-expr],
|
||||||
|
and the pattern variables from all matches (which must be distinct)
|
||||||
|
are bound with a single @scheme[body] sequence. The result of the
|
||||||
|
@scheme[with-syntax] form is the result of the last @scheme[body],
|
||||||
|
which is in tail position with respect to the @scheme[with-syntax]
|
||||||
|
form.
|
||||||
|
|
||||||
|
If any @scheme[pattern] fails to match the corresponding
|
||||||
|
@scheme[stx-expr], the @exnraise[exn:fail:syntax].
|
||||||
|
|
||||||
|
A @scheme[with-syntax] form is roughly equivalent to the following
|
||||||
|
@scheme[syntax-case] form:
|
||||||
|
|
||||||
|
@schemeblock[
|
||||||
|
(syntax-case (list stx-expr ...) ()
|
||||||
|
[(pattern ...) (let () body ...+)])
|
||||||
|
]
|
||||||
|
|
||||||
|
However, if any individual @scheme[stx-expr] produces a
|
||||||
|
non-@tech{syntax object}, then it is converted to one using
|
||||||
|
@scheme[datum->syntax] and the lexical context and source location of
|
||||||
|
the individual @scheme[stx-expr].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform/subs[(syntax template)
|
||||||
|
([template id
|
||||||
|
(template-elem ...)
|
||||||
|
(template-elem ...+ . template)
|
||||||
|
(code:line #,(tt "#")(template-elem ...))
|
||||||
|
(ellipses stat-template)
|
||||||
|
const]
|
||||||
|
[template-elem (code:line template ellipses ...)]
|
||||||
|
[stat-template id
|
||||||
|
(stat-template ...)
|
||||||
|
(stat-template ... . stat-template)
|
||||||
|
(code:line #,(tt "#")(stat-template ...))
|
||||||
|
const]
|
||||||
|
[ellipses #,ellipses-id])]{
|
||||||
|
|
||||||
|
Constructs a syntax object based on a @scheme[template],which can
|
||||||
|
inlude @tech{pattern variables} bound by @scheme[syntax-case] or
|
||||||
|
@scheme[with-syntax].
|
||||||
|
|
||||||
|
Template forms produce a syntax object as follows:
|
||||||
|
|
||||||
|
@specsubform[id]{
|
||||||
|
|
||||||
|
If @scheme[id] is bound as a @tech{pattern variable}, then
|
||||||
|
@scheme[id] as a template produces the @tech{pattern variable}'s
|
||||||
|
match result. Unless the @scheme[id] is a sub-@scheme[template] that is
|
||||||
|
replicated by @scheme[ellipses] in a larger @scheme[template], the
|
||||||
|
@tech{pattern variable}'s value must be a syntax object with a
|
||||||
|
@tech{depth marker} of @math{0} (as opposed to a list of
|
||||||
|
matches).
|
||||||
|
|
||||||
|
More generally, if the @tech{pattern variable}'s value has a depth
|
||||||
|
marker @math{n}, then it can only appear within a template where it
|
||||||
|
is replicated by at least @math{n} @scheme[ellipses]es. In that case,
|
||||||
|
the template will be replicated enough times to use each match result
|
||||||
|
at least once.
|
||||||
|
|
||||||
|
If @scheme[id] is not bound as a pattern variable, then @scheme[id]
|
||||||
|
as a template produces @scheme[(quote-syntax id)].}
|
||||||
|
|
||||||
|
@specsubform[(template-elem ...)]{
|
||||||
|
|
||||||
|
Produces a syntax object whose datum is a list, and where the
|
||||||
|
elements of the list correspond to syntax objects producesd by the
|
||||||
|
@scheme[template-elem]s.
|
||||||
|
|
||||||
|
A @scheme[template-elem] is a sub-@scheme[template] replicated by any
|
||||||
|
number of @scheme[ellipses]es:
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{If the sub-@scheme[template] is replicated by no
|
||||||
|
@scheme[ellipses]es, then it generates a single syntax object to
|
||||||
|
incorporate into the result syntax object.}
|
||||||
|
|
||||||
|
@item{If the sub-@scheme[template] is replicated by one
|
||||||
|
@scheme[ellipses], then it generates a sequence of syntax objects
|
||||||
|
that is ``inlined'' into the resulting syntax object.
|
||||||
|
|
||||||
|
The number of generated elements depends the values of
|
||||||
|
@tech{pattern variables} referenced within the
|
||||||
|
sub-@scheme[template]. There must be at least one @tech{pattern
|
||||||
|
variable} whose value is has a @tech{depth marker} less than the
|
||||||
|
number of @scheme[ellipses]es after the pattern variable within the
|
||||||
|
sub-@scheme[template].
|
||||||
|
|
||||||
|
If a @tech{pattern variable} is replicated by more
|
||||||
|
@scheme[ellipses]es in a @scheme[template] than the @tech{depth
|
||||||
|
marker} of its binding, then the @tech{pattern variable}'s result
|
||||||
|
is determined normally for inner @scheme[ellipses]es (up to the
|
||||||
|
binding's @tech{depth marker}), and then the result is replicated
|
||||||
|
as necessary to satisfy outer @scheme[ellipses]es.}
|
||||||
|
|
||||||
|
@item{For each @scheme[ellipses] after the first one, the preceding
|
||||||
|
element (with earlier replicating @scheme[ellipses]s) is
|
||||||
|
conceptually wrapped with parentheses for generating output, and
|
||||||
|
then the wrapping parentheses are removed in the resulting syntax
|
||||||
|
object.}}}
|
||||||
|
|
||||||
|
@specsubform[(template-elem ... . template)]{
|
||||||
|
|
||||||
|
Like the previous form, but the result is not necessarily a list;
|
||||||
|
instead, the place of the empty list in resulting syntax object's
|
||||||
|
datum is taken by the syntax object produced by @scheme[template].}
|
||||||
|
|
||||||
|
@specsubform[(code:line #,(tt "#")(template-elem ...))]{
|
||||||
|
|
||||||
|
Like the @scheme[(template-elem ...)] form, but producing a syntax
|
||||||
|
object whose datum is a vector instead of a list.}
|
||||||
|
|
||||||
|
@specsubform[(ellipses stat-template)]{
|
||||||
|
|
||||||
|
Produces the same result as @scheme[stat-template], which is like a
|
||||||
|
@scheme[template], but @|ellipses-id| is treated like a @scheme[id]
|
||||||
|
(with no pattern binding).}
|
||||||
|
|
||||||
|
@specsubform[const]{
|
||||||
|
|
||||||
|
A @scheme[const] template is any form that does not match the
|
||||||
|
preceding cases, and it produces the result @scheme[(quote-syntac
|
||||||
|
const)].}
|
||||||
|
|
||||||
|
A @scheme[(#,(schemekeywordfont "syntax") template)] form is normally
|
||||||
|
abbreviated as @scheme[#'template]; see also
|
||||||
|
@secref["mz:parse-quote"]. If @scheme[template] contains no pattern
|
||||||
|
variables, then @scheme[#'template] is equivalent to
|
||||||
|
@scheme[(quote-syntax template)].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(quasisyntax template)]{
|
||||||
|
|
||||||
|
Like @scheme[syntax], but @scheme[(#,(schemekeywordfont "unsyntax")
|
||||||
|
_expr)] and @scheme[(#,(schemekeywordfont "unsyntax-splicing") _expr)]
|
||||||
|
escape to an expression within the @scheme[template].
|
||||||
|
|
||||||
|
The @scheme[_expr] must produce a syntax object (or syntax list) to be
|
||||||
|
substituted in place of the @scheme[unsyntax] or
|
||||||
|
@scheme[unsyntax-splicing] form within the quasiquoting template, just
|
||||||
|
like @scheme[unquote] and @scheme[unquote-splicing] within
|
||||||
|
@scheme[quasiquote]. (If the escaped expression does not generate a
|
||||||
|
syntax object, it is converted to one in the same was as for the
|
||||||
|
right-hand sides of @scheme[with-syntax].) Nested
|
||||||
|
@scheme[quasisyntax]es introduce quasiquoting layers in the same way
|
||||||
|
as nested @scheme[quasiquote]s.
|
||||||
|
|
||||||
|
Also analogous @scheme[quasiquote], the reader converts @litchar{#`}
|
||||||
|
to @scheme[quasisyntax], @litchar{#,} to @scheme[unsyntax], and
|
||||||
|
@litchar["#,@"] to @scheme[unsyntax-splicing]. See also
|
||||||
|
@secref["mz:parse-quote"].}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(unsyntax expr)]{
|
||||||
|
|
||||||
|
Illegal as an expression form. The @scheme[unsyntax] form is for use
|
||||||
|
only with a @scheme[quasisyntax] template.}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(unsyntax-splicing expr)]{
|
||||||
|
|
||||||
|
Illegal as an expression form. The @scheme[unsyntax-splicing] form is
|
||||||
|
for use only with a @scheme[quasisyntax] template.}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(syntax/loc stx-expr template)]{
|
||||||
|
|
||||||
|
Like @scheme[syntax], except that the immediate resulting syntax
|
||||||
|
object takes its source-location information from the result of
|
||||||
|
@scheme[stx-expr] (which must produce a syntax object), unless the
|
||||||
|
@scheme[template] is just a pattern variable.}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(quasisyntax/loc stx-expr template)]{
|
||||||
|
|
||||||
|
Like @scheme[quasisyntax], but with source-location assignment like
|
||||||
|
@scheme[syntax/loc].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(syntax-rules (literal-id ...)
|
||||||
|
[(id . pattern) template] ...)]{
|
||||||
|
|
||||||
|
Equivalent to
|
||||||
|
|
||||||
|
@schemeblock[
|
||||||
|
(lambda (stx)
|
||||||
|
(syntax-case stx (literal-id ...)
|
||||||
|
[(_generated-id . pattern) (syntax template)] ...))
|
||||||
|
]
|
||||||
|
|
||||||
|
where each @scheme[_generated-id] binds no identifier in the
|
||||||
|
corresponding @scheme[template].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(syntax-id-rules (literal-id ...)
|
||||||
|
[pattern template] ...)]{
|
||||||
|
|
||||||
|
Equivalent to
|
||||||
|
|
||||||
|
@schemeblock[
|
||||||
|
(lambda (stx)
|
||||||
|
(make-set!-transformer
|
||||||
|
(syntax-case stx (literal-id ...)
|
||||||
|
[pattern (syntax template)] ...)))
|
||||||
|
]}
|
||||||
|
|
||||||
|
|
||||||
|
@ellipses-defn{
|
||||||
|
|
||||||
|
The @|ellipses-id| transformer binding prohibits @|ellipses-id| from being
|
||||||
|
used as an expression. This binding useful only in syntax patterns and
|
||||||
|
templates, where it indicates repetitions of a pattern or
|
||||||
|
template. See @scheme[syntax-case] and @scheme[syntax].}
|
||||||
|
|
||||||
|
@defidform[_]{
|
||||||
|
|
||||||
|
The @scheme[_] transformer binding prohibits @scheme[_] from being
|
||||||
|
used as an expression. This binding useful only in syntax patterns,
|
||||||
|
where it indicates a pattern that matches any syntax object. See
|
||||||
|
@scheme[syntax-case].}
|
|
@ -4,7 +4,7 @@
|
||||||
@require["mz.ss"]
|
@require["mz.ss"]
|
||||||
|
|
||||||
@;------------------------------------------------------------------------
|
@;------------------------------------------------------------------------
|
||||||
@title{Syntax Model}
|
@title[#:tag "mz:syntax-model"]{Syntax Model}
|
||||||
|
|
||||||
The syntax of a Scheme program is defined by
|
The syntax of a Scheme program is defined by
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ process, and when the @tech{expansion} process encounters a
|
||||||
new binding information.
|
new binding information.
|
||||||
|
|
||||||
@;------------------------------------------------------------------------
|
@;------------------------------------------------------------------------
|
||||||
@section{Identifiers and Binding}
|
@section[#:tag "mz:id-model"]{Identifiers and Binding}
|
||||||
|
|
||||||
@guideintro["guide:binding"]{binding}
|
@guideintro["guide:binding"]{binding}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ identifier has a @tech{top-level binding} or @tech{module binding},
|
||||||
then it can have different such bindings in different phase levels.
|
then it can have different such bindings in different phase levels.
|
||||||
|
|
||||||
@;------------------------------------------------------------------------
|
@;------------------------------------------------------------------------
|
||||||
@section{Syntax Objects}
|
@section[#:tag "mz:stxobj-model"]{Syntax Objects}
|
||||||
|
|
||||||
A @deftech{syntax object} combines a simpler Scheme value, such as a
|
A @deftech{syntax object} combines a simpler Scheme value, such as a
|
||||||
symbol or pair, with @deftech{lexical information} about bindings and
|
symbol or pair, with @deftech{lexical information} about bindings and
|
||||||
|
@ -147,7 +147,7 @@ information that @scheme[_datum] had when it was parsed as part of the
|
||||||
@section[#:tag "mz:expansion"]{Expansion@aux-elem{ (Parsing)}}
|
@section[#:tag "mz:expansion"]{Expansion@aux-elem{ (Parsing)}}
|
||||||
|
|
||||||
@deftech{Expansion} recursively processes a @tech{syntax object} in a
|
@deftech{Expansion} recursively processes a @tech{syntax object} in a
|
||||||
particular phase level, starting with phase level 0. @tech{Bindings}
|
particular phase level, starting with @tech{phase level} 0. @tech{Bindings}
|
||||||
from the @tech{syntax object}'s @tech{lexical information} drive the
|
from the @tech{syntax object}'s @tech{lexical information} drive the
|
||||||
expansion process, and cause new bindings to be introduced for the
|
expansion process, and cause new bindings to be introduced for the
|
||||||
lexical information of sub-expressions. In some cases, a
|
lexical information of sub-expressions. In some cases, a
|
||||||
|
@ -219,7 +219,7 @@ one whose binding is @scheme[define-values]). In all cases,
|
||||||
identifiers above typeset as syntactic-form names refer to the
|
identifiers above typeset as syntactic-form names refer to the
|
||||||
bindings defined in @secref["mz:syntax"].
|
bindings defined in @secref["mz:syntax"].
|
||||||
|
|
||||||
Only phase levels 0 and 1 are relevant for following the parse of a
|
Only @tech{phase levels} 0 and 1 are relevant for following the parse of a
|
||||||
program (though the @scheme[_datum] in a @scheme[quote-syntax] form
|
program (though the @scheme[_datum] in a @scheme[quote-syntax] form
|
||||||
preserves its information for all phase levels). In particular, the
|
preserves its information for all phase levels). In particular, the
|
||||||
relevant phase level is 0, except for the @scheme[_expr]s in a
|
relevant phase level is 0, except for the @scheme[_expr]s in a
|
||||||
|
@ -425,7 +425,7 @@ binding @scheme[x] and the body @scheme[y] are not
|
||||||
@scheme[bound-identifier=?].
|
@scheme[bound-identifier=?].
|
||||||
|
|
||||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
@subsection{Transformer Bindings}
|
@subsection[#:tag "mz:transformer-model"]{Transformer Bindings}
|
||||||
|
|
||||||
In a @tech{top-level context} or @tech{module context}, when the
|
In a @tech{top-level context} or @tech{module context}, when the
|
||||||
expander encounters a @scheme[define-syntaxes] form, the binding that
|
expander encounters a @scheme[define-syntaxes] form, the binding that
|
||||||
|
@ -487,6 +487,12 @@ is the one left with a mark, and the reference @scheme[x] has no mark,
|
||||||
so the binding @scheme[x] is not @scheme[bound-identifier=?] to the
|
so the binding @scheme[x] is not @scheme[bound-identifier=?] to the
|
||||||
body @scheme[x].
|
body @scheme[x].
|
||||||
|
|
||||||
|
The @scheme[set!] form and the @scheme[make-set!-transformer]
|
||||||
|
procedure work together to support @deftech{assignment transformers}
|
||||||
|
that transformer @scheme[set!] expression. @tech{Assignment
|
||||||
|
transformers} are applied by @scheme[set!] in the same way as a normal
|
||||||
|
transformer by the macro expander.
|
||||||
|
|
||||||
The expander's handling of @scheme[letrec-values+syntaxes] is similar
|
The expander's handling of @scheme[letrec-values+syntaxes] is similar
|
||||||
to its handling of @scheme[define-syntaxes]. A
|
to its handling of @scheme[define-syntaxes]. A
|
||||||
@scheme[letrec-values+syntaxes] mist be expanded in an arbitrary phase
|
@scheme[letrec-values+syntaxes] mist be expanded in an arbitrary phase
|
||||||
|
|
|
@ -745,12 +745,17 @@ Equivalent to @scheme[(when (not test-expr) expr ...)].
|
||||||
|
|
||||||
@defform[(set! id expr)]{
|
@defform[(set! id expr)]{
|
||||||
|
|
||||||
Evaluates @scheme[expr] and installs the result into the location for
|
If @scheme[id] is bound as syntax to an @tech{assignment transformer},
|
||||||
@scheme[id], which must be bound as a local variable or defined as a
|
as produced by @scheme[make-set!-transformer], then this form is
|
||||||
@tech{top-level variable} or @tech{module-level variable}. If
|
expanded by calling the assignment transformer with the full
|
||||||
@scheme[id] refers to an imported binding, a syntax error is reported.
|
expressions.
|
||||||
If @scheme[id] refers to a @tech{top-level variable} that has not been
|
|
||||||
defined, the @exnraise[exn:fail:contract].
|
Otherwise, evaluates @scheme[expr] and installs the result into the
|
||||||
|
location for @scheme[id], which must be bound as a local variable or
|
||||||
|
defined as a @tech{top-level variable} or @tech{module-level
|
||||||
|
variable}. If @scheme[id] refers to an imported binding, a syntax
|
||||||
|
error is reported. If @scheme[id] refers to a @tech{top-level
|
||||||
|
variable} that has not been defined, the @exnraise[exn:fail:contract].
|
||||||
|
|
||||||
@defexamples[
|
@defexamples[
|
||||||
(define x 12)
|
(define x 12)
|
||||||
|
@ -764,7 +769,8 @@ x
|
||||||
|
|
||||||
@defform[(set!-values (id ...) expr)]{
|
@defform[(set!-values (id ...) expr)]{
|
||||||
|
|
||||||
Evaluates @scheme[expr], which must produce as many values as supplied
|
Assuming that all @scheme[id]s refer to variables, this form evaluates
|
||||||
|
@scheme[expr], which must produce as many values as supplied
|
||||||
@scheme[id]s. The location of each @scheme[id] is filled wih to the
|
@scheme[id]s. The location of each @scheme[id] is filled wih to the
|
||||||
corresponding value from @scheme[expr] in the same way as for
|
corresponding value from @scheme[expr] in the same way as for
|
||||||
@scheme[set!].
|
@scheme[set!].
|
||||||
|
@ -774,7 +780,17 @@ corresponding value from @scheme[expr] in the same way as for
|
||||||
[b 2])
|
[b 2])
|
||||||
(set!-values (a b) (values b a))
|
(set!-values (a b) (values b a))
|
||||||
(list a b))
|
(list a b))
|
||||||
]}
|
]
|
||||||
|
|
||||||
|
More generally, the @scheme[set!-values] form is expanded to
|
||||||
|
|
||||||
|
@schemeblock[
|
||||||
|
(let-values ([(_tmp-id ...) expr])
|
||||||
|
(set! id _tmp-id) ...)
|
||||||
|
]
|
||||||
|
|
||||||
|
which triggers further expansion if any @scheme[id] has a transformer
|
||||||
|
binding to an @tech{assignment transformer}.}
|
||||||
|
|
||||||
@;------------------------------------------------------------------------
|
@;------------------------------------------------------------------------
|
||||||
@include-section["for.scrbl"]
|
@include-section["for.scrbl"]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user