template.rkt (2326B)
1 #lang racket/base 2 (require (for-syntax racket/base 3 racket/struct 4 auto-syntax-e/utils) 5 (only-in racket/private/template 6 metafunction)) 7 (provide (rename-out [syntax template] 8 [syntax/loc template/loc] 9 [quasisyntax quasitemplate] 10 [quasisyntax/loc quasitemplate/loc] 11 [~? ??] 12 [~@ ?@]) 13 define-template-metafunction 14 syntax-local-template-metafunction-introduce) 15 16 ;; ============================================================ 17 ;; Metafunctions 18 19 ;; TODO: once PR https://github.com/racket/racket/pull/1591 is merged, use 20 ;; the exported prop:template-metafunction, template-metafunction? and 21 ;; template-metafunction-accessor. 22 (define-syntax (define-template-metafunction stx) 23 (syntax-case stx () 24 [(dsm (id arg ...) . body) 25 #'(dsm id (lambda (arg ...) . body))] 26 [(dsm id expr) 27 (identifier? #'id) 28 (with-syntax ([(internal-id) (generate-temporaries #'(id))]) 29 #'(begin (define internal-id (make-hygienic-metafunction expr)) 30 (define-syntax id (metafunction (quote-syntax internal-id)))))])) 31 32 (define current-template-metafunction-introducer 33 (make-parameter (lambda (stx) (if (syntax-transforming?) (syntax-local-introduce stx) stx)))) 34 35 36 (define old-template-metafunction-introducer 37 (make-parameter #f)) 38 39 (define (syntax-local-template-metafunction-introduce stx) 40 (let ([mark (current-template-metafunction-introducer)] 41 [old-mark (old-template-metafunction-introducer)]) 42 (unless old-mark 43 (error 'syntax-local-template-metafunction-introduce 44 "must be called within the dynamic extent of a template metafunction")) 45 (mark (old-mark stx)))) 46 47 (define ((make-hygienic-metafunction transformer) stx) 48 (define mark (make-syntax-introducer)) 49 (define old-mark (current-template-metafunction-introducer)) 50 (parameterize ((current-template-metafunction-introducer mark) 51 (old-template-metafunction-introducer old-mark)) 52 (define r (call-with-continuation-barrier (lambda () (transformer (mark (old-mark stx)))))) 53 (unless (syntax? r) 54 (raise-syntax-error #f "result of template metafunction was not syntax" stx)) 55 (old-mark (mark r))))