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 'syntax-error "Missing or extra expression"))
29 (define exception:missing-expr
30 (cons 'syntax-error "Missing expression"))
31 (define exception:missing-body-expr
32 (cons 'syntax-error "Missing body expression"))
33 (define exception:extra-expr
34 (cons 'syntax-error "Extra expression"))
35 (define exception:illegal-empty-combination
36 (cons 'syntax-error "Illegal empty combination"))
38 (define exception:bad-bindings
39 (cons 'syntax-error "Bad bindings"))
40 (define exception:bad-binding
41 (cons 'syntax-error "Bad binding"))
42 (define exception:duplicate-binding
43 (cons 'syntax-error "Duplicate binding"))
44 (define exception:bad-body
45 (cons 'misc-error "^bad body"))
46 (define exception:bad-formals
47 (cons 'syntax-error "Bad formals"))
48 (define exception:bad-formal
49 (cons 'syntax-error "Bad formal"))
50 (define exception:duplicate-formal
51 (cons 'syntax-error "Duplicate formal"))
53 (define exception:missing-clauses
54 (cons 'syntax-error "Missing clauses"))
55 (define exception:misplaced-else-clause
56 (cons 'syntax-error "Misplaced else clause"))
57 (define exception:bad-case-clause
58 (cons 'syntax-error "Bad case clause"))
59 (define exception:bad-case-labels
60 (cons 'syntax-error "Bad case labels"))
61 (define exception:bad-cond-clause
62 (cons 'syntax-error "Bad cond clause"))
65 (with-test-prefix "expressions"
67 (with-test-prefix "Bad argument list"
69 (pass-if-exception "improper argument list of length 1"
70 exception:wrong-num-args
71 (eval '(let ((foo (lambda (x y) #t)))
73 (interaction-environment)))
75 (pass-if-exception "improper argument list of length 2"
76 exception:wrong-num-args
77 (eval '(let ((foo (lambda (x y) #t)))
79 (interaction-environment))))
81 (with-test-prefix "missing or extra expression"
84 ;; *Note:* In many dialects of Lisp, the empty combination, (),
85 ;; is a legitimate expression. In Scheme, combinations must
86 ;; have at least one subexpression, so () is not a syntactically
90 (pass-if-exception "empty parentheses \"()\""
91 exception:illegal-empty-combination
93 (interaction-environment)))))
95 (with-test-prefix "quote"
98 (with-test-prefix "quasiquote"
100 (with-test-prefix "unquote"
102 (pass-if "repeated execution"
103 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
104 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
106 (with-test-prefix "unquote-splicing"
108 (pass-if-exception "extra arguments"
109 exception:missing/extra-expr
110 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
112 (with-test-prefix "begin"
114 (pass-if "legal (begin)"
118 (expect-fail-exception "illegal (begin)"
123 (with-test-prefix "lambda"
125 (with-test-prefix "bad formals"
127 (pass-if-exception "(lambda)"
128 exception:missing-expr
130 (interaction-environment)))
132 (pass-if-exception "(lambda . \"foo\")"
133 exception:bad-expression
134 (eval '(lambda . "foo")
135 (interaction-environment)))
137 (pass-if-exception "(lambda \"foo\")"
138 exception:missing-expr
139 (eval '(lambda "foo")
140 (interaction-environment)))
142 (pass-if-exception "(lambda \"foo\" #f)"
143 exception:bad-formals
144 (eval '(lambda "foo" #f)
145 (interaction-environment)))
147 (pass-if-exception "(lambda (x 1) 2)"
149 (eval '(lambda (x 1) 2)
150 (interaction-environment)))
152 (pass-if-exception "(lambda (1 x) 2)"
154 (eval '(lambda (1 x) 2)
155 (interaction-environment)))
157 (pass-if-exception "(lambda (x \"a\") 2)"
159 (eval '(lambda (x "a") 2)
160 (interaction-environment)))
162 (pass-if-exception "(lambda (\"a\" x) 2)"
164 (eval '(lambda ("a" x) 2)
165 (interaction-environment))))
167 (with-test-prefix "duplicate formals"
170 (pass-if-exception "(lambda (x x) 1)"
171 exception:duplicate-formal
172 (eval '(lambda (x x) 1)
173 (interaction-environment)))
176 (pass-if-exception "(lambda (x x x) 1)"
177 exception:duplicate-formal
178 (eval '(lambda (x x x) 1)
179 (interaction-environment))))
181 (with-test-prefix "bad body"
183 (pass-if-exception "(lambda ())"
184 exception:missing-expr
186 (interaction-environment)))))
188 (with-test-prefix "let"
190 (with-test-prefix "bindings"
192 (pass-if-exception "late binding"
193 exception:unbound-var
194 (let ((x 1) (y x)) y)))
196 (with-test-prefix "bad bindings"
198 (pass-if-exception "(let)"
199 exception:missing-expr
201 (interaction-environment)))
203 (pass-if-exception "(let 1)"
204 exception:missing-expr
206 (interaction-environment)))
208 (pass-if-exception "(let (x))"
209 exception:missing-expr
211 (interaction-environment)))
213 (pass-if-exception "(let ((x)))"
214 exception:missing-expr
216 (interaction-environment)))
218 (pass-if-exception "(let (x) 1)"
219 exception:bad-binding
221 (interaction-environment)))
223 (pass-if-exception "(let ((x)) 3)"
224 exception:bad-binding
226 (interaction-environment)))
228 (pass-if-exception "(let ((x 1) y) x)"
229 exception:bad-binding
230 (eval '(let ((x 1) y) x)
231 (interaction-environment)))
233 (pass-if-exception "(let ((1 2)) 3)"
234 exception:bad-variable
235 (eval '(let ((1 2)) 3)
236 (interaction-environment))))
238 (with-test-prefix "duplicate bindings"
240 (pass-if-exception "(let ((x 1) (x 2)) x)"
241 exception:duplicate-binding
242 (eval '(let ((x 1) (x 2)) x)
243 (interaction-environment))))
245 (with-test-prefix "bad body"
247 (pass-if-exception "(let ())"
248 exception:missing-expr
250 (interaction-environment)))
252 (pass-if-exception "(let ((x 1)))"
253 exception:missing-expr
255 (interaction-environment)))))
257 (with-test-prefix "named let"
259 (with-test-prefix "initializers"
261 (pass-if "evaluated in outer environment"
263 (eqv? (let f ((n (f 1))) n) -1))))
265 (with-test-prefix "bad bindings"
267 (pass-if-exception "(let x (y))"
268 exception:missing-expr
270 (interaction-environment))))
272 (with-test-prefix "bad body"
274 (pass-if-exception "(let x ())"
275 exception:missing-expr
277 (interaction-environment)))
279 (pass-if-exception "(let x ((y 1)))"
280 exception:missing-expr
281 (eval '(let x ((y 1)))
282 (interaction-environment)))))
284 (with-test-prefix "let*"
286 (with-test-prefix "bindings"
288 (pass-if "(let* ((x 1) (x 2)) ...)"
292 (pass-if "(let* ((x 1) (x x)) ...)"
296 (with-test-prefix "bad bindings"
298 (pass-if-exception "(let*)"
299 exception:missing-expr
301 (interaction-environment)))
303 (pass-if-exception "(let* 1)"
304 exception:missing-expr
306 (interaction-environment)))
308 (pass-if-exception "(let* (x))"
309 exception:missing-expr
311 (interaction-environment)))
313 (pass-if-exception "(let* (x) 1)"
314 exception:bad-binding
316 (interaction-environment)))
318 (pass-if-exception "(let* ((x)) 3)"
319 exception:bad-binding
320 (eval '(let* ((x)) 3)
321 (interaction-environment)))
323 (pass-if-exception "(let* ((x 1) y) x)"
324 exception:bad-binding
325 (eval '(let* ((x 1) y) x)
326 (interaction-environment)))
328 (pass-if-exception "(let* x ())"
329 exception:bad-bindings
331 (interaction-environment)))
333 (pass-if-exception "(let* x (y))"
334 exception:bad-bindings
336 (interaction-environment)))
338 (pass-if-exception "(let* ((1 2)) 3)"
339 exception:bad-variable
340 (eval '(let* ((1 2)) 3)
341 (interaction-environment))))
343 (with-test-prefix "bad body"
345 (pass-if-exception "(let* ())"
346 exception:missing-expr
348 (interaction-environment)))
350 (pass-if-exception "(let* ((x 1)))"
351 exception:missing-expr
352 (eval '(let* ((x 1)))
353 (interaction-environment)))))
355 (with-test-prefix "letrec"
357 (with-test-prefix "bindings"
359 (pass-if-exception "initial bindings are undefined"
360 exception:unbound-var
362 (letrec ((x 1) (y x)) y))))
364 (with-test-prefix "bad bindings"
366 (pass-if-exception "(letrec)"
367 exception:missing-expr
369 (interaction-environment)))
371 (pass-if-exception "(letrec 1)"
372 exception:missing-expr
374 (interaction-environment)))
376 (pass-if-exception "(letrec (x))"
377 exception:missing-expr
379 (interaction-environment)))
381 (pass-if-exception "(letrec (x) 1)"
382 exception:bad-binding
383 (eval '(letrec (x) 1)
384 (interaction-environment)))
386 (pass-if-exception "(letrec ((x)) 3)"
387 exception:bad-binding
388 (eval '(letrec ((x)) 3)
389 (interaction-environment)))
391 (pass-if-exception "(letrec ((x 1) y) x)"
392 exception:bad-binding
393 (eval '(letrec ((x 1) y) x)
394 (interaction-environment)))
396 (pass-if-exception "(letrec x ())"
397 exception:bad-bindings
399 (interaction-environment)))
401 (pass-if-exception "(letrec x (y))"
402 exception:bad-bindings
403 (eval '(letrec x (y))
404 (interaction-environment)))
406 (pass-if-exception "(letrec ((1 2)) 3)"
407 exception:bad-variable
408 (eval '(letrec ((1 2)) 3)
409 (interaction-environment))))
411 (with-test-prefix "duplicate bindings"
413 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
414 exception:duplicate-binding
415 (eval '(letrec ((x 1) (x 2)) x)
416 (interaction-environment))))
418 (with-test-prefix "bad body"
420 (pass-if-exception "(letrec ())"
421 exception:missing-expr
423 (interaction-environment)))
425 (pass-if-exception "(letrec ((x 1)))"
426 exception:missing-expr
427 (eval '(letrec ((x 1)))
428 (interaction-environment)))))
430 (with-test-prefix "if"
432 (with-test-prefix "missing or extra expressions"
434 (pass-if-exception "(if)"
435 exception:missing/extra-expr
437 (interaction-environment)))
439 (pass-if-exception "(if 1 2 3 4)"
440 exception:missing/extra-expr
442 (interaction-environment)))))
444 (with-test-prefix "cond"
446 (with-test-prefix "bad or missing clauses"
448 (pass-if-exception "(cond)"
449 exception:missing-clauses
451 (interaction-environment)))
453 (pass-if-exception "(cond #t)"
454 exception:bad-cond-clause
456 (interaction-environment)))
458 (pass-if-exception "(cond 1)"
459 exception:bad-cond-clause
461 (interaction-environment)))
463 (pass-if-exception "(cond 1 2)"
464 exception:bad-cond-clause
466 (interaction-environment)))
468 (pass-if-exception "(cond 1 2 3)"
469 exception:bad-cond-clause
471 (interaction-environment)))
473 (pass-if-exception "(cond 1 2 3 4)"
474 exception:bad-cond-clause
475 (eval '(cond 1 2 3 4)
476 (interaction-environment)))
478 (pass-if-exception "(cond ())"
479 exception:bad-cond-clause
481 (interaction-environment)))
483 (pass-if-exception "(cond () 1)"
484 exception:bad-cond-clause
486 (interaction-environment)))
488 (pass-if-exception "(cond (1) 1)"
489 exception:bad-cond-clause
491 (interaction-environment)))))
493 (with-test-prefix "cond =>"
495 (with-test-prefix "cond is hygienic"
497 (pass-if "bound 'else is handled correctly"
498 (eq? (let ((else 'ok)) (cond (else))) 'ok))
500 (pass-if "bound '=> is handled correctly"
501 (eq? (let ((=> #f)) (cond (#t => 'ok))) 'ok)))
503 (with-test-prefix "else is handled correctly"
507 (eq? (cond (else =>)) 'foo)))
509 (pass-if "else => identity"
511 (eq? (cond (else => identity)) identity))))
513 (with-test-prefix "wrong number of arguments"
515 (pass-if-exception "=> (lambda (x y) #t)"
516 exception:wrong-num-args
517 (cond (1 => (lambda (x y) #t))))))
519 (with-test-prefix "case"
521 (pass-if "clause with empty labels list"
522 (case 1 (() #f) (else #t)))
524 (with-test-prefix "case is hygienic"
526 (pass-if-exception "bound 'else is handled correctly"
527 exception:bad-case-labels
528 (eval '(let ((else #f)) (case 1 (else #f)))
529 (interaction-environment))))
531 (with-test-prefix "bad or missing clauses"
533 (pass-if-exception "(case)"
534 exception:missing-clauses
536 (interaction-environment)))
538 (pass-if-exception "(case . \"foo\")"
539 exception:bad-expression
540 (eval '(case . "foo")
541 (interaction-environment)))
543 (pass-if-exception "(case 1)"
544 exception:missing-clauses
546 (interaction-environment)))
548 (pass-if-exception "(case 1 . \"foo\")"
549 exception:bad-expression
550 (eval '(case 1 . "foo")
551 (interaction-environment)))
553 (pass-if-exception "(case 1 \"foo\")"
554 exception:bad-case-clause
555 (eval '(case 1 "foo")
556 (interaction-environment)))
558 (pass-if-exception "(case 1 ())"
559 exception:bad-case-clause
561 (interaction-environment)))
563 (pass-if-exception "(case 1 (\"foo\"))"
564 exception:bad-case-clause
565 (eval '(case 1 ("foo"))
566 (interaction-environment)))
568 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
569 exception:bad-case-labels
570 (eval '(case 1 ("foo" "bar"))
571 (interaction-environment)))
573 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
574 exception:bad-expression
575 (eval '(case 1 ((2) "bar") . "foo")
576 (interaction-environment)))
578 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
579 exception:bad-case-clause
580 (eval '(case 1 ((2) "bar") (else))
581 (interaction-environment)))
583 (pass-if-exception "(case 1 (else #f) . \"foo\")"
584 exception:bad-expression
585 (eval '(case 1 (else #f) . "foo")
586 (interaction-environment)))
588 (pass-if-exception "(case 1 (else #f) ((1) #t))"
589 exception:misplaced-else-clause
590 (eval '(case 1 (else #f) ((1) #t))
591 (interaction-environment)))))
593 (with-test-prefix "top-level define"
595 (pass-if "binding is created before expression is evaluated"
602 (interaction-environment))
605 (with-test-prefix "currying"
607 (pass-if "(define ((foo)) #f)"
611 (interaction-environment))))
613 (with-test-prefix "missing or extra expressions"
615 (pass-if-exception "(define)"
616 exception:missing-expr
618 (interaction-environment)))))
620 (with-test-prefix "internal define"
622 (pass-if "internal defines become letrec"
623 (eval '(let ((a identity) (b identity) (c identity))
624 (define (a x) (if (= x 0) 'a (b (- x 1))))
625 (define (b x) (if (= x 0) 'b (c (- x 1))))
626 (define (c x) (if (= x 0) 'c (a (- x 1))))
627 (and (eq? 'a (a 0) (a 3))
629 (eq? 'c (a 2) (a 5))))
630 (interaction-environment)))
632 (pass-if "internal defines with begin"
634 (eval '(let ((a identity) (b identity) (c identity))
635 (define (a x) (if (= x 0) 'a (b (- x 1))))
637 (define (b x) (if (= x 0) 'b (c (- x 1)))))
638 (define (c x) (if (= x 0) 'c (a (- x 1))))
639 (and (eq? 'a (a 0) (a 3))
641 (eq? 'c (a 2) (a 5))))
642 (interaction-environment))))
644 (pass-if "internal defines with empty begin"
646 (eval '(let ((a identity) (b identity) (c identity))
647 (define (a x) (if (= x 0) 'a (b (- x 1))))
649 (define (b x) (if (= x 0) 'b (c (- x 1))))
650 (define (c x) (if (= x 0) 'c (a (- x 1))))
651 (and (eq? 'a (a 0) (a 3))
653 (eq? 'c (a 2) (a 5))))
654 (interaction-environment))))
656 (pass-if "internal defines with macro application"
659 (defmacro my-define forms
660 (cons 'define forms))
661 (let ((a identity) (b identity) (c identity))
662 (define (a x) (if (= x 0) 'a (b (- x 1))))
663 (my-define (b x) (if (= x 0) 'b (c (- x 1))))
664 (define (c x) (if (= x 0) 'c (a (- x 1))))
665 (and (eq? 'a (a 0) (a 3))
667 (eq? 'c (a 2) (a 5)))))
668 (interaction-environment))))
670 (pass-if-exception "missing body expression"
671 exception:missing-body-expr
672 (eval '(let () (define x #t))
673 (interaction-environment)))
675 (pass-if "unmemoization"
683 (procedure-source foo)
684 '(lambda () (letrec ((bar (lambda () (quote ok)))) (bar)))))
685 (interaction-environment))))
687 (with-test-prefix "set!"
689 (with-test-prefix "missing or extra expressions"
691 (pass-if-exception "(set!)"
692 exception:missing/extra-expr
694 (interaction-environment)))
696 (pass-if-exception "(set! 1)"
697 exception:missing/extra-expr
699 (interaction-environment)))
701 (pass-if-exception "(set! 1 2 3)"
702 exception:missing/extra-expr
704 (interaction-environment))))
706 (with-test-prefix "bad variable"
708 (pass-if-exception "(set! \"\" #t)"
709 exception:bad-variable
711 (interaction-environment)))
713 (pass-if-exception "(set! 1 #t)"
714 exception:bad-variable
716 (interaction-environment)))
718 (pass-if-exception "(set! #t #f)"
719 exception:bad-variable
721 (interaction-environment)))
723 (pass-if-exception "(set! #f #t)"
724 exception:bad-variable
726 (interaction-environment)))
728 (pass-if-exception "(set! #\\space #f)"
729 exception:bad-variable
730 (eval '(set! #\space #f)
731 (interaction-environment)))))
733 (with-test-prefix "quote"
735 (with-test-prefix "missing or extra expression"
737 (pass-if-exception "(quote)"
738 exception:missing/extra-expr
740 (interaction-environment)))
742 (pass-if-exception "(quote a b)"
743 exception:missing/extra-expr
745 (interaction-environment)))))
747 (with-test-prefix "while"
749 (define (unreachable)
750 (error "unreachable code has been reached!"))
752 ;; Return a new procedure COND which when called (COND) will return #t the
753 ;; first N times, then #f, then any further call is an error. N=0 is
754 ;; allowed, in which case #f is returned by the first call.
755 (define (make-iterations-cond n)
758 (error "oops, condition re-tested after giving false"))
767 (pass-if-exception "too few args" exception:wrong-num-args
768 (eval '(while) (interaction-environment)))
770 (with-test-prefix "empty body"
774 (let ((cond (make-iterations-cond n)))
778 (pass-if "initially false"
783 (with-test-prefix "in empty environment"
785 ;; an environment with no bindings at all
786 (define empty-environment
789 (pass-if "empty body"
794 (pass-if "initially false"
801 (let ((cond (make-iterations-cond 3)))
802 (eval `(,while (,cond)
807 (with-test-prefix "iterations"
811 (let ((cond (make-iterations-cond n))
817 (with-test-prefix "break"
819 (pass-if-exception "too many args" exception:wrong-num-args
823 (with-test-prefix "from cond"
834 (let ((cond (make-iterations-cond n))
844 (with-test-prefix "from body"
854 (let ((cond (make-iterations-cond n))
864 (pass-if "from nested"
866 (let ((outer-break break))
873 (pass-if "from recursive"
874 (let ((outer-break #f))
879 (set! outer-break break)
885 (error "broke only from inner loop")))
889 (with-test-prefix "continue"
891 (pass-if-exception "too many args" exception:wrong-num-args
895 (with-test-prefix "from cond"
899 (let ((cond (make-iterations-cond n))
910 (with-test-prefix "from body"
914 (let ((cond (make-iterations-cond n))
922 (pass-if "from nested"
923 (let ((cond (make-iterations-cond 3)))
925 (let ((outer-continue continue))
931 (pass-if "from recursive"
932 (let ((outer-continue #f))
934 (let ((cond (make-iterations-cond 3))
939 (error "continued only to inner loop"))
944 (set! outer-continue continue)