Refactors to eliminate copied code
This commit is contained in:
parent
604960f5f5
commit
b3f45d3c84
|
@ -8,7 +8,7 @@
|
||||||
"error.ss"
|
"error.ss"
|
||||||
racket/trace
|
racket/trace
|
||||||
racket/contract
|
racket/contract
|
||||||
(lib "list.ss")
|
racket/list
|
||||||
(lib "etc.ss")
|
(lib "etc.ss")
|
||||||
(for-syntax syntax/parse
|
(for-syntax syntax/parse
|
||||||
syntax/parse/experimental/contract))
|
syntax/parse/experimental/contract))
|
||||||
|
@ -41,69 +41,62 @@
|
||||||
[_ (datum->syntax (identifier-prune-lexical-context #'whatever '(#%datum))
|
[_ (datum->syntax (identifier-prune-lexical-context #'whatever '(#%datum))
|
||||||
(syntax->datum stx) stx)]))))
|
(syntax->datum stx) stx)]))))
|
||||||
|
|
||||||
(define-syntax (term-match/single stx)
|
(define-for-syntax (term-matcher orig-stx make-matcher)
|
||||||
(syntax-case stx ()
|
(syntax-case orig-stx ()
|
||||||
[(_ lang [pattern rhs] ...)
|
[(form-name lang [pattern rhs] ...)
|
||||||
(begin
|
(begin
|
||||||
(unless (identifier? #'lang)
|
(unless (identifier? #'lang)
|
||||||
(raise-syntax-error 'term-match/single "expected an identifier in the language position" stx #'lang))
|
(raise-syntax-error (syntax-e #'form-name) "expected an identifier in the language position" orig-stx #'lang))
|
||||||
(let ([lang-nts (language-id-nts #'lang 'term-match/single)])
|
(let ([lang-nts (language-id-nts #'lang (syntax-e #'form-name))])
|
||||||
(with-syntax ([(((names ...) (names/ellipses ...)) ...)
|
(with-syntax ([(((names ...) (names/ellipses ...)) ...)
|
||||||
(map (λ (x) (let-values ([(names names/ellipses) (extract-names lang-nts 'term-match/single #t x)])
|
(map (λ (x) (call-with-values
|
||||||
(list names names/ellipses)))
|
(λ () (extract-names lang-nts (syntax-e #'form-name) #t x))
|
||||||
|
list))
|
||||||
(syntax->list (syntax (pattern ...))))]
|
(syntax->list (syntax (pattern ...))))]
|
||||||
[(side-conditions-rewritten ...)
|
[(side-conditions-rewritten ...)
|
||||||
(map (λ (x) (rewrite-side-conditions/check-errs lang-nts 'term-match #t x))
|
(map (λ (x) (rewrite-side-conditions/check-errs lang-nts (syntax-e #'form-name) #t x))
|
||||||
(syntax->list (syntax (pattern ...))))]
|
(syntax->list (syntax (pattern ...))))]
|
||||||
[(cp-x ...) (generate-temporaries #'(pattern ...))])
|
[(cp-x ...) (generate-temporaries #'(pattern ...))]
|
||||||
#'(let ([lang-x lang])
|
[make-matcher make-matcher])
|
||||||
(let ([cp-x (compile-pattern lang-x `side-conditions-rewritten #t)] ...)
|
#'(make-matcher
|
||||||
(λ (exp)
|
'form-name lang
|
||||||
((let/ec k
|
(list 'pattern ...)
|
||||||
(let ([match (match-pattern cp-x exp)])
|
(list (compile-pattern lang `side-conditions-rewritten #t) ...)
|
||||||
(when match
|
(list (λ (match)
|
||||||
(unless (null? (cdr match))
|
(term-let/error-name
|
||||||
(redex-error
|
form-name
|
||||||
'term-match/single
|
([names/ellipses (lookup-binding (mtch-bindings match) 'names)] ...)
|
||||||
"pattern ~s matched term ~e multiple ways"
|
rhs)) ...)))))]))
|
||||||
'pattern
|
|
||||||
exp))
|
|
||||||
(k (λ ()
|
|
||||||
(term-let/error-name
|
|
||||||
term-match/single
|
|
||||||
([names/ellipses (lookup-binding (mtch-bindings (car match)) 'names)] ...)
|
|
||||||
rhs)))))
|
|
||||||
...
|
|
||||||
(redex-error 'term-match/single "no patterns matched ~e" exp)))))))))]))
|
|
||||||
|
|
||||||
|
(define-syntax (term-match/single stx)
|
||||||
|
(term-matcher stx #'term-match/single/proc))
|
||||||
(define-syntax (term-match stx)
|
(define-syntax (term-match stx)
|
||||||
(syntax-case stx ()
|
(term-matcher stx #'term-match/proc))
|
||||||
[(_ lang [pattern rhs] ...)
|
|
||||||
(begin
|
(define ((term-match/proc form-name lang ps cps rhss) term)
|
||||||
(unless (identifier? #'lang)
|
(append-map
|
||||||
(raise-syntax-error 'term-match "expected an identifier" stx #'lang))
|
(λ (cp rhs)
|
||||||
(let ([lang-nts (language-id-nts #'lang 'term-match)])
|
(let ([matches (match-pattern cp term)])
|
||||||
(with-syntax ([(((names ...) (names/ellipses ...)) ...)
|
(if matches
|
||||||
(map (λ (x) (let-values ([(names names/ellipses) (extract-names lang-nts 'term-match #t x)])
|
(map rhs matches)
|
||||||
(list names names/ellipses)))
|
'())))
|
||||||
(syntax->list (syntax (pattern ...))))]
|
cps rhss))
|
||||||
[(side-conditions-rewritten ...)
|
|
||||||
(map (λ (x) (rewrite-side-conditions/check-errs lang-nts 'term-match #t x))
|
(define ((term-match/single/proc form-name lang ps cps rhss) term)
|
||||||
(syntax->list (syntax (pattern ...))))]
|
(let loop ([ps ps] [cps cps] [rhss rhss])
|
||||||
[(cp-x ...) (generate-temporaries #'(pattern ...))])
|
(if (null? ps)
|
||||||
#'(let ([lang-x lang])
|
(redex-error form-name "no patterns matched ~e" term)
|
||||||
(let ([cp-x (compile-pattern lang-x `side-conditions-rewritten #t)] ...)
|
(let ([match (match-pattern (car cps) term)])
|
||||||
(λ (exp)
|
(if match
|
||||||
(append
|
(begin
|
||||||
(let ([matches (match-pattern cp-x exp)])
|
(unless (null? (cdr match))
|
||||||
(if matches
|
(redex-error
|
||||||
(map (λ (match)
|
form-name
|
||||||
(term-let/error-name
|
"pattern ~s matched term ~e multiple ways"
|
||||||
term-match
|
(car ps)
|
||||||
([names/ellipses (lookup-binding (mtch-bindings match) 'names)] ...)
|
term))
|
||||||
rhs))
|
((car rhss) (car match)))
|
||||||
matches)
|
(loop (cdr ps) (cdr cps) (cdr rhss)))))))
|
||||||
'())) ...)))))))]))
|
|
||||||
|
|
||||||
(define-syntax (compatible-closure stx)
|
(define-syntax (compatible-closure stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
|
|
@ -2036,6 +2036,9 @@
|
||||||
'(x y))
|
'(x y))
|
||||||
'(x . y))
|
'(x . y))
|
||||||
|
|
||||||
|
(test ((term-match/single empty-language [() 'a] [() 'b])
|
||||||
|
'())
|
||||||
|
'a)
|
||||||
|
|
||||||
(test (with-handlers ((exn:fail:redex? (λ (x) 'right-exn))
|
(test (with-handlers ((exn:fail:redex? (λ (x) 'right-exn))
|
||||||
((λ (x) #t) (λ (x) 'wrong-exn)))
|
((λ (x) #t) (λ (x) 'wrong-exn)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user