Add prop:match-expander' and
prop:legacy-match-expander'.
This commit is contained in:
parent
81dd112f57
commit
591dcc4a27
|
@ -6,14 +6,17 @@
|
||||||
(only-in "match-expander.rkt"
|
(only-in "match-expander.rkt"
|
||||||
define-match-expander)
|
define-match-expander)
|
||||||
"define-forms.rkt"
|
"define-forms.rkt"
|
||||||
"struct.rkt"
|
"struct.rkt"
|
||||||
(for-syntax "parse.rkt"
|
(for-syntax "parse.rkt"
|
||||||
(only-in "patterns.rkt" match-...-nesting)))
|
(only-in "patterns.rkt"
|
||||||
|
match-...-nesting
|
||||||
|
prop:match-expander prop:legacy-match-expander)))
|
||||||
|
|
||||||
(provide (for-syntax match-...-nesting)
|
(provide (for-syntax match-...-nesting
|
||||||
|
prop:match-expander prop:legacy-match-expander)
|
||||||
match-equality-test
|
match-equality-test
|
||||||
define-match-expander
|
define-match-expander
|
||||||
struct* ==
|
struct* ==
|
||||||
exn:misc:match?)
|
exn:misc:match?)
|
||||||
|
|
||||||
(define-forms parse
|
(define-forms parse
|
||||||
|
|
|
@ -138,13 +138,16 @@
|
||||||
error-msg)
|
error-msg)
|
||||||
(let* ([expander* (syntax-local-value expander)]
|
(let* ([expander* (syntax-local-value expander)]
|
||||||
[transformer (accessor expander*)]
|
[transformer (accessor expander*)]
|
||||||
|
;; this transformer might have been defined w/ `syntax-id-rules'
|
||||||
[transformer (if (set!-transformer? transformer)
|
[transformer (if (set!-transformer? transformer)
|
||||||
(set!-transformer-procedure transformer)
|
(set!-transformer-procedure transformer)
|
||||||
transformer)])
|
transformer)])
|
||||||
(unless transformer (raise-syntax-error #f error-msg expander*))
|
(unless transformer (raise-syntax-error #f error-msg expander*))
|
||||||
(let* ([introducer (make-syntax-introducer)]
|
(let* ([introducer (make-syntax-introducer)]
|
||||||
[mstx (introducer (syntax-local-introduce stx))]
|
[mstx (introducer (syntax-local-introduce stx))]
|
||||||
[mresult (transformer mstx)]
|
[mresult (if (procedure-arity-includes? transformer 2)
|
||||||
|
(transformer expander* mstx)
|
||||||
|
(transformer mstx))]
|
||||||
[result (syntax-local-introduce (introducer mresult))])
|
[result (syntax-local-introduce (introducer mresult))])
|
||||||
;(emit-local-step stx result #:id expander)
|
;(emit-local-step stx result #:id expander)
|
||||||
(parse result))))
|
(parse result))))
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
(lambda (x y) (eq? (syntax-e x) (syntax-e y)))
|
(lambda (x y) (eq? (syntax-e x) (syntax-e y)))
|
||||||
[(expander args ...)
|
[(expander args ...)
|
||||||
(and (identifier? #'expander)
|
(and (identifier? #'expander)
|
||||||
(match-expander?
|
(legacy-match-expander?
|
||||||
(syntax-local-value #'expander (lambda () #f))))
|
(syntax-local-value #'expander (λ () #f))))
|
||||||
(match-expander-transform
|
(match-expander-transform
|
||||||
parse #'expander disarmed-stx match-expander-legacy-xform
|
parse #'expander disarmed-stx legacy-match-expander-proc
|
||||||
"This expander only works with the standard match syntax")]
|
"This expander only works with the standard match syntax")]
|
||||||
[(and p ...)
|
[(and p ...)
|
||||||
(make-And (map parse (syntax->list #'(p ...))))]
|
(make-And (map parse (syntax->list #'(p ...))))]
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
(match-expander? (syntax-local-value #'expander
|
(match-expander? (syntax-local-value #'expander
|
||||||
(lambda () #f))))
|
(lambda () #f))))
|
||||||
(match-expander-transform
|
(match-expander-transform
|
||||||
rearm+parse #'expander disarmed-stx match-expander-match-xform
|
rearm+parse #'expander disarmed-stx match-expander-proc
|
||||||
"This expander only works with the legacy match syntax")]
|
"This expander only works with the legacy match syntax")]
|
||||||
[(var v)
|
[(var v)
|
||||||
(identifier? #'v)
|
(identifier? #'v)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#lang scheme/base
|
#lang racket/base
|
||||||
|
|
||||||
(require syntax/boundmap
|
(require syntax/boundmap
|
||||||
scheme/contract
|
racket/contract
|
||||||
(for-syntax scheme/base))
|
(for-syntax racket/base))
|
||||||
|
|
||||||
(provide (except-out (all-defined-out)
|
(provide (except-out (all-defined-out)
|
||||||
struct-key-ht
|
struct-key-ht
|
||||||
|
@ -208,20 +208,45 @@
|
||||||
[vars-seen (listof (cons/c identifier?
|
[vars-seen (listof (cons/c identifier?
|
||||||
identifier?))])))
|
identifier?))])))
|
||||||
|
|
||||||
(define-struct match-expander (match-xform legacy-xform macro-xform)
|
|
||||||
#| #:property prop:procedure (lambda (me stx)
|
|
||||||
(define xf (match-expander-macro-xform me))
|
|
||||||
(define xf* (if (set!-transformer? xf)
|
|
||||||
(set!-transformer-procedure xf)
|
|
||||||
xf))
|
|
||||||
(xf* stx))|#
|
|
||||||
#:property prop:set!-transformer (lambda (me stx)
|
|
||||||
(define xf (match-expander-macro-xform me))
|
|
||||||
(if (set!-transformer? xf)
|
|
||||||
((set!-transformer-procedure xf) stx)
|
|
||||||
(syntax-case stx (set!)
|
|
||||||
[(set! . _)
|
|
||||||
(raise-syntax-error #f "cannot mutate syntax identifier" stx)]
|
|
||||||
[_ (xf stx)]))))
|
|
||||||
|
|
||||||
(provide (struct-out match-expander))
|
(struct acc-prop (n acc))
|
||||||
|
(define (make-struct-type-property/accessor name [guard #f] [supers null])
|
||||||
|
(define-values (p pred? acc)
|
||||||
|
(make-struct-type-property name
|
||||||
|
(λ (pval sinfo)
|
||||||
|
(cond [(exact-nonnegative-integer? pval)
|
||||||
|
(acc-prop pval (cadddr sinfo))]
|
||||||
|
[else (if (procedure? guard)
|
||||||
|
(guard pval sinfo)
|
||||||
|
pval)]))
|
||||||
|
supers))
|
||||||
|
(values p pred? (lambda (v)
|
||||||
|
(define v* (acc v))
|
||||||
|
(if (acc-prop? v*)
|
||||||
|
((acc-prop-acc v*) v (acc-prop-n v*))
|
||||||
|
v*))))
|
||||||
|
|
||||||
|
(define-values (prop:match-expander match-expander? match-expander-proc)
|
||||||
|
(make-struct-type-property/accessor 'prop:match-expander))
|
||||||
|
|
||||||
|
(define-values (prop:legacy-match-expander legacy-match-expander? legacy-match-expander-proc)
|
||||||
|
(make-struct-type-property/accessor 'prop:legacy-match-expander ))
|
||||||
|
|
||||||
|
(define make-match-expander
|
||||||
|
(let ()
|
||||||
|
(define-struct match-expander (match-xform legacy-xform macro-xform)
|
||||||
|
#:property prop:set!-transformer (lambda (me stx)
|
||||||
|
(define xf (match-expander-macro-xform me))
|
||||||
|
(if (set!-transformer? xf)
|
||||||
|
((set!-transformer-procedure xf) stx)
|
||||||
|
(syntax-case stx (set!)
|
||||||
|
[(set! . _)
|
||||||
|
(raise-syntax-error #f "cannot mutate syntax identifier" stx)]
|
||||||
|
[_ (xf stx)])))
|
||||||
|
#:property prop:match-expander (struct-field-index match-xform)
|
||||||
|
#:property prop:legacy-match-expander (struct-field-index legacy-xform))
|
||||||
|
(values make-match-expander)))
|
||||||
|
|
||||||
|
(provide match-expander? legacy-match-expander?
|
||||||
|
match-expander-proc legacy-match-expander-proc
|
||||||
|
prop:match-expander prop:legacy-match-expander)
|
||||||
|
|
|
@ -525,6 +525,35 @@ For example, to extend the pattern matcher and destructure syntax lists,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defthing[prop:match-expander struct-type-property?]{
|
||||||
|
|
||||||
|
A @tech{structure type property} to identify structure types that act
|
||||||
|
as @tech{match expanders} like the ones created by
|
||||||
|
@racket[define-match-expander].
|
||||||
|
|
||||||
|
The property value must be an exact non-negative integer or a
|
||||||
|
procedure of one or two arguments. In the former case, the integer
|
||||||
|
designates a field within the structure that should contain a
|
||||||
|
procedure; the integer must be between @racket[0] (inclusive) and the
|
||||||
|
number of non-automatic fields in the structure type (exclusive, not
|
||||||
|
counting supertype fields), and the designated field must also be
|
||||||
|
specified as immutable.
|
||||||
|
|
||||||
|
If the property value is a procedure of one argument, then the
|
||||||
|
procedure serves as the transformer for match expansion. If the property value is a procedure of two
|
||||||
|
arguments, then the first argument is the structure whose type has
|
||||||
|
@racket[prop:match-expander] property, and the second argument is a
|
||||||
|
syntax object as for a @tech{match expander}..
|
||||||
|
|
||||||
|
If the property value is a @tech{assignment transformer}, then the wrapped
|
||||||
|
procedure is extracted with
|
||||||
|
@racket[set!-transformer-procedure] before it is called.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defthing[prop:legacy-match-expander struct-type-property?]{
|
||||||
|
Like @racket[prop:match-expander], but for the legacy match syntax.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@defparam[match-equality-test comp-proc (any/c any/c . -> . any)]{
|
@defparam[match-equality-test comp-proc (any/c any/c . -> . any)]{
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user