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
21 (define exception:bad-bindings
22 (cons 'misc-error "^bad bindings"))
23 (define exception:duplicate-bindings
24 (cons 'misc-error "^duplicate bindings"))
25 (define exception:bad-body
26 (cons 'misc-error "^bad body"))
27 (define exception:bad-formals
28 (cons 'misc-error "^bad formals"))
29 (define exception:duplicate-formals
30 (cons 'misc-error "^duplicate formals"))
31 (define exception:bad-var
32 (cons 'misc-error "^bad variable"))
33 (define exception:bad/missing-clauses
34 (cons 'misc-error "^bad or missing clauses"))
35 (define exception:missing/extra-expr
36 (cons 'misc-error "^missing or extra expression"))
39 (with-test-prefix "expressions"
41 (with-test-prefix "missing or extra expression"
44 ;; *Note:* In many dialects of Lisp, the empty combination, (),
45 ;; is a legitimate expression. In Scheme, combinations must
46 ;; have at least one subexpression, so () is not a syntactically
50 (pass-if-exception "empty parentheses \"()\""
51 exception:missing/extra-expr
54 (with-test-prefix "quote"
57 (with-test-prefix "quasiquote"
59 (with-test-prefix "unquote"
61 (pass-if "repeated execution"
62 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
63 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
65 (with-test-prefix "unquote-splicing"
67 (pass-if-exception "extra arguments"
68 exception:missing/extra-expr
69 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
71 (with-test-prefix "begin"
73 (pass-if "legal (begin)"
77 (expect-fail-exception "illegal (begin)"
82 (with-test-prefix "lambda"
84 (with-test-prefix "bad formals"
86 (pass-if-exception "(lambda)"
90 (pass-if-exception "(lambda . \"foo\")"
94 (pass-if-exception "(lambda \"foo\")"
98 (pass-if-exception "(lambda \"foo\" #f)"
100 (eval '(lambda "foo" #f)
101 (interaction-environment)))
103 (pass-if-exception "(lambda (x 1) 2)"
104 exception:bad-formals
107 (pass-if-exception "(lambda (1 x) 2)"
108 exception:bad-formals
111 (pass-if-exception "(lambda (x \"a\") 2)"
112 exception:bad-formals
115 (pass-if-exception "(lambda (\"a\" x) 2)"
116 exception:bad-formals
119 (with-test-prefix "duplicate formals"
122 (pass-if-exception "(lambda (x x) 1)"
123 exception:duplicate-formals
127 (pass-if-exception "(lambda (x x x) 1)"
128 exception:duplicate-formals
131 (with-test-prefix "bad body"
133 (pass-if-exception "(lambda ())"
137 (with-test-prefix "let"
139 (with-test-prefix "bindings"
141 (pass-if-exception "late binding"
142 exception:unbound-var
143 (let ((x 1) (y x)) y)))
145 (with-test-prefix "bad bindings"
147 (pass-if-exception "(let)"
148 exception:bad-bindings
151 (pass-if-exception "(let 1)"
152 exception:bad-bindings
155 (pass-if-exception "(let (x))"
156 exception:bad-bindings
159 ;; FIXME: Wouldn't one rather expect a 'bad bindings' error?
160 ;; (Even although the body is bad as well...)
161 (pass-if-exception "(let ((x)))"
165 (pass-if-exception "(let (x) 1)"
166 exception:bad-bindings
169 (pass-if-exception "(let ((x)) 3)"
170 exception:bad-bindings
173 (pass-if-exception "(let ((x 1) y) x)"
174 exception:bad-bindings
177 (pass-if-exception "(let ((1 2)) 3)"
179 (eval '(let ((1 2)) 3)
180 (interaction-environment))))
182 (with-test-prefix "duplicate bindings"
184 (pass-if-exception "(let ((x 1) (x 2)) x)"
185 exception:duplicate-bindings
186 (let ((x 1) (x 2)) x)))
188 (with-test-prefix "bad body"
190 (pass-if-exception "(let ())"
194 (pass-if-exception "(let ((x 1)))"
198 (with-test-prefix "named let"
200 (with-test-prefix "initializers"
202 (pass-if "evaluated in outer environment"
204 (eqv? (let f ((n (f 1))) n) -1))))
206 (with-test-prefix "bad bindings"
208 (pass-if-exception "(let x (y))"
209 exception:bad-bindings
212 (with-test-prefix "bad body"
214 (pass-if-exception "(let x ())"
218 (pass-if-exception "(let x ((y 1)))"
222 (with-test-prefix "let*"
224 (with-test-prefix "bindings"
226 (pass-if "(let* ((x 1) (x 2)) ...)"
230 (pass-if "(let* ((x 1) (x x)) ...)"
234 (with-test-prefix "bad bindings"
236 (pass-if-exception "(let*)"
237 exception:bad-bindings
240 (pass-if-exception "(let* 1)"
241 exception:bad-bindings
244 (pass-if-exception "(let* (x))"
245 exception:bad-bindings
248 (pass-if-exception "(let* (x) 1)"
249 exception:bad-bindings
252 (pass-if-exception "(let* ((x)) 3)"
253 exception:bad-bindings
256 (pass-if-exception "(let* ((x 1) y) x)"
257 exception:bad-bindings
260 (pass-if-exception "(let* x ())"
261 exception:bad-bindings
263 (interaction-environment)))
265 (pass-if-exception "(let* x (y))"
266 exception:bad-bindings
268 (interaction-environment)))
270 (pass-if-exception "(let* ((1 2)) 3)"
272 (eval '(let* ((1 2)) 3)
273 (interaction-environment))))
275 (with-test-prefix "bad body"
277 (pass-if-exception "(let* ())"
281 (pass-if-exception "(let* ((x 1)))"
285 (with-test-prefix "letrec"
287 (with-test-prefix "bindings"
289 (pass-if-exception "initial bindings are undefined"
290 exception:unbound-var
292 (letrec ((x 1) (y x)) y))))
294 (with-test-prefix "bad bindings"
296 (pass-if-exception "(letrec)"
297 exception:bad-bindings
300 (pass-if-exception "(letrec 1)"
301 exception:bad-bindings
304 (pass-if-exception "(letrec (x))"
305 exception:bad-bindings
308 (pass-if-exception "(letrec (x) 1)"
309 exception:bad-bindings
312 (pass-if-exception "(letrec ((x)) 3)"
313 exception:bad-bindings
316 (pass-if-exception "(letrec ((x 1) y) x)"
317 exception:bad-bindings
318 (letrec ((x 1) y) x))
320 (pass-if-exception "(letrec x ())"
321 exception:bad-bindings
323 (interaction-environment)))
325 (pass-if-exception "(letrec x (y))"
326 exception:bad-bindings
327 (eval '(letrec x (y))
328 (interaction-environment)))
330 (pass-if-exception "(letrec ((1 2)) 3)"
332 (eval '(letrec ((1 2)) 3)
333 (interaction-environment))))
335 (with-test-prefix "duplicate bindings"
337 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
338 exception:duplicate-bindings
339 (letrec ((x 1) (x 2)) x)))
341 (with-test-prefix "bad body"
343 (pass-if-exception "(letrec ())"
347 (pass-if-exception "(letrec ((x 1)))"
351 (with-test-prefix "if"
353 (with-test-prefix "missing or extra expressions"
355 (pass-if-exception "(if)"
356 exception:missing/extra-expr
358 (interaction-environment)))
360 (pass-if-exception "(if 1 2 3 4)"
361 exception:missing/extra-expr
363 (interaction-environment)))))
365 (with-test-prefix "cond"
367 (with-test-prefix "bad or missing clauses"
369 (pass-if-exception "(cond)"
370 exception:bad/missing-clauses
373 (pass-if-exception "(cond #t)"
374 exception:bad/missing-clauses
377 (pass-if-exception "(cond 1)"
378 exception:bad/missing-clauses
381 (pass-if-exception "(cond 1 2)"
382 exception:bad/missing-clauses
385 (pass-if-exception "(cond 1 2 3)"
386 exception:bad/missing-clauses
389 (pass-if-exception "(cond 1 2 3 4)"
390 exception:bad/missing-clauses
393 (pass-if-exception "(cond ())"
394 exception:bad/missing-clauses
397 (pass-if-exception "(cond () 1)"
398 exception:bad/missing-clauses
401 (pass-if-exception "(cond (1) 1)"
402 exception:bad/missing-clauses
405 (with-test-prefix "cond =>"
407 (with-test-prefix "else is handled correctly"
411 (eq? (cond (else =>)) 'foo)))
413 (pass-if "else => identity"
415 (eq? (cond (else => identity)) identity))))
417 (with-test-prefix "bad formals"
419 (pass-if-exception "=> (lambda (x 1) 2)"
420 exception:bad-formals
421 (cond (1 => (lambda (x 1) 2))))))
423 (with-test-prefix "case"
425 (with-test-prefix "bad or missing clauses"
427 (pass-if-exception "(case)"
428 exception:bad/missing-clauses
431 (pass-if-exception "(case . \"foo\")"
432 exception:bad/missing-clauses
435 (pass-if-exception "(case 1)"
436 exception:bad/missing-clauses
439 (pass-if-exception "(case 1 . \"foo\")"
440 exception:bad/missing-clauses
443 (pass-if-exception "(case 1 \"foo\")"
444 exception:bad/missing-clauses
447 (pass-if-exception "(case 1 ())"
448 exception:bad/missing-clauses
451 (pass-if-exception "(case 1 (\"foo\"))"
452 exception:bad/missing-clauses
455 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
456 exception:bad/missing-clauses
457 (case 1 ("foo" "bar")))
459 ;; According to R5RS, the following one is syntactically correct.
460 ;; (pass-if-exception "(case 1 (() \"bar\"))"
461 ;; exception:bad/missing-clauses
462 ;; (case 1 (() "bar")))
464 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
465 exception:bad/missing-clauses
466 (case 1 ((2) "bar") . "foo"))
468 (pass-if-exception "(case 1 (else #f) ((1) #t))"
469 exception:bad/missing-clauses
470 (case 1 ((2) "bar") (else)))
472 (pass-if-exception "(case 1 (else #f) . \"foo\")"
473 exception:bad/missing-clauses
474 (case 1 (else #f) . "foo"))
476 (pass-if-exception "(case 1 (else #f) ((1) #t))"
477 exception:bad/missing-clauses
478 (case 1 (else #f) ((1) #t)))))
480 (with-test-prefix "define"
482 (with-test-prefix "currying"
484 (pass-if "(define ((foo)) #f)"
488 (with-test-prefix "missing or extra expressions"
490 (pass-if-exception "(define)"
491 exception:missing/extra-expr
494 (with-test-prefix "set!"
496 (with-test-prefix "missing or extra expressions"
498 (pass-if-exception "(set!)"
499 exception:missing/extra-expr
501 (interaction-environment)))
503 (pass-if-exception "(set! 1)"
504 exception:missing/extra-expr
506 (interaction-environment)))
508 (pass-if-exception "(set! 1 2 3)"
509 exception:missing/extra-expr
511 (interaction-environment))))
513 (with-test-prefix "bad variable"
515 (pass-if-exception "(set! \"\" #t)"
518 (interaction-environment)))
520 (pass-if-exception "(set! 1 #t)"
523 (interaction-environment)))
525 (pass-if-exception "(set! #t #f)"
528 (interaction-environment)))
530 (pass-if-exception "(set! #f #t)"
533 (interaction-environment)))
535 (pass-if-exception "(set! #\space #f)"
537 (eval '(set! #\space #f)
538 (interaction-environment)))))
540 (with-test-prefix "quote"
542 (with-test-prefix "missing or extra expression"
544 (pass-if-exception "(quote)"
545 exception:missing/extra-expr
547 (interaction-environment)))
549 (pass-if-exception "(quote a b)"
550 exception:missing/extra-expr
552 (interaction-environment)))))
554 (with-test-prefix "while"
556 (define (unreachable)
557 (error "unreachable code has been reached!"))
559 ;; an environment with no bindings at all
560 (define empty-environment
563 ;; Return a new procedure COND which when called (COND) will return #t the
564 ;; first N times, then #f, then any further call is an error. N=0 is
565 ;; allowed, in which case #f is returned by the first call.
566 (define (make-iterations-cond n)
569 (error "oops, condition re-tested after giving false"))
578 (pass-if-exception "too few args" exception:wrong-num-args
581 (with-test-prefix "empty body"
585 (let ((cond (make-iterations-cond n)))
589 (pass-if "initially false"
594 (with-test-prefix "in empty environment"
596 (pass-if "empty body"
601 (pass-if "initially false"
608 (let ((cond (make-iterations-cond 3)))
609 (eval `(,while (,cond)
614 (with-test-prefix "iterations"
618 (let ((cond (make-iterations-cond n))
624 (with-test-prefix "break"
626 (pass-if-exception "too many args" exception:wrong-num-args
630 (with-test-prefix "from cond"
641 (let ((cond (make-iterations-cond n))
651 (with-test-prefix "from body"
661 (let ((cond (make-iterations-cond n))
671 (pass-if "from nested"
673 (let ((outer-break break))
680 (with-test-prefix "continue"
682 (pass-if-exception "too many args" exception:wrong-num-args
686 (with-test-prefix "from cond"
690 (let ((cond (make-iterations-cond n))
701 (with-test-prefix "from body"
705 (let ((cond (make-iterations-cond n))
713 (pass-if "from nested"
714 (let ((cond (make-iterations-cond 3)))
716 (let ((outer-continue continue))