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:misplaced-else-clause
39 (cons 'syntax-error "Misplaced else clause"))
40 (define exception:bad-case-clause
41 (cons 'syntax-error "Bad case clause"))
42 (define exception:bad-case-labels
43 (cons 'syntax-error "Bad case labels"))
44 (define exception:bad-cond-clause
45 (cons 'syntax-error "Bad cond clause"))
46 (define exception:bad-var
47 (cons 'misc-error "^bad variable"))
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:missing-clauses
440 (interaction-environment)))
442 (pass-if-exception "(cond #t)"
443 exception:bad-cond-clause
445 (interaction-environment)))
447 (pass-if-exception "(cond 1)"
448 exception:bad-cond-clause
450 (interaction-environment)))
452 (pass-if-exception "(cond 1 2)"
453 exception:bad-cond-clause
455 (interaction-environment)))
457 (pass-if-exception "(cond 1 2 3)"
458 exception:bad-cond-clause
460 (interaction-environment)))
462 (pass-if-exception "(cond 1 2 3 4)"
463 exception:bad-cond-clause
464 (eval '(cond 1 2 3 4)
465 (interaction-environment)))
467 (pass-if-exception "(cond ())"
468 exception:bad-cond-clause
470 (interaction-environment)))
472 (pass-if-exception "(cond () 1)"
473 exception:bad-cond-clause
475 (interaction-environment)))
477 (pass-if-exception "(cond (1) 1)"
478 exception:bad-cond-clause
480 (interaction-environment)))))
482 (with-test-prefix "cond =>"
484 (with-test-prefix "cond is hygienic"
486 (pass-if "bound 'else is handled correctly"
487 (eq? (let ((else 'ok)) (cond (else))) 'ok))
489 (pass-if "bound '=> is handled correctly"
490 (eq? (let ((=> #f)) (cond (#t => 'ok))) 'ok)))
492 (with-test-prefix "else is handled correctly"
496 (eq? (cond (else =>)) 'foo)))
498 (pass-if "else => identity"
500 (eq? (cond (else => identity)) identity))))
502 (with-test-prefix "wrong number of arguments"
504 (pass-if-exception "=> (lambda (x y) #t)"
505 exception:wrong-num-args
506 (cond (1 => (lambda (x y) #t))))))
508 (with-test-prefix "case"
510 (pass-if "clause with empty labels list"
511 (case 1 (() #f) (else #t)))
513 (with-test-prefix "case is hygienic"
515 (pass-if-exception "bound 'else is handled correctly"
516 exception:bad-case-labels
517 (eval '(let ((else #f)) (case 1 (else #f)))
518 (interaction-environment))))
520 (with-test-prefix "bad or missing clauses"
522 (pass-if-exception "(case)"
523 exception:missing-clauses
525 (interaction-environment)))
527 (pass-if-exception "(case . \"foo\")"
528 exception:bad-expression
529 (eval '(case . "foo")
530 (interaction-environment)))
532 (pass-if-exception "(case 1)"
533 exception:missing-clauses
535 (interaction-environment)))
537 (pass-if-exception "(case 1 . \"foo\")"
538 exception:bad-expression
539 (eval '(case 1 . "foo")
540 (interaction-environment)))
542 (pass-if-exception "(case 1 \"foo\")"
543 exception:bad-case-clause
544 (eval '(case 1 "foo")
545 (interaction-environment)))
547 (pass-if-exception "(case 1 ())"
548 exception:bad-case-clause
550 (interaction-environment)))
552 (pass-if-exception "(case 1 (\"foo\"))"
553 exception:bad-case-clause
554 (eval '(case 1 ("foo"))
555 (interaction-environment)))
557 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
558 exception:bad-case-labels
559 (eval '(case 1 ("foo" "bar"))
560 (interaction-environment)))
562 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
563 exception:bad-expression
564 (eval '(case 1 ((2) "bar") . "foo")
565 (interaction-environment)))
567 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
568 exception:bad-case-clause
569 (eval '(case 1 ((2) "bar") (else))
570 (interaction-environment)))
572 (pass-if-exception "(case 1 (else #f) . \"foo\")"
573 exception:bad-expression
574 (eval '(case 1 (else #f) . "foo")
575 (interaction-environment)))
577 (pass-if-exception "(case 1 (else #f) ((1) #t))"
578 exception:misplaced-else-clause
579 (eval '(case 1 (else #f) ((1) #t))
580 (interaction-environment)))))
582 (with-test-prefix "define"
584 (with-test-prefix "currying"
586 (pass-if "(define ((foo)) #f)"
590 (with-test-prefix "missing or extra expressions"
592 (pass-if-exception "(define)"
593 exception:missing/extra-expr
595 (interaction-environment)))))
597 (with-test-prefix "set!"
599 (with-test-prefix "missing or extra expressions"
601 (pass-if-exception "(set!)"
602 exception:missing/extra-expr
604 (interaction-environment)))
606 (pass-if-exception "(set! 1)"
607 exception:missing/extra-expr
609 (interaction-environment)))
611 (pass-if-exception "(set! 1 2 3)"
612 exception:missing/extra-expr
614 (interaction-environment))))
616 (with-test-prefix "bad variable"
618 (pass-if-exception "(set! \"\" #t)"
621 (interaction-environment)))
623 (pass-if-exception "(set! 1 #t)"
626 (interaction-environment)))
628 (pass-if-exception "(set! #t #f)"
631 (interaction-environment)))
633 (pass-if-exception "(set! #f #t)"
636 (interaction-environment)))
638 (pass-if-exception "(set! #\space #f)"
640 (eval '(set! #\space #f)
641 (interaction-environment)))))
643 (with-test-prefix "quote"
645 (with-test-prefix "missing or extra expression"
647 (pass-if-exception "(quote)"
648 exception:missing/extra-expr
650 (interaction-environment)))
652 (pass-if-exception "(quote a b)"
653 exception:missing/extra-expr
655 (interaction-environment)))))
657 (with-test-prefix "while"
659 (define (unreachable)
660 (error "unreachable code has been reached!"))
662 ;; Return a new procedure COND which when called (COND) will return #t the
663 ;; first N times, then #f, then any further call is an error. N=0 is
664 ;; allowed, in which case #f is returned by the first call.
665 (define (make-iterations-cond n)
668 (error "oops, condition re-tested after giving false"))
677 (pass-if-exception "too few args" exception:wrong-num-args
678 (eval '(while) (interaction-environment)))
680 (with-test-prefix "empty body"
684 (let ((cond (make-iterations-cond n)))
688 (pass-if "initially false"
693 (with-test-prefix "in empty environment"
695 ;; an environment with no bindings at all
696 (define empty-environment
699 (pass-if "empty body"
704 (pass-if "initially false"
711 (let ((cond (make-iterations-cond 3)))
712 (eval `(,while (,cond)
717 (with-test-prefix "iterations"
721 (let ((cond (make-iterations-cond n))
727 (with-test-prefix "break"
729 (pass-if-exception "too many args" exception:wrong-num-args
733 (with-test-prefix "from cond"
744 (let ((cond (make-iterations-cond n))
754 (with-test-prefix "from body"
764 (let ((cond (make-iterations-cond n))
774 (pass-if "from nested"
776 (let ((outer-break break))
783 (pass-if "from recursive"
784 (let ((outer-break #f))
789 (set! outer-break break)
795 (error "broke only from inner loop")))
799 (with-test-prefix "continue"
801 (pass-if-exception "too many args" exception:wrong-num-args
805 (with-test-prefix "from cond"
809 (let ((cond (make-iterations-cond n))
820 (with-test-prefix "from body"
824 (let ((cond (make-iterations-cond n))
832 (pass-if "from nested"
833 (let ((cond (make-iterations-cond 3)))
835 (let ((outer-continue continue))
841 (pass-if "from recursive"
842 (let ((outer-continue #f))
844 (let ((cond (make-iterations-cond 3))
849 (error "continued only to inner loop"))
854 (set! outer-continue continue)