syntax/parse: allow pattern expanders to produce EH patterns
fixes #1427
This commit is contained in:
parent
a5f0e6dcfc
commit
471f37158a
|
@ -4,7 +4,7 @@
|
||||||
syntax/parse/debug
|
syntax/parse/debug
|
||||||
syntax/parse/define
|
syntax/parse/define
|
||||||
"setup.rkt"
|
"setup.rkt"
|
||||||
(for-syntax syntax/parse))
|
(for-syntax syntax/parse racket/syntax))
|
||||||
|
|
||||||
;; Main syntax class and pattern tests
|
;; Main syntax class and pattern tests
|
||||||
|
|
||||||
|
@ -620,6 +620,21 @@
|
||||||
(+ x y z))))
|
(+ x y z))))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
(test-case "eh pattern-expander"
|
||||||
|
(define-syntax ~oncekw
|
||||||
|
(pattern-expander
|
||||||
|
(λ (stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ kw pat ...)
|
||||||
|
(keyword? (syntax-e #'kw))
|
||||||
|
(with-syntax ([name (format-id #'kw "~a-kw" (keyword->string (syntax-e #'kw)))])
|
||||||
|
#'(~once (~seq (~and kw name) pat ...)
|
||||||
|
#:name (format "the ~a keyword" 'kw)))]))))
|
||||||
|
(check-equal? (syntax-parse #'(m #:a #:b 1 #:a)
|
||||||
|
[(_ (~or #:a (~oncekw #:b b)) ...)
|
||||||
|
(syntax->datum #'(b-kw b))])
|
||||||
|
'(#:b 1)))
|
||||||
|
|
||||||
(test-case "this-syntax"
|
(test-case "this-syntax"
|
||||||
(let ()
|
(let ()
|
||||||
(define-syntax-class identity
|
(define-syntax-class identity
|
||||||
|
|
|
@ -459,26 +459,14 @@
|
||||||
(and (identifier? #'id)
|
(and (identifier? #'id)
|
||||||
(not-shadowed? #'id)
|
(not-shadowed? #'id)
|
||||||
(pattern-expander? (syntax-local-value #'id (λ () #f))))
|
(pattern-expander? (syntax-local-value #'id (λ () #f))))
|
||||||
(let* ([proc (pattern-expander-proc (syntax-local-value #'id))]
|
(begin (disappeared! #'id)
|
||||||
[introducer (make-syntax-introducer)]
|
(recur (expand-pattern (syntax-local-value #'id) stx)))]
|
||||||
[mstx (introducer (syntax-local-introduce stx))]
|
|
||||||
[mresult (parameterize ([current-syntax-parse-pattern-introducer introducer])
|
|
||||||
(proc mstx))]
|
|
||||||
[result (syntax-local-introduce (introducer mresult))])
|
|
||||||
(disappeared! #'id)
|
|
||||||
(recur result))]
|
|
||||||
[(id . rst)
|
[(id . rst)
|
||||||
(and (identifier? #'id)
|
(and (identifier? #'id)
|
||||||
(not-shadowed? #'id)
|
(not-shadowed? #'id)
|
||||||
(pattern-expander? (syntax-local-value #'id (λ () #f))))
|
(pattern-expander? (syntax-local-value #'id (λ () #f))))
|
||||||
(let* ([proc (pattern-expander-proc (syntax-local-value #'id))]
|
(begin (disappeared! #'id)
|
||||||
[introducer (make-syntax-introducer)]
|
(recur (expand-pattern (syntax-local-value #'id) stx)))]
|
||||||
[mstx (introducer (syntax-local-introduce stx))]
|
|
||||||
[mresult (parameterize ([current-syntax-parse-pattern-introducer introducer])
|
|
||||||
(proc mstx))]
|
|
||||||
[result (syntax-local-introduce (introducer mresult))])
|
|
||||||
(disappeared! #'id)
|
|
||||||
(recur result))]
|
|
||||||
[wildcard
|
[wildcard
|
||||||
(and (wildcard? #'wildcard)
|
(and (wildcard? #'wildcard)
|
||||||
(not-shadowed? #'wildcard))
|
(not-shadowed? #'wildcard))
|
||||||
|
@ -608,6 +596,16 @@
|
||||||
(let ([lp (parse-single-pattern (datum->syntax #f contents #'s) decls)])
|
(let ([lp (parse-single-pattern (datum->syntax #f contents #'s) decls)])
|
||||||
(pat:pstruct key lp)))])))
|
(pat:pstruct key lp)))])))
|
||||||
|
|
||||||
|
;; expand-pattern : pattern-expander Syntax -> Syntax
|
||||||
|
(define (expand-pattern pe stx)
|
||||||
|
(let* ([proc (pattern-expander-proc pe)]
|
||||||
|
[introducer (make-syntax-introducer)]
|
||||||
|
[mstx (introducer (syntax-local-introduce stx))]
|
||||||
|
[mresult (parameterize ([current-syntax-parse-pattern-introducer introducer])
|
||||||
|
(proc mstx))]
|
||||||
|
[result (syntax-local-introduce (introducer mresult))])
|
||||||
|
result))
|
||||||
|
|
||||||
;; parse-ellipsis-head-pattern : stx DeclEnv -> (listof EllipsisHeadPattern)
|
;; parse-ellipsis-head-pattern : stx DeclEnv -> (listof EllipsisHeadPattern)
|
||||||
(define (parse-ellipsis-head-pattern stx decls)
|
(define (parse-ellipsis-head-pattern stx decls)
|
||||||
(for/list ([ehpat+hstx (in-list (parse*-ellipsis-head-pattern stx decls #t))])
|
(for/list ([ehpat+hstx (in-list (parse*-ellipsis-head-pattern stx decls #t))])
|
||||||
|
@ -617,8 +615,22 @@
|
||||||
;; -> (listof (list EllipsisHeadPattern stx/eh-alternative))
|
;; -> (listof (list EllipsisHeadPattern stx/eh-alternative))
|
||||||
(define (parse*-ellipsis-head-pattern stx decls allow-or?
|
(define (parse*-ellipsis-head-pattern stx decls allow-or?
|
||||||
#:context [ctx (current-syntax-context)])
|
#:context [ctx (current-syntax-context)])
|
||||||
|
(define (recur stx) (parse*-ellipsis-head-pattern stx decls allow-or? #:context ctx))
|
||||||
|
(define not-shadowed? (make-not-shadowed? decls))
|
||||||
(syntax-case* stx (~eh-var ~or ~between ~optional ~once)
|
(syntax-case* stx (~eh-var ~or ~between ~optional ~once)
|
||||||
(make-not-shadowed-id=? decls)
|
(make-not-shadowed-id=? decls)
|
||||||
|
[id
|
||||||
|
(and (identifier? #'id)
|
||||||
|
(not-shadowed? #'id)
|
||||||
|
(pattern-expander? (syntax-local-value #'id (lambda () #f))))
|
||||||
|
(begin (disappeared! #'id)
|
||||||
|
(recur (expand-pattern (syntax-local-value #'id) stx)))]
|
||||||
|
[(id . rst)
|
||||||
|
(and (identifier? #'id)
|
||||||
|
(not-shadowed? #'id)
|
||||||
|
(pattern-expander? (syntax-local-value #'id (lambda () #f))))
|
||||||
|
(begin (disappeared! #'id)
|
||||||
|
(recur (expand-pattern (syntax-local-value #'id) stx)))]
|
||||||
[(~eh-var name eh-alt-set-id)
|
[(~eh-var name eh-alt-set-id)
|
||||||
(disappeared! stx)
|
(disappeared! stx)
|
||||||
(let ()
|
(let ()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user