11.4 Syntax Transformers
(make-set!-transformer proc) → set!-transformer? |
proc : (syntax? . -> . syntax?) |
Creates a syntax transformer that cooperates with set!. If the result of make-set!-transformer is bound to identifier as a transformer binding, then proc is applied as a transformer when identifier is used in an expression position, or when it is used as the target of a set! assignment as (set! identifier expr). When the identifier appears as a set! target, the entire set! expression is provided to the transformer.
Examples: | ||||||||||||
| ||||||||||||
(1 3) |
(set!-transformer? v) → boolean? |
v : any/c |
Returns #t if v is a value created by make-set!-transformer, #f otherwise.
(set!-transformer-procedure transformer) |
→ (syntax? . -> . syntax?) |
transformer : set!-transformer? |
Returns the procedure that was passed to make-set!-transformer to create transformer.
| ||||||||||||||
id-stx : syntax? | ||||||||||||||
|
Creates a rename transformer that, when used as a transformer binding, acts as a transformer that insert the identifier id-stx in place of whatever identifier binds the transformer, including in non-application positions, and in set! expressions. Such a transformer could be written manually, but the one created by make-rename-transformer cooperates specially with syntax-local-value and syntax-local-make-delta-introducer.
(rename-transformer? v) → boolean? |
v : any/c |
Returns #t if v is a value created by make-rename-transformer, #f otherwise.
(rename-transformer-target transformer) → syntax? |
transformer : rename-transformer? |
Returns the identifier passed to make-rename-transformer to create transformer.
| ||||||||||||||||||||||||||||
stx : syntax? | ||||||||||||||||||||||||||||
context-v : (or/c 'expression 'top-level 'module 'module-begin list?) | ||||||||||||||||||||||||||||
stop-ids : (or/c (listof identifier?) #f) | ||||||||||||||||||||||||||||
intdef-ctx : (or/c internal-definition-context? #f) = #f |
Expands stx in the lexical context of the expression currently being expanded. The context-v argument is used as the result of syntax-local-context for immediate expansions; for a particular internal-definition context, generate a unique value and cons it onto the current result of syntax-local-context if it is a list.
When an identifier in stop-ids is encountered by the expander in a subexpression, expansions stops for the subexpression. If #%app, #%top, or #%datum appears in stop-ids, then application, top-level variable reference, and literal data expressions without the respective explicit form are not wrapped with the explicit form. If stop-ids is #f instead of a list, then stx is expanded only as long as the outermost form of stx is a macro (i.e., expansion does not proceed to sub-expressions).
The optional intdef-ctx argument must be either #f or the result of syntax-local-make-definition-context. In the latter case, lexical information for internal definitions is added to stx before it is expanded. The lexical information is also added to the expansion result (because the expansion might introduce bindings or references to internal-definition bindings).
Expansion of stx can use certificates for the expression already being expanded (see Syntax Certificates) , and inactive certificates associated with stx are activated for stx (see Syntax Certificates). Furthermore, if the transformer is defined within a module (i.e., the current expansion was triggered by a use of a module-defined identifier with a transformer binding) or if the current expression is being expanded for the body of a module, then the expansion of stx can use any identifier defined by the module.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
| ||||||||
stx : syntax? |
Like local-expand given 'expression and an empty stop list, but with two results: a syntax object for the fully expanded expression, and a syntax object whose content is opaque. The latter can be used in place of the former (perhaps in a larger expression produced by a macro transformer), and when the macro expander encounters the opaque object, it substitutes the fully expanded expression without re-expanding it; the exn:fail:syntax exception is raised if the expansion context includes bindings or marks that were not present for the original expansion, in which case re-expansion might produce different results. Consistent use of syntax-local-expand-expression and the opaque object thus avoids quadratic expansion times when local expansions are nested.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
| ||||||||||||||||||||||||||||
stx : syntax? | ||||||||||||||||||||||||||||
context-v : (or/c 'expression 'top-level 'module 'module-begin list?) | ||||||||||||||||||||||||||||
stop-ids : (or/c (listof identifier?) #f) | ||||||||||||||||||||||||||||
intdef-ctx : (or/c internal-definition-context? #f) = #f |
Like local-expand, but stx is expanded as a transformer expression instead of a run-time expression.
| |||||||||||||||||||||||||||||||||||
stx : syntax? | |||||||||||||||||||||||||||||||||||
context-v : (or/c 'expression 'top-level 'module 'module-begin list?) | |||||||||||||||||||||||||||||||||||
stop-ids : (or/c (listof identifier?) #f) | |||||||||||||||||||||||||||||||||||
intdef-ctx : (or/c internal-definition-context? #f) = #f | |||||||||||||||||||||||||||||||||||
lift-ctx : any/c = (gensym 'lifts) |
Like local-expand, the result is a syntax object that represents a begin expression. Lifted expressions – from calls to syntax-local-lift-expression during the expansion of stx – appear with their identifiers in define-values forms, and the expansion of stx is the last expression in the begin. The lift-ctx value is reported by syntax-local-lift-context during local expansion. The lifted expressions are not expanded, but instead left as provided in the begin form.
| ||||||||||||||||||||||||||||
stx : syntax? | ||||||||||||||||||||||||||||
context-v : (or/c 'expression 'top-level 'module 'module-begin list?) | ||||||||||||||||||||||||||||
stop-ids : (or/c (listof identifier?) #f) | ||||||||||||||||||||||||||||
intdef-ctx : (or/c internal-definition-context? #f) = #f |
Like local-expand/capture-lifts, but stx is expanded as a transformer expression instead of a run-time expression. Lifted expressions are reported as define-values forms (in the transformer environment).
(internal-definition-context? v) → boolean? |
v : any/c |
Returns #t if v is an internal-definition context, #f otherwise.
(syntax-local-make-definition-context) |
→ internal-definition-context? |
Creates an opaque internal-definition context value to be used with local-expand and other functions. A transformer should create one context for each set of internal definitions to be expanded, and use it when expanding any form whose lexical context should include the definitions. After discovering an internal define-values or define-syntaxes form, use syntax-local-bind-syntaxes to add bindings to the context. Finally, the transformer must call internal-definition-context-seal after all bindings have been added; if an unsealed internal-definition context is detected in a fully expanded expression, the exn:fail:contract exception is raised.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
| |||||||||||||||||||||
id-list : (listof identifier?) | |||||||||||||||||||||
expr : (or/c syntax? #f) | |||||||||||||||||||||
intdef-ctx : internal-definition-context? |
Binds each identifier in id-list within the internal-definition context represented by intdef-ctx, where intdef-ctx is the result of syntax-local-make-definition-context. Supply #f for expr when the identifiers correspond to define-values bindings, and supply a compile-time expression when the identifiers correspond to define-syntaxes bindings; the later case, the number of values produces by the expression should match the number of identifiers, otherwise the exn:fail:contract:arity exception is raised.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(internal-definition-context-seal intdef-ctx) → void? |
intdef-ctx : internal-definition-context? |
Indicates that no further bindings will be added to intdef-ctx, which must not be sealed already. See also syntax-local-make-definition-context.
| ||||||||
→ identifier? | ||||||||
id-stx : identifier? | ||||||||
intdef-ctx : internal-definition-context? |
Removes intdef-ctx from the lexical information of id-stx. This operation is useful for correlating an identifier that is bound in an internal-definition context with its binding before the internal-definition context was created.
| |||||||||||||||||||||
id-stx : syntax? | |||||||||||||||||||||
failure-thunk : (or/c (-> any) #f) = #f | |||||||||||||||||||||
|
Returns the transformer binding value of id-stx in either the context associated with intdef-ctx (if not #f) or the context of the expression being expanded (if indef-ctx is #f). If intdef-ctx is provided, it must be an extension of the context of the expression being expanded.
If id-stx is bound to a rename transformer created with make-rename-transformer, syntax-local-value effectively calls itself with the target of the rename and returns that result, instead of the rename transformer.
If id-stx has no transformer binding (via define-syntax, let-syntax, etc.) in that environment, the result is obtained by applying failure-thunk if not #f. If failure-thunk is false, the exn:fail:contract exception is raised.
Resolving id-stx can use certificates for the expression being transformed (see Syntax Certificates) as well as inactive certificates associated with id-stx (see Syntax Certificates). Furthermore, if the transformer is defined within a module (i.e., the current transformation was triggered by a use of a module-defined identifier) or if the current expression is being expanded for the body of a module, then resolving id-stx can access any identifier defined by the module.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-lift-expression stx) → identifier? |
stx : syntax? |
Returns a fresh identifier, and cooperates with the module, letrec-syntaxes+values, define-syntaxes, begin-for-syntax, and top-level expanders to bind the generated identifier to the expression stx.
A run-time expression within a module is lifted to the module’s top level, just before the expression whose expansion requests the lift. Similarly, a run-time expression outside of a module is lifted to a top-level definition. A compile-time expression in a letrec-syntaxes+values or define-syntaxes binding is lifted to a let wrapper around the corresponding right-hand side of the binding. A compile-time expression within begin-for-syntax is lifted to a define-for-syntax declaration just before the requesting expression.
Other syntactic forms can capture lifts by using local-expand/capture-lifts or local-transformer-expand/capture-lifts.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-lift-context) → any/c |
Returns a value that represents the target for expressions lifted via syntax-local-lift-expression. That is, for different transformer calls for which this procedure returns the same value (as determined by eq?), lifted expressions for the two transformer are moved to the same place. Thus, the result is useful for caching lift information to avoid redundant lifts.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-lift-module-end-declaration stx) → void? |
stx : syntax? |
Cooperates with the module form to insert stx as a top-level declaration at the end of the module currently being expanded. If the current expression being transformed is not within a module form, or if it is not a run-time expression, then the exn:fail:contract exception is raised. If the current expression being transformed is not in the module top-level, then stx is eventually expanded in an expression context.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
| ||||||||||||||
quoted-raw-require-spec : any/c | ||||||||||||||
stx : syntax? |
Lifts a #%require form corresponding to quoted-raw-require-spec to the top-level or to the top of the module currently being expanded, wrapping it with for-meta if the current expansion context is not phase level 0.
The resulting syntax object is the same as stx, except that a fresh syntax mark is added. The same syntax mark is added to the lifted #%require form, so that the #%require form can bind uses of imported identifiers in the resulting syntax object (assuming that the lexical information of stx includes the binding environment into which the #%require is lifted).
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-name) → (or/c symbol? #f) |
Returns an inferred name for the expression position being transformed, or #f if no such name is available. See also Inferred Value Names.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-context) |
→ (or/c 'expression 'top-level 'module 'module-begin list?) |
Returns an indication of the context for expansion that triggered a syntax transformer call. See Expansion Context for more information on contexts.
The symbol results indicate that the expression is being expanded for an expression context, a top-level context, a module context, or a module-begin context.
A list result indicates expansion in an internal-definition context. The identity of the lists’s first element (i.e., its eq?ness) reflects the identity of the internal-definition context; in particular two transformer expansions receive the same first value if and only if they are invoked for the same internal-definition context. Later values in the list similarly identify internal-definition contexts that are still being expanded, and that required the expansion of nested internal-definition contexts.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-phase-level) → (or/c exact-integer? #f) |
During the dynamic extent of a syntax transformer application by the expander, the result is the phase level of the form being expanded. Otherwise, the result is 0.
| ||||||||
mod-path : module-path? |
Returns three lists of symbols that represent the provided bindings of the module named by mod-path. The first list corresponds to the phase level 0 exports of the module, the second list corresponds to the phase level -1 exports of the module, and the last list corresponds to the label phase level exports of the module.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-get-shadower id-stx) → identifier? |
id-stx : identifier? |
Returns id-stx if no binding in the current expansion context shadows id-stx (ignoring unsealed internal-definition contexts), if id-stx has no module bindings in its lexical information, and if the current expansion context is not a module context.
If a binding of inner-identifier shadows id-stx, the result is the same as (syntax-local-get-shadower inner-identifier), except that it has the location and properties of id-stx. When searching for a shadowing binding, bindings from unsealed internal-definition contexts are ignored.
Otherwise, the result is the same as id-stx with its module bindings (if any) removed from its lexical information, and the lexical information of the current module context (if any) added.
Thus, the result is an identifier corresponding to the innermost shadowing of id-stx in the current context if its shadowed, and a module-contextless version of id-stx otherwise.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-certifier [active?]) | ||||||
| ||||||
active? : boolean? = #f |
Returns a procedure that captures any certificates currently available for syntax-local-value or local-expand. The procedure accepts one to three arguments: stx (required), key (optional), and intro (optional). The procedure’s result is a syntax object like stx, except that it includes the captured certificates as inactive (see Syntax Certificates) if active? is #f (the default) or active otherwise. If key is supplied and not #f, it is associated with each captured certificate for later use through syntax-recertify. If intro is supplied, and if it is not #f (the default), then it must be a procedure created by make-syntax-introducer, in which case the certificate applies only to parts of stx that are marked as introduced by intro.
Supply #t for active? when the syntax to be certified can be safely used in any context by any party, and where access to the syntax object should not confer any additional access. Supply #f for active? when the syntax to be certified is not accessible to parties that might abuse the access that the certificate provides, and when the certified syntax eventually appears (via macro expansion) within a larger expression from which it cannot be safely extracted by other parties.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-transforming?) → boolean? |
Returns #t during the dynamic extent of a syntax transformer application by the expander, #f otherwise.
(syntax-local-introduce stx) → syntax? |
stx : syntax? |
Produces a syntax object that is like stx, except that a syntax mark for the current expansion is added (possibly canceling an existing mark in parts of stx). See Transformer Bindings for information on syntax marks.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(make-syntax-introducer) → (syntax? . -> . syntax?) |
Produces a procedure that behaves like syntax-local-introduce, but using a fresh syntax mark. Multiple applications of the same make-syntax-introducer result procedure use the same mark, and different result procedures use distinct marks.
| ||||||||||||
→ (syntax? . -> . syntax?) | ||||||||||||
ext-stx : syntax? | ||||||||||||
base-stx : (or/c syntax? #f) | ||||||||||||
|
Produces a procedure that behaves like syntax-local-introduce, but using the syntax marks of ext-stx that are not shared with base-stx. If ext-stx does not extend the set of marks in base-stx or if base-stx is #f, and if ext-stx has a module binding in the phase level indicated by phase-level, then any marks of ext-stx that would be needed to preserve its binding are not transferred in an introduction.
This procedure is potentially useful when m-id has a transformer binding that records some orig-id, and a use of m-id introduces a binding of orig-id. In that case, the syntax marks in the use of m-id since the binding of m-id should be transferred to the binding instance of orig-id, so that it captures uses with the same lexical context as the use of m-id.
More typically, however, syntax-local-make-delta-introducer should be used, since it cooperates with rename transformers.
(syntax-local-make-delta-introducer id) |
→ (identifier? . -> . identifier?) |
id : identifier? |
Determines the binding of id. If the binding is not a rename transformer, the result is an introducer as created by make-syntax-delta-introducer using id and the binding of id in the environment of expansion. If the binding is a rename transformer, then the introducer is one composed with the target of the rename transformer and its binding. Furthermore, the delta-introduce functions associated with the rename transformers (supplied as the second argument to make-rename-transformer) are composed (in first-to-last order) before the introducers created with make-syntax-delta-introducer (which are composed last-to-first).
The exn:fail:contract exception is raised if id or any identifier in its rename-transformer chain has no binding.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander, otherwise the exn:fail:contract exception is raised.
(syntax-local-transforming-module-provides?) → boolean? |
Returns #t while a provide transformer is running (see make-provide-transformer) or while a expand sub-form of #%provide is expanded, #f otherwise.
(syntax-local-module-defined-identifiers) | |||||||
|
Can be called only while syntax-local-transforming-module-provides? returns #t.
It returns two lists of identifiers corresponding to all definitions within the module being expanded. This information is used for implementing provide sub-forms like all-defined-out.
The first result list corresponds to phase 0 (i.e., normal) definitions, and the second corresponds to phase -1 (i.e., for-syntax) definitions.
| ||||||||
| ||||||||
mod-path : (or/c module-path? #f) | ||||||||
phase-level : (or/c exact-integer? #f #t) |
Can be called only while syntax-local-transforming-module-provides? returns #t.
It returns an association list mapping phase levels to lists of identifiers. Each list of identifiers includes all bindings imported (into the module being expanded) using the module path mod-path, or all modules if mod-path is #f. The association list includes all identifiers imported with a phase-level shift, of all shifts if phase-level is #t.
When an identifier is renamed on import, the result association list includes the identifier by its internal name. Use identifier-binding to obtain more information about the identifier.
11.4.1 require Transformers
(require scheme/require-transform) |
The bindings documented in this section are provided by the scheme/require-transform library, not scheme/base or scheme.
A transformer binding whose value is a structure with the prop:require-transformer property implements a derived require-spec for require.
The transformer is called with the syntax object representing its use as a require-spec within a require form, and the result must be two lists: a list of imports and a list of import-sources.
If the derived form contains a sub-form that is a require-spec, then it can call expand-import to transform the sub-require-spec to lists of imports and import sources.
See also define-require-syntax, which supports macro-style require transformers.
| ||||||||
stx : syntax? |
Expands the given require-spec to lists of imports and import sources. The latter specifies modules to be instantiated or visited, so the modules that it represents should be a superset of the modules represented in the former list (so that a module will be instantiated or visited even if all of imports are eventually filtered from the former list).
(make-require-transformer proc) → require-transformer? | |||||||||
|
Creates a require transformer (i.e., a structure with the prop:require-transformer property) using the given procedure as the transformer.
prop:require-transformer : struct-type-property? |
A property to identify require transformers. The property value must be a procedure that takes a syntax object and returns import and import-source lists.
(require-transformer? v) → boolean? |
v : any/c |
Returns #t if v has the prop:require-transformer property, #f otherwise.
| |||||||||||||||||||||||||||||||||||
local-id : identifier? | |||||||||||||||||||||||||||||||||||
src-sym : symbol? | |||||||||||||||||||||||||||||||||||
src-mod-path : module-path? | |||||||||||||||||||||||||||||||||||
mode : (or/c exact-integer? #f) | |||||||||||||||||||||||||||||||||||
req-mode : (or/c exact-integer? #f) | |||||||||||||||||||||||||||||||||||
orig-mode : (or/c exact-integer? #f) | |||||||||||||||||||||||||||||||||||
orig-stx : syntax? |
A structure representing a single imported identifier:
local-id – the identifier to be bound within the importing module.
src-sym – the external name of the binding as exported from its source module.
src-mod-path – a module path (relative to the importing module) for the source of the imported binding.
orig-stx – a syntax object for the source of the import, used for error reporting.
mode – the phase level of the binding in the importing module.
req-mode – the phase level shift of the import relative to the exporting module.
orig-mode – the phase level of the binding as exported by the exporting module.
(struct import-source (mod-path-stx mode)) | |||||||||
| |||||||||
mode : (or/c exact-integer? #f) |
A structure representing an imported module, which must be instantiated or visited even if no binding is imported into a module.
mod-path-stx – a module path (relative to the importing module) for the source of the imported binding.
mode – the phase level shift the import.
(syntax-local-require-certifier) | ||||||
|
Like syntax-local-certifier, but to certify syntax objects that correspond to require sub-forms, so that expand-import can deconstruct the syntax object as necessary to expand it.
11.4.2 provide Transformers
(require scheme/provide-transform) |
The bindings documented in this section are provided by the scheme/provide-transform library, not scheme/base or scheme.
A transformer binding whose value is a structure with the prop:provide-transformer property implements a derived provide-spec for provide.
The transformer is called with the syntax object representing its use as a provide-spec within a provide form and a list of symbols representing the export modes specified by enclosing provide-specs. The result must be a list of exports.
If the derived form contains a sub-form that is a provide-spec, then it can call expand-export to transform the sub-provide-spec to a lists of exports.
See also define-provide-syntax, which supports macro-style provide transformers.
(expand-export stx modes) → (listof export?) |
stx : syntax? |
modes : (listof (or/c exact-integer? #f)) |
Expands the given provide-spec to a list of exports. The modes list controls the expansion of sub-provide-specs; for example, an identifier refers to a phase level 0 binding unless the modes list specifies otherwise. Normally, modes is either empty or contains a single element.
(make-provide-transformer proc) → provide-transformer? | ||||||||
|
Creates a provide transformer (i.e., a structure with the prop:provide-transformer property) using the given procedure as the transformer.
prop:provide-transformer : struct-type-property? |
A property to identify provide transformers. The property value must be a procedure that takes a syntax object and mode list and returns an export list.
(provide-transformer? v) → boolean? |
v : any/c |
Returns #t if v has the prop:provide-transformer property, #f otherwise.
(struct export (local-id out-sym mode protect? orig-stx)) |
local-id : identifier? |
out-sym : symbol? |
mode : (or/c exact-integer? #f) |
protect? : any/c |
orig-stx : syntax? |
A structure representing a single imported identifier:
local-id – the identifier that is bound within the exporting module.
out-sym – the external name of the binding.
orig-stx – a syntax object for the source of the export, used for error reporting.
protect? – indicates whether the identifier should be protected (see Code Inspectors).
mode – the phase level of the binding in the exporting module.
(syntax-local-provide-certifier) | ||||||
|
Like syntax-local-certifier, but to certify syntax objects that correspond to provide sub-forms, so that expand-export can deconstruct the syntax object as necessary to expand it.