added make-variable-like-transformer
This commit is contained in:
parent
26a57f6420
commit
f5b86c1ddd
|
@ -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
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
@;{----}
|
||||
|
||||
|
|
|
@ -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))]))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user