► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 12 | Macros

12.1 | Pattern-Based Syntax Matching
12.2 | Syntax Object Content
12.3 | Syntax Object Bindings
12.4 | Syntax Transformers
12.5 | Syntax Parameters
12.6 | Local Binding with Splicing Body
12.7 | Syntax Object Properties
12.8 | Syntax Taints
12.9 | Expanding Top-Level Forms
12.10 | File Inclusion
12.11 | Syntax Utilities

► | 12.4 | Syntax Transformers

12.4.1 | require Transformers
12.4.2 | provide Transformers
12.4.3 | Keyword-Argument Conversion Introspection

On this page:

set!-transformer?
make-set!-transformer
set!-transformer-procedure
prop: set!-transformer
rename-transformer?
make-rename-transformer
rename-transformer-target
prop: rename-transformer
local-expand
syntax-local-expand-expression
local-transformer-expand
local-expand/ capture-lifts
local-transformer-expand/ capture-lifts
internal-definition-context?
syntax-local-make-definition-context
syntax-local-bind-syntaxes
internal-definition-context-binding-identifiers
internal-definition-context-introduce
internal-definition-context-seal
identifier-remove-from-definition-context
prop: expansion-contexts
syntax-local-value
syntax-local-value/ immediate
syntax-local-lift-expression
syntax-local-lift-values-expression
syntax-local-lift-context
syntax-local-lift-module
syntax-local-lift-module-end-declaration
syntax-local-lift-require
syntax-local-lift-provide
syntax-local-name
syntax-local-context
syntax-local-phase-level
syntax-local-module-exports
syntax-local-submodules
syntax-local-get-shadower
syntax-local-make-delta-introducer
syntax-local-certifier
syntax-transforming?
syntax-transforming-with-lifts?
syntax-transforming-module-expression?
syntax-local-identifier-as-binding
syntax-local-introduce
make-syntax-introducer
make-interned-syntax-introducer
make-syntax-delta-introducer
syntax-local-transforming-module-provides?
syntax-local-module-defined-identifiers
syntax-local-module-required-identifiers
prop: liberal-define-context
liberal-define-context?
12.4.1`` require Transformers
expand-import
make-require-transformer
prop: require-transformer
require-transformer?
import
import-source
current-require-module-path
convert-relative-module-path
syntax-local-require-certifier
12.4.2`` provide Transformers
expand-export
pre-expand-export
make-provide-transformer
make-provide-pre-transformer
prop: provide-transformer
prop: provide-pre-transformer
provide-transformer?
provide-pre-transformer?
export
syntax-local-provide-certifier
12.4.3`` Keyword-Argument Conversion Introspection
syntax-procedure-alias-property
syntax-procedure-converted-arguments-property

top ← prev up next →

#### 12.4`` Syntax Transformers

> > procedure

> > (set!-transformer? v) → boolean?

> v : any/c

Returns #t if v is a value created by make-set!-transformer or an instance of a structure type with the prop:set!-transformer property, #f otherwise.

> > procedure

> > (make-set!-transformer proc) → set!-transformer?

> proc : (syntax? . -> . syntax?)

Creates an assignment transformer that cooperates with set!. If the result of make-set!-transformer is bound to id as a transformer binding, then proc is applied as a transformer when id is used in an expression position, or when it is used as the target of a set! assignment as (set! id expr). When the identifier appears as a set! target, the entire set! expression is provided to the transformer.

Example:

> > (let ([x 1]
> [y 2])
> (let-syntax ([x (make-set!-transformer
> (lambda (stx)
> (syntax-case stx (set!)
> ; Redirect mutation of x to y
> [(set! id v) #'(set! y v)]
> ; Normal use of x really gets x
> [id (identifier? #'id) #'x])))])
> (begin
> (set! x 3)
> (list x y))))

> '(1 3)

> > procedure

> > (set!-transformer-procedure transformer)

> → (syntax? . -> . syntax?)
> transformer : set!-transformer?

Returns the procedure that was passed to make-set!-transformer to create transformer or that is identified by the prop:set!-transformer property of transformer.

> > value

> > prop:set!-transformer : struct-type-property?

A structure type property to identify structure types that act as assignment transformers like the ones created by make-set!-transformer.

The property value must be an exact integer or procedure of one or two arguments. In the former case, the integer designates a field within the structure that should contain a procedure; the integer must be between 0 (inclusive) and the number of non-automatic fields in the structure type (exclusive, not counting supertype fields), and the designated field must also be specified as immutable.

If the property value is a procedure of one argument, then the procedure serves as a syntax transformer and for set! transformations. If the property value is a procedure of two arguments, then the first argument is the structure whose type has prop:set!-transformer property, and the second argument is a syntax object as for a syntax transformer and for set! transformations; set!-transformer-procedure applied to the structure produces a new function that accepts just the syntax object and calls the procedure associated through the property. Finally, if the property value is an integer, the target identifier is extracted from the structure instance; if the field value is not a procedure of one argument, then a procedure that always calls raise-syntax-error is used, instead.

If a value has both the prop:set!-transformer and prop:rename-transformer properties, then the latter takes precedence. If a structure type has the prop:set!-transformer and prop:procedure properties, then the former takes precedence for the purposes of macro expansion.

> > procedure

> > (rename-transformer? v) → boolean?

> v : any/c

Returns #t if v is a value created by make-rename-transformer or an instance of a structure type with the prop:rename-transformer property, #f otherwise.

Examples:

> > (rename-transformer? (make-rename-transformer #'values))
> #t
> > (rename-transformer? 'not-a-rename-transformer)
> #f

> > procedure

> > (make-rename-transformer id-stx) → rename-transformer?

> id-stx : syntax?

Creates a rename transformer that, when used as a transformer binding, acts as a transformer that inserts the identifier id-stx in place of whatever identifier binds the transformer, including in non-application positions, in set! expressions.

Such a transformer could be written manually, but the one created by make-rename-transformer triggers special cooperation with the parser and other syntactic forms when id is bound to the rename transformer:

- The parser installs a free-identifier=? and identifier-binding equivalence between id and id-stx, as long as id-stx does not have a true value for the 'not-free-identifier=? syntax property.

- A provide of id provides the binding indicated by id-stx instead of id, as long as id-stx does not have a true value for the 'not-free-identifier=? syntax property and as long as id-stx has a binding.

- If provide exports id, it uses a symbol-valued 'nominal-id property of id-stx to specify the “nominal source identifier” of the binding as reported by identifier-binding.

- If id-stx has a true value for the 'not-provide-all-defined syntax property, then id (or its target) is not exported by all-defined-out.

- The syntax-local-value function recognizes rename-transformer bindings and consult their targets.

Examples:

> > (define-syntax my-or (make-rename-transformer #'or))
> > (my-or #f #t)
> #t
> > (free-identifier=? #'my-or #'or)
> #t

Changed in version 6.3 of package base: Removed an optional second argument.

> > procedure

> > (rename-transformer-target transformer) → identifier?

> transformer : rename-transformer?

Returns the identifier passed to make-rename-transformer to create transformer or as indicated by a prop:rename-transformer property on transformer.

Example:

> > (rename-transformer-target (make-rename-transformer #'or))
> #<syntax:eval:8:0 or>

> > value

> > prop:rename-transformer : struct-type-property?

A structure type property to identify structure types that act as rename transformers like the ones created by make-rename-transformer.

The property value must be an exact integer, an identifier syntax object, or a procedure that takes one argument. In the former case, the integer designates a field within the structure that should contain an identifier; the integer must be between 0 (inclusive) and the number of non-automatic fields in the structure type (exclusive, not counting supertype fields), and the designated field must also be specified as immutable.

If the property value is an identifier, the identifier serves as the target for renaming, just like the first argument to make-rename-transformer. If the property value is an integer, the target identifier is extracted from the structure instance; if the field value is not an identifier, then an identifier ? with an empty context is used, instead.

If the property value is a procedure that takes one argument, then the procedure is called to obtain the identifier that the rename transformer will use as a target identifier. The returned identifier should probably have the 'not-free-identifier=? syntax property. If the procedure returns any value that is not an identifier, the exn:fail:contract exception is raised.

Examples:

> ; Example of a procedure argument for prop:rename-transformer
> > (define-syntax slv-1 'first-transformer-binding)
> > (define-syntax slv-2 'second-transformer-binding)

> > (begin-for-syntax
> (struct slv-cooperator (redirect-to-first?)
> #:property prop:rename-transformer
> (λ (inst)
> (if (slv-cooperator-redirect-to-first? inst)
> #'slv-1
> #'slv-2))))

> > (define-syntax (slv-lookup stx)
> (syntax-case stx ()
> [(_ id)
> #`'#,(syntax-local-value #'id)]))

> > (define-syntax slv-inst-1 (slv-cooperator #t))
> > (define-syntax slv-inst-2 (slv-cooperator #f))
> > (slv-lookup slv-inst-1)
> 'first-transformer-binding
> > (slv-lookup slv-inst-2)
> 'second-transformer-binding

Changed in version 6.3 of package base: the property now accepts a procedure of one argument.

> > procedure

> > (local-expand |  | stx |  |  |  |
> > |  | context-v |  |  |  |
> > |  | stop-ids |  |  |  |
> > | [ | intdef-ctx]) |  | → |  | syntax?

> stx : any/c
> context-v : (or/c 'expression 'top-level 'module 'module-begin list?)
> stop-ids : (or/c (listof identifier?) empty #f)

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?)
> #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; a list indicates an internal-definition context, and more information on the form of the list is below. If stx is not already a syntax object, it is coerced with (datum->syntax #f stx) before expansion.

The stop-ids argument controls how far local-expand expands stx:

- If stop-ids is an empty list, then stx is recursively expanded (i.e. expansion proceeds to sub-expressions). The result is guaranteed to be a fully-expanded form, which can include the bindings listed in Fully Expanded Programs, plus #%expression in any expression position.

- If stop-ids is a list containing just module*, then expansion proceeds as if stop-ids were an empty list, except that expansion does not recur to submodules defined with module* (which are left unexpanded in the result).

- If stop-ids is any other list, then begin, quote, set!, #%plain-lambda, case-lambda, let-values, letrec-values, if, begin0, with-continuation-mark, letrec-syntaxes+values, #%plain-app, #%expression, #%top, and #%variable-reference are implicitly added to stop-ids. Expansion proceeds recursively, stopping when the expander encounters any of the forms in stop-ids, and the result is the partially-expanded form.

  When the expander would normally implicitly introduce a #%app, #%datum, or #%top identifier as described in Expansion Steps, it checks to see if an identifier with the same binding as the one to be introduced appears in stop-ids. If so, the identifier is not introduced; the result of expansion is the bare application, literal data expression, or unbound identifier rather than one wrapped in the respective explicit form.

  When #%plain-module-begin is not in stop-ids, the #%plain-module-begin transformer detects and expands sub-forms (such as define-values) regardless of the identifiers presence in stop-ids.

  Expansion does not replace the scopes in a local-variable reference to match the binding identifier.

- 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, and it does not replace the scopes in a local-variable reference to match the binding identifier). The #%app, #%datum, and #%top identifiers are never introduced.

Independent of stop-ids, when local-expand encounters an identifier that has a local binding but no binding in the current expansion context, the variable is left as-is (as opposed to triggering an “out of context” syntax error).

When context-v is 'module-begin, and the result of expansion is a #%plain-module-begin form, then a 'submodule syntax property is added to each enclosed module form (but not module* forms) in the same way as by module expansion.

If the intdef-ctx argument is an internal-definition context, its bindings and bindings from all parent internal-definition contexts are added to the local binding context during the dynamic extent of the call to local-expand. Additionally, unless #f was provided for the add-scope? argument to syntax-local-make-definition-context when the internal-definition context was created, its scope (but not the scopes of any parent internal-definition contexts) is added to the lexical information for both stx prior to its expansion and the expansion result (because the expansion might introduce bindings or references to internal-definition bindings). If intdef-ctx is a list, all bindings from all of the provided internal-definition contexts and their parents are added to the local binding context, and the scope from each context for which add-scope? was not #f is added in the same way. For backwards compatibility, providing #f for intdef-ctx is treated the same as providing an empty list.

For a particular internal-definition context, generate a unique value and put it into a list for context-v. To allow liberal expansion of define forms, the generated value should be an instance of a structure with a true value for prop:liberal-define-context. If the internal-definition context is meant to be self-contained, the list for context-v should contain only the generated value; if the internal-definition context is meant to splice into an immediately enclosing context, then when syntax-local-context produces a list, cons the generated value onto that list.

When expressions are expanded via local-expand with an internal-definition context intdef-ctx, and when the expanded expressions are incorporated into an overall form new-stx, then typically internal-definition-context-track should be applied to intdef-ctx and new-stx to provide expansion history to external tools.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Examples:

> > (define-syntax-rule (do-print x ...)
> (printf x ...))

> > (define-syntax-rule (hello x)
> (do-print "hello ~a" x))

> > (define-syntax (show stx)
> (syntax-case stx ()
> [(_ x)
> (let ([partly (local-expand #'(hello x)
> 'expression
> (list #'do-print))]
> [fully (local-expand #'(hello x)
> 'expression
> #f)])
> (printf "partly expanded: ~s\n" (syntax->datum partly))
> (printf "fully expanded: ~s\n" (syntax->datum fully))
> fully)]))

> > (show 1)

> partly expanded: (do-print "hello ~a" 1)
> fully expanded: (printf "hello ~a" 1)
> hello 1

Changed in version 6.0.1.3 of package base: Changed treatment of #%top so that it is never introduced as an explicit wrapper.
Changed in version 6.0.90.27: Loosened the contract on the intdef-ctx argument to allow an empty list, which is treated the same way as #f.

> > procedure

> > (syntax-local-expand-expression |  | stx |
> > | [ | opaque-only?]) |

> →

> (if opaque-only? #f syntax?) |  | syntax?

> stx : any/c
> opaque-only? : any/c = #f

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 scopes 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.

If opaque-only? is true, then the first result is #f instead of the expanded expression. Obtaining only the second, opaque result can be more efficient in some expansion contexts.

Unlike local-expand, syntax-local-expand-expression normally produces an expanded expression that contains no #%expression forms. However, if syntax-local-expand-expression is used within an expansion that is triggered by an enclosing local-expand call, then the result of syntax-local-expand-expression can include #%expression forms.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Changed in version 6.90.0.13 of package base: Added the opaque-only? argument.

> > procedure

> > (local-transformer-expand |  | stx |  |  |  |
> > |  | context-v |  |  |  |
> > |  | stop-ids |  |  |  |
> > | [ | intdef-ctx]) |  | → |  | syntax?

> stx : any/c
> context-v : (or/c 'expression 'top-level list?)
> stop-ids : (or/c (listof identifier?) #f)

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?)
> #f)

> =

> '()

Like local-expand, but stx is expanded as a transformer expression instead of a run-time expression.

Any lifted expressions—from calls to syntax-local-lift-expression during the expansion of stx—are captured in the result. If context-v is 'top-level, then lifts are captured in a begin form, otherwise lifts are captured in let-values forms. If no expressions are lifted during expansion, then no begin or let-values wrapper is added.

Changed in version 6.5.0.3 of package base: Allow and capture lifts in a 'top-level context.

> > procedure

> > (local-expand/capture-lifts |  | stx |  |  |  |
> > |  | context-v |  |  |  |
> > |  | stop-ids |  |  |  |
> > | [ | intdef-ctx |  |  |  |
> > |  | lift-ctx]) |  | → |  | syntax?

> stx : any/c
> 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?
> (listof internal-definition-context?)
> #f)

> =

> '()

> lift-ctx : any/c = (gensym 'lifts)

Like local-expand, but 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.

If context-v is 'top-level or 'module, then module forms can appear in the result as added via syntax-local-lift-module. If context-v is 'module, then module* forms can appear, too.

> > procedure

> > (local-transformer-expand/capture-lifts |  | stx |  |  |  |
> > |  | context-v |  |  |  |
> > |  | stop-ids |  |  |  |
> > | [ | intdef-ctx |  |  |  |
> > |  | lift-ctx]) |  | → |  | syntax?

> stx : any/c
> context-v : (or/c 'expression 'top-level list?)
> stop-ids : (or/c (listof identifier?) #f)

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?)
> #f)

> =

> '()

> lift-ctx : any/c = (gensym 'lifts)

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

> > procedure

> > (internal-definition-context? v) → boolean?

> v : any/c

Returns #t if v is an internal-definition context, #f otherwise.

> > procedure

> > (syntax-local-make-definition-context | [ | parent-ctx |
> > |  | add-scope?]) |

> → internal-definition-context?
> parent-ctx : (or/c internal-definition-context? #f) = #f
> add-scope? : any/c = #t

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.

An internal-definition context internally creates a scope to represent the context. Unless add-scope? is #f, the scope is added to any form that is expanded within the context or that appears as the result of a (partial) expansion within the context.

If parent-ctx is not #f, then parent-ctx is made the parent internal-definition context for the new internal-definition context. Whenever the new context’s bindings are added to the local binding context (e.g. by providing the context to local-expand, syntax-local-bind-syntaxes, or syntax-local-value), then the bindings from parent-ctx are also added as well. If parent-ctx was also created with a parent internal-definition context, bindings from its parent are also added, and so on recursively. Note that the scopes of parent contexts are not added implicitly, only the bindings, even when the scope of the child context would be implicitly added. If the scopes of parent definition contexts should be added, the parent contexts must be provided explicitly.

Additionally, if the created definition context is intended to be spliced into a surrounding definition context, the surrounding context should always be provided for the parent-ctx argument to ensure the necessary use-site scopes are added to macros expanded in the context. Otherwise, expansion of nested definitions can be inconsistent with the expansion of definitions in the surrounding context.

The scope associated with a new definition context is pruned from quote-syntax forms only when it is created during the dynamic extent of a syntax transformer application or in a begin-for-syntax form (potentially nested) within a module being expanded.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Changed in version 6.3 of package base: Added the add-scope? argument, and made calling internal-definition-context-seal no longer necessary.

> > procedure

> > (syntax-local-bind-syntaxes |  | id-list |  |  |  |
> > |  | expr |  |  |  |
> > |  | intdef-ctx |  |  |  |
> > | [ | extra-intdef-ctxs]) |  | → |  | void?

> id-list : (listof identifier?)
> expr : (or/c syntax? #f)
> intdef-ctx : internal-definition-context?

> extra-intdef-ctxs

> :

> (or/c internal-definition-context?
> (listof 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; in the latter case, the number of values produced by the expression should match the number of identifiers, otherwise the exn:fail:contract:arity exception is raised.

When expr is not #f, it is expanded in an expression context and evaluated in the current transformer environment. In this case, the bindings and lexical information from both intdef-ctx and extra-intdef-ctxs are used to enrich expr’s lexical information and extend the local binding context in the same way as the fourth argument to local-expand. If expr is #f, the value provided for extra-intdef-ctxs is ignored.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Changed in version 6.90.0.27 of package base: Added the extra-intdef-ctxs argument.

> > procedure

> > (internal-definition-context-binding-identifiers intdef-ctx)

> → (listof identifier?)
> intdef-ctx : internal-definition-context?

Returns a list of all binding identifiers registered for intdef-ctx through syntax-local-bind-syntaxes. Each identifier in the returned list includes the internal-definition context’s scope.

Added in version 6.3.0.4 of package base.

> > procedure

> > (internal-definition-context-introduce |  | intdef-ctx |  |  |  |
> > |  | stx |  |  |  |
> > | [ | mode]) |  | → |  | syntax?

> intdef-ctx : internal-definition-context?
> stx : syntax?
> mode : (or/c 'flip 'add 'remove) = 'flip

Flips, adds, or removes (depending on mode) the scope for intdef-ctx for all parts of stx.

Added in version 6.3 of package base.

> > procedure

> > (internal-definition-context-seal intdef-ctx) → void?

> intdef-ctx : internal-definition-context?

For backward compatibility only; has no effect.

> > procedure

> > (identifier-remove-from-definition-context |  | id-stx |
> > |  | intdef-ctx) |

> → identifier?
> id-stx : identifier?

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?))

Removes all of the scopes of intdef-ctx (or of each element in a list intdef-ctx) from id-stx.

The identifier-remove-from-definition-context function is provided for backward compatibility; the more general internal-definition-context-introduce function is preferred.

Changed in version 6.3 of package base: Simplified the operation to scope removal.

> > value

> > prop:expansion-contexts : struct-type-property?

A structure type property to constrain the use of macro transformers and rename transformers. The property’s value must be a list of symbols, where the allowed symbols are 'expression, 'top-level, 'module, 'module-begin, and 'definition-context. Each symbol corresponds to an expansion context in the same way as for local-expand or as reported by syntax-local-context, except that 'definition-context is used (instead of a list) to represent an internal-definition context.

If an identifier is bound to a transformer whose list does not include a symbol for a particular use of the identifier, then the use is adjusted as follows:

- In a 'module-begin context, then the use is wrapped in a begin form.

- In a 'module, 'top-level, 'internal-definition or context, if 'expression is present in the list, then the use is wrapped in an #%expression form.

- Otherwise, a syntax error is reported.

The prop:expansion-contexts property is most useful in combination with prop:rename-transformer, since a general transformer procedure can use syntax-local-context. Furthermore, a prop:expansion-contexts property makes the most sense when a rename transformer’s identifier has the 'not-free-identifier=? property, otherwise a definition of the binding creates a binding alias that effectively routes around the prop:expansion-contexts property.

Added in version 6.3 of package base.

> > procedure

> > (syntax-local-value |  | id-stx |  |  |  |
> > | [ | failure-thunk |  |  |  |
> > |  | intdef-ctx]) |  | → |  | any

> id-stx : identifier?
> failure-thunk : (or/c (-> any) #f) = #f

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?)
> #f)

> =

> '()

Returns the transformer binding value of the identifier id-stx in the context of the current expansion. If intdef-ctx is not #f, bindings from all provided definition contexts are also considered. Unlike the fourth argument to local-expand, the scopes associated with the provided definition contexts are not used to enrich id-stx’s lexical information.

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.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Examples:

> > (define-syntax swiss-cheeses? #t)

> > (define-syntax (transformer stx)
> (if (syntax-local-value #'swiss-cheeses?)
> #''(gruyère emmental raclette)
> #''(roquefort camembert boursin)))

> > (transformer)
> '(gruyère emmental raclette)

Examples:

> > (define-syntax (transformer-2 stx)
> (syntax-local-value #'something-else (λ () (error "no binding"))))

> > (transformer-2)
> no binding

Examples:

> > (define-syntax nachos #'(printf "nachos~n"))
> > (define-syntax chips (make-rename-transformer #'nachos))

> > (define-syntax (transformer-3 stx)
> (syntax-local-value #'chips))

> > (transformer-3)
> nachos

Changed in version 6.90.0.27 of package base: Changed intdef-ctx to accept a list of internal-definition contexts in addition to a single internal-definition context or #f.

> > procedure

> > (syntax-local-value/immediate |  | id-stx |  |  |  |
> > | [ | failure-thunk |  |  |  |
> > |  | intdef-ctx]) |  | → |  | any

> id-stx : syntax?
> failure-thunk : (or/c (-> any) #f) = #f

> intdef-ctx

> :

> (or/c internal-definition-context?
> (listof internal-definition-context?)
> #f)

> =

> '()

Like syntax-local-value, but the result is normally two values. If id-stx is bound to a rename transformer, the results are the rename transformer and the identifier in the transformer. Beware that provide on an id bound to a rename transformer may export the target of the rename instead of id. See make-rename-transformer for more information. If id-stx is not bound to a rename transformer, then the results are the value that syntax-local-value would produce and #f.

If id-stx has no transformer binding, then failure-thunk is called (and it can return any number of values), or an exception is raised if failure-thunk is #f.

Examples:

> > (define-syntax agent-007 (make-rename-transformer #'james-bond))

> > (define-syntax (show-secret-identity stx)
> (syntax-parse stx
> [(_ name:id)
> (define-values [_ orig-name] (syntax-local-value/immediate #'name))
> #`'(name #,orig-name)]))

> > (show-secret-identity agent-007)
> '(agent-007 james-bond)

> > procedure

> > (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 declaration just before the requesting expression within the begin-for-syntax.

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 or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.
In addition, this procedure can be called only when a lift target is available, as indicated by syntax-transforming-with-lifts?.

> > procedure

> > (syntax-local-lift-values-expression n stx)

> → (listof identifier?)
> n : exact-nonnegative-integer?
> stx : syntax?

Like syntax-local-lift-expression, but binds the result to n identifiers, and returns a list of the n identifiers.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (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 or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-lift-module stx) → void?

> stx : syntax?

Cooperates with the module form or top-level expansion to add stx as a module declaration in the enclosing module or top-level. The stx form must start with module or module*, where the latter is only allowed within the expansion of a module.

The module is not immediately declared when syntax-local-lift-module returns. Instead, the module declaration is recorded for processing when expansion returns to the enclosing module body or top-level sequence.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.
If the current expression being transformed is not within a module form or within a top-level expansion, then the exn:fail:contract exception is raised. If stx form does not start with module or module*, or if it starts with module* in a top-level context, the exn:fail:contract exception is raised.

Added in version 6.3 of package base.

> > procedure

> > (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 in phase level 0 and not in the module top-level, then stx is eventually expanded in an expression context. If the current expression being transformed is in a higher phase level (i.e., nested within some number of begin-for-syntaxes within a module top-level), then the lifted declaration is placed at the very end of the module (under a suitable number of begin-for-syntaxes), instead of merely the end of the enclosing begin-for-syntax.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.
If the current expression being transformed is not within a module form (see syntax-transforming-module-expression?), then the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-lift-require |  | raw-require-spec |  |  |  |
> > |  | stx) |  | → |  | syntax?

> raw-require-spec : any/c
> stx : syntax?

Lifts a #%require form corresponding to raw-require-spec (either as a syntax object or datum) to the top-level or to the top of the module currently being expanded or to an enclosing begin-for-syntax.

The resulting syntax object is the same as stx, except that a fresh scope is added. The same scope 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).

If raw-require-spec and stx are part of the input to a transformer, then typically syntax-local-introduce should be applied to each before passing them to syntax-local-lift-require, and then syntax-local-introduce should be applied to the result of syntax-local-lift-require. Otherwise, marks added by the macro expander can prevent access to the new imports.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Changed in version 6.90.0.27 of package base: Changed the scope added to inputs from a macro-introduction scope to one that does not affect whether or not the resulting syntax is considered original as reported by syntax-original?.

> > procedure

> > (syntax-local-lift-provide raw-provide-spec-stx) → void?

> raw-provide-spec-stx : syntax?

Lifts a #%provide form corresponding to raw-provide-spec-stx to the top of the module currently being expanded or to an enclosing begin-for-syntax.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.
If the current expression being transformed is not within a module form (see syntax-transforming-module-expression?), then the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-name) → any/c

Returns an inferred name for the expression position being transformed, or #f if no such name is available. A name is normally a symbol or an identifier. See also Inferred Value Names.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (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 list’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 or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-phase-level) → exact-integer?

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.

Examples:

> ; a macro bound at phase 0

> > (define-syntax (print-phase-level stx)
> (printf "phase level: ~a~n" (syntax-local-phase-level))
> #'(void))

> > (require (for-meta 2 racket/base))

> > (begin-for-syntax
> ; a macro bound at phase 1
> (define-syntax (print-phase-level stx)
> (printf "phase level: ~a~n" (syntax-local-phase-level))
> #'(void)))

> > (print-phase-level)
> phase level: 0
> > (begin-for-syntax (print-phase-level))
> phase level: 1

> > procedure

> > (syntax-local-module-exports mod-path)

> → (listof (cons/c (or/c exact-integer? #f) (listof symbol?)))

> mod-path

> :

> (or/c module-path?
> (syntax/c module-path?))

Returns an association list from phase-level numbers (or #f for the label phase level) to lists of symbols, where the symbols are the names of provided bindings from mod-path at the corresponding phase level.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-submodules) → (listof symbol?)

Returns a list of submodule names that are declared via module (as opposed to module*) in the current expansion context.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

> > procedure

> > (syntax-local-get-shadower |  | id-stx |  |  |  |
> > | [ | only-generated?]) |  | → |  | identifier?

> id-stx : identifier?
> only-generated? : any/c = #f

Adds scopes to id-stx so that it refers to bindings in the current expansion context or could bind any identifier obtained via (syntax-local-get-shadower id-stx) in more nested contexts. If only-generated? is true, the phase-spanning scope of the enclosing module or namespace is omitted from the added scopes, however, which limits the bindings that can be referenced (and therefore avoids certain ambiguous references).

This function is intended for the implementation of syntax-parameterize and local-require.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Changed in version 6.3 of package base: Simplified to the minimal functionality needed for syntax-parameterize and local-require.

> > procedure

> > (syntax-local-make-delta-introducer id-stx) → procedure?

> id-stx : identifier?

For (limited) backward compatibility only; raises exn:fail:unsupported.

Changed in version 6.3 of package base: changed to raise exn:fail:supported.

> > procedure

> > (syntax-local-certifier [active?])

> →

> ((syntax?) (any/c (or/c procedure? #f))
> . ->* . syntax?)

> active? : boolean? = #f

For backward compatibility only; returns a procedure that returns its first argument.

> > procedure

> > (syntax-transforming?) → boolean?

Returns #t during the dynamic extent of a syntax transformer application by the expander and while a module is being visited, #f otherwise.

> > procedure

> > (syntax-transforming-with-lifts?) → boolean?

Returns #t if (syntax-transforming?) produces #t and a target context is available for lifting expressions (via syntax-local-lift-expression), #f otherwise.

Currently, (syntax-transforming?) implies (syntax-transforming-with-lifts?).

Added in version 6.3.0.9 of package base.

> > procedure

> > (syntax-transforming-module-expression?) → boolean?

Returns #t during the dynamic extent of a syntax transformer application by the expander for an expression within a module form, #f otherwise.

> > procedure

> > (syntax-local-identifier-as-binding id-stx) → identifier?

> id-stx : identifier?

Returns an identifier like id-stx, but without use-site scopes that were previously added to the identifier as part of a macro expansion in the current definition context.

In a syntax transformer that runs in a non-expression context and forces the expansion of subforms with local-expand, use syntax-local-identifier-as-binding on an identifier from the expansion before moving it into a binding position or comparing with with bound-identifier=?. Otherwise, the results can be inconsistent with the way that define works in the same definition context.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Added in version 6.3 of package base.

> > procedure

> > (syntax-local-introduce stx) → syntax?

> stx : syntax?

Produces a syntax object that is like stx, except that the presence of scopes for the current expansion—both the macro-introduction scope and the use-site scope, if any—is flipped on all parts of the syntax object. See Transformer Bindings for information on macro-introduction and use-site scopes.

This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (see syntax-transforming?), otherwise the exn:fail:contract exception is raised.

Example:

> > (module example racket
> (define-syntax (require-math stx)
> (syntax-local-introduce #'(require racket/math)))
> (require-math)
> pi)

> > procedure

> > (make-syntax-introducer [as-use-site?])

> → ((syntax?) ((or/c 'flip 'add 'remove)) . ->* . syntax?)
> as-use-site? : any/c = #f

Produces a procedure that encapsulates a fresh scope and flips, adds, or removes it in a given syntax object. By default, the fresh scope is a macro-introduction scope, but providing a true value for as-use-site? creates a scope that is like a use-site scope; the difference is in how the scopes are treated by syntax-original?.

The action of the generated procedure can be 'flip (the default) to flip the presence of a scope in each part of a given syntax object, 'add to add the scope to each regardless of whether it is present already, or 'remove to remove the scope when it is currently present in any part.

Multiple applications of the same make-syntax-introducer result procedure use the same scope, and different result procedures use distinct scopes.

Changed in version 6.3 of package base: Added the optional as-use-site? argument, and added the optional operation argument in the result procedure.

> > procedure

> > (make-interned-syntax-introducer key)

> → ((syntax?) ((or/c 'flip 'add 'remove)) . ->* . syntax?)
> key : symbol?

Like make-syntax-introducer, but the encapsulated scope is interned. Multiple calls to make-interned-syntax-introducer with the same key will produce procedures that flip, add, or remove the same scope, even across phases and module instantiations. Furthermore, the scope remains consistent even when embedded in compiled code, so a scope created with make-interned-syntax-introducer will retain its identity in syntax objects loaded from compiled code. (In this sense, the relationship between make-syntax-introducer and make-interned-syntax-introducer is analogous to the relationship between gensym and quote.)

This function is intended for the implementation of separate binding environments within a single phase, for which the scope associated with each environment must be the same across modules.

Unlike make-syntax-introducer, the scope added by a procedure created with make-interned-syntax-introducer is always treated like a use-site scope, not a macro-introduction scope, so it does not affect originalness as reported by syntax-original?.

Added in version 6.90.0.28 of package base.

> > procedure

> > (make-syntax-delta-introducer |  | ext-stx |
> > |  | base-stx |
> > | [ | phase-level]) |

> → ((syntax?) ((or/c 'flip 'add 'remove)) . ->* . syntax?)
> ext-stx : identifier?
> base-stx : (or/c syntax? #f)

> | phase-level |  | : |  | (or/c #f exact-integer?)
> |  |  | = |  | (syntax-local-phase-level)

Produces a procedure that behaves like the result of make-syntax-introducer, but using a set of scopes from ext-stx and with a default action of 'add.

- If the scopes of base-stx are a subset of the scopes of ext-stx, then the result of make-syntax-delta-introducer adds, removes, or flips scopes that are in the set for ext-stx and not in the set for base-stx.

- If the scopes of base-stx are not a subset of the scopes of ext-stx, but if it has a binding, then the set of scopes associated with the binding id subtracted from the set of scopes for ext-stx, and the result of make-syntax-delta-introducer adds, removes, or flips that difference.

A #f value for base-stx is equivalent to a syntax object with no scopes.

This procedure is potentially useful when some 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 scopes one the use of m-id added 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.

If ext-stx is tainted or armed, then an identifier result from the created procedure is tainted.

> > procedure

> > (syntax-local-transforming-module-provides?) → boolean?

Returns #t while a provide transformer is running (see make-provide-transformer) or while an expand sub-form of #%provide is expanded, #f otherwise.

> > procedure

> > (syntax-local-module-defined-identifiers)

> → (and/c hash? immutable?)

Can be called only while syntax-local-transforming-module-provides? returns #t.

It returns a hash table mapping a phase-level number (such as 0) to a list of all definitions at that phase level within the module being expanded. This information is used for implementing provide sub-forms like all-defined-out.

Beware that the phase-level keys are absolute relative to the enclosing module, and not relative to the current transformer phase level as reported by syntax-local-phase-level.

> > procedure

> > (syntax-local-module-required-identifiers |  | mod-path |
> > |  | phase-level) |

> →

> (or/c (listof (cons/c (or/c exact-integer? #f)
> (listof identifier?)))
> #f)

> 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, or all shifts if phase-level is #t. If phase-level is not #t, the result can be #f if no identifiers are exported at that phase.

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.

Beware that the phase-level keys are absolute relative to the enclosing module, and not relative to the current transformer phase level as reported by syntax-local-phase-level.

> > value

> > prop:liberal-define-context : struct-type-property?

> > procedure

> > (liberal-define-context? v) → boolean?

> v : any/c

An instance of a structure type with a true value for the prop:liberal-define-context property can be used as an element of an internal-definition context representation in the result of syntax-local-context or the second argument of local-expand. Such a value indicates that the context supports liberal expansion of define forms into potentially multiple define-values and define-syntaxes forms. The 'module and 'module-body contexts implicitly allow liberal expansion.

The liberal-define-context? predicate returns #t if v is an instance of a structure with a true value for the prop:liberal-define-context property, #f otherwise.

##### 12.4.1`` require Transformers

(require racket/require-transform) | package: base

The bindings documented in this section are provided by the racket/require-transform library, not racket/base or racket.

A transformer binding whose value is a structure with the prop:require-transformer property implements a derived require-spec for require as a require transformer.

A require 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.

> > procedure

> > (expand-import require-spec)

> →

> (listof import?) |  | (listof import-source?)

> require-spec : 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).

> > procedure

> > (make-require-transformer proc) → require-transformer?

> proc

> :

> (syntax? . -> . (values
> (listof import?)
> (listof import-source?)))

Creates a require transformer using the given procedure as the transformer. Often used in combination with expand-import.

Examples:

> > (require (for-syntax racket/require-transform))

> > (define-syntax printing
> (make-require-transformer
> (lambda (stx)
> (syntax-case stx ()
> [(_ path)
> (printf "Importing: ~a~n" #'path)
> (expand-import #'path)]))))

> > (require (printing racket/match))
> Importing: #<syntax:eval:37:0 racket/match>

> > value

> > prop:require-transformer : struct-type-property?

A property to identify require transformers. The property value must be a procedure that takes the structure and returns a transformer procedure; the returned transformer procedure takes a syntax object and returns import and import-source lists.

> > procedure

> > (require-transformer? v) → boolean?

> v : any/c

Returns #t if v has the prop:require-transformer property, #f otherwise.

> > struct

> > (struct |  | import | ( | local-id
> > |  |  |  | src-sym
> > |  |  |  | src-mod-path
> > |  |  |  | mode
> > |  |  |  | req-mode
> > |  |  |  | orig-mode
> > |  |  |  | orig-stx)

> #:extra-constructor-name make-import)
> local-id : identifier?
> src-sym : symbol?

> src-mod-path

> :

> (or/c module-path?
> (syntax/c 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.

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

- orig-stx — a syntax object for the source of the import, used for error reporting.

> > struct

> > (struct |  | import-source (mod-path-stx mode)

> #:extra-constructor-name make-import-source)
> mod-path-stx : (syntax/c module-path?)
> 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 of the import.

> > parameter

> > (current-require-module-path) → (or/c #f module-path-index?)

> (current-require-module-path module-path) → void?
> module-path : (or/c #f module-path-index?)

A parameter that determines how relative require-level module paths are expanded to #%require-level module paths by convert-relative-module-path (which is used implicitly by all built-in require sub-forms).

When the value of current-require-module-path is #f, relative module paths are left as-is, which means that the require context determines the resolution of the module path.

The require form parameterizes current-require-module-path as #f while invoking sub-form transformers, while relative-in parameterizes to a given module path.

> > procedure

> > (convert-relative-module-path module-path)

> →

> (or/c module-path?
> (syntax/c module-path?))

> module-path

> :

> (or/c module-path?
> (syntax/c module-path?))

Converts module-path according to current-require-module-path.

If module-path is not relative or if the value of current-require-module-path is #f, then module-path is returned. Otherwise, module-path is converted to an absolute module path that is equivalent to module-path relative to the value of current-require-module-path.

> > procedure

> > (syntax-local-require-certifier)

> →

> ((syntax?) (or/c #f (syntax? . -> . syntax?))
> . ->* . syntax?)

For backward compatibility only; returns a procedure that returns its first argument.

##### 12.4.2`` provide Transformers

(require racket/provide-transform) | package: base

The bindings documented in this section are provided by the racket/provide-transform library, not racket/base or racket.

A transformer binding whose value is a structure with the prop:provide-transformer property implements a derived provide-spec for provide as a provide transformer. A provide transformer is applied as part of the last phase of a module’s expansion, after all other declarations and expressions within the module are expanded.

A transformer binding whose value is a structure with the prop:provide-pre-transformer property implements a derived provide-spec for provide as a provide pre-transformer. A provide pre-transformer is applied as part of the first phase of a module’s expansion. Since it is used in the first phase, a provide pre-transformer can use functions such as syntax-local-lift-expression to introduce expressions and definitions in the enclosing module.

An identifier can have a transformer binding to a value that acts both as a provide transformer and provide pre-transformer. The result of a provide pre-transformer is not automatically re-expanded, so a provide pre-transformer can usefully expand to itself in that case.

A 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 of a provide transformer must be a list of exports, while the result of a provide pre-transformer is a syntax object to be used as a provide-spec in the last phase of module expansion.

If a derived form contains a sub-form that is a provide-spec, then it can call expand-export or pre-expand-export to transform the sub-provide-spec sub-form.

See also define-provide-syntax, which supports macro-style provide transformers.

> > procedure

> > (expand-export provide-spec modes) → (listof export?)

> provide-spec : 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 binding in the phase level of the enclosing provide form, unless the modes list specifies otherwise. Normally, modes is either empty or contains a single element.

> > procedure

> > (pre-expand-export provide-spec modes) → syntax?

> provide-spec : syntax?
> modes : (listof (or/c exact-integer? #f))

Expands the given provide-spec at the level of provide pre-transformers. The modes argument is the same as for expand-export.

> > procedure

> > (make-provide-transformer proc) → provide-transformer?

> proc

> :

> (syntax? (listof (or/c exact-integer? #f))
> . -> . (listof export?))

> (make-provide-transformer proc pre-proc)
> → (and/c provide-transformer? provide-pre-transformer?)

> proc

> :

> (syntax? (listof (or/c exact-integer? #f))
> . -> . (listof export?))

> pre-proc

> :

> (syntax? (listof (or/c exact-integer? #f))
> . -> . syntax?)

Creates a provide transformer (i.e., a structure with the prop:provide-transformer property) using the given procedure as the transformer. If a pre-proc is provided, then the result is also a provide pre-transformer. Often used in combination with expand-export and/or pre-expand-export.

> > procedure

> > (make-provide-pre-transformer pre-proc)

> → provide-pre-transformer?

> pre-proc

> :

> (syntax? (listof (or/c exact-integer? #f))
> . -> . syntax?)

Like make-provide-transformer, but for a value that is a provide pre-transformer, only. Often used in combination with pre-expand-export.

Examples:

> > (module m racket
> (require
> (for-syntax racket/provide-transform syntax/parse syntax/stx))
> (define-syntax wrapped-out
> (make-provide-pre-transformer
> (lambda (stx modes)
> (syntax-parse stx
> [(_ f ...)
> #:with (wrapped-f ...)
> (stx-map
> syntax-local-lift-expression
> #'((lambda args
> (printf "applying ~a, args: ~a\n" 'f args)
> (apply f args)) ...))
> (pre-expand-export
> #'(rename-out [wrapped-f f] ...) modes)]))))
> (provide (wrapped-out + -)))

> > (require 'm)
> > (- 1 (+ 2 3))

> applying +, args: (2 3)
> applying -, args: (1 5)

> -4

> > value

> > prop:provide-transformer : struct-type-property?

A property to identify provide transformers. The property value must be a procedure that takes the structure and returns a transformer procedure; the returned transformer procedure takes a syntax object and mode list and returns an export list.

> > value

> > prop:provide-pre-transformer : struct-type-property?

A property to identify provide pre-transformers. The property value must be a procedure that takes the structure and returns a transformer procedure; the returned transformer procedure takes a syntax object and mode list and returns a syntax object.

> > procedure

> > (provide-transformer? v) → boolean?

> v : any/c

Returns #t if v has the prop:provide-transformer property, #f otherwise.

> > procedure

> > (provide-pre-transformer? v) → boolean?

> v : any/c

Returns #t if v has the prop:provide-pre-transformer property, #f otherwise.

> > struct

> > (struct |  | export (local-id out-sym mode protect? orig-stx)

> #:extra-constructor-name make-export)
> 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.

- mode — the phase level of the binding in the exporting module.

- protect? — indicates whether the identifier should be protected (see Code Inspectors).

- orig-stx — a syntax object for the source of the export, used for error reporting.

> > procedure

> > (syntax-local-provide-certifier)

> →

> ((syntax?) (or/c #f (syntax? . -> . syntax?))
> . ->* . syntax?)

For backward compatibility only; returns a procedure that returns its first argument.

##### 12.4.3`` Keyword-Argument Conversion Introspection

(require racket/keyword-transform) | package: base

The bindings documented in this section are provided by the racket/keyword-transform library, not racket/base or racket.

> > procedure

> > (syntax-procedure-alias-property stx)

> →

> (or/c #f
> (letrec ([val? (recursive-contract
> (or/c (cons/c identifier? identifier?)
> (cons/c val? val?)))])
> val?))

> stx : syntax?

> > procedure

> > (syntax-procedure-converted-arguments-property stx)

> →

> (or/c #f
> (letrec ([val? (recursive-contract
> (or/c (cons/c identifier? identifier?)
> (cons/c val? val?)))])
> val?))

> stx : syntax?

Reports the value of a syntax property that can be attached to an identifier by the expansion of a keyword-application form. See lambda for more information about the property.

The property value is normally a pair consisting of the original identifier and an identifier that appears in the expansion. Property-value merging via syntax-track-origin can make the value a pair of such values, and so on.

top ← prev up next →