added make-variable-like-transformer

This commit is contained in:
Ryan Culpepper 2012-08-19 14:38:30 -04:00
parent 26a57f6420
commit f5b86c1ddd
2 changed files with 54 additions and 2 deletions

View File

@ -43,6 +43,33 @@ phase level is 1.
]
}
@defproc[(make-variable-like-transformer [reference-stx syntax?]
[setter-stx (or/c syntax? #f) #f])
set!-transformer?]{
Creates a transformer that replaces references to the macro identifier
with @racket[reference-stx]. Uses of the macro in operator position
are interpreted as an application with @racket[reference-stx] as the
function and the arguments as given.
If the macro identifier is used as the target of a @racket[set!] form,
then the @racket[set!] form expands into the application of
@racket[setter-stx] to the @racket[set!] expression's right-hand side,
if @racket[setter-stx] is syntax; otherwise, the identifier is
considered immutable and a syntax error is raised.
@examples[#:eval the-eval
(define the-box (box add1))
(define-syntax op
(make-variable-like-transformer
#'(unbox the-box)
#'(lambda (v) (set-box! the-box v))))
(op 5)
(set! op 0)
op
]
}
@;{----}

View File

@ -2,7 +2,8 @@
;; owner: ryanc (and cce and stamourv, where noted)
(require racket/syntax
syntax/stx
(for-syntax racket/base))
(for-syntax racket/base)
(for-template racket/base))
(provide (rename-out [stx-map syntax-map])
@ -16,7 +17,8 @@
;; by ryanc
explode-module-path-index
phase-of-enclosing-module)
phase-of-enclosing-module
make-variable-like-transformer)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@ -78,3 +80,26 @@
(define-syntax-rule (phase-of-enclosing-module)
(variable-reference->module-base-phase
(#%variable-reference)))
(define (make-variable-like-transformer ref-stx [set!-handler #f])
(unless (syntax? ref-stx)
(raise-type-error 'make-variable-like-transformer "syntax?" ref-stx))
(unless (or (syntax? set!-handler) (procedure? set!-handler) (eq? set!-handler #f))
(raise-type-error 'make-variable-like-transformer "(or/c syntax? procedure? #f)" set!-handler))
(make-set!-transformer
(lambda (stx)
(syntax-case stx (set!)
[id
(identifier? #'id)
ref-stx]
[(set! id val)
(cond [(procedure? set!-handler)
(set!-handler stx)]
[(syntax? set!-handler)
(with-syntax ([setter set!-handler])
(syntax/loc stx (setter val)))]
[else
(raise-syntax-error #f "cannot mutate identifier" stx #'id)])]
[(id . args)
(let ([stx* (cons #'(#%expression id) (cdr (syntax-e stx)))])
(datum->syntax stx stx* stx))]))))