1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

syntax-case: fix error reporting for misplaced ellipses.

Reported by taylanbayirli@gmail.com (Taylan Ulrich B.).

* module/ice-9/psyntax.scm (cvt*): Use 'syntax-case' to destructure
  the pattern tail, instead of 'pair?', 'car', and 'cdr'.
  (gen-clause): When checking for errors, check for misplaced ellipsis
  before duplicate pattern variables, to improve the error message in
  case of multiple misplaced ellipses.

* module/ice-9/psyntax-pp.scm: Regenerate.

* test-suite/tests/syntax.test: Add tests.
This commit is contained in:
Mark H Weaver 2013-12-13 12:53:24 -05:00
parent d8c476b68d
commit aa8630efb3
3 changed files with 80 additions and 19 deletions

View file

@ -2072,14 +2072,17 @@
(lambda (pattern keys)
(letrec*
((cvt* (lambda (p* n ids)
(if (not (pair? p*))
(cvt p* n ids)
(let* ((tmp p*) (tmp ($sc-dispatch tmp '(any . any))))
(if tmp
(apply (lambda (x y)
(call-with-values
(lambda () (cvt* (cdr p*) n ids))
(lambda () (cvt* y n ids))
(lambda (y ids)
(call-with-values
(lambda () (cvt (car p*) n ids))
(lambda (x ids) (values (cons x y) ids))))))))
(lambda () (cvt x n ids))
(lambda (x ids) (values (cons x y) ids))))))
tmp)
(cvt p* n ids)))))
(v-reverse
(lambda (x)
(let loop ((r '()) (x x))
@ -2162,10 +2165,10 @@
(call-with-values
(lambda () (convert-pattern pat keys))
(lambda (p pvars)
(cond ((not (distinct-bound-ids? (map car pvars)))
(syntax-violation 'syntax-case "duplicate pattern variable" pat))
((not (and-map (lambda (x) (not (ellipsis? (car x)))) pvars))
(cond ((not (and-map (lambda (x) (not (ellipsis? (car x)))) pvars))
(syntax-violation 'syntax-case "misplaced ellipsis" pat))
((not (distinct-bound-ids? (map car pvars)))
(syntax-violation 'syntax-case "duplicate pattern variable" pat))
(else
(let ((y (gen-var 'tmp)))
(build-application

View file

@ -2341,15 +2341,16 @@
(lambda (pattern keys)
(define cvt*
(lambda (p* n ids)
(if (not (pair? p*))
(cvt p* n ids)
(syntax-case p* ()
((x . y)
(call-with-values
(lambda () (cvt* (cdr p*) n ids))
(lambda () (cvt* #'y n ids))
(lambda (y ids)
(call-with-values
(lambda () (cvt (car p*) n ids))
(lambda () (cvt #'x n ids))
(lambda (x ids)
(values (cons x y) ids))))))))
(values (cons x y) ids))))))
(_ (cvt p* n ids)))))
(define (v-reverse x)
(let loop ((r '()) (x x))
@ -2429,10 +2430,10 @@
(lambda () (convert-pattern pat keys))
(lambda (p pvars)
(cond
((not (distinct-bound-ids? (map car pvars)))
(syntax-violation 'syntax-case "duplicate pattern variable" pat))
((not (and-map (lambda (x) (not (ellipsis? (car x)))) pvars))
(syntax-violation 'syntax-case "misplaced ellipsis" pat))
((not (distinct-bound-ids? (map car pvars)))
(syntax-violation 'syntax-case "duplicate pattern variable" pat))
(else
(let ((y (gen-var 'tmp)))
;; fat finger binding and references to temp variable y

View file

@ -1171,3 +1171,60 @@
(unreachable))))))
(r 'outer))
#t)))
(with-test-prefix "syntax-case"
(pass-if-syntax-error "duplicate pattern variable"
'(syntax-case . "duplicate pattern variable")
(eval '(lambda (e)
(syntax-case e ()
((a b c d e d f) #f)))
(interaction-environment)))
(with-test-prefix "misplaced ellipses"
(pass-if-syntax-error "bare ellipsis"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
(... #f)))
(interaction-environment)))
(pass-if-syntax-error "ellipsis singleton"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
((...) #f)))
(interaction-environment)))
(pass-if-syntax-error "ellipsis in car"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
((... . _) #f)))
(interaction-environment)))
(pass-if-syntax-error "ellipsis in cdr"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
((_ . ...) #f)))
(interaction-environment)))
(pass-if-syntax-error "two ellipses in the same list"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
((x ... y ...) #f)))
(interaction-environment)))
(pass-if-syntax-error "three ellipses in the same list"
'(syntax-case . "misplaced ellipsis")
(eval '(lambda (e)
(syntax-case e ()
((x ... y ... z ...) #f)))
(interaction-environment)))))
;;; Local Variables:
;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
;;; End: