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
|
||||
defform defform* defform/subs defform*/subs defform/none
|
||||
defidform
|
||||
specform specform/subs
|
||||
specsubform specsubform/subs specspecsubform specspecsubform/subs specsubform/inline
|
||||
schemegrammar schemegrammar*
|
||||
|
@ -311,6 +312,15 @@
|
|||
'(spec) (list (lambda (ignored) (schemeblock0 spec)))
|
||||
null null
|
||||
(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
|
||||
(syntax-rules ()
|
||||
[(_ #:literals (lit ...) spec desc ...)
|
||||
|
@ -837,7 +847,11 @@
|
|||
(apply
|
||||
append
|
||||
(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)])
|
||||
(cond
|
||||
[(symbol? form) (if (or (meta-symbol? form)
|
||||
|
@ -869,7 +883,10 @@
|
|||
(eq? form (car forms))
|
||||
(make-target-element
|
||||
#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))))))))
|
||||
forms form-procs)
|
||||
(if (null? sub-procs)
|
||||
|
|
|
@ -363,6 +363,7 @@
|
|||
(let ([c (syntax-e c)])
|
||||
(let ([s (format "~s" c)])
|
||||
(if (and (symbol? c)
|
||||
((string-length s) . > . 1)
|
||||
(char=? (string-ref s 0) #\_))
|
||||
(values (substring s 1) #t #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")
|
||||
@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["control.scrbl"]
|
||||
@include-section["concurrency.scrbl"]
|
||||
@include-section["macros.scrbl"]
|
||||
@include-section["security.scrbl"]
|
||||
@include-section["io.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"]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@title{Syntax Model}
|
||||
@title[#:tag "mz:syntax-model"]{Syntax Model}
|
||||
|
||||
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.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Identifiers and Binding}
|
||||
@section[#:tag "mz:id-model"]{Identifiers and 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.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Syntax Objects}
|
||||
@section[#:tag "mz:stxobj-model"]{Syntax Objects}
|
||||
|
||||
A @deftech{syntax object} combines a simpler Scheme value, such as a
|
||||
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)}}
|
||||
|
||||
@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
|
||||
expansion process, and cause new bindings to be introduced for the
|
||||
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
|
||||
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
|
||||
preserves its information for all phase levels). In particular, the
|
||||
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=?].
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@subsection{Transformer Bindings}
|
||||
@subsection[#:tag "mz:transformer-model"]{Transformer Bindings}
|
||||
|
||||
In a @tech{top-level context} or @tech{module context}, when the
|
||||
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
|
||||
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
|
||||
to its handling of @scheme[define-syntaxes]. A
|
||||
@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)]{
|
||||
|
||||
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].
|
||||
If @scheme[id] is bound as syntax to an @tech{assignment transformer},
|
||||
as produced by @scheme[make-set!-transformer], then this form is
|
||||
expanded by calling the assignment transformer with the full
|
||||
expressions.
|
||||
|
||||
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[
|
||||
(define x 12)
|
||||
|
@ -764,7 +769,8 @@ x
|
|||
|
||||
@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
|
||||
corresponding value from @scheme[expr] in the same way as for
|
||||
@scheme[set!].
|
||||
|
@ -774,7 +780,17 @@ corresponding value from @scheme[expr] in the same way as for
|
|||
[b 2])
|
||||
(set!-values (a b) (values b a))
|
||||
(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"]
|
||||
|
|
Loading…
Reference in New Issue
Block a user