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-misc
28 (cons 'misc-error "^missing or extra expression"))
29 (define exception:missing/extra-expr
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 'syntax-error "Bad bindings"))
38 (define exception:bad-binding
39 (cons 'syntax-error "Bad binding"))
40 (define exception:duplicate-binding
41 (cons 'syntax-error "Duplicate binding"))
42 (define exception:bad-body
43 (cons 'misc-error "^bad body"))
44 (define exception:bad-formals
45 (cons 'syntax-error "Bad formals"))
46 (define exception:bad-formal
47 (cons 'syntax-error "Bad formal"))
48 (define exception:duplicate-formal
49 (cons 'syntax-error "Duplicate formal"))
51 (define exception:missing-clauses
52 (cons 'syntax-error "Missing clauses"))
53 (define exception:misplaced-else-clause
54 (cons 'syntax-error "Misplaced else clause"))
55 (define exception:bad-case-clause
56 (cons 'syntax-error "Bad case clause"))
57 (define exception:bad-case-labels
58 (cons 'syntax-error "Bad case labels"))
59 (define exception:bad-cond-clause
60 (cons 'syntax-error "Bad cond clause"))
63 (with-test-prefix "expressions"
65 (with-test-prefix "Bad argument list"
67 (pass-if-exception "improper argument list of length 1"
68 exception:wrong-num-args
69 (eval '(let ((foo (lambda (x y) #t)))
71 (interaction-environment)))
73 (pass-if-exception "improper argument list of length 2"
74 exception:wrong-num-args
75 (eval '(let ((foo (lambda (x y) #t)))
77 (interaction-environment))))
79 (with-test-prefix "missing or extra expression"
82 ;; *Note:* In many dialects of Lisp, the empty combination, (),
83 ;; is a legitimate expression. In Scheme, combinations must
84 ;; have at least one subexpression, so () is not a syntactically
88 (pass-if-exception "empty parentheses \"()\""
89 exception:missing/extra-expr-misc
91 (interaction-environment)))))
93 (with-test-prefix "quote"
96 (with-test-prefix "quasiquote"
98 (with-test-prefix "unquote"
100 (pass-if "repeated execution"
101 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
102 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
104 (with-test-prefix "unquote-splicing"
106 (pass-if-exception "extra arguments"
107 exception:missing/extra-expr
108 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
110 (with-test-prefix "begin"
112 (pass-if "legal (begin)"
116 (expect-fail-exception "illegal (begin)"
121 (with-test-prefix "lambda"
123 (with-test-prefix "bad formals"
125 (pass-if-exception "(lambda)"
126 exception:missing-expr
128 (interaction-environment)))
130 (pass-if-exception "(lambda . \"foo\")"
131 exception:bad-expression
132 (eval '(lambda . "foo")
133 (interaction-environment)))
135 (pass-if-exception "(lambda \"foo\")"
136 exception:missing-expr
137 (eval '(lambda "foo")
138 (interaction-environment)))
140 (pass-if-exception "(lambda \"foo\" #f)"
141 exception:bad-formals
142 (eval '(lambda "foo" #f)
143 (interaction-environment)))
145 (pass-if-exception "(lambda (x 1) 2)"
147 (eval '(lambda (x 1) 2)
148 (interaction-environment)))
150 (pass-if-exception "(lambda (1 x) 2)"
152 (eval '(lambda (1 x) 2)
153 (interaction-environment)))
155 (pass-if-exception "(lambda (x \"a\") 2)"
157 (eval '(lambda (x "a") 2)
158 (interaction-environment)))
160 (pass-if-exception "(lambda (\"a\" x) 2)"
162 (eval '(lambda ("a" x) 2)
163 (interaction-environment))))
165 (with-test-prefix "duplicate formals"
168 (pass-if-exception "(lambda (x x) 1)"
169 exception:duplicate-formal
170 (eval '(lambda (x x) 1)
171 (interaction-environment)))
174 (pass-if-exception "(lambda (x x x) 1)"
175 exception:duplicate-formal
176 (eval '(lambda (x x x) 1)
177 (interaction-environment))))
179 (with-test-prefix "bad body"
181 (pass-if-exception "(lambda ())"
182 exception:missing-expr
184 (interaction-environment)))))
186 (with-test-prefix "let"
188 (with-test-prefix "bindings"
190 (pass-if-exception "late binding"
191 exception:unbound-var
192 (let ((x 1) (y x)) y)))
194 (with-test-prefix "bad bindings"
196 (pass-if-exception "(let)"
197 exception:missing-expr
199 (interaction-environment)))
201 (pass-if-exception "(let 1)"
202 exception:missing-expr
204 (interaction-environment)))
206 (pass-if-exception "(let (x))"
207 exception:missing-expr
209 (interaction-environment)))
211 (pass-if-exception "(let ((x)))"
212 exception:missing-expr
214 (interaction-environment)))
216 (pass-if-exception "(let (x) 1)"
217 exception:bad-binding
219 (interaction-environment)))
221 (pass-if-exception "(let ((x)) 3)"
222 exception:bad-binding
224 (interaction-environment)))
226 (pass-if-exception "(let ((x 1) y) x)"
227 exception:bad-binding
228 (eval '(let ((x 1) y) x)
229 (interaction-environment)))
231 (pass-if-exception "(let ((1 2)) 3)"
232 exception:bad-variable
233 (eval '(let ((1 2)) 3)
234 (interaction-environment))))
236 (with-test-prefix "duplicate bindings"
238 (pass-if-exception "(let ((x 1) (x 2)) x)"
239 exception:duplicate-binding
240 (eval '(let ((x 1) (x 2)) x)
241 (interaction-environment))))
243 (with-test-prefix "bad body"
245 (pass-if-exception "(let ())"
246 exception:missing-expr
248 (interaction-environment)))
250 (pass-if-exception "(let ((x 1)))"
251 exception:missing-expr
253 (interaction-environment)))))
255 (with-test-prefix "named let"
257 (with-test-prefix "initializers"
259 (pass-if "evaluated in outer environment"
261 (eqv? (let f ((n (f 1))) n) -1))))
263 (with-test-prefix "bad bindings"
265 (pass-if-exception "(let x (y))"
266 exception:missing-expr
268 (interaction-environment))))
270 (with-test-prefix "bad body"
272 (pass-if-exception "(let x ())"
273 exception:missing-expr
275 (interaction-environment)))
277 (pass-if-exception "(let x ((y 1)))"
278 exception:missing-expr
279 (eval '(let x ((y 1)))
280 (interaction-environment)))))
282 (with-test-prefix "let*"
284 (with-test-prefix "bindings"
286 (pass-if "(let* ((x 1) (x 2)) ...)"
290 (pass-if "(let* ((x 1) (x x)) ...)"
294 (with-test-prefix "bad bindings"
296 (pass-if-exception "(let*)"
297 exception:missing-expr
299 (interaction-environment)))
301 (pass-if-exception "(let* 1)"
302 exception:missing-expr
304 (interaction-environment)))
306 (pass-if-exception "(let* (x))"
307 exception:missing-expr
309 (interaction-environment)))
311 (pass-if-exception "(let* (x) 1)"
312 exception:bad-binding
314 (interaction-environment)))
316 (pass-if-exception "(let* ((x)) 3)"
317 exception:bad-binding
318 (eval '(let* ((x)) 3)
319 (interaction-environment)))
321 (pass-if-exception "(let* ((x 1) y) x)"
322 exception:bad-binding
323 (eval '(let* ((x 1) y) x)
324 (interaction-environment)))
326 (pass-if-exception "(let* x ())"
327 exception:bad-bindings
329 (interaction-environment)))
331 (pass-if-exception "(let* x (y))"
332 exception:bad-bindings
334 (interaction-environment)))
336 (pass-if-exception "(let* ((1 2)) 3)"
337 exception:bad-variable
338 (eval '(let* ((1 2)) 3)
339 (interaction-environment))))
341 (with-test-prefix "bad body"
343 (pass-if-exception "(let* ())"
344 exception:missing-expr
346 (interaction-environment)))
348 (pass-if-exception "(let* ((x 1)))"
349 exception:missing-expr
350 (eval '(let* ((x 1)))
351 (interaction-environment)))))
353 (with-test-prefix "letrec"
355 (with-test-prefix "bindings"
357 (pass-if-exception "initial bindings are undefined"
358 exception:unbound-var
360 (letrec ((x 1) (y x)) y))))
362 (with-test-prefix "bad bindings"
364 (pass-if-exception "(letrec)"
365 exception:missing-expr
367 (interaction-environment)))
369 (pass-if-exception "(letrec 1)"
370 exception:missing-expr
372 (interaction-environment)))
374 (pass-if-exception "(letrec (x))"
375 exception:missing-expr
377 (interaction-environment)))
379 (pass-if-exception "(letrec (x) 1)"
380 exception:bad-binding
381 (eval '(letrec (x) 1)
382 (interaction-environment)))
384 (pass-if-exception "(letrec ((x)) 3)"
385 exception:bad-binding
386 (eval '(letrec ((x)) 3)
387 (interaction-environment)))
389 (pass-if-exception "(letrec ((x 1) y) x)"
390 exception:bad-binding
391 (eval '(letrec ((x 1) y) x)
392 (interaction-environment)))
394 (pass-if-exception "(letrec x ())"
395 exception:bad-bindings
397 (interaction-environment)))
399 (pass-if-exception "(letrec x (y))"
400 exception:bad-bindings
401 (eval '(letrec x (y))
402 (interaction-environment)))
404 (pass-if-exception "(letrec ((1 2)) 3)"
405 exception:bad-variable
406 (eval '(letrec ((1 2)) 3)
407 (interaction-environment))))
409 (with-test-prefix "duplicate bindings"
411 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
412 exception:duplicate-binding
413 (eval '(letrec ((x 1) (x 2)) x)
414 (interaction-environment))))
416 (with-test-prefix "bad body"
418 (pass-if-exception "(letrec ())"
419 exception:missing-expr
421 (interaction-environment)))
423 (pass-if-exception "(letrec ((x 1)))"
424 exception:missing-expr
425 (eval '(letrec ((x 1)))
426 (interaction-environment)))))
428 (with-test-prefix "if"
430 (with-test-prefix "missing or extra expressions"
432 (pass-if-exception "(if)"
433 exception:missing/extra-expr
435 (interaction-environment)))
437 (pass-if-exception "(if 1 2 3 4)"
438 exception:missing/extra-expr
440 (interaction-environment)))))
442 (with-test-prefix "cond"
444 (with-test-prefix "bad or missing clauses"
446 (pass-if-exception "(cond)"
447 exception:missing-clauses
449 (interaction-environment)))
451 (pass-if-exception "(cond #t)"
452 exception:bad-cond-clause
454 (interaction-environment)))
456 (pass-if-exception "(cond 1)"
457 exception:bad-cond-clause
459 (interaction-environment)))
461 (pass-if-exception "(cond 1 2)"
462 exception:bad-cond-clause
464 (interaction-environment)))
466 (pass-if-exception "(cond 1 2 3)"
467 exception:bad-cond-clause
469 (interaction-environment)))
471 (pass-if-exception "(cond 1 2 3 4)"
472 exception:bad-cond-clause
473 (eval '(cond 1 2 3 4)
474 (interaction-environment)))
476 (pass-if-exception "(cond ())"
477 exception:bad-cond-clause
479 (interaction-environment)))
481 (pass-if-exception "(cond () 1)"
482 exception:bad-cond-clause
484 (interaction-environment)))
486 (pass-if-exception "(cond (1) 1)"
487 exception:bad-cond-clause
489 (interaction-environment)))))
491 (with-test-prefix "cond =>"
493 (with-test-prefix "cond is hygienic"
495 (pass-if "bound 'else is handled correctly"
496 (eq? (let ((else 'ok)) (cond (else))) 'ok))
498 (pass-if "bound '=> is handled correctly"
499 (eq? (let ((=> #f)) (cond (#t => 'ok))) 'ok)))
501 (with-test-prefix "else is handled correctly"
505 (eq? (cond (else =>)) 'foo)))
507 (pass-if "else => identity"
509 (eq? (cond (else => identity)) identity))))
511 (with-test-prefix "wrong number of arguments"
513 (pass-if-exception "=> (lambda (x y) #t)"
514 exception:wrong-num-args
515 (cond (1 => (lambda (x y) #t))))))
517 (with-test-prefix "case"
519 (pass-if "clause with empty labels list"
520 (case 1 (() #f) (else #t)))
522 (with-test-prefix "case is hygienic"
524 (pass-if-exception "bound 'else is handled correctly"
525 exception:bad-case-labels
526 (eval '(let ((else #f)) (case 1 (else #f)))
527 (interaction-environment))))
529 (with-test-prefix "bad or missing clauses"
531 (pass-if-exception "(case)"
532 exception:missing-clauses
534 (interaction-environment)))
536 (pass-if-exception "(case . \"foo\")"
537 exception:bad-expression
538 (eval '(case . "foo")
539 (interaction-environment)))
541 (pass-if-exception "(case 1)"
542 exception:missing-clauses
544 (interaction-environment)))
546 (pass-if-exception "(case 1 . \"foo\")"
547 exception:bad-expression
548 (eval '(case 1 . "foo")
549 (interaction-environment)))
551 (pass-if-exception "(case 1 \"foo\")"
552 exception:bad-case-clause
553 (eval '(case 1 "foo")
554 (interaction-environment)))
556 (pass-if-exception "(case 1 ())"
557 exception:bad-case-clause
559 (interaction-environment)))
561 (pass-if-exception "(case 1 (\"foo\"))"
562 exception:bad-case-clause
563 (eval '(case 1 ("foo"))
564 (interaction-environment)))
566 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
567 exception:bad-case-labels
568 (eval '(case 1 ("foo" "bar"))
569 (interaction-environment)))
571 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
572 exception:bad-expression
573 (eval '(case 1 ((2) "bar") . "foo")
574 (interaction-environment)))
576 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
577 exception:bad-case-clause
578 (eval '(case 1 ((2) "bar") (else))
579 (interaction-environment)))
581 (pass-if-exception "(case 1 (else #f) . \"foo\")"
582 exception:bad-expression
583 (eval '(case 1 (else #f) . "foo")
584 (interaction-environment)))
586 (pass-if-exception "(case 1 (else #f) ((1) #t))"
587 exception:misplaced-else-clause
588 (eval '(case 1 (else #f) ((1) #t))
589 (interaction-environment)))))
591 (with-test-prefix "define"
593 (with-test-prefix "currying"
595 (pass-if "(define ((foo)) #f)"
599 (with-test-prefix "missing or extra expressions"
601 (pass-if-exception "(define)"
602 exception:missing-expr
604 (interaction-environment)))))
606 (with-test-prefix "set!"
608 (with-test-prefix "missing or extra expressions"
610 (pass-if-exception "(set!)"
611 exception:missing/extra-expr
613 (interaction-environment)))
615 (pass-if-exception "(set! 1)"
616 exception:missing/extra-expr
618 (interaction-environment)))
620 (pass-if-exception "(set! 1 2 3)"
621 exception:missing/extra-expr
623 (interaction-environment))))
625 (with-test-prefix "bad variable"
627 (pass-if-exception "(set! \"\" #t)"
628 exception:bad-variable
630 (interaction-environment)))
632 (pass-if-exception "(set! 1 #t)"
633 exception:bad-variable
635 (interaction-environment)))
637 (pass-if-exception "(set! #t #f)"
638 exception:bad-variable
640 (interaction-environment)))
642 (pass-if-exception "(set! #f #t)"
643 exception:bad-variable
645 (interaction-environment)))
647 (pass-if-exception "(set! #\space #f)"
648 exception:bad-variable
649 (eval '(set! #\space #f)
650 (interaction-environment)))))
652 (with-test-prefix "quote"
654 (with-test-prefix "missing or extra expression"
656 (pass-if-exception "(quote)"
657 exception:missing/extra-expr
659 (interaction-environment)))
661 (pass-if-exception "(quote a b)"
662 exception:missing/extra-expr
664 (interaction-environment)))))
666 (with-test-prefix "while"
668 (define (unreachable)
669 (error "unreachable code has been reached!"))
671 ;; Return a new procedure COND which when called (COND) will return #t the
672 ;; first N times, then #f, then any further call is an error. N=0 is
673 ;; allowed, in which case #f is returned by the first call.
674 (define (make-iterations-cond n)
677 (error "oops, condition re-tested after giving false"))
686 (pass-if-exception "too few args" exception:wrong-num-args
687 (eval '(while) (interaction-environment)))
689 (with-test-prefix "empty body"
693 (let ((cond (make-iterations-cond n)))
697 (pass-if "initially false"
702 (with-test-prefix "in empty environment"
704 ;; an environment with no bindings at all
705 (define empty-environment
708 (pass-if "empty body"
713 (pass-if "initially false"
720 (let ((cond (make-iterations-cond 3)))
721 (eval `(,while (,cond)
726 (with-test-prefix "iterations"
730 (let ((cond (make-iterations-cond n))
736 (with-test-prefix "break"
738 (pass-if-exception "too many args" exception:wrong-num-args
742 (with-test-prefix "from cond"
753 (let ((cond (make-iterations-cond n))
763 (with-test-prefix "from body"
773 (let ((cond (make-iterations-cond n))
783 (pass-if "from nested"
785 (let ((outer-break break))
792 (pass-if "from recursive"
793 (let ((outer-break #f))
798 (set! outer-break break)
804 (error "broke only from inner loop")))
808 (with-test-prefix "continue"
810 (pass-if-exception "too many args" exception:wrong-num-args
814 (with-test-prefix "from cond"
818 (let ((cond (make-iterations-cond n))
829 (with-test-prefix "from body"
833 (let ((cond (make-iterations-cond n))
841 (pass-if "from nested"
842 (let ((cond (make-iterations-cond 3)))
844 (let ((outer-continue continue))
850 (pass-if "from recursive"
851 (let ((outer-continue #f))
853 (let ((cond (make-iterations-cond 3))
858 (error "continued only to inner loop"))
863 (set! outer-continue continue)