
Port `examples`, `interactions`, etc., to use the new `examples` form of `scribble/examples`. The main intended effect is to ensure that errors are produced by examples only as specifically indicated.
442 lines
17 KiB
Racket
442 lines
17 KiB
Racket
#lang scribble/doc
|
|
@(require "mz.rkt")
|
|
|
|
@(define stx-eval (make-base-eval))
|
|
@(stx-eval '(require (for-syntax racket/base)))
|
|
|
|
@title[#:tag "stxops"]{Syntax Object Content}
|
|
|
|
|
|
@defproc[(syntax? [v any/c]) boolean?]{
|
|
|
|
Returns @racket[#t] if @racket[v] is a @tech{syntax object}, @racket[#f]
|
|
otherwise. See also @secref["stxobj-model"].
|
|
|
|
@examples[#:eval stx-eval
|
|
(syntax? #'quinoa)
|
|
(syntax? #'(spelt triticale buckwheat))
|
|
(syntax? (datum->syntax #f 'millet))
|
|
(syntax? "barley")
|
|
]}
|
|
|
|
|
|
@defproc[(identifier? [v any/c]) boolean?]{
|
|
|
|
Returns @racket[#t] if @racket[v] is a @tech{syntax object} and
|
|
@racket[(syntax-e stx)] produces a symbol.
|
|
|
|
@examples[#:eval stx-eval
|
|
(identifier? #'linguine)
|
|
(identifier? #'(if wheat? udon soba))
|
|
(identifier? 'ramen)
|
|
(identifier? 15)
|
|
]}
|
|
|
|
|
|
@defproc[(syntax-source [stx syntax?]) any]{
|
|
|
|
Returns the source for the @tech{syntax object} @racket[stx], or @racket[#f]
|
|
if none is known. The source is represented by an arbitrary value
|
|
(e.g., one passed to @racket[read-syntax]), but it is typically a file
|
|
path string.}
|
|
|
|
|
|
@defproc[(syntax-line [stx syntax?])
|
|
(or/c exact-positive-integer? #f)]{
|
|
|
|
Returns the line number (positive exact integer) for the start of the
|
|
@tech{syntax object} in its source, or @racket[#f] if the line number or
|
|
source is unknown. The result is @racket[#f] if and only if
|
|
@racket[(syntax-column stx)] produces @racket[#f]. See also
|
|
@secref["linecol"].}
|
|
|
|
|
|
@defproc[(syntax-column [stx syntax?])
|
|
(or/c exact-nonnegative-integer? #f)]{
|
|
|
|
Returns the column number (non-negative exact integer) for the start
|
|
of the @tech{syntax object} in its source, or @racket[#f] if the source
|
|
column is unknown. The result is @racket[#f] if and only if
|
|
@racket[(syntax-line stx)] produces @racket[#f]. See also
|
|
@secref["linecol"].}
|
|
|
|
|
|
@defproc[(syntax-position [stx syntax?])
|
|
(or/c exact-positive-integer? #f)]{
|
|
|
|
Returns the character position (positive exact integer) for the start
|
|
of the @tech{syntax object} in its source, or @racket[#f] if the source
|
|
position is unknown. See also @secref["linecol"].}
|
|
|
|
|
|
@defproc[(syntax-span [stx syntax?])
|
|
(or/c exact-nonnegative-integer? #f)]{
|
|
|
|
Returns the span (non-negative exact integer) in characters of the
|
|
@tech{syntax object} in its source, or @racket[#f] if the span is
|
|
unknown.}
|
|
|
|
|
|
@defproc[(syntax-original? [stx syntax?]) boolean?]{
|
|
|
|
Returns @racket[#t] if @racket[stx] has the property that
|
|
@racket[read-syntax] attaches to the
|
|
@tech{syntax object}s that they generate (see @secref["stxprops"]), and if
|
|
@racket[stx]'s @tech{lexical information} does not include any macro-introduction scopes (which indicate that the
|
|
object was introduced by a syntax transformer; see
|
|
@secref["stxobj-model"]). The result is @racket[#f] otherwise.
|
|
|
|
This predicate can be used to distinguish @tech{syntax object}s in an expanded
|
|
expression that were directly present in the original expression, as
|
|
opposed to @tech{syntax object}s inserted by macros.
|
|
|
|
The (hidden) property to represent original syntax is dropped for a
|
|
syntax object that is marshaled as part of compiled code; see also
|
|
@racket[current-compile].}
|
|
|
|
|
|
@defproc[(syntax-source-module [stx syntax?] [source? any/c #f])
|
|
(or/c module-path-index? symbol? path? resolved-module-path? #f)]{
|
|
|
|
Returns an indication of the module whose source contains
|
|
@racket[stx], or @racket[#f] if no source module for @racket[stx]
|
|
can be inferred from its lexical context. If
|
|
@racket[source?] is @racket[#f], then result is a module path index or
|
|
symbol (see @secref["modpathidx"]) or a @tech{resolved module path}; if @racket[source?] is true, the
|
|
result is a path or symbol corresponding to the loaded module's
|
|
source in the sense of @racket[current-module-declare-source].}
|
|
|
|
|
|
@defproc[(syntax-e [stx syntax?]) any]{
|
|
|
|
Unwraps the immediate datum structure from a @tech{syntax object},
|
|
leaving nested syntax structure (if any) in place. The result of
|
|
@racket[(syntax-e stx)] is one of the following:
|
|
|
|
@itemize[
|
|
|
|
@item{a symbol}
|
|
|
|
@item{a @tech{syntax pair} (described below)}
|
|
|
|
@item{the empty list}
|
|
|
|
@item{an immutable vector containing @tech{syntax object}s}
|
|
|
|
@item{an immutable box containing @tech{syntax object}s}
|
|
|
|
@item{an immutable @tech{hash table} containing @tech{syntax
|
|
object} values (but not necessarily @tech{syntax object} keys)}
|
|
|
|
@item{an immutable @tech{prefab} structure containing @tech{syntax object}s}
|
|
|
|
@item{some other kind of datum---usually a number, boolean, or
|
|
string---that is @tech{interned} when
|
|
@racket[datum-intern-literal] would convert the
|
|
value}
|
|
|
|
]
|
|
|
|
@examples[#:eval stx-eval
|
|
(syntax-e #'a)
|
|
(syntax-e #'(x . y))
|
|
(syntax-e #'#(1 2 (+ 3 4)))
|
|
(syntax-e #'#&"hello world")
|
|
(syntax-e #'#hash((imperial . "yellow") (festival . "green")))
|
|
(syntax-e #'#(point 3 4))
|
|
(syntax-e #'3)
|
|
(syntax-e #'"three")
|
|
(syntax-e #'#t)
|
|
]
|
|
|
|
A @deftech{syntax pair} is a pair containing a @tech{syntax object} as its
|
|
first element, and either the empty list, a syntax pair, or a syntax
|
|
object as its second element.
|
|
|
|
A @tech{syntax object} that is the result of @racket[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 @tech{syntax object} @italic{only} for parentheses in the
|
|
source. See @secref["parse-pair"] for more information.
|
|
|
|
If @racket[stx] is @tech{tainted} or @tech{armed}, then any syntax
|
|
object in the result of @racket[(syntax-e stx)] is @tech{tainted}, and
|
|
multiple calls to @racket[syntax-e] may return values that are not
|
|
@racket[eq?]. For a @racket[stx] that is not @tech{armed}, the results from
|
|
multiple calls to @racket[syntax-e] of @racket[stx] are @racket[eq?].}
|
|
|
|
|
|
@defproc[(syntax->list [stx syntax?]) (or/c list? #f)]{
|
|
|
|
Returns a list of @tech{syntax object}s or @racket[#f]. The result is a list
|
|
of @tech{syntax object}s when @racket[(syntax->datum stx)] would produce a
|
|
list. In other words, @tech{syntax pairs} in @racket[(syntax-e stx)]
|
|
are flattened.
|
|
|
|
If @racket[stx] is @tech{tainted} or @tech{armed}, then any syntax
|
|
object in the result of @racket[(syntax->list stx)] is @tech{tainted}.
|
|
|
|
@examples[#:eval stx-eval
|
|
(syntax->list #'())
|
|
(syntax->list #'(1 (+ 3 4) 5 6))
|
|
(syntax->list #'a)
|
|
]}
|
|
|
|
|
|
@defproc[(syntax->datum [stx syntax?]) any]{
|
|
|
|
Returns a datum by stripping the lexical information, source-location
|
|
information, properties, and tamper status from @racket[stx]. Inside of
|
|
pairs, (immutable) vectors, (immutable) boxes, immutable @tech{hash
|
|
table} values (not keys), and immutable @tech{prefab} structures,
|
|
@tech{syntax object}s are recursively stripped.
|
|
|
|
The stripping operation does not mutate @racket[stx]; it creates new
|
|
pairs, vectors, boxes, hash tables, and @tech{prefab} structures as
|
|
needed to strip lexical and source-location information recursively.
|
|
|
|
@examples[#:eval stx-eval
|
|
(syntax->datum #'a)
|
|
(syntax->datum #'(x . y))
|
|
(syntax->datum #'#(1 2 (+ 3 4)))
|
|
(syntax->datum #'#&"hello world")
|
|
(syntax->datum #'#hash((imperial . "yellow") (festival . "green")))
|
|
(syntax->datum #'#(point 3 4))
|
|
(syntax->datum #'3)
|
|
(syntax->datum #'"three")
|
|
(syntax->datum #'#t)
|
|
]}
|
|
|
|
@defproc[(datum->syntax [ctxt (or/c syntax? #f)]
|
|
[v any/c]
|
|
[srcloc (or/c syntax? #f
|
|
(list/c any/c
|
|
(or/c exact-positive-integer? #f)
|
|
(or/c exact-nonnegative-integer? #f)
|
|
(or/c exact-positive-integer? #f)
|
|
(or/c exact-nonnegative-integer? #f))
|
|
(vector/c any/c
|
|
(or/c exact-positive-integer? #f)
|
|
(or/c exact-nonnegative-integer? #f)
|
|
(or/c exact-positive-integer? #f)
|
|
(or/c exact-nonnegative-integer? #f)))
|
|
#f]
|
|
[prop (or/c syntax? #f) #f]
|
|
[ignored (or/c syntax? #f) #f])
|
|
syntax?]{
|
|
|
|
Converts the @tech{datum} @racket[v] to a @tech{syntax object}.
|
|
The contents of pairs, vectors, and boxes, the fields of @tech{prefab}
|
|
structures, and the values of immutable hash tables are recursively converted.
|
|
The keys of @tech{prefab} structures and the keys of immutable hash tables are
|
|
not converted. Mutable vectors and boxes are replaced by immutable vectors and
|
|
boxes. For any kind of value other than a
|
|
pair, vector, box, immutable @tech{hash table}, immutable
|
|
@tech{prefab} structure, or @tech{syntax object}, conversion means
|
|
wrapping the value with lexical information, source-location
|
|
information, and properties after the value is @tech{interned}
|
|
via @racket[datum-intern-literal].
|
|
|
|
Converted objects in @racket[v] are given the lexical context
|
|
information of @racket[ctxt] and the source-location information of
|
|
@racket[srcloc]. If @racket[v] is not already a @tech{syntax object},
|
|
then the resulting immediate @tech{syntax object} is given the
|
|
properties (see @secref["stxprops"]) of @racket[prop] (even the
|
|
hidden ones that would not be visible via @racket[syntax-property-symbol-keys]); if @racket[v]
|
|
is a pair, vector, box, immutable @tech{hash table}, or immutable
|
|
@tech{prefab} structure, recursively converted values are not given
|
|
properties. If @racket[ctxt] is @tech{tainted} or
|
|
@tech{armed}, then the resulting syntax object from
|
|
@racket[datum->syntax] is @tech{tainted}.
|
|
|
|
Any of @racket[ctxt], @racket[srcloc], or @racket[prop] can be
|
|
@racket[#f], in which case the resulting syntax has no lexical
|
|
context, source information, and/or new properties.
|
|
|
|
If @racket[srcloc] is not @racket[#f] or a @tech{syntax object}, it
|
|
must be a list or vector of five elements:
|
|
|
|
@racketblock[
|
|
(list source-name line column position span)
|
|
@#,elem{or} (vector source-name line column position span)
|
|
]
|
|
|
|
where @racket[source-name] is an arbitrary value for the source
|
|
name; @racket[line] is an integer for the source line, or @racket[#f];
|
|
@racket[column] is an integer for the source column, or @racket[#f];
|
|
@racket[position] is an integer for the source position, or
|
|
@racket[#f]; and @racket[span] is an integer for the source span, or
|
|
@racket[#f]. The @racket[line] and @racket[column] values must both be
|
|
numbers or both be @racket[#f], otherwise the
|
|
@exnraise[exn:fail:contract].
|
|
|
|
Graph structure is not preserved by the conversion of @racket[v] to a
|
|
@tech{syntax object}. Instead, @racket[v] is essentially unfolded into
|
|
a tree. If @racket[v] has a cycle through pairs, vectors, boxes,
|
|
immutable @tech{hash tables}, and immutable @tech{prefab} structures,
|
|
then the @exnraise[exn:fail:contract].
|
|
|
|
The @racket[ignored] argument is allowed for backward compatibility
|
|
and has no effect on the returned syntax object.}
|
|
|
|
|
|
@defproc[(datum-intern-literal [v any/c]) any/c]{
|
|
|
|
Converts some values to be consistent with an @tech{interned} result
|
|
produced by the default reader in @racket[read-syntax] mode.
|
|
|
|
If @racket[v] is a @tech{number}, @tech{character}, @tech{string},
|
|
@tech{byte string}, or @tech{regular expression}, then the result is a
|
|
value that is @racket[equal?] to @racket[v] and @racket[eq?] to a
|
|
potential result of the default reader. (Note that mutable strings and
|
|
byte strings are @tech{interned} as immutable strings and byte
|
|
strings.)
|
|
|
|
If @racket[v] is an @tech{uninterned} or an @tech{unreadable symbol},
|
|
the result is still @racket[v], since an @tech{interned} symbol would
|
|
not be @racket[equal?] to @racket[v].
|
|
|
|
The conversion process does not traverse compound values. For example,
|
|
if @racket[v] is a @tech{pair} containing strings, then the strings
|
|
within @racket[v] are not @tech{interned}.
|
|
|
|
If @racket[_v1] and @racket[_v2] are @racket[equal?] but not
|
|
@racket[eq?], then it is possible that @racket[(datum-intern-literal
|
|
_v1)] will return @racket[_v1] and---sometime after @racket[_v1]
|
|
becomes unreachable as determined by the garbage collector (see
|
|
@secref["gc-model"])---@racket[(datum-intern-literal _v2)] can still
|
|
return @racket[_v2]. In other words, @racket[datum-intern-literal]
|
|
may adopt a given value as an @tech{interned} representative, but
|
|
if a former representative becomes otherwise unreachable, then
|
|
@racket[datum-intern-literal] may adopt a new representative.}
|
|
|
|
|
|
@defproc[(syntax-shift-phase-level [stx syntax?]
|
|
[shift (or/c exact-integer? #f)])
|
|
syntax?]{
|
|
|
|
Returns a syntax object that is like @racket[stx], but with all of its
|
|
top-level and module bindings shifted by @racket[shift] @tech{phase
|
|
levels}. If @racket[shift] is @racket[#f], then only bindings
|
|
at @tech{phase level} 0 are shifted to the @tech{label phase level}.
|
|
If @racket[shift] is @racket[0], then the result is @racket[stx].}
|
|
|
|
|
|
@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
|
|
@racket[stx-pair] contains elements. The @racket[stx-pair] argument
|
|
must be a syntax pair that can be flattened into a list. The elements
|
|
of @racket[stx-pair] can be anything, but string, symbol, keyword
|
|
(possibly wrapped as syntax), and identifier elements will be embedded
|
|
in the corresponding generated name, which is useful for debugging
|
|
purposes.
|
|
|
|
The generated identifiers are built with interned symbols (not
|
|
@racket[gensym]s); see also @secref["print-compiled"].
|
|
|
|
@examples[#:eval stx-eval
|
|
(generate-temporaries '(a b c d))
|
|
(generate-temporaries #'(1 2 3 4))
|
|
(define-syntax (set!-values stx)
|
|
(syntax-case stx ()
|
|
[(_ (id ...) expr)
|
|
(with-syntax ([(temp ...) (generate-temporaries #'(id ...))])
|
|
#'(let-values ([(temp ...) expr])
|
|
(set! id temp) ... (void)))]))
|
|
]}
|
|
|
|
|
|
@defproc[(identifier-prune-lexical-context [id-stx identifier?]
|
|
[syms (listof symbol?) (list (syntax-e id-stx))])
|
|
identifier?]{
|
|
|
|
Returns an identifier with the same binding as @racket[id-stx], but
|
|
without lexical information from @racket[id-stx] that does not apply
|
|
to the symbols in @racket[syms], where even further extension of the
|
|
lexical information drops information for other symbols. In
|
|
particular, transferring the lexical context via
|
|
@racket[datum->syntax] from the result of this function to a symbol
|
|
other than one in @racket[syms] produces an identifier with no binding.
|
|
|
|
See also @racket[quote-syntax/prune].}
|
|
|
|
|
|
@defproc[(identifier-prune-to-source-module [id-stx identifier?])
|
|
identifier?]{
|
|
|
|
Returns an identifier with its lexical context minimized to that
|
|
needed for @racket[syntax-source-module]. The minimized lexical
|
|
context does not include any bindings.}
|
|
|
|
|
|
@defproc[(syntax-recertify [new-stx syntax?]
|
|
[old-stx syntax?]
|
|
[inspector inspector?]
|
|
[key any/c])
|
|
syntax?]{
|
|
|
|
For backward compatibility only; returns @racket[new-stx].}
|
|
|
|
|
|
@defproc[(syntax-debug-info [stx syntax?]
|
|
[phase (or/c exact-integer? #f) (syntax-local-phase-level)]
|
|
[all-bindings? any/c #f])
|
|
hash?]{
|
|
|
|
Produces a hash table that describes the @tech{lexical information} of
|
|
@racket[stx] (not counting components when @racket[(syntax-e stx)]
|
|
would return a compound value). The result can include---but is not
|
|
limited to---the following keys:
|
|
|
|
@itemlist[
|
|
|
|
@item{@racket['name] --- the result of @racket[(syntax-e stx)], if it is a symbol.}
|
|
|
|
@item{@racket['context] --- a list of vectors, where each vector represents a scope
|
|
attached to @racket[stx].
|
|
|
|
Each vector starts with a number that is distinct for every
|
|
scope. A symbol afterward provides a hint at the scope's
|
|
origin: @racket['module] for a @racket[module] scope,
|
|
@racket['macro] for a macro-introduction scope,
|
|
@racket['use-site] for a macro use-site scope, or
|
|
@racket['local] for a local binding form. In the case of a
|
|
@racket['module] scope that corresponds to the inside edge, the
|
|
module's name and a phase (since an inside-edge scope is
|
|
generated for each phase) are shown.}
|
|
|
|
@item{@racket['bindings] --- a list of bindings, each represented by
|
|
a hash table. A binding table can include---but is not limited
|
|
to---the following keys:
|
|
|
|
@itemlist[
|
|
|
|
@item{@racket['name] --- the symbolic name for the binding.}
|
|
|
|
@item{@racket['context] --- the scopes, as a list of vectors,
|
|
for the binding.}
|
|
|
|
@item{@racket['local] --- a symbol representing a @tech{local binding};
|
|
when this key is present, @racket['module] is absent.}
|
|
|
|
@item{@racket['module] --- an encoding of a import from another module;
|
|
when this key is present, @racket['local] is absent.}
|
|
|
|
@item{@racket['free-identifier=?] --- a hash table of debugging information
|
|
from an identifier for which the binding is an alias.}
|
|
|
|
]}
|
|
|
|
@item{@racket['fallbacks] --- a list of hash tables like the one
|
|
produced by @racket[syntax-debug-info] for cross-namespace binding fallbacks.}
|
|
|
|
]
|
|
|
|
@history[#:added "6.3"]}
|
|
|
|
@close-eval[stx-eval]
|
|
|