fix a ... match pattern when a is already bound

This commit is contained in:
Alex Shinn 2020-09-06 22:59:42 +09:00
parent 9c6020e22d
commit 993a6469fe
2 changed files with 22 additions and 19 deletions

View file

@ -49,6 +49,8 @@
(let ((a '(1 2))) (match a ((and (a 2) (1 b)) (+ a b)) (_ #f))))
(test "duplicate quasiquote" 'ok
(match '(a b) ((or `(a ,x) `(,x b)) 'ok) (_ #f)))
(test "duplicate before ellipsis" #f
(match '(1 2) ((a a ...) a) (else #f)))
(test "ellipses" '((a b c) (1 2 3))
(match '((a . 1) (b . 2) (c . 3))

View file

@ -564,25 +564,26 @@
(define-syntax match-gen-ellipsis
(syntax-rules ()
((_ v p () g+s (sk ...) fk i ((id id-ls) ...))
(match-check-identifier p
;; simplest case equivalent to (p ...), just bind the list
(let ((p v))
(if (list? p)
(sk ... i)
fk))
;; simple case, match all elements of the list
(let loop ((ls v) (id-ls '()) ...)
(cond
((null? ls)
(let ((id (reverse id-ls)) ...) (sk ... i)))
((pair? ls)
(let ((w (car ls)))
(match-one w p ((car ls) (set-car! ls))
(match-drop-ids (loop (cdr ls) (cons id id-ls) ...))
fk i)))
(else
fk)))))
;; TODO: restore fast path when p is not already bound
;; ((_ v p () g+s (sk ...) fk i ((id id-ls) ...))
;; (match-check-identifier p
;; ;; simplest case equivalent to (p ...), just bind the list
;; (let ((p v))
;; (if (list? p)
;; (sk ... i)
;; fk))
;; ;; simple case, match all elements of the list
;; (let loop ((ls v) (id-ls '()) ...)
;; (cond
;; ((null? ls)
;; (let ((id (reverse id-ls)) ...) (sk ... i)))
;; ((pair? ls)
;; (let ((w (car ls)))
;; (match-one w p ((car ls) (set-car! ls))
;; (match-drop-ids (loop (cdr ls) (cons id id-ls) ...))
;; fk i)))
;; (else
;; fk)))))
((_ v p r g+s sk fk (i ...) ((id id-ls) ...))
;; general case, trailing patterns to match, keep track of the
;; remaining list length so we don't need any backtracking