On this page:
5.1 Extracting Inferred Names
syntax-local-infer-name
5.2 Support for local-expand
build-expand-context
generate-expand-context
5.3 Parsing define-like Forms
normalize-definition
5.4 Flattening begin Forms
flatten-begin
5.5 Expanding define-struct-like Forms
parse-define-struct
build-struct-names
build-struct-generation
build-struct-generation*
build-struct-expand-info
struct-declaration-info?
generate-struct-declaration
5.6 Resolving include-like Paths
resolve-path-spec
5.7 Controlling Syntax Templates
transform-template

5 Macro Transformer Helpers

5.1 Extracting Inferred Names

 (require syntax/name)

(syntax-local-infer-name stx)  any/c
  stx : syntax?
Similar to syntax-local-name except that stx is checked for an 'inferred-name property (which overrides any inferred name). If neither syntax-local-name nor 'inferred-name produce a name, or if the 'inferred-name property value is #<void>, then a name is constructed from the source-location information in stx, if any. If no name can be constructed, the result is #f.

5.2 Support for local-expand

 (require syntax/context)

(build-expand-context v)  list?
  v : (or/c symbol? list?)
Returns a list suitable for use as a context argument to local-expand for an internal-definition context. The v argument represents the immediate context for expansion. The context list builds on (syntax-local-context) if it is a list.

Calls build-expand-context with a generated symbol.

5.3 Parsing define-like Forms

 (require syntax/define)

(normalize-definition defn-stx    
  lambda-id-stx    
  [check-context?    
  opt+kws?])  
identifier? syntax?
  defn-stx : syntax?
  lambda-id-stx : identifier?
  check-context? : boolean? = #t
  opt+kws? : boolean? = #t
Takes a definition form whose shape is like define (though possibly with a different name) and returns two values: the defined identifier and the right-hand side expression.

To generate the right-hand side, this function may need to insert uses of lambda. The lambda-id-stx argument provides a suitable lambda identifier.

If the definition is ill-formed, a syntax error is raised. If check-context? is true, then a syntax error is raised if (syntax-local-context) indicates that the current context is an expression context. The default value of check-context? is #t.

If opt-kws? is #t, then arguments of the form [id expr], keyword id, and keyword [id expr] are allowed, and they are preserved in the expansion.

5.4 Flattening begin Forms

 (require syntax/flatten-begin)

(flatten-begin stx)  (listof syntax?)
  stx : syntax?
Extracts the sub-expressions from a begin-like form, reporting an error if stx does not have the right shape (i.e., a syntax list). The resulting syntax objects have annotations transferred from stx using syntax-track-origin.

5.5 Expanding define-struct-like Forms

 (require syntax/struct)

(parse-define-struct stx orig-stx)  
identifier?
(or/c identifier? false/c)
(listof identifier?)
syntax?
  stx : syntax?
  orig-stx : syntax?
Parses stx as a define-struct form, but uses orig-stx to report syntax errors (under the assumption that orig-stx is the same as stx, or that they at least share sub-forms). The result is four values: an identifier for the struct type name, a identifier or #f for the super-name, a list of identifiers for fields, and a syntax object for the inspector expression.

(build-struct-names name-id 
  field-ids 
  [#:constructor-name ctr-name] 
  omit-sel? 
  omit-set? 
  [src-stx]) 
  (listof identifier?)
  name-id : identifier?
  field-ids : (listof identifier?)
  ctr-name : (or/c identifier? #f) = #f
  omit-sel? : boolean?
  omit-set? : boolean?
  src-stx : (or/c syntax? false/c) = #f
Generates the names bound by define-struct given an identifier for the struct type name and a list of identifiers for the field names. The result is a list of identifiers:

If omit-sel? is true, then the selector names are omitted from the result list. If omit-set? is true, then the setter names are omitted from the result list.

The default src-stx is #f; it is used to provide a source location to the generated identifiers.

(build-struct-generation name-id 
  field-ids 
  [#:constructor-name ctr-name] 
  omit-sel? 
  omit-set? 
  [super-type 
  prop-value-list 
  immutable-k-list]) 
  (listof identifier?)
  name-id : identifier?
  field-ids : (listof identifier?)
  ctr-name : (or/c identifier? #f) = #f
  omit-sel? : boolean?
  omit-set? : boolean?
  super-type : any/c = #f
  prop-value-list : list? = '(list)
  immutable-k-list : list? = '(list)
Takes the same arguments as build-struct-names and generates an S-expression for code using make-struct-type to generate the structure type and return values for the identifiers created by build-struct-names. The optional super-type, prop-value-list, and immutable-k-list parameters take S-expressions that are used as the corresponding argument expressions to make-struct-type.

(build-struct-generation* all-name-ids 
  name-id 
  field-ids 
  [#:constructor-name ctr-name] 
  omit-sel? 
  omit-set? 
  [super-type 
  prop-value-list 
  immutable-k-list]) 
  (listof identifier?)
  all-name-ids : (listof identifier?)
  name-id : identifier?
  field-ids : (listof identifier?)
  ctr-name : (or/c identifier? #f) = #f
  omit-sel? : boolean?
  omit-set? : boolean?
  super-type : any/c = #f
  prop-value-list : list? = '(list)
  immutable-k-list : list? = '(list)
Like build-struct-generation, but given the names produced by build-struct-names, instead of re-generating them.

(build-struct-expand-info name-id    
  field-ids    
  [#:omit-constructor? no-ctr?    
  #:constructor-name ctr-name    
  #:omit-struct-type? no-type?]    
  omit-sel?    
  omit-set?    
  base-name    
  base-getters    
  base-setters)  any
  name-id : identifier?
  field-ids : (listof identifier?)
  no-ctr? : any/c = #f
  ctr-name : (or/c identifier? #f) = #f
  no-type? : any/c = #f
  omit-sel? : boolean?
  omit-set? : boolean?
  base-name : (or/c identifier? boolean?)
  base-getters : (listof (or/c identifier? false/c))
  base-setters : (listof (or/c identifier? false/c))
Takes mostly the same arguments as build-struct-names, plus a parent identifier/#t/#f and a list of accessor and mutator identifiers (possibly ending in #f) for a parent type, and generates an S-expression for expansion-time code to be used in the binding for the structure name.

If no-ctr? is true, then the constructor name is omitted from the expansion-time information. Similarly, if no-type? is true, then the structure-type name is omitted.

A #t for the base-name means no super-type, #f means that the super-type (if any) is unknown, and an identifier indicates the super-type identifier.

Returns #t if x has the shape of expansion-time information for structure type declarations, #f otherwise. See Structure Type Transformer Binding.

(generate-struct-declaration orig-stx    
  name-id    
  super-id-or-false    
  field-id-list    
  current-context    
  make-make-struct-type    
  [omit-sel?    
  omit-set?])  syntax?
  orig-stx : syntax?
  name-id : identifier?
  super-id-or-false : (or/c identifier? false/c)
  field-id-list : (listof identifier?)
  current-context : any/c
  make-make-struct-type : procedure?
  omit-sel? : boolean? = #f
  omit-set? : boolean? = #f
This procedure implements the core of a define-struct expansion.

The generate-struct-declaration procedure is called by a macro expander to generate the expansion, where the name-id, super-id-or-false, and field-id-list arguments provide the main parameters. The current-context argument is normally the result of syntax-local-context. The orig-stx argument is used for syntax errors. The optional omit-sel? and omit-set? arguments default to #f; a #t value suppresses definitions of field selectors or mutators, respectively.

The make-struct-type procedure is called to generate the expression to actually create the struct type. Its arguments are orig-stx, name-id-stx, defined-name-stxes, and super-info. The first two are as provided originally to generate-struct-declaration, the third is the set of names generated by build-struct-names, and the last is super-struct info obtained by resolving super-id-or-false when it is not #f, #f otherwise.

The result should be an expression whose values are the same as the result of make-struct-type. Thus, the following is a basic make-make-struct-type:

(lambda (orig-stx name-stx defined-name-stxes super-info)
  #`(make-struct-type '#,name-stx
                       #,(and super-info (list-ref super-info 0))
                       #,(/ (- (length defined-name-stxes) 3) 2)
                       0 #f))

but an actual make-make-struct-type will likely do more.

5.6 Resolving include-like Paths

 (require syntax/path-spec)

(resolve-path-spec path-spec-stx    
  source-stx    
  expr-stx    
  build-path-stx)  complete-path?
  path-spec-stx : syntax?
  source-stx : syntax?
  expr-stx : syntax?
  build-path-stx : syntax?
Resolves the syntactic path specification path-spec-stx as for include.

The source-stx specifies a syntax object whose source-location information determines relative-path resolution. The expr-stx is used for reporting syntax errors. The build-path-stx is usually #'build-path; it provides an identifier to compare to parts of path-spec-stx to recognize the build-path keyword.

5.7 Controlling Syntax Templates

 (require syntax/template)

(transform-template template-stx 
  #:save save-proc 
  #:restore-stx restore-proc-stx 
  [#:leaf-save leaf-save-proc 
  #:leaf-restore-stx leaf-restore-proc-stx 
  #:leaf-datum-stx leaf-datum-proc-stx 
  #:pvar-save pvar-save-proc 
  #:pvar-restore-stx pvar-restore-stx 
  #:cons-stx cons-proc-stx 
  #:ellipses-end-stx ellipses-end-stx 
  #:constant-as-leaf? constant-as-leaf?]) 
  syntax?
  template-stx : syntax?
  save-proc : (syntax? . -> . any/c)
  restore-proc-stx : syntax?
  leaf-save-proc : (syntax? . -> . any/c) = save-proc
  leaf-restore-proc-stx : syntax? = #'(lambda (data stx) stx)
  leaf-datum-proc-stx : syntax? = #'(lambda (v) v)
  pvar-save-proc : (identifier? . -> . any/c) = (lambda (x) #f)
  pvar-restore-stx : syntax? = #'(lambda (d stx) stx)
  cons-proc-stx : syntax? = cons
  ellipses-end-stx : syntax? = #'values
  constant-as-leaf? : boolean? = #f
Produces an representation of an expression similar to #`(syntax #,template-stx), but functions like save-proc can collect information that might otherwise be lost by syntax (such as properties when the syntax object is marshaled within bytecode), and run-time functions like the one specified by restore-proc-stx can use the saved information or otherwise process the syntax object that is generated by the template.

The save-proc is applied to each syntax object in the representation of the original template (i.e., in template-stx). If constant-as-leaf? is #t, then save-proc is applied only to syntax objects that contain at least one pattern variable in a sub-form. The result of save-proc is provided back as the first argument to restore-proc-stx, which indicates a function with a contract (-> any/c syntax any/c any/c); the second argument to restore-proc-stx is the syntax object that syntax generates, and the last argument is a datum that have been processed recursively (by functions such as restore-proc-stx) and that normally would be converted back to a syntax object using the second argument’s context, source, and properties. Note that save-proc works at expansion time (with respect to the template form), while restore-proc-stx indicates a function that is called at run time (for the template form), and the data that flows from save-proc to restore-proc-stx crosses phases via quote.

The leaf-save-proc and leaf-restore-proc-stx procedures are analogous to save-proc and restore-proc-stx, but they are applied to leaves, so there is no third argument for recursively processed sub-forms. The function indicated by leaf-restore-proc-stx should have the contract (-> any/c syntax? any/c).

The leaf-datum-proc-stx procedure is applied to leaves that are not syntax objects, which can happen because pairs and the empty list are not always individually wrapped as syntax objects. The function should have the contract (-> any/c any/c). When constant-as-leaf? is #f, the only possible argument to the procedure is null.

The pvar-save and pvar-restore-stx procedures are analogous to save-proc and restore-proc-stx, but they are applied to pattern variables. The pvar-restore-stx procedure should have the contract (-> any/c syntax? any/c), where the second argument corresponds to the substitution of the pattern variable.

The cons-proc-stx procedure is used to build intermediate pairs, including pairs passed to restore-proc-stx and pairs that do not correspond to syntax objects.

The ellipses-end-stx procedure is an extra filter on the syntax object that follows a sequence of ... ellipses in the template. The procedure should have the contract (-> any/c any/c).

The following example illustrates a use of transform-template to implement a syntax/shape form that preserves the 'paren-shape property from the original template, even if the template code is marshaled within bytecode.

(define-for-syntax (get-shape-prop stx)
  (syntax-property stx 'paren-shape))
 
(define (add-shape-prop v stx datum)
  (syntax-property (datum->syntax stx datum stx stx stx)
                   'paren-shape
                   v))
 
(define-syntax (syntax/shape stx)
  (syntax-case stx ()
    [(_ tmpl)
     (transform-template #'tmpl
                         #:save get-shape-prop
                         #:restore-stx #'add-shape-prop)]))