3.2.1 mischief/transform: Syntax Transformers
(require mischief/transform) | package: mischief-dev |
3.2.1.1 Converting Values to/from Syntax
procedure
(to-syntax x [ #:stx stx #:context context #:source source #:prop prop]) → syntax? x : any/c stx : (or/c syntax? #false) = #false context : (or/c syntax? #false) = stx source : source-location? = stx prop : (or/c syntax? #false) = stx
> (define stx (to-syntax 'car #:stx #'here)) > stx #<syntax:1:0 car>
> (build-source-location stx) (srcloc 'eval 1 0 1 1)
> (free-identifier=? stx #'car) #t
procedure
(quote-transformer x) → syntax?
x : any/c
> (to-datum (quote-transformer (list '(1 2) #'(3 4)))) '`((1 2) ,(quote-syntax (3 4)))
3.2.1.2 Constructing Identifiers
procedure
(fresh [ x #:source source #:add-suffix? add-suffix?]) → identifier?
x : (or/c symbol? string? identifier? keyword? char? number?) = 'fresh source : source-location? = (if (identifier? x) x #false) add-suffix? : boolean? = #true
> (fresh) sym: undefined;
cannot use before initialization
> (fresh) sym: undefined;
cannot use before initialization
> (define x #'x) > (define fresh-x (fresh x #:add-suffix? #false)) > x #<syntax:9:0 x>
> fresh-x #<syntax:9:0 x>
> (free-identifier=? x fresh-x) #f
procedure
(format-fresh fmt arg ... [ #:source source #:add-suffix? add-suffix?]) → identifier? fmt : string? arg : (or/c symbol? string? identifier? keyword? char? number?) source : source-location? = #false add-suffix? : boolean? = #true
(fresh (format-symbol fmt arg ...) #:source source #:add-suffix? add-suffix?)
> (format-fresh "~a-~a" #'string #'length) sym: undefined;
cannot use before initialization
procedure
(fresh-mark) → (-> syntax? syntax?)
> (define id1 (fresh)) sym: undefined;
cannot use before initialization
> (define mark (fresh-mark)) > (define id2 (mark id1)) id1: undefined;
cannot reference an identifier before its definition
in module: 'program
> (define id3 (mark id2)) id2: undefined;
cannot reference an identifier before its definition
in module: 'program
> (bound-identifier=? id1 id2) id1: undefined;
cannot reference an identifier before its definition
in module: 'program
> (bound-identifier=? id2 id3) id2: undefined;
cannot reference an identifier before its definition
in module: 'program
> (bound-identifier=? id1 id3) id1: undefined;
cannot reference an identifier before its definition
in module: 'program
procedure
(identifier-upcase id) → identifier?
id : identifier?
procedure
(identifier-downcase id) → identifier?
id : identifier?
procedure
(identifier-titlecase id) → identifier?
id : identifier?
procedure
(identifier-foldcase id) → identifier?
id : identifier?
> (identifier-upcase #'Two-words) #<syntax:22:0 TWO-WORDS>
> (identifier-downcase #'Two-words) #<syntax:23:0 two-words>
> (identifier-titlecase #'Two-words) #<syntax:24:0 Two-Words>
> (identifier-foldcase #'Two-words) #<syntax:25:0 two-words>
3.2.1.3 Common Syntax Transformer Patterns
procedure
(id-transform original replace) → syntax?
original : syntax? replace : (or/c syntax? (-> identifier? syntax?))
> (id-transform #'simple-identifier #'replacement) #<syntax:26:0 replacement>
> (id-transform #'(simple macro application) #'replacement) #<syntax:27:0 (#%app replacement macro appl...>
> (id-transform #'(set! macro application) #'replacement) #<syntax:28:0 (set! replacement application)>
procedure
(id-transformer proc)
→ (and/c set!-transformer? (-> syntax? syntax?)) proc : (-> identifier? syntax?)
> (define x 1) > (define-syntax X (id-transformer identifier-downcase)) > (set! X (add1 X)) > X 2
procedure
(set!-transformer proc)
→ (and/c set!-transformer? (-> syntax? syntax?)) proc : (-> syntax? syntax?)
> (define-for-syntax f (set!-transformer (lambda {x} #'(error 'undefined "Oh, no!")))) > (define-syntax (x stx) (f stx)) > x undefined: Oh, no!
> (x 1) undefined: Oh, no!
> (set! x 1) eval:37:0: set!: cannot mutate syntax identifier
at: x
in: (set! x 1)
> (define-syntax y f) > y undefined: Oh, no!
> (y 1) undefined: Oh, no!
> (set! y 1) undefined: Oh, no!
procedure
(rename-transformer id)
→ (and/c (-> syntax? syntax?) rename-transformer?) id : identifier?
procedure
(rename-transformers id ...)
→
(and/c (-> syntax? syntax?) rename-transformer?) ... id : identifier?
> (define-syntaxes {pair left right} (rename-transformers #'cons #'car #'cdr)) > (pair (left '(1 2)) (right '(3 4))) '(1 4)
> (define-syntax (tuple stx) ((rename-transformer #'list) stx)) > tuple #<procedure:list>
> (tuple 1 2 3) '(1 2 3)
3.2.1.4 Phase 1 Helpers
procedure
(syntax-error stx fmt x ...) → none/c
stx : syntax? fmt : string? x : any/c
procedure
> (module var-ref-example racket (require (for-syntax mischief/transform)) (define-syntax (macro stx) (printf "Transforming: ~s\n" (resolved-module-path-name (variable-reference->resolved-module-path (syntax-local-variable-reference)))) #'(begin)) (macro)) Transforming: var-ref-example
> (require 'var-ref-example)
procedure
(check-missing-identifier actual expected)
→ (or/c identifier? #false) actual : (listof identifier?) expected : (listof identifier?)