1 ;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
3 ;;;; Copyright (C) 2001, 2003 Free Software Foundation, Inc.
5 ;;;; This program is free software; you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation; either version 2, or (at your option)
8 ;;;; any later version.
10 ;;;; This program is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;;;; GNU General Public License for more details.
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with this software; see the file COPYING. If not, write to
17 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 ;;;; Boston, MA 02111-1307 USA
20 (define-module (test-suite test-syntax)
21 :use-module (test-suite lib))
24 (define exception:bad-expression
25 (cons 'syntax-error "Bad expression"))
26 (define exception:bad-bindings
27 (cons 'misc-error "^bad bindings"))
28 (define exception:duplicate-bindings
29 (cons 'misc-error "^duplicate bindings"))
30 (define exception:bad-body
31 (cons 'misc-error "^bad body"))
32 (define exception:bad-formals
33 (cons 'misc-error "^bad formals"))
34 (define exception:duplicate-formals
35 (cons 'misc-error "^duplicate formals"))
36 (define exception:missing-clauses
37 (cons 'syntax-error "Missing clauses"))
38 (define exception:bad-var
39 (cons 'misc-error "^bad variable"))
40 (define exception:bad/missing-clauses
41 (cons 'misc-error "^bad or missing clauses"))
42 (define exception:bad-case-clause
43 (cons 'syntax-error "Bad case clause"))
44 (define exception:extra-case-clause
45 (cons 'syntax-error "Extra case clause"))
46 (define exception:bad-case-labels
47 (cons 'syntax-error "Bad case labels"))
48 (define exception:missing/extra-expr
49 (cons 'misc-error "^missing or extra expression"))
52 (with-test-prefix "expressions"
54 (with-test-prefix "Bad argument list"
56 (pass-if-exception "improper argument list of length 1"
57 exception:wrong-num-args
58 (eval '(let ((foo (lambda (x y) #t)))
60 (interaction-environment)))
62 (pass-if-exception "improper argument list of length 2"
63 exception:wrong-num-args
64 (eval '(let ((foo (lambda (x y) #t)))
66 (interaction-environment))))
68 (with-test-prefix "missing or extra expression"
71 ;; *Note:* In many dialects of Lisp, the empty combination, (),
72 ;; is a legitimate expression. In Scheme, combinations must
73 ;; have at least one subexpression, so () is not a syntactically
77 (pass-if-exception "empty parentheses \"()\""
78 exception:missing/extra-expr
80 (interaction-environment)))))
82 (with-test-prefix "quote"
85 (with-test-prefix "quasiquote"
87 (with-test-prefix "unquote"
89 (pass-if "repeated execution"
90 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
91 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
93 (with-test-prefix "unquote-splicing"
95 (pass-if-exception "extra arguments"
96 exception:missing/extra-expr
97 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
99 (with-test-prefix "begin"
101 (pass-if "legal (begin)"
105 (expect-fail-exception "illegal (begin)"
110 (with-test-prefix "lambda"
112 (with-test-prefix "bad formals"
114 (pass-if-exception "(lambda)"
115 exception:bad-formals
117 (interaction-environment)))
119 (pass-if-exception "(lambda . \"foo\")"
120 exception:bad-formals
121 (eval '(lambda . "foo")
122 (interaction-environment)))
124 (pass-if-exception "(lambda \"foo\")"
125 exception:bad-formals
126 (eval '(lambda "foo")
127 (interaction-environment)))
129 (pass-if-exception "(lambda \"foo\" #f)"
130 exception:bad-formals
131 (eval '(lambda "foo" #f)
132 (interaction-environment)))
134 (pass-if-exception "(lambda (x 1) 2)"
135 exception:bad-formals
136 (eval '(lambda (x 1) 2)
137 (interaction-environment)))
139 (pass-if-exception "(lambda (1 x) 2)"
140 exception:bad-formals
141 (eval '(lambda (1 x) 2)
142 (interaction-environment)))
144 (pass-if-exception "(lambda (x \"a\") 2)"
145 exception:bad-formals
146 (eval '(lambda (x "a") 2)
147 (interaction-environment)))
149 (pass-if-exception "(lambda (\"a\" x) 2)"
150 exception:bad-formals
151 (eval '(lambda ("a" x) 2)
152 (interaction-environment))))
154 (with-test-prefix "duplicate formals"
157 (pass-if-exception "(lambda (x x) 1)"
158 exception:duplicate-formals
159 (eval '(lambda (x x) 1)
160 (interaction-environment)))
163 (pass-if-exception "(lambda (x x x) 1)"
164 exception:duplicate-formals
165 (eval '(lambda (x x x) 1)
166 (interaction-environment))))
168 (with-test-prefix "bad body"
170 (pass-if-exception "(lambda ())"
173 (interaction-environment)))))
175 (with-test-prefix "let"
177 (with-test-prefix "bindings"
179 (pass-if-exception "late binding"
180 exception:unbound-var
181 (let ((x 1) (y x)) y)))
183 (with-test-prefix "bad bindings"
185 (pass-if-exception "(let)"
186 exception:bad-bindings
188 (interaction-environment)))
190 (pass-if-exception "(let 1)"
191 exception:bad-bindings
193 (interaction-environment)))
195 (pass-if-exception "(let (x))"
196 exception:bad-bindings
198 (interaction-environment)))
200 ;; FIXME: Wouldn't one rather expect a 'bad bindings' error?
201 ;; (Even although the body is bad as well...)
202 (pass-if-exception "(let ((x)))"
205 (interaction-environment)))
207 (pass-if-exception "(let (x) 1)"
208 exception:bad-bindings
210 (interaction-environment)))
212 (pass-if-exception "(let ((x)) 3)"
213 exception:bad-bindings
215 (interaction-environment)))
217 (pass-if-exception "(let ((x 1) y) x)"
218 exception:bad-bindings
219 (eval '(let ((x 1) y) x)
220 (interaction-environment)))
222 (pass-if-exception "(let ((1 2)) 3)"
224 (eval '(let ((1 2)) 3)
225 (interaction-environment))))
227 (with-test-prefix "duplicate bindings"
229 (pass-if-exception "(let ((x 1) (x 2)) x)"
230 exception:duplicate-bindings
231 (eval '(let ((x 1) (x 2)) x)
232 (interaction-environment))))
234 (with-test-prefix "bad body"
236 (pass-if-exception "(let ())"
239 (interaction-environment)))
241 (pass-if-exception "(let ((x 1)))"
244 (interaction-environment)))))
246 (with-test-prefix "named let"
248 (with-test-prefix "initializers"
250 (pass-if "evaluated in outer environment"
252 (eqv? (let f ((n (f 1))) n) -1))))
254 (with-test-prefix "bad bindings"
256 (pass-if-exception "(let x (y))"
257 exception:bad-bindings
259 (interaction-environment))))
261 (with-test-prefix "bad body"
263 (pass-if-exception "(let x ())"
266 (interaction-environment)))
268 (pass-if-exception "(let x ((y 1)))"
270 (eval '(let x ((y 1)))
271 (interaction-environment)))))
273 (with-test-prefix "let*"
275 (with-test-prefix "bindings"
277 (pass-if "(let* ((x 1) (x 2)) ...)"
281 (pass-if "(let* ((x 1) (x x)) ...)"
285 (with-test-prefix "bad bindings"
287 (pass-if-exception "(let*)"
288 exception:bad-bindings
290 (interaction-environment)))
292 (pass-if-exception "(let* 1)"
293 exception:bad-bindings
295 (interaction-environment)))
297 (pass-if-exception "(let* (x))"
298 exception:bad-bindings
300 (interaction-environment)))
302 (pass-if-exception "(let* (x) 1)"
303 exception:bad-bindings
305 (interaction-environment)))
307 (pass-if-exception "(let* ((x)) 3)"
308 exception:bad-bindings
309 (eval '(let* ((x)) 3)
310 (interaction-environment)))
312 (pass-if-exception "(let* ((x 1) y) x)"
313 exception:bad-bindings
314 (eval '(let* ((x 1) y) x)
315 (interaction-environment)))
317 (pass-if-exception "(let* x ())"
318 exception:bad-bindings
320 (interaction-environment)))
322 (pass-if-exception "(let* x (y))"
323 exception:bad-bindings
325 (interaction-environment)))
327 (pass-if-exception "(let* ((1 2)) 3)"
329 (eval '(let* ((1 2)) 3)
330 (interaction-environment))))
332 (with-test-prefix "bad body"
334 (pass-if-exception "(let* ())"
337 (interaction-environment)))
339 (pass-if-exception "(let* ((x 1)))"
341 (eval '(let* ((x 1)))
342 (interaction-environment)))))
344 (with-test-prefix "letrec"
346 (with-test-prefix "bindings"
348 (pass-if-exception "initial bindings are undefined"
349 exception:unbound-var
351 (letrec ((x 1) (y x)) y))))
353 (with-test-prefix "bad bindings"
355 (pass-if-exception "(letrec)"
356 exception:bad-bindings
358 (interaction-environment)))
360 (pass-if-exception "(letrec 1)"
361 exception:bad-bindings
363 (interaction-environment)))
365 (pass-if-exception "(letrec (x))"
366 exception:bad-bindings
368 (interaction-environment)))
370 (pass-if-exception "(letrec (x) 1)"
371 exception:bad-bindings
372 (eval '(letrec (x) 1)
373 (interaction-environment)))
375 (pass-if-exception "(letrec ((x)) 3)"
376 exception:bad-bindings
377 (eval '(letrec ((x)) 3)
378 (interaction-environment)))
380 (pass-if-exception "(letrec ((x 1) y) x)"
381 exception:bad-bindings
382 (eval '(letrec ((x 1) y) x)
383 (interaction-environment)))
385 (pass-if-exception "(letrec x ())"
386 exception:bad-bindings
388 (interaction-environment)))
390 (pass-if-exception "(letrec x (y))"
391 exception:bad-bindings
392 (eval '(letrec x (y))
393 (interaction-environment)))
395 (pass-if-exception "(letrec ((1 2)) 3)"
397 (eval '(letrec ((1 2)) 3)
398 (interaction-environment))))
400 (with-test-prefix "duplicate bindings"
402 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
403 exception:duplicate-bindings
404 (eval '(letrec ((x 1) (x 2)) x)
405 (interaction-environment))))
407 (with-test-prefix "bad body"
409 (pass-if-exception "(letrec ())"
412 (interaction-environment)))
414 (pass-if-exception "(letrec ((x 1)))"
416 (eval '(letrec ((x 1)))
417 (interaction-environment)))))
419 (with-test-prefix "if"
421 (with-test-prefix "missing or extra expressions"
423 (pass-if-exception "(if)"
424 exception:missing/extra-expr
426 (interaction-environment)))
428 (pass-if-exception "(if 1 2 3 4)"
429 exception:missing/extra-expr
431 (interaction-environment)))))
433 (with-test-prefix "cond"
435 (with-test-prefix "bad or missing clauses"
437 (pass-if-exception "(cond)"
438 exception:bad/missing-clauses
440 (interaction-environment)))
442 (pass-if-exception "(cond #t)"
443 exception:bad/missing-clauses
445 (interaction-environment)))
447 (pass-if-exception "(cond 1)"
448 exception:bad/missing-clauses
450 (interaction-environment)))
452 (pass-if-exception "(cond 1 2)"
453 exception:bad/missing-clauses
455 (interaction-environment)))
457 (pass-if-exception "(cond 1 2 3)"
458 exception:bad/missing-clauses
460 (interaction-environment)))
462 (pass-if-exception "(cond 1 2 3 4)"
463 exception:bad/missing-clauses
464 (eval '(cond 1 2 3 4)
465 (interaction-environment)))
467 (pass-if-exception "(cond ())"
468 exception:bad/missing-clauses
470 (interaction-environment)))
472 (pass-if-exception "(cond () 1)"
473 exception:bad/missing-clauses
475 (interaction-environment)))
477 (pass-if-exception "(cond (1) 1)"
478 exception:bad/missing-clauses
480 (interaction-environment)))))
482 (with-test-prefix "cond =>"
484 (with-test-prefix "cond is hygienic"
486 (expect-fail "bound 'else is handled correctly"
488 (eq? (let ((else 'ok)) (cond (else))) 'ok)))
490 (expect-fail "bound '=> is handled correctly"
492 (eq? (let ((=> #f)) (cond (#t => 'ok))) 'ok))))
494 (with-test-prefix "else is handled correctly"
498 (eq? (cond (else =>)) 'foo)))
500 (pass-if "else => identity"
502 (eq? (cond (else => identity)) identity))))
504 (with-test-prefix "wrong number of arguments"
506 (pass-if-exception "=> (lambda (x y) #t)"
507 exception:wrong-num-args
508 (cond (1 => (lambda (x y) #t))))))
510 (with-test-prefix "case"
512 (pass-if "clause with empty labels list"
513 (case 1 (() #f) (else #t)))
515 (with-test-prefix "case is hygienic"
517 (pass-if-exception "bound 'else is handled correctly"
518 exception:bad-case-labels
519 (eval '(let ((else #f)) (case 1 (else #f)))
520 (interaction-environment))))
522 (with-test-prefix "bad or missing clauses"
524 (pass-if-exception "(case)"
525 exception:missing-clauses
527 (interaction-environment)))
529 (pass-if-exception "(case . \"foo\")"
530 exception:bad-expression
531 (eval '(case . "foo")
532 (interaction-environment)))
534 (pass-if-exception "(case 1)"
535 exception:missing-clauses
537 (interaction-environment)))
539 (pass-if-exception "(case 1 . \"foo\")"
540 exception:bad-expression
541 (eval '(case 1 . "foo")
542 (interaction-environment)))
544 (pass-if-exception "(case 1 \"foo\")"
545 exception:bad-case-clause
546 (eval '(case 1 "foo")
547 (interaction-environment)))
549 (pass-if-exception "(case 1 ())"
550 exception:bad-case-clause
552 (interaction-environment)))
554 (pass-if-exception "(case 1 (\"foo\"))"
555 exception:bad-case-clause
556 (eval '(case 1 ("foo"))
557 (interaction-environment)))
559 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
560 exception:bad-case-labels
561 (eval '(case 1 ("foo" "bar"))
562 (interaction-environment)))
564 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
565 exception:bad-expression
566 (eval '(case 1 ((2) "bar") . "foo")
567 (interaction-environment)))
569 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
570 exception:bad-case-clause
571 (eval '(case 1 ((2) "bar") (else))
572 (interaction-environment)))
574 (pass-if-exception "(case 1 (else #f) . \"foo\")"
575 exception:bad-expression
576 (eval '(case 1 (else #f) . "foo")
577 (interaction-environment)))
579 (pass-if-exception "(case 1 (else #f) ((1) #t))"
580 exception:extra-case-clause
581 (eval '(case 1 (else #f) ((1) #t))
582 (interaction-environment)))))
584 (with-test-prefix "define"
586 (with-test-prefix "currying"
588 (pass-if "(define ((foo)) #f)"
592 (with-test-prefix "missing or extra expressions"
594 (pass-if-exception "(define)"
595 exception:missing/extra-expr
597 (interaction-environment)))))
599 (with-test-prefix "set!"
601 (with-test-prefix "missing or extra expressions"
603 (pass-if-exception "(set!)"
604 exception:missing/extra-expr
606 (interaction-environment)))
608 (pass-if-exception "(set! 1)"
609 exception:missing/extra-expr
611 (interaction-environment)))
613 (pass-if-exception "(set! 1 2 3)"
614 exception:missing/extra-expr
616 (interaction-environment))))
618 (with-test-prefix "bad variable"
620 (pass-if-exception "(set! \"\" #t)"
623 (interaction-environment)))
625 (pass-if-exception "(set! 1 #t)"
628 (interaction-environment)))
630 (pass-if-exception "(set! #t #f)"
633 (interaction-environment)))
635 (pass-if-exception "(set! #f #t)"
638 (interaction-environment)))
640 (pass-if-exception "(set! #\space #f)"
642 (eval '(set! #\space #f)
643 (interaction-environment)))))
645 (with-test-prefix "quote"
647 (with-test-prefix "missing or extra expression"
649 (pass-if-exception "(quote)"
650 exception:missing/extra-expr
652 (interaction-environment)))
654 (pass-if-exception "(quote a b)"
655 exception:missing/extra-expr
657 (interaction-environment)))))
659 (with-test-prefix "while"
661 (define (unreachable)
662 (error "unreachable code has been reached!"))
664 ;; Return a new procedure COND which when called (COND) will return #t the
665 ;; first N times, then #f, then any further call is an error. N=0 is
666 ;; allowed, in which case #f is returned by the first call.
667 (define (make-iterations-cond n)
670 (error "oops, condition re-tested after giving false"))
679 (pass-if-exception "too few args" exception:wrong-num-args
680 (eval '(while) (interaction-environment)))
682 (with-test-prefix "empty body"
686 (let ((cond (make-iterations-cond n)))
690 (pass-if "initially false"
695 (with-test-prefix "in empty environment"
697 ;; an environment with no bindings at all
698 (define empty-environment
701 (pass-if "empty body"
706 (pass-if "initially false"
713 (let ((cond (make-iterations-cond 3)))
714 (eval `(,while (,cond)
719 (with-test-prefix "iterations"
723 (let ((cond (make-iterations-cond n))
729 (with-test-prefix "break"
731 (pass-if-exception "too many args" exception:wrong-num-args
735 (with-test-prefix "from cond"
746 (let ((cond (make-iterations-cond n))
756 (with-test-prefix "from body"
766 (let ((cond (make-iterations-cond n))
776 (pass-if "from nested"
778 (let ((outer-break break))
785 (pass-if "from recursive"
786 (let ((outer-break #f))
791 (set! outer-break break)
797 (error "broke only from inner loop")))
801 (with-test-prefix "continue"
803 (pass-if-exception "too many args" exception:wrong-num-args
807 (with-test-prefix "from cond"
811 (let ((cond (make-iterations-cond n))
822 (with-test-prefix "from body"
826 (let ((cond (make-iterations-cond n))
834 (pass-if "from nested"
835 (let ((cond (make-iterations-cond 3)))
837 (let ((outer-continue continue))
843 (pass-if "from recursive"
844 (let ((outer-continue #f))
846 (let ((cond (make-iterations-cond 3))
851 (error "continued only to inner loop"))
856 (set! outer-continue continue)