12.4 Syntax Transformers (original) (raw)
12.4 Syntax Transformers🔗ℹ
Returns #t if v is a value created bymake-set!-transformer or an instance of a structure type with the prop:set!-transformer property, #f otherwise.
Creates an assignment transformer that cooperates withset!. If the result of make-set!-transformer is bound to id as a transformer binding, thenproc is applied as a transformer when id is used in an expression position, or when it is used as the target of aset! assignment as (set! id expr). When the identifier appears as a set! target, the entire set!expression is provided to the transformer.
Example:
Returns the procedure that was passed tomake-set!-transformer to create transformer or that is identified by the prop:set!-transformer property oftransformer.
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 hasprop: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 callsraise-syntax-error is used, instead.
If a value has both the prop:set!-transformer andprop:rename-transformer properties, then the latter takes precedence. If a structure type has the prop:set!-transformerand prop:procedure properties, then the former takes precedence for the purposes of macro expansion.
Returns #t if v is a value created bymake-rename-transformer or an instance of a structure type with the prop:rename-transformer property, #fotherwise.
Examples:
Creates a rename transformer that, when used as atransformer 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 bymake-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=? andidentifier-binding equivalence between idand 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 propertyand as long as id-stx has a binding.
- If provide exports id, it uses a symbol-valued 'nominal-id property ofid-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 byall-defined-out.
- The syntax-local-value function recognizes rename-transformer bindings and consult their targets.
Examples:
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.
Returns the identifier passed to make-rename-transformer to create transformer or as indicated by aprop:rename-transformer property on transformer.
Example:
The property value must be an exact integer, an identifiersyntax 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 tomake-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-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.
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 #%expressionin any expression position.
- If stop-ids is a list containing just module*, then expansion proceeds as ifstop-ids were an empty list, except that expansion does not recur to submodulesdefined 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-referenceare 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 instop-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 asdefine-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 enclosedmodule form (but not module* forms) in the same way as bymodule expansion.
If the intdef-ctx argument is an internal-definition context, its bindings andbindings from all parent internal-definition contexts are added to thelocal binding context during the dynamic extent of the call to local-expand. Additionally, unless #f was provided for the add-scope? argument tosyntax-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 theintdef-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 allowliberal expansion of define forms, the generated value should be an instance of a structure with a true value forprop:liberal-define-context. If the internal-definition context is meant to be self-contained, the list for context-vshould 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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Examples:
> (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 asprotected in the sense of protect-out.
Changed in version 6.0.1.3 of package base: Changed treatment of #%topso 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.
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; theexn:fail:syntax exception is raised if the expansion context includesscopes 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 #finstead of the expanded expression. Obtaining only the second, opaque result can be more efficient in some expansion contexts.
Unlike local-expand, syntax-local-expand-expressionnormally produces an expanded expression that contains no#%expression forms. However, ifsyntax-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
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.
Like local-expand, but stx is expanded as a transformer expression instead of a run-time expression.
Any lifted expressions—from calls tosyntax-local-lift-expression during the expansion ofstx—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 beginor let-values wrapper is added.
This procedure’s binding is provided asprotected 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.
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 ofstx—appear with their identifiers in define-valuesforms, and the expansion of stx is the last expression in thebegin. The lift-ctx value is reported bysyntax-local-lift-context during local expansion. The lifted expressions are not expanded, but instead left as provided in thebegin form.
If context-v is 'top-level or 'module, thenmodule forms can appear in the result as added viasyntax-local-lift-module. If context-v is'module, then module* forms can appear, too.
This procedure’s binding is provided asprotected in the sense of protect-out.
Changed in version 8.2.0.4 of package base: Changed binding to protected.
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 asprotected in the sense of protect-out.
Changed in version 8.2.0.4 of package base: Changed binding to protected.
Applies the procedure transformer to the vs in a new expansion context and local binding context. Adds and flipsmacro-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 theintdef-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 adduse-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Added in version 8.2.0.7 of package base.
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, usesyntax-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. Theinside-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 foradd-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’sbindings are added to the local binding context (e.g. by providing the context tolocal-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 aparent 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 thebindings, even when the inside-edge scope of the child context would be implicitly added. If thescopes 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-ctxargument 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 fromquote-syntax forms only when it is created during the dynamic extent of a syntax transformer application or in abegin-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Changed in version 6.3 of package base: Added the add-scope? argument, and made callinginternal-definition-context-sealno longer necessary.
Changed in version 8.2.0.7: Added the outside-edge scope and use-site scopetracking behaviors.
Like make-syntax-introducer, but the encapsulatedscope is pruned from quote-syntax forms, much like the scopes associated with a new definition context (seesyntax-local-make-definition-context). The nameargument is used as the symbolic name, which serves as a debugging aid.
Typically, internal-definition-context-add-scopes andinternal-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-syntaxforms.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Added in version 8.12.0.8 of package base.
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.
Use when splicing a binding originating within the intdef-ctx into a surrounding context.
Added in version 8.2.0.7 of package base.
Binds each identifier in id-list within theinternal-definition context represented by intdef-ctx, whereintdef-ctx is the result ofsyntax-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-ctxsis also added to each identifier in id-list before binding.
Supply #f forexpr when the identifiers correspond todefine-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 theexn: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 enrichexpr’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 (seesyntax-transforming?), otherwise theexn: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 # to the list of bound identifiers.
Returns a list of all binding identifiers registered forintdef-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.
Flips, adds, or removes (depending on mode) the scopefor intdef-ctx for all parts of stx.
This function is provided for backwards compatibility;internal-definition-context-add-scopes andinternal-definition-context-splice-binding-identifier are preferred. See also syntax-local-make-definition-context-introducer for encapsulating a single scope that should be pruned fromquote-syntax forms.
Added in version 6.3 of package base.
For backward compatibility only; has no effect.
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; theinternal-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 macrotransformers 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 forlocal-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 generaltransformer 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 theprop:expansion-contexts property.
Added in version 6.3 of package base.
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, thescopes associated with the provided definition contexts are not used to enrichid-stx’s lexical information.
If id-stx is bound to a rename transformer created with make-rename-transformer, syntax-local-valueeffectively calls itself with the target of the rename and returns that result, instead of the rename transformer.
If id-stx has no transformer binding (viadefine-syntax, let-syntax, etc.) in that environment, the result is obtained by applying failure-thunkif not #f. If failure-thunk is false, theexn: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 (seesyntax-transforming?), otherwise theexn: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:
> (transformer-2) no binding
This procedure’s binding is provided asprotected 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.
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 anid bound to a rename transformer may export the target of the rename instead of id. Seemake-rename-transformer for more information. Ifid-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, thenfailure-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)) > (show-secret-identity agent-007) '(agent-007 james-bond)
This procedure’s binding is provided asprotected in the sense of protect-out.
Changed in version 8.2.0.4 of package base: Changed binding to protected.
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 aletrec-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 withinbegin-for-syntax is lifted to a definedeclaration just before the requesting expression within thebegin-for-syntax.
Other syntactic forms can capture lifts by usinglocal-expand/capture-lifts orlocal-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
In addition, this procedure can be called only when a lift target is available, as indicated bysyntax-transforming-with-lifts?.
Like syntax-local-lift-expression, but binds the result ton identifiers, and returns a list of the nidentifiers.
This procedure must be called during the dynamic extent of a syntax transformer application by the expander or while a module is visited (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Returns a value that represents the target for expressions lifted viasyntax-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Cooperates with the module form or top-level expansion to addstx 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 whensyntax-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 (seesyntax-transforming?), otherwise theexn: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 withmodule 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.
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 ofbegin-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 (seesyntax-transforming?), otherwise theexn: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.
Lifts a #%require form corresponding toraw-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 ofstx 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 (seesyntax-transforming?), otherwise theexn: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 bysyntax-original?.
Changed in version 8.6.0.4: Added the new-scope? optional argument.
Lifts a #%provide form corresponding toraw-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 (seesyntax-transforming?), otherwise theexn: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.
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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
(syntax-local-context) → (or/c 'expression 'top-level 'module 'module-begin list?)
Returns an indication of the context for expansion that triggered asyntax transformer call. See Expansion Contextfor more information on contexts.
The symbol results indicate that the expression is being expanded for an expression context, a top-level context, amodule 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., itseq?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 sameinternal-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 (seesyntax-transforming?), otherwise theexn: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:
Returns an association list from phase level andbinding 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 (seesyntax-transforming?), otherwise theexn: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 viamodule (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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Returns a list of distinct interned symbols corresponding tobinding 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 reachableinterned 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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Added in version 8.2.0.7 of package base.
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 scopeof 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 ofsyntax-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Changed in version 6.3 of package base: Simplified to the minimal functionality needed for syntax-parameterizeand local-require.
Changed in version 6.3 of package base: changed to raise exn:fail:supported.
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 beingvisited, #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.
Returns #t during the dynamic extent of a syntax transformer application by the expander in a module-begin context and when the expansion is part of a compilation process where a compiled module can be returned directly. See also module.
Added in version 8.13.0.7 of package base.
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, usesyntax-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Added in version 6.3 of package base.
Changed in version 8.2.0.7: Added the optionalintdef-ctx argument.
Produces a syntax object that is like stx, except that the presence of scopes for the current expansion—both themacro-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 (seesyntax-transforming?), otherwise theexn:fail:contract exception is raised.
Example:
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 foras-use-site? creates a scope that is like a use-site scope; the difference is in how the scopes are treated bysyntax-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 samemake-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 optionalas-use-site? argument, and added the optional operation argument in the result procedure.
Like make-syntax-introducer, but the encapsulated scope is an interned scope. Multiple calls tomake-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-introducerand make-interned-syntax-introducer is analogous to the relationship betweengensym 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 withmake-interned-syntax-introducer is always treated like a use-site scope, not amacro-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.
Produces a procedure that behaves like the result ofmake-syntax-introducer, but using a set of scopes fromext-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 ofmake-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 ofmake-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 ofm-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 (seemake-provide-transformer) or while an expand sub-form of#%provide is expanded, #f otherwise.
Can be called only whilesyntax-local-transforming-module-provides? returns#t.
It returns a hash table mapping a phase-level number (such as0) to a list of all definitions at that phase levelwithin 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.
Can be called only whilesyntax-local-transforming-module-provides? returns#t.
It returns an association list mapping phase level andbinding space combinations to lists of identifiers. Each list of identifiers includes all bindings imported (into the module being expanded) using the module pathmod-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. Useidentifier-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 theprop: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 oflocal-expand. Such a value indicates that the context supports liberal expansion of define forms into potentially multiple define-values anddefine-syntaxes forms. The 'module and'module-body contexts implicitly allow liberal expansion.
The liberal-define-context? predicate returns #t ifv is an instance of a structure with a true value for theprop: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 theprop:require-transformer property implements a derivedrequire-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 ofimport-sources.
If the derived form contains a sub-form that is arequire-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-stylerequire transformers.
Expands the given require-spec to lists of imports and import sources. The latter specifies modules to beinstantiated 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 orvisited even if all of imports are eventually filtered from the former list).
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)) > (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.
Returns #t if v has theprop:require-transformer property, #f otherwise.
A structure representing a single imported identifier:
- local-id — the identifier to be bound within the importing module, but without any space-specific scope implied by mode.
- 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 and binding space of the binding in the importing module, which must be the same as (phase+space+ orig-mode req-mode).
- req-mode — the phase level shift andbinding space shift of the import relative to the exporting module.
- orig-mode — the phase level and binding space of the binding as exported by the exporting module.
- orig-stx — a syntax object for the source of the import, used for error reporting.
Changed in version 8.2.0.3 of package base: Generalized modes to phase–space combinations.
A structure representing an imported module, which must beinstantiated 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 andbinding space shift of the import.
Changed in version 8.2.0.3 of package base: Generalized mode to phase–space combinations.
A parameter that determines how relative require-level module paths are expanded to #%require-level module paths byconvert-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 therequire context determines the resolution of the module path.
The require form parameterizescurrent-require-module-path as #f while invoking sub-form transformers, while relative-in parameterizes to a given module path.
(convert-relative-module-path module-path)
Converts module-path according to current-require-module-path.
If module-path is not relative or if the value ofcurrent-require-module-path is #f, thenmodule-path is returned. Otherwise, module-path is converted to an absolute module path that is equivalent tomodule-path relative to the value ofcurrent-require-module-path.
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 (seesyntax-transforming?), otherwise theexn: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.
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 theprop:provide-transformer property implements a derivedprovide-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 theprop:provide-pre-transformer property implements a derivedprovide-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 aprovide 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 enclosingprovide-specs. The result of a provide transformermust be a list of exports, while the result of aprovide pre-transformer is a syntax object to be used as aprovide-spec in the last phase of module expansion.
If a derived form contains a sub-form that is aprovide-spec, then it can call expand-export orpre-expand-export to transform the sub-provide-specsub-form.
See also define-provide-syntax, which supports macro-styleprovide transformers.
Expands the given provide-spec to a list of exports. Themodes list controls the expansion of sub-provide-specs; for example, an identifier refers to a binding in the phase level of the enclosing provideform, 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.
Expands the given provide-spec at the level of provide pre-transformers. The modes argument is the same as forexpand-export.
Changed in version 8.2.0.3 of package base: Generalized modes to phase–space combinations.
Creates a provide transformer (i.e., a structure with theprop:provide-transformer property) using the given procedure as the transformer. If a pre-proc is provided, then the result is also aprovide pre-transformer. Often used in combination with expand-export and/orpre-expand-export.
Like make-provide-transformer, but for a value that is aprovide pre-transformer, only. Often used in combination with pre-expand-export.
Examples:
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.
Returns #t if v has theprop:provide-transformer property, #f otherwise.
Returns #t if v has theprop:provide-pre-transformer property, #f otherwise.
A structure representing a single exported identifier:
- local-id — the identifier that is bound within the exporting module.
- out-id — the external name of the binding.
- mode — the phase level and binding space of the export (which affects how it is imported).
- 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.
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, themake-export constructor also accepts a symbol, and aexport-out-sym function returns the syntax-evalue of the out-id.
This function is intended for backward compatibility. Useexport-out-id directly, instead.
Added in version 8.9.0.5 of package base.
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.
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 bymake-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.
Returns #t if v is a value created bymake-portal-syntax, #f otherwise.
Added in version 8.3.0.8 of package base.
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 viaidentifier-binding-portal-syntax.
Added in version 8.3.0.8 of package base.
Returns the content of portal syntax created withmake-portal-syntax.
Added in version 8.3.0.8 of package base.