1 Syntax Object Helpers
1.1 Deconstructing Syntax Objects
Returns
#t if
v is either a pair or a syntax object
representing a pair (see
syntax pair).
Returns
#t if
v is a list, or if it is a sequence of
pairs leading to a syntax object such that
syntax->list would
produce a list.
Produces a list by flatting out a trailing syntax object using
syntax->list.
Returns
#t if
a-id and
b-id are
free-identifier=?, or if
a-id and
b-id have
the same name (as extracted by
syntax-e) and
a-id
has no binding other than at the top level.
This procedure is useful in conjunction with syntax-case* to
match procedure names that are normally bound by Racket. For
example, the include macro uses this procedure to recognize
build-path; using free-identifier=? would not work
well outside of module, since the top-level
build-path is a distinct variable from the racket/base export
(though it’s bound to the same procedure, initially).
1.2 Matching Fully-Expanded Expressions
The trans?-expr boolean expression replaces the comparison
procedure, and instead selects simply between normal-phase comparisons
or transformer-phase comparisons. The clauses are the same as in
syntax-case*.
The primitive syntactic forms must have their normal bindings in the
context of the kernel-syntax-case expression. Beware that
kernel-syntax-case does not work in a module whose language
is mzscheme, since the binding of if from
mzscheme is different than the primitive if.
A syntactic form like
kernel-syntax-case, except that it
takes an additional list of extra literals that are in addition to the
primitive Racket forms.
Generalizes
kernel-syntax-case to work at an arbitrary phase
level, as indicated by
phase-expr.
Generalizes
kernel-syntax-case* to work at an arbitrary phase
level, as indicated by
phase-expr.
Returns a list of identifiers that are bound normally,
for-syntax, and
for-template to the primitive
Racket forms for expressions, internal-definition positions, and
module-level and top-level positions. This function is useful for
generating a list of stopping points to provide to
local-expand.
In addition to the identifiers listed in Fully Expanded Programs, the list
includes letrec-syntaxes+values, which is the core form for
local expand-time binding and can appear in the result of
local-expand.
See also syntax/id-table for an implementation of
identifier mappings using the scheme/dict dictionary
interface.
Produces a hash-table-like value for storing a mapping from syntax
identifiers to arbitrary values.
The mapping uses bound-identifier=? to compare mapping keys,
but also uses a hash table based on symbol equality to make the
mapping efficient in the common case (i.e., where non-equivalent
identifiers are derived from different symbolic names).
Like hash-table-get for bound-identifier mappings.
Like hash-table-put! for bound-identifier mappings.
Like hash-table-for-each.
Like hash-table-map.
Produces a hash-table-like value for storing a mapping from syntax
identifiers to arbitrary values.
The mapping uses free-identifier=? to compare mapping keys,
but also uses a hash table based on symbol equality to make the
mapping efficient in the common case (i.e., where non-equivalent
identifiers are derived from different symbolic names at their
definition sites).
Like hash-table-get for free-identifier mappings.
Like hash-table-put! for free-identifier mappings.
Like hash-table-for-each.
Like hash-table-map.
1.4 Identifier dictionaries
This module provides functionality like that of
syntax/boundmap but with more operations, standard
names, implementation of the scheme/dict interface,
and immutable (functionally-updating) variants.
Bound-identifier tables implement the dictionary interface of
scheme/dict. Consequently, all of the appropriate generic
functions (dict-ref, dict-map, etc) can be used on
free-identifier tables.
Produces a dictionary mapping syntax identifiers to arbitrary
values. The mapping uses
bound-identifier=? to compare keys,
but also uses a hash table based on symbol equality to make the
mapping efficient in the common case. The two procedures produce
mutable and immutable dictionaries, respectively.
The identifiers are compared at phase level phase. The
default value is generally appropriate for identifier tables used by
macros, but code that analyzes fully-expanded programs may need to
create identifier tables at multiple different phases.
The optional init-dict argument provides the initial
mappings. It must be a dictionary, and its keys must all be
identifiers. If the init-dict dictionary has multiple
distinct entries whose keys are bound-identifier=?, only one
of the entries appears in the new id-table, and it is not specified
which entry is picked.
Predicate for the mutable and immutable variants of bound-identifier
tables, respectively.
Like
hash-ref for bound identifier tables. In particular, if
id is not found, the
failure argument is applied if
it is a procedure, or simply returned otherwise.
Like
hash-set! for mutable bound-identifier tables.
Like
hash-set for immutable bound-identifier tables.
Like
hash-remove for immutable bound-identifier tables.
Like
hash-map for bound-identifier tables.
Free-identifier tables implement the dictionary interface of
scheme/dict. Consequently, all of the appropriate generic
functions (dict-ref, dict-map, etc) can be used on
free-identifier tables.
1.5 Rendering Syntax Objects with Formatting
Builds a string with newlines and indenting according to the source
locations in stx-list; the outer pair of parens are not
rendered from stx-list.
1.6 Computing the Free Variables of an Expression
1.7 Replacing Lexical Context
Removes all lexical context from stx, preserving
source-location information and properties.
Uses the lexical context of ctx-stx to replace the lexical
context of all parts of stx, preserving source-location
information and properties of stx.
1.8 Helpers for Processing Keyword Syntax
The syntax/keyword module contains procedures for
parsing keyword options in macros.
keyword-table | | = | | (dict-of keyword (listof check-procedure)) |
A keyword-table is a dictionary (dict?) mapping keywords to
lists of check-procedures. (Note that an association list is a
suitable dictionary.) The keyword’s arity is the length of the list of
procedures.
Example: |
| current-directory: `exists' access denied for | /var/tmp/racket/src/build/ |
|
check-procedure | | = | | (syntax syntax -> any) |
A check procedure consumes the syntax to check and a context syntax
object for error reporting and either raises an error to reject the
syntax or returns a value as its parsed representation.
options | | = | | (listof (list keyword syntax-keyword any ...)) |
Parsed options are represented as an list of option entries. Each
entry contains the keyword, the syntax of the keyword (for error
reporting), and the list of parsed values returned by the keyword’s
list of check procedures. The list contains the parsed options in the
order they appeared in the input, and a keyword that occurs multiple
times in the input occurs multiple times in the options list.
Parses the keyword options in the syntax stx (stx
may be an improper syntax list). The keyword options are described in
the table association list. Each entry in table
should be a list whose first element is a keyword and whose subsequent
elements are procedures for checking the arguments following the
keyword. The keyword’s arity (number of arguments) is determined by
the number of procedures in the entry. Only fixed-arity keywords are
supported.
Parsing stops normally when the syntax list does not have a keyword at
its head (it may be empty, start with a non-keyword term, or it may be
a non-list syntax object). Two values are returned: the parsed
options and the rest of the syntax (generally either a
syntax object or a list of syntax objects).
A variety of errors and exceptional conditions can occur during the
parsing process. The following keyword arguments determine the
behavior in those situations.
The #:context ctx argument is used to report all errors in
parsing syntax. In addition, ctx is passed as the final
argument to all provided handler procedures. Macros using
parse-keyword-options should generally pass the syntax object
for the whole macro use as ctx.
If no-duplicates? is a non-false value, then duplicate
keyword options are not allowed. If a duplicate is seen, the keyword’s
associated check procedures are not called and an incompatibility is
reported.
The incompatible argument is a list of incompatibility
entries, where each entry is a list of at least two
keywords. If any keyword in the entry occurs after any other keyword
in the entry, an incompatibility is reported.
Note that including a keyword in an incompatibility entry does not
prevent it from occurring multiple times. To disallow duplicates of
some keywords (as opposed to all keywords), include those keywords in
the incompatible list as being incompatible with
themselves. That is, include them twice:
; Disallow duplicates of only the #:foo keyword |
(parse-keyword-options .... #:incompatible '((#:foo #:foo))) |
When an incompatibility occurs, the
incompatible-handler is tail-called with the two keywords
causing the incompatibility (in the order that they occurred in the
syntax list, so the keyword triggering the incompatibility occurs
second), the syntax list starting with the occurrence of the second
keyword, and the context (ctx). If the incompatibility is due
to a duplicate, the two keywords are the same.
When a keyword is not followed by enough arguments according to its
arity in table, the too-short-handler is tail-called
with the keyword, the options parsed thus far, the syntax list
starting with the occurrence of the keyword, and ctx.
When a keyword occurs in the syntax list that is not in
table, the not-in-table-handler is tail-called with
the keyword, the options parsed thus far, the syntax list
starting with the occurrence of the keyword, and ctx.
Handlers typically escape—all of the default handlers raise
errors—but if they return, they should return two values: the parsed
options and a syntax object; these are returned as the results
of parse-keyword-options.
Examples: |
| current-directory: `exists' access denied for | /var/tmp/racket/src/build/ | | current-directory: `exists' access denied for | /var/tmp/racket/src/build/ |
|
Like
parse-keyword-options, but checks that there are no
terms left over after parsing all of the keyword options. If there
are,
not-eol-handler is tail-called with the
options
parsed thus far, the leftover syntax, and
ctx.
Selects the values associated with one keyword from the parsed
options. The resulting list has as many items as there were
occurrences of the keyword, and each element is a list whose length is
the arity of the keyword.
Like
options-select, except that the given keyword must occur
either zero or one times in
options. If the keyword occurs,
the associated list of parsed argument values is returned. Otherwise,
the
default list is returned.
Like
options-select, except that the given keyword must occur
either zero or one times in
options. If the keyword occurs,
the associated list of parsed argument values must have exactly one
element, and that element is returned. If the keyword does not occur
in
options, the
default value is returned.
A
check-procedure that accepts any non-keyword term. It does
not actually check that the term is a valid expression.
Lifts a
check-procedure to accept syntax lists of whatever the
original procedure accepted.
1.9 Legacy Zodiac Interface
The interface is similar to Zodiac—enough to be useful for
porting—but different in many ways. See the source
"zodiac-sig.rkt" for details. New software should not use this
compatibility layer.