doc work: reference on syntax objects

svn: r6882
This commit is contained in:
Matthew Flatt 2007-07-10 07:08:16 +00:00
parent 5117dd03d9
commit 8470b61466
10 changed files with 805 additions and 17 deletions

View File

@ -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)

View File

@ -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))))]

View 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 ...)))

View File

@ -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"]

View File

@ -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"]

View 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.}

View 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.}

View 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].}

View File

@ -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

View File

@ -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"]