Generic Syntax Expanders
(require generic-syntax-expanders) | |
package: generic-syntax-expanders |
This library provides forms to define generic syntax expanders. These are essentially macros that have no meaning on their own, but other macros can be told to expand all generic syntax expanders of some type in some portion of their body before themselves expanding. This is similar to how Racket’s built in match form has match expanders, which allows the grammar of the match form to be extended with custom match expanders using define-match-expander. This library generalizes the concept, making complex macros more composable and extensible.
Source code can be found at https://github.com/jackfirth/generic-syntax-expanders
1 Expanders And Transformers
(require generic-syntax-expanders/expanders) | |
package: generic-syntax-expanders |
Generic expanders are implemented as values of the expander? struct bound with define-syntax, that store both a type and a transformer procedure. Future versions of this library may support storing an additional transformer for use outside expander-contexts in normal syntax parsing. This could be used for better error messages, or for an expander meant to have meaning in both a particularly typed expansion context and a normal expression expansion context.
struct
(struct expander (type transformer) #:extra-constructor-name make-expander) type : expander-type? transformer : (-> syntax? syntax?)
procedure
(expander-of-type? type expander) → boolean?
type : expander-type? expander : expander?
Examples: | ||||||||
|
procedure
(expand-stx-tree-with-expanders-of-type type syntax) → syntax? type : expander-type? syntax : syntax?
2 Expander Types
(require generic-syntax-expanders/expander-types) | |
package: generic-syntax-expanders |
Under the hood, each generic expander defined with this library has an associated expander type. Syntax transformers built with this library examine this type to determine whether or not they should expand them.
predicate
expander-type? : predicate/c
Examples: | ||||
|
procedure
Example: | ||
|
procedure
(make-union-expander-type type ...+) → expander-type?
type : expander-type?
Example: | ||
|
procedure
(expander-type-includes? type-1 type-2) → boolean?
type-1 : expander-type? type-2 : expander-type?
Examples: | |||||||||||||||||||||||||
|
3 Defining Generic Syntax Expanders
(require generic-syntax-expanders/define-expanders) | |
package: generic-syntax-expanders |
This module provides a high-level API for creating generic expanders for use with other macros.
syntax
(define-expander-type id)
id-expander-type - a new unique expander-type? bound at phase level 1
make-id-expander - a procedure bound at phase level 1 that accepts a transformer procedure and returns an expander? with id-expander-type
id-expander? - a predicate bound at phase level 1 recognizing expanders produced by make-id-expander
define-id-expander? - a syntactic form at phase level 0 that takes an identifier and a transformer procedure and binds the identifier as a id-expander? for use in a transformer environment
expand-all-id-expanders - a procedure bound at phase level 1 that’s equivalent to expand-all-expanders-of-type with the id-expander-type as the type argument
4 Lens Scoped Syntax Transformers
(require generic-syntax-expanders/scoped-transformers) | |
package: generic-syntax-expanders |
This module uses the lens package to create syntax transformers that affect only some small subpiece of a syntax object and compose them with other transformers. This allows for the creation of a macro that cedes control to other macros to pre-expand parts of its body before the macro expands. Combined with the syntax transformer produced by define-expander-type, this makes it easy to define a macro that expands all instances of a generic expander type in a specific subpiece of its body, turning it into an extensible macro.
procedure
((with-scoped-pre-transformer transformer stx-lens pre-transformer) stx) → syntax? transformer : (-> syntax? syntax?) stx-lens : lens? pre-transformer : (-> syntax? syntax?) stx : syntax?
procedure
((with-scoped-pre-transformers transformer pre-transformer-lens-pairs) stx) → syntax? transformer : (-> syntax? syntax?)
pre-transformer-lens-pairs :
(listof (list/c lens? (-> syntax? syntax?))) stx : syntax?
5 Lens Scoped Syntax Transformers - Definition Form
(require generic-syntax-expanders/define-scoped-transformers) | |
package: generic-syntax-expanders |
Syntax definition forms built on with-scoped-pre-transformer and friends.
syntax
(define-syntax-with-scoped-pre-transformers id ([stx-lens pre-transformer] ...) transformer-expr)