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
syntax-local-apply-transformer
internal-definition-context?
syntax-local-make-definition-context
syntax-local-make-definition-context-introducer
internal-definition-context-add-scopes
internal-definition-context-splice-binding-identifier
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-module-interned-scope-symbols
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-lift-require-top-level-form
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
export-out-sym
syntax-local-provide-certifier
12.4.3 Keyword-Argument Conversion Introspection
syntax-procedure-alias-property
syntax-procedure-converted-arguments-property
12.4.4 Portal Syntax Bindings
portal-syntax?
make-portal-syntax
portal-syntax-content

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.

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:

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.
Changed in version 7.4.0.10: Adjusted rename-transformer expansion to add a macro-introduction scope, the same as regular macro expansion.

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:

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?
      #f
      (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:

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

For backwards compatibility, when 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 inside-edge scope from each context for which add-scope? was not #f is added in the same way.

Expansion records use-site scopes for removal from definition bindings. When the intdef-ctx argument is an internal-definition context, use-site scopes are recorded with that context. When intdef-ctx is #f or (for backwards compatibility) a list, use-site scopes are recorded with the current expand context.

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

This procedure’s binding is provided as protected in the sense of protect-out.

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.
Changed in version 8.2.0.4: Changed binding to protected.

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.
This procedure’s binding is provided as protected in the sense of protect-out.

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

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?
      #f
      (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 stxare 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.

This procedure’s binding is provided as protected in the sense of protect-out.

Changed in version 6.5.0.3 of package base: Allowed and captured lifts in a 'top-level context.
Changed in version 8.2.0.4: Changed binding to protected.

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?
      #f
      (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 stxappear 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.

This procedure’s binding is provided as protected in the sense of protect-out.

Changed in version 8.2.0.4 of package base: Changed binding to protected.

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?
      #f
      (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).

This procedure’s binding is provided as protected in the sense of protect-out.

Changed in version 8.2.0.4 of package base: Changed binding to protected.

procedure

(syntax-local-apply-transformer transformer    
  binding-id    
  context-v    
  intdef-ctx    
  v ...)  any
  transformer : procedure?
  binding-id : (or/c identifier? #f)
  context-v : (or/c 'expression 'top-level 'module 'module-begin list?)
  intdef-ctx : (or/c internal-definition-context? #f)
  v : any/c
Applies the procedure transformer to the vs in a new expansion context and local binding context. Adds and flips macro-introduction scopes and use-site scopes on the arguments and return values in the same manner as syntax transformer application. The arguments and returns may be any value; scopes are manipulated only for those that are syntax objects.

The context-v argument is as in local-expand, and the intdef-ctx is an internal-definition context value or #f. The binding-id specifies a binding associated with the transformer, which the expander uses to determine whether to add use-site scopes and which code inspector to use during expansion.

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 8.2.0.7 of package base.

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.

Before expanding forms whose lexical context should include the definitions, the transformer should use internal-definition-context-add-scopes to apply the context’s scopes to the syntax. Calls to procedures such as local-expand to expand the forms should provide the internal-definition context value as an argument.

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 an outside-edge scope and an inside-edge scope to represent the context. The inside-edge 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. For backward compatibility, providing #f for add-scope? disables this behavior.

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

An internal-definition context also tracks use-site scopes created during expansion within the definition context, so that they can be removed from bindings created in the context, at syntax-local-identifier-as-binding, and at internal-definition-context-splice-binding-identifier.

The scopes associated with a new definition context are 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.
Changed in version 8.2.0.7: Added the outside-edge scope and use-site scope tracking behaviors.

procedure

(syntax-local-make-definition-context-introducer [name])

  ((syntax?) ((or/c 'flip 'add 'remove)) . ->* . syntax?)
  name : (and/c symbol? (not/c 'macro)) = 'intdef
Like make-syntax-introducer, but the encapsulated scope is pruned from quote-syntax forms, much like the scopes associated with a new definition context (see syntax-local-make-definition-context). The name argument is used as the symbolic name, which serves as a debugging aid.

Typically, internal-definition-context-add-scopes and internal-definition-context-splice-binding-identifier are preferred, but this function can be useful when you are sure that you want a single scope that should be pruned from quote-syntax 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.

Added in version 8.12.0.8 of package base.

procedure

(internal-definition-context-add-scopes intdef-ctx    
  stx)  syntax?
  intdef-ctx : internal-definition-context?
  stx : syntax?
Adds the outside-edge scope and inside-edge scope for intdef-ctx to stx.

Use this function to apply the definition context scopes to syntax that originates within the definition context before expansion.

Added in version 8.2.0.7 of package base.

procedure

(internal-definition-context-splice-binding-identifier 
  intdef-ctx 
  id) 
  syntax?
  intdef-ctx : internal-definition-context?
  id : identifier?
Removes scopes associated with the intdef-ctx from id: the outside-edge scope, the inside-edge scope, and use-site scopes created by expansions within the definition context.

Use when splicing a binding originating within the intdef-ctx into a surrounding context.

Added in version 8.2.0.7 of package base.

procedure

(syntax-local-bind-syntaxes id-list 
  expr 
  intdef-ctx 
  [extra-intdef-ctxs]) 
  (listof identifier?)
  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. Returns identifiers with lexical information matching the new bindings.

For backwards compatibility, the lexical information of each element of extra-intdef-ctxs is also added to each identifier in id-list before binding.

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.
Changed in version 8.2.0.7: Changed the return value from #<void> to the list of bound identifiers.

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.

This function is provided for backwards compatibility; internal-definition-context-add-scopes and internal-definition-context-splice-binding-identifier are preferred. See also syntax-local-make-definition-context-introducer for encapsulating a single scope that should be pruned from quote-syntax forms.

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 internal-definition-context-splice-binding-identifier function is preferred.

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

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?
      #f
      (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

This procedure’s binding is provided as protected in the sense of protect-out.

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.
Changed in version 8.2.0.4: Changed binding to protected.

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?
      #f
      (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)

This procedure’s binding is provided as protected in the sense of protect-out.

Changed in version 8.2.0.4 of package base: Changed binding to protected.

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

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.

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    
  [new-scope?])  syntax?
  raw-require-spec : any/c
  stx : syntax?
  new-scope? : any/c = #t
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 if new-scope? is true. 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 new-scope? is #f, then the result exactly stx, and no scope is added to the lifted #%require form; in that case, take care to ensure that the lifted require does not change the meaning of already-expanded identifiers in the module, otherwise re-expansion of the enclosing module will not produce the same result as the expanded module.

If raw-require-spec is part of the input to a transformer, then typically syntax-local-introduce should be applied before passing it to 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?.
Changed in version 8.6.0.4: Added the new-scope? optional argument.

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.

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 phase+space? (listof symbol?)))
  mod-path : 
(or/c module-path?
      (syntax/c module-path?))
Returns an association list from phase level and binding space combinations 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.

Changed in version 8.2.0.3 of package base: Generalized result to phase–space combinations.

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.

Returns a list of distinct interned symbols corresponding to binding spaces that have been used, so far, for binding within the current expansion context’s module or top-level namespace. The result is conservative in the sense that it may include additional symbols that have not been used in the current module or namespace.

The current implementation returns all symbols for reachable interned scopes, but that behavior may change in the future to return a less conservative list of symbols.

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 8.2.0.7 of package base.

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.

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

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.

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    
  [intdef-ctx])  identifier?
  id-stx : identifier?
  intdef-ctx : (or/c internal-definition-context? #f) = #f
Returns an identifier like id-stx, but without use-site scopes that were previously added to the identifier as part of a macro expansion. When the intdef-ctx is an internal-definition context, the function removes use-site scopes created during expansion in that context. When it is #f (the default), it removes use-site scopes created during expansion in the current expansion 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 it 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.
Changed in version 8.2.0.7: Added the optional intdef-ctx argument.

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 : (and/c symbol? symbol-interned?)
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 spaces 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.
Changed in version 8.2.0.4: Added the constraint that key is interned.

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.

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, then an identifier result from the created procedure is tainted.

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

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 
  shift) 
  
(or/c (listof (cons/c phase+space?
                      (listof identifier?)))
      #f)
  mod-path : (or/c module-path? #f)
  shift : (or/c #t phase+space-shift?)
Can be called only while syntax-local-transforming-module-provides? returns #t.

It returns an association list mapping phase level and binding space combinations 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 and binding space shift as represented by shift, or all shifts if shift is #t. If shift is not #t, the result can be #f if no identifiers are imported at that shift.

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 shifts are absolute relative to the enclosing module, and not relative to the current transformer phase level as reported by syntax-local-phase-level.

Changed in version 8.2.0.3 of package base: Generalized shift and result to phase–space combinations.

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🔗ℹ

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)
          (begin
            (printf "Importing: ~a~n" #'path)
            (expand-import #'path))]))))
> (require (printing racket/match))

Importing: #<syntax:eval:37:0 racket/match>

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 : phase+space?
  req-mode : phase+space-shift?
  orig-mode : phase+space?
  orig-stx : syntax?
A structure representing a single imported identifier:

Changed in version 8.2.0.3 of package base: Generalized modes to phase–space combinations.

struct

(struct import-source (mod-path-stx mode)
    #:extra-constructor-name make-import-source)
  mod-path-stx : (syntax/c module-path?)
  mode : phase+space-shift?
A structure representing an imported module, which must be instantiated or visited even if no binding is imported into a module.

Changed in version 8.2.0.3 of package base: Generalized mode to phase–space combinations.

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-lift-require-top-level-form top-level-stx)

  void?
  top-level-stx : syntax?
Lifts top-level-stx to the top-level of the enclosing module, immediately following the require that is 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.
In addition, this procedure may only be called while expanding a require transformer.

Added in version 8.12.0.13 of package base.

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🔗ℹ

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 phase+space?)
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.

Changed in version 8.2.0.3 of package base: Generalized modes to phase–space combinations.

procedure

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

  provide-spec : syntax?
  modes : (listof phase+space?)
Expands the given provide-spec at the level of provide pre-transformers. The modes argument is the same as for expand-export.

Changed in version 8.2.0.3 of package base: Generalized modes to phase–space combinations.

procedure

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

  proc : 
(syntax? (listof phase+space?)
 . -> . (listof export?))
(make-provide-transformer proc pre-proc)
  (and/c provide-transformer? provide-pre-transformer?)
  proc : 
(syntax? (listof phase+space?)
 . -> . (listof export?))
  pre-proc : 
(syntax? (listof phase+space?)
 . -> . 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 phase+space?)
 . -> . 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

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.

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-id mode protect? orig-stx)
    #:extra-constructor-name make-export)
  local-id : identifier?
  out-id : identifier?
  mode : phase+space?
  protect? : any/c
  orig-stx : syntax?
A structure representing a single exported identifier:

Changed in version 8.2.0.3 of package base: Generalized mode to phase–space combinations.

Changed in version 8.9.0.5 of package base: Changed the out-sym field to out-id. For backward compatibility, the make-export constructor also accepts a symbol, and a export-out-sym function returns the syntax-e value of the out-id.

procedure

(export-out-sym ex)  symbol?

  ex : export?
Composes syntax-e with export-out-id.

This function is intended for backward compatibility. Use export-out-id directly, instead.

Added in version 8.9.0.5 of package base.

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🔗ℹ

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.

12.4.4 Portal Syntax Bindings🔗ℹ

An identifier bound to portal syntax value created by make-portal-syntax does not act as a transformer, but it encapsulates a syntax object that can be accessed in inspected even without instantiating the enclosing module. Portal syntax is also bound using the portal form of #%require.

procedure

(portal-syntax? v)  boolean?

  v : any/c
Returns #t if v is a value created by make-portal-syntax, #f otherwise.

Added in version 8.3.0.8 of package base.

procedure

(make-portal-syntax stx)  portal-syntax?

  stx : syntax?
Creates portal syntax with the content stx.

When define-syntax or define-syntaxes binds an identifier to portal syntax immediately in a module body, then in addition to being accessible via syntax-local-value while expanding, the portal syntax content is accessible via identifier-binding-portal-syntax.

Added in version 8.3.0.8 of package base.

procedure

(portal-syntax-content portal)  syntax?

  portal : portal-syntax?
Returns the content of portal syntax created with make-portal-syntax.

Added in version 8.3.0.8 of package base.