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"))
27 (define exception:missing/extra-expr
28 (cons 'misc-error "^missing or extra expression"))
29 (define exception:missing/extra-expr-syntax
30 (cons 'syntax-error "^missing or extra expression"))
31 (define exception:missing-expr
32 (cons 'syntax-error "Missing expression"))
33 (define exception:extra-expr
34 (cons 'syntax-error "Extra expression"))
36 (define exception:bad-bindings
37 (cons 'misc-error "^bad bindings"))
38 (define exception:duplicate-bindings
39 (cons 'misc-error "^duplicate bindings"))
40 (define exception:bad-body
41 (cons 'misc-error "^bad body"))
42 (define exception:bad-formals
43 (cons 'misc-error "^bad formals"))
44 (define exception:duplicate-formals
45 (cons 'misc-error "^duplicate formals"))
47 (define exception:missing-clauses
48 (cons 'syntax-error "Missing clauses"))
49 (define exception:misplaced-else-clause
50 (cons 'syntax-error "Misplaced else clause"))
51 (define exception:bad-case-clause
52 (cons 'syntax-error "Bad case clause"))
53 (define exception:bad-case-labels
54 (cons 'syntax-error "Bad case labels"))
55 (define exception:bad-cond-clause
56 (cons 'syntax-error "Bad cond clause"))
58 (define exception:bad-var
59 (cons 'misc-error "^bad variable"))
62 (with-test-prefix "expressions"
64 (with-test-prefix "Bad argument list"
66 (pass-if-exception "improper argument list of length 1"
67 exception:wrong-num-args
68 (eval '(let ((foo (lambda (x y) #t)))
70 (interaction-environment)))
72 (pass-if-exception "improper argument list of length 2"
73 exception:wrong-num-args
74 (eval '(let ((foo (lambda (x y) #t)))
76 (interaction-environment))))
78 (with-test-prefix "missing or extra expression"
81 ;; *Note:* In many dialects of Lisp, the empty combination, (),
82 ;; is a legitimate expression. In Scheme, combinations must
83 ;; have at least one subexpression, so () is not a syntactically
87 (pass-if-exception "empty parentheses \"()\""
88 exception:missing/extra-expr
90 (interaction-environment)))))
92 (with-test-prefix "quote"
95 (with-test-prefix "quasiquote"
97 (with-test-prefix "unquote"
99 (pass-if "repeated execution"
100 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
101 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
103 (with-test-prefix "unquote-splicing"
105 (pass-if-exception "extra arguments"
106 exception:missing/extra-expr
107 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
109 (with-test-prefix "begin"
111 (pass-if "legal (begin)"
115 (expect-fail-exception "illegal (begin)"
120 (with-test-prefix "lambda"
122 (with-test-prefix "bad formals"
124 (pass-if-exception "(lambda)"
125 exception:bad-formals
127 (interaction-environment)))
129 (pass-if-exception "(lambda . \"foo\")"
130 exception:bad-formals
131 (eval '(lambda . "foo")
132 (interaction-environment)))
134 (pass-if-exception "(lambda \"foo\")"
135 exception:bad-formals
136 (eval '(lambda "foo")
137 (interaction-environment)))
139 (pass-if-exception "(lambda \"foo\" #f)"
140 exception:bad-formals
141 (eval '(lambda "foo" #f)
142 (interaction-environment)))
144 (pass-if-exception "(lambda (x 1) 2)"
145 exception:bad-formals
146 (eval '(lambda (x 1) 2)
147 (interaction-environment)))
149 (pass-if-exception "(lambda (1 x) 2)"
150 exception:bad-formals
151 (eval '(lambda (1 x) 2)
152 (interaction-environment)))
154 (pass-if-exception "(lambda (x \"a\") 2)"
155 exception:bad-formals
156 (eval '(lambda (x "a") 2)
157 (interaction-environment)))
159 (pass-if-exception "(lambda (\"a\" x) 2)"
160 exception:bad-formals
161 (eval '(lambda ("a" x) 2)
162 (interaction-environment))))
164 (with-test-prefix "duplicate formals"
167 (pass-if-exception "(lambda (x x) 1)"
168 exception:duplicate-formals
169 (eval '(lambda (x x) 1)
170 (interaction-environment)))
173 (pass-if-exception "(lambda (x x x) 1)"
174 exception:duplicate-formals
175 (eval '(lambda (x x x) 1)
176 (interaction-environment))))
178 (with-test-prefix "bad body"
180 (pass-if-exception "(lambda ())"
183 (interaction-environment)))))
185 (with-test-prefix "let"
187 (with-test-prefix "bindings"
189 (pass-if-exception "late binding"
190 exception:unbound-var
191 (let ((x 1) (y x)) y)))
193 (with-test-prefix "bad bindings"
195 (pass-if-exception "(let)"
196 exception:bad-bindings
198 (interaction-environment)))
200 (pass-if-exception "(let 1)"
201 exception:bad-bindings
203 (interaction-environment)))
205 (pass-if-exception "(let (x))"
206 exception:bad-bindings
208 (interaction-environment)))
210 ;; FIXME: Wouldn't one rather expect a 'bad bindings' error?
211 ;; (Even although the body is bad as well...)
212 (pass-if-exception "(let ((x)))"
215 (interaction-environment)))
217 (pass-if-exception "(let (x) 1)"
218 exception:bad-bindings
220 (interaction-environment)))
222 (pass-if-exception "(let ((x)) 3)"
223 exception:bad-bindings
225 (interaction-environment)))
227 (pass-if-exception "(let ((x 1) y) x)"
228 exception:bad-bindings
229 (eval '(let ((x 1) y) x)
230 (interaction-environment)))
232 (pass-if-exception "(let ((1 2)) 3)"
234 (eval '(let ((1 2)) 3)
235 (interaction-environment))))
237 (with-test-prefix "duplicate bindings"
239 (pass-if-exception "(let ((x 1) (x 2)) x)"
240 exception:duplicate-bindings
241 (eval '(let ((x 1) (x 2)) x)
242 (interaction-environment))))
244 (with-test-prefix "bad body"
246 (pass-if-exception "(let ())"
249 (interaction-environment)))
251 (pass-if-exception "(let ((x 1)))"
254 (interaction-environment)))))
256 (with-test-prefix "named let"
258 (with-test-prefix "initializers"
260 (pass-if "evaluated in outer environment"
262 (eqv? (let f ((n (f 1))) n) -1))))
264 (with-test-prefix "bad bindings"
266 (pass-if-exception "(let x (y))"
267 exception:bad-bindings
269 (interaction-environment))))
271 (with-test-prefix "bad body"
273 (pass-if-exception "(let x ())"
276 (interaction-environment)))
278 (pass-if-exception "(let x ((y 1)))"
280 (eval '(let x ((y 1)))
281 (interaction-environment)))))
283 (with-test-prefix "let*"
285 (with-test-prefix "bindings"
287 (pass-if "(let* ((x 1) (x 2)) ...)"
291 (pass-if "(let* ((x 1) (x x)) ...)"
295 (with-test-prefix "bad bindings"
297 (pass-if-exception "(let*)"
298 exception:bad-bindings
300 (interaction-environment)))
302 (pass-if-exception "(let* 1)"
303 exception:bad-bindings
305 (interaction-environment)))
307 (pass-if-exception "(let* (x))"
308 exception:bad-bindings
310 (interaction-environment)))
312 (pass-if-exception "(let* (x) 1)"
313 exception:bad-bindings
315 (interaction-environment)))
317 (pass-if-exception "(let* ((x)) 3)"
318 exception:bad-bindings
319 (eval '(let* ((x)) 3)
320 (interaction-environment)))
322 (pass-if-exception "(let* ((x 1) y) x)"
323 exception:bad-bindings
324 (eval '(let* ((x 1) y) x)
325 (interaction-environment)))
327 (pass-if-exception "(let* x ())"
328 exception:bad-bindings
330 (interaction-environment)))
332 (pass-if-exception "(let* x (y))"
333 exception:bad-bindings
335 (interaction-environment)))
337 (pass-if-exception "(let* ((1 2)) 3)"
339 (eval '(let* ((1 2)) 3)
340 (interaction-environment))))
342 (with-test-prefix "bad body"
344 (pass-if-exception "(let* ())"
347 (interaction-environment)))
349 (pass-if-exception "(let* ((x 1)))"
351 (eval '(let* ((x 1)))
352 (interaction-environment)))))
354 (with-test-prefix "letrec"
356 (with-test-prefix "bindings"
358 (pass-if-exception "initial bindings are undefined"
359 exception:unbound-var
361 (letrec ((x 1) (y x)) y))))
363 (with-test-prefix "bad bindings"
365 (pass-if-exception "(letrec)"
366 exception:bad-bindings
368 (interaction-environment)))
370 (pass-if-exception "(letrec 1)"
371 exception:bad-bindings
373 (interaction-environment)))
375 (pass-if-exception "(letrec (x))"
376 exception:bad-bindings
378 (interaction-environment)))
380 (pass-if-exception "(letrec (x) 1)"
381 exception:bad-bindings
382 (eval '(letrec (x) 1)
383 (interaction-environment)))
385 (pass-if-exception "(letrec ((x)) 3)"
386 exception:bad-bindings
387 (eval '(letrec ((x)) 3)
388 (interaction-environment)))
390 (pass-if-exception "(letrec ((x 1) y) x)"
391 exception:bad-bindings
392 (eval '(letrec ((x 1) y) x)
393 (interaction-environment)))
395 (pass-if-exception "(letrec x ())"
396 exception:bad-bindings
398 (interaction-environment)))
400 (pass-if-exception "(letrec x (y))"
401 exception:bad-bindings
402 (eval '(letrec x (y))
403 (interaction-environment)))
405 (pass-if-exception "(letrec ((1 2)) 3)"
407 (eval '(letrec ((1 2)) 3)
408 (interaction-environment))))
410 (with-test-prefix "duplicate bindings"
412 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
413 exception:duplicate-bindings
414 (eval '(letrec ((x 1) (x 2)) x)
415 (interaction-environment))))
417 (with-test-prefix "bad body"
419 (pass-if-exception "(letrec ())"
422 (interaction-environment)))
424 (pass-if-exception "(letrec ((x 1)))"
426 (eval '(letrec ((x 1)))
427 (interaction-environment)))))
429 (with-test-prefix "if"
431 (with-test-prefix "missing or extra expressions"
433 (pass-if-exception "(if)"
434 exception:missing/extra-expr-syntax
436 (interaction-environment)))
438 (pass-if-exception "(if 1 2 3 4)"
439 exception:missing/extra-expr-syntax
441 (interaction-environment)))))
443 (with-test-prefix "cond"
445 (with-test-prefix "bad or missing clauses"
447 (pass-if-exception "(cond)"
448 exception:missing-clauses
450 (interaction-environment)))
452 (pass-if-exception "(cond #t)"
453 exception:bad-cond-clause
455 (interaction-environment)))
457 (pass-if-exception "(cond 1)"
458 exception:bad-cond-clause
460 (interaction-environment)))
462 (pass-if-exception "(cond 1 2)"
463 exception:bad-cond-clause
465 (interaction-environment)))
467 (pass-if-exception "(cond 1 2 3)"
468 exception:bad-cond-clause
470 (interaction-environment)))
472 (pass-if-exception "(cond 1 2 3 4)"
473 exception:bad-cond-clause
474 (eval '(cond 1 2 3 4)
475 (interaction-environment)))
477 (pass-if-exception "(cond ())"
478 exception:bad-cond-clause
480 (interaction-environment)))
482 (pass-if-exception "(cond () 1)"
483 exception:bad-cond-clause
485 (interaction-environment)))
487 (pass-if-exception "(cond (1) 1)"
488 exception:bad-cond-clause
490 (interaction-environment)))))
492 (with-test-prefix "cond =>"
494 (with-test-prefix "cond is hygienic"
496 (pass-if "bound 'else is handled correctly"
497 (eq? (let ((else 'ok)) (cond (else))) 'ok))
499 (pass-if "bound '=> is handled correctly"
500 (eq? (let ((=> #f)) (cond (#t => 'ok))) 'ok)))
502 (with-test-prefix "else is handled correctly"
506 (eq? (cond (else =>)) 'foo)))
508 (pass-if "else => identity"
510 (eq? (cond (else => identity)) identity))))
512 (with-test-prefix "wrong number of arguments"
514 (pass-if-exception "=> (lambda (x y) #t)"
515 exception:wrong-num-args
516 (cond (1 => (lambda (x y) #t))))))
518 (with-test-prefix "case"
520 (pass-if "clause with empty labels list"
521 (case 1 (() #f) (else #t)))
523 (with-test-prefix "case is hygienic"
525 (pass-if-exception "bound 'else is handled correctly"
526 exception:bad-case-labels
527 (eval '(let ((else #f)) (case 1 (else #f)))
528 (interaction-environment))))
530 (with-test-prefix "bad or missing clauses"
532 (pass-if-exception "(case)"
533 exception:missing-clauses
535 (interaction-environment)))
537 (pass-if-exception "(case . \"foo\")"
538 exception:bad-expression
539 (eval '(case . "foo")
540 (interaction-environment)))
542 (pass-if-exception "(case 1)"
543 exception:missing-clauses
545 (interaction-environment)))
547 (pass-if-exception "(case 1 . \"foo\")"
548 exception:bad-expression
549 (eval '(case 1 . "foo")
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 ())"
558 exception:bad-case-clause
560 (interaction-environment)))
562 (pass-if-exception "(case 1 (\"foo\"))"
563 exception:bad-case-clause
564 (eval '(case 1 ("foo"))
565 (interaction-environment)))
567 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
568 exception:bad-case-labels
569 (eval '(case 1 ("foo" "bar"))
570 (interaction-environment)))
572 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
573 exception:bad-expression
574 (eval '(case 1 ((2) "bar") . "foo")
575 (interaction-environment)))
577 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
578 exception:bad-case-clause
579 (eval '(case 1 ((2) "bar") (else))
580 (interaction-environment)))
582 (pass-if-exception "(case 1 (else #f) . \"foo\")"
583 exception:bad-expression
584 (eval '(case 1 (else #f) . "foo")
585 (interaction-environment)))
587 (pass-if-exception "(case 1 (else #f) ((1) #t))"
588 exception:misplaced-else-clause
589 (eval '(case 1 (else #f) ((1) #t))
590 (interaction-environment)))))
592 (with-test-prefix "define"
594 (with-test-prefix "currying"
596 (pass-if "(define ((foo)) #f)"
600 (with-test-prefix "missing or extra expressions"
602 (pass-if-exception "(define)"
603 exception:missing-expr
605 (interaction-environment)))))
607 (with-test-prefix "set!"
609 (with-test-prefix "missing or extra expressions"
611 (pass-if-exception "(set!)"
612 exception:missing/extra-expr
614 (interaction-environment)))
616 (pass-if-exception "(set! 1)"
617 exception:missing/extra-expr
619 (interaction-environment)))
621 (pass-if-exception "(set! 1 2 3)"
622 exception:missing/extra-expr
624 (interaction-environment))))
626 (with-test-prefix "bad variable"
628 (pass-if-exception "(set! \"\" #t)"
631 (interaction-environment)))
633 (pass-if-exception "(set! 1 #t)"
636 (interaction-environment)))
638 (pass-if-exception "(set! #t #f)"
641 (interaction-environment)))
643 (pass-if-exception "(set! #f #t)"
646 (interaction-environment)))
648 (pass-if-exception "(set! #\space #f)"
650 (eval '(set! #\space #f)
651 (interaction-environment)))))
653 (with-test-prefix "quote"
655 (with-test-prefix "missing or extra expression"
657 (pass-if-exception "(quote)"
658 exception:missing/extra-expr
660 (interaction-environment)))
662 (pass-if-exception "(quote a b)"
663 exception:missing/extra-expr
665 (interaction-environment)))))
667 (with-test-prefix "while"
669 (define (unreachable)
670 (error "unreachable code has been reached!"))
672 ;; Return a new procedure COND which when called (COND) will return #t the
673 ;; first N times, then #f, then any further call is an error. N=0 is
674 ;; allowed, in which case #f is returned by the first call.
675 (define (make-iterations-cond n)
678 (error "oops, condition re-tested after giving false"))
687 (pass-if-exception "too few args" exception:wrong-num-args
688 (eval '(while) (interaction-environment)))
690 (with-test-prefix "empty body"
694 (let ((cond (make-iterations-cond n)))
698 (pass-if "initially false"
703 (with-test-prefix "in empty environment"
705 ;; an environment with no bindings at all
706 (define empty-environment
709 (pass-if "empty body"
714 (pass-if "initially false"
721 (let ((cond (make-iterations-cond 3)))
722 (eval `(,while (,cond)
727 (with-test-prefix "iterations"
731 (let ((cond (make-iterations-cond n))
737 (with-test-prefix "break"
739 (pass-if-exception "too many args" exception:wrong-num-args
743 (with-test-prefix "from cond"
754 (let ((cond (make-iterations-cond n))
764 (with-test-prefix "from body"
774 (let ((cond (make-iterations-cond n))
784 (pass-if "from nested"
786 (let ((outer-break break))
793 (pass-if "from recursive"
794 (let ((outer-break #f))
799 (set! outer-break break)
805 (error "broke only from inner loop")))
809 (with-test-prefix "continue"
811 (pass-if-exception "too many args" exception:wrong-num-args
815 (with-test-prefix "from cond"
819 (let ((cond (make-iterations-cond n))
830 (with-test-prefix "from body"
834 (let ((cond (make-iterations-cond n))
842 (pass-if "from nested"
843 (let ((cond (make-iterations-cond 3)))
845 (let ((outer-continue continue))
851 (pass-if "from recursive"
852 (let ((outer-continue #f))
854 (let ((cond (make-iterations-cond 3))
859 (error "continued only to inner loop"))
864 (set! outer-continue continue)