* tests/syntax.test: Added various tests to check that
[bpt/guile.git] / test-suite / tests / syntax.test
1 ;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
2 ;;;;
3 ;;;; Copyright (C) 2001,2003,2004 Free Software Foundation, Inc.
4 ;;;;
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.
9 ;;;;
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.
14 ;;;;
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
19
20 (define-module (test-suite test-syntax)
21 :use-module (test-suite lib))
22
23
24 (define exception:bad-expression
25 (cons 'syntax-error "Bad expression"))
26
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"))
37
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"))
52
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"))
63
64
65 (with-test-prefix "expressions"
66
67 (with-test-prefix "Bad argument list"
68
69 (pass-if-exception "improper argument list of length 1"
70 exception:wrong-num-args
71 (eval '(let ((foo (lambda (x y) #t)))
72 (foo . 1))
73 (interaction-environment)))
74
75 (pass-if-exception "improper argument list of length 2"
76 exception:wrong-num-args
77 (eval '(let ((foo (lambda (x y) #t)))
78 (foo 1 . 2))
79 (interaction-environment))))
80
81 (with-test-prefix "missing or extra expression"
82
83 ;; R5RS says:
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
87 ;; valid expression.
88
89 ;; Fixed on 2001-3-3
90 (pass-if-exception "empty parentheses \"()\""
91 exception:illegal-empty-combination
92 (eval '()
93 (interaction-environment)))))
94
95 (with-test-prefix "quote"
96 #t)
97
98 (with-test-prefix "quasiquote"
99
100 (with-test-prefix "unquote"
101
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))))))
105
106 (with-test-prefix "unquote-splicing"
107
108 (pass-if-exception "extra arguments"
109 exception:missing/extra-expr
110 (quasiquote ((unquote-splicing (list 1 2) (list 3 4)))))))
111
112 (with-test-prefix "begin"
113
114 (pass-if "legal (begin)"
115 (begin)
116 #t)
117
118 (with-test-prefix "unmemoization"
119
120 (pass-if "normal begin"
121 (let ((foo (lambda () (if (= 1 1) (begin (+ 1) (+ 2))))))
122 (foo) ; make sure, memoization has been performed
123 (equal? (procedure-source foo)
124 '(lambda () (if (= 1 1) (begin (+ 1) (+ 2)))))))
125
126 (pass-if "redundant nested begin"
127 (let ((foo (lambda () (if (= 1 1) (begin (+ 1) (begin (+ 2) (+ 3)))))))
128 (foo) ; make sure, memoization has been performed
129 (equal? (procedure-source foo)
130 '(lambda () (if (= 1 1) (begin (+ 1) (begin (+ 2) (+ 3))))))))
131
132 (pass-if "redundant begin at start of body"
133 (let ((foo (lambda () (begin (+ 1) (+ 2))))) ; should be optimized
134 (foo) ; make sure, memoization has been performed
135 (equal? (procedure-source foo)
136 '(lambda () (begin (+ 1) (+ 2)))))))
137
138 (expect-fail-exception "illegal (begin)"
139 exception:bad-body
140 (if #t (begin))
141 #t))
142
143 (with-test-prefix "lambda"
144
145 (with-test-prefix "unmemoization"
146
147 (pass-if "normal lambda"
148 (let ((foo (lambda () (lambda (x y) (+ x y)))))
149 ((foo) 1 2) ; make sure, memoization has been performed
150 (equal? (procedure-source foo)
151 '(lambda () (lambda (x y) (+ x y))))))
152
153 (pass-if "lambda with documentation"
154 (let ((foo (lambda () (lambda (x y) "docstring" (+ x y)))))
155 ((foo) 1 2) ; make sure, memoization has been performed
156 (equal? (procedure-source foo)
157 '(lambda () (lambda (x y) "docstring" (+ x y)))))))
158
159 (with-test-prefix "bad formals"
160
161 (pass-if-exception "(lambda)"
162 exception:missing-expr
163 (eval '(lambda)
164 (interaction-environment)))
165
166 (pass-if-exception "(lambda . \"foo\")"
167 exception:bad-expression
168 (eval '(lambda . "foo")
169 (interaction-environment)))
170
171 (pass-if-exception "(lambda \"foo\")"
172 exception:missing-expr
173 (eval '(lambda "foo")
174 (interaction-environment)))
175
176 (pass-if-exception "(lambda \"foo\" #f)"
177 exception:bad-formals
178 (eval '(lambda "foo" #f)
179 (interaction-environment)))
180
181 (pass-if-exception "(lambda (x 1) 2)"
182 exception:bad-formal
183 (eval '(lambda (x 1) 2)
184 (interaction-environment)))
185
186 (pass-if-exception "(lambda (1 x) 2)"
187 exception:bad-formal
188 (eval '(lambda (1 x) 2)
189 (interaction-environment)))
190
191 (pass-if-exception "(lambda (x \"a\") 2)"
192 exception:bad-formal
193 (eval '(lambda (x "a") 2)
194 (interaction-environment)))
195
196 (pass-if-exception "(lambda (\"a\" x) 2)"
197 exception:bad-formal
198 (eval '(lambda ("a" x) 2)
199 (interaction-environment))))
200
201 (with-test-prefix "duplicate formals"
202
203 ;; Fixed on 2001-3-3
204 (pass-if-exception "(lambda (x x) 1)"
205 exception:duplicate-formal
206 (eval '(lambda (x x) 1)
207 (interaction-environment)))
208
209 ;; Fixed on 2001-3-3
210 (pass-if-exception "(lambda (x x x) 1)"
211 exception:duplicate-formal
212 (eval '(lambda (x x x) 1)
213 (interaction-environment))))
214
215 (with-test-prefix "bad body"
216
217 (pass-if-exception "(lambda ())"
218 exception:missing-expr
219 (eval '(lambda ())
220 (interaction-environment)))))
221
222 (with-test-prefix "let"
223
224 (with-test-prefix "unmemoization"
225
226 (pass-if "normal let"
227 (let ((foo (lambda () (let ((i 1) (j 2)) (+ i j)))))
228 (foo) ; make sure, memoization has been performed
229 (equal? (procedure-source foo)
230 '(lambda () (let ((i 1) (j 2)) (+ i j)))))))
231
232 (with-test-prefix "bindings"
233
234 (pass-if-exception "late binding"
235 exception:unbound-var
236 (let ((x 1) (y x)) y)))
237
238 (with-test-prefix "bad bindings"
239
240 (pass-if-exception "(let)"
241 exception:missing-expr
242 (eval '(let)
243 (interaction-environment)))
244
245 (pass-if-exception "(let 1)"
246 exception:missing-expr
247 (eval '(let 1)
248 (interaction-environment)))
249
250 (pass-if-exception "(let (x))"
251 exception:missing-expr
252 (eval '(let (x))
253 (interaction-environment)))
254
255 (pass-if-exception "(let ((x)))"
256 exception:missing-expr
257 (eval '(let ((x)))
258 (interaction-environment)))
259
260 (pass-if-exception "(let (x) 1)"
261 exception:bad-binding
262 (eval '(let (x) 1)
263 (interaction-environment)))
264
265 (pass-if-exception "(let ((x)) 3)"
266 exception:bad-binding
267 (eval '(let ((x)) 3)
268 (interaction-environment)))
269
270 (pass-if-exception "(let ((x 1) y) x)"
271 exception:bad-binding
272 (eval '(let ((x 1) y) x)
273 (interaction-environment)))
274
275 (pass-if-exception "(let ((1 2)) 3)"
276 exception:bad-variable
277 (eval '(let ((1 2)) 3)
278 (interaction-environment))))
279
280 (with-test-prefix "duplicate bindings"
281
282 (pass-if-exception "(let ((x 1) (x 2)) x)"
283 exception:duplicate-binding
284 (eval '(let ((x 1) (x 2)) x)
285 (interaction-environment))))
286
287 (with-test-prefix "bad body"
288
289 (pass-if-exception "(let ())"
290 exception:missing-expr
291 (eval '(let ())
292 (interaction-environment)))
293
294 (pass-if-exception "(let ((x 1)))"
295 exception:missing-expr
296 (eval '(let ((x 1)))
297 (interaction-environment)))))
298
299 (with-test-prefix "named let"
300
301 (with-test-prefix "initializers"
302
303 (pass-if "evaluated in outer environment"
304 (let ((f -))
305 (eqv? (let f ((n (f 1))) n) -1))))
306
307 (with-test-prefix "bad bindings"
308
309 (pass-if-exception "(let x (y))"
310 exception:missing-expr
311 (eval '(let x (y))
312 (interaction-environment))))
313
314 (with-test-prefix "bad body"
315
316 (pass-if-exception "(let x ())"
317 exception:missing-expr
318 (eval '(let x ())
319 (interaction-environment)))
320
321 (pass-if-exception "(let x ((y 1)))"
322 exception:missing-expr
323 (eval '(let x ((y 1)))
324 (interaction-environment)))))
325
326 (with-test-prefix "let*"
327
328 (with-test-prefix "unmemoization"
329
330 (pass-if "normal let*"
331 (let ((foo (lambda () (let* ((x 1) (y 2)) (+ x y)))))
332 (foo) ; make sure, memoization has been performed
333 (equal? (procedure-source foo)
334 '(lambda () (let* ((x 1) (y 2)) (+ x y))))))
335
336 (pass-if "let* without bindings"
337 (let ((foo (lambda () (let ((x 1) (y 2))
338 (let* ()
339 (and (= x 1) (= y 2)))))))
340 (foo) ; make sure, memoization has been performed
341 (equal? (procedure-source foo)
342 '(lambda () (let ((x 1) (y 2))
343 (let* ()
344 (and (= x 1) (= y 2)))))))))
345
346 (with-test-prefix "bindings"
347
348 (pass-if "(let* ((x 1) (x 2)) ...)"
349 (let* ((x 1) (x 2))
350 (= x 2)))
351
352 (pass-if "(let* ((x 1) (x x)) ...)"
353 (let* ((x 1) (x x))
354 (= x 1)))
355
356 (pass-if "(let ((x 1) (y 2)) (let* () ...))"
357 (let ((x 1) (y 2))
358 (let* ()
359 (and (= x 1) (= y 2))))))
360
361 (with-test-prefix "bad bindings"
362
363 (pass-if-exception "(let*)"
364 exception:missing-expr
365 (eval '(let*)
366 (interaction-environment)))
367
368 (pass-if-exception "(let* 1)"
369 exception:missing-expr
370 (eval '(let* 1)
371 (interaction-environment)))
372
373 (pass-if-exception "(let* (x))"
374 exception:missing-expr
375 (eval '(let* (x))
376 (interaction-environment)))
377
378 (pass-if-exception "(let* (x) 1)"
379 exception:bad-binding
380 (eval '(let* (x) 1)
381 (interaction-environment)))
382
383 (pass-if-exception "(let* ((x)) 3)"
384 exception:bad-binding
385 (eval '(let* ((x)) 3)
386 (interaction-environment)))
387
388 (pass-if-exception "(let* ((x 1) y) x)"
389 exception:bad-binding
390 (eval '(let* ((x 1) y) x)
391 (interaction-environment)))
392
393 (pass-if-exception "(let* x ())"
394 exception:bad-bindings
395 (eval '(let* x ())
396 (interaction-environment)))
397
398 (pass-if-exception "(let* x (y))"
399 exception:bad-bindings
400 (eval '(let* x (y))
401 (interaction-environment)))
402
403 (pass-if-exception "(let* ((1 2)) 3)"
404 exception:bad-variable
405 (eval '(let* ((1 2)) 3)
406 (interaction-environment))))
407
408 (with-test-prefix "bad body"
409
410 (pass-if-exception "(let* ())"
411 exception:missing-expr
412 (eval '(let* ())
413 (interaction-environment)))
414
415 (pass-if-exception "(let* ((x 1)))"
416 exception:missing-expr
417 (eval '(let* ((x 1)))
418 (interaction-environment)))))
419
420 (with-test-prefix "letrec"
421
422 (with-test-prefix "unmemoization"
423
424 (pass-if "normal letrec"
425 (let ((foo (lambda () (letrec ((i 1) (j 2)) (+ i j)))))
426 (foo) ; make sure, memoization has been performed
427 (equal? (procedure-source foo)
428 '(lambda () (letrec ((i 1) (j 2)) (+ i j)))))))
429
430 (with-test-prefix "bindings"
431
432 (pass-if-exception "initial bindings are undefined"
433 exception:unbound-var
434 (let ((x 1))
435 (letrec ((x 1) (y x)) y))))
436
437 (with-test-prefix "bad bindings"
438
439 (pass-if-exception "(letrec)"
440 exception:missing-expr
441 (eval '(letrec)
442 (interaction-environment)))
443
444 (pass-if-exception "(letrec 1)"
445 exception:missing-expr
446 (eval '(letrec 1)
447 (interaction-environment)))
448
449 (pass-if-exception "(letrec (x))"
450 exception:missing-expr
451 (eval '(letrec (x))
452 (interaction-environment)))
453
454 (pass-if-exception "(letrec (x) 1)"
455 exception:bad-binding
456 (eval '(letrec (x) 1)
457 (interaction-environment)))
458
459 (pass-if-exception "(letrec ((x)) 3)"
460 exception:bad-binding
461 (eval '(letrec ((x)) 3)
462 (interaction-environment)))
463
464 (pass-if-exception "(letrec ((x 1) y) x)"
465 exception:bad-binding
466 (eval '(letrec ((x 1) y) x)
467 (interaction-environment)))
468
469 (pass-if-exception "(letrec x ())"
470 exception:bad-bindings
471 (eval '(letrec x ())
472 (interaction-environment)))
473
474 (pass-if-exception "(letrec x (y))"
475 exception:bad-bindings
476 (eval '(letrec x (y))
477 (interaction-environment)))
478
479 (pass-if-exception "(letrec ((1 2)) 3)"
480 exception:bad-variable
481 (eval '(letrec ((1 2)) 3)
482 (interaction-environment))))
483
484 (with-test-prefix "duplicate bindings"
485
486 (pass-if-exception "(letrec ((x 1) (x 2)) x)"
487 exception:duplicate-binding
488 (eval '(letrec ((x 1) (x 2)) x)
489 (interaction-environment))))
490
491 (with-test-prefix "bad body"
492
493 (pass-if-exception "(letrec ())"
494 exception:missing-expr
495 (eval '(letrec ())
496 (interaction-environment)))
497
498 (pass-if-exception "(letrec ((x 1)))"
499 exception:missing-expr
500 (eval '(letrec ((x 1)))
501 (interaction-environment)))))
502
503 (with-test-prefix "if"
504
505 (with-test-prefix "unmemoization"
506
507 (pass-if "normal if"
508 (let ((foo (lambda (x) (if x (+ 1) (+ 2)))))
509 (foo #t) ; make sure, memoization has been performed
510 (foo #f) ; make sure, memoization has been performed
511 (equal? (procedure-source foo)
512 '(lambda (x) (if x (+ 1) (+ 2))))))
513
514 (pass-if "if without else"
515 (let ((foo (lambda (x) (if x (+ 1)))))
516 (foo #t) ; make sure, memoization has been performed
517 (foo #f) ; make sure, memoization has been performed
518 (equal? (procedure-source foo)
519 '(lambda (x) (if x (+ 1))))))
520
521 (pass-if "if #f without else"
522 (let ((foo (lambda () (if #f #f))))
523 (foo) ; make sure, memoization has been performed
524 (equal? (procedure-source foo)
525 `(lambda () (if #f #f))))))
526
527 (with-test-prefix "missing or extra expressions"
528
529 (pass-if-exception "(if)"
530 exception:missing/extra-expr
531 (eval '(if)
532 (interaction-environment)))
533
534 (pass-if-exception "(if 1 2 3 4)"
535 exception:missing/extra-expr
536 (eval '(if 1 2 3 4)
537 (interaction-environment)))))
538
539 (with-test-prefix "cond"
540
541 (with-test-prefix "cond is hygienic"
542
543 (pass-if "bound 'else is handled correctly"
544 (eq? (let ((else 'ok)) (cond (else))) 'ok))
545
546 (with-test-prefix "bound '=> is handled correctly"
547
548 (pass-if "#t => 'ok"
549 (let ((=> 'foo))
550 (eq? (cond (#t => 'ok)) 'ok)))
551
552 (pass-if "else =>"
553 (let ((=> 'foo))
554 (eq? (cond (else =>)) 'foo)))
555
556 (pass-if "else => identity"
557 (let ((=> 'foo))
558 (eq? (cond (else => identity)) identity)))))
559
560 (with-test-prefix "unmemoization"
561
562 (pass-if "normal clauses"
563 (let ((foo (lambda (x) (cond ((= x 1) 'bar) ((= x 2) 'baz)))))
564 (foo 1) ; make sure, memoization has been performed
565 (foo 2) ; make sure, memoization has been performed
566 (equal? (procedure-source foo)
567 '(lambda (x) (cond ((= x 1) 'bar) ((= x 2) 'baz))))))
568
569 (pass-if "else"
570 (let ((foo (lambda () (cond (else 'bar)))))
571 (foo) ; make sure, memoization has been performed
572 (equal? (procedure-source foo)
573 '(lambda () (cond (else 'bar))))))
574
575 (pass-if "=>"
576 (let ((foo (lambda () (cond (#t => identity)))))
577 (foo) ; make sure, memoization has been performed
578 (equal? (procedure-source foo)
579 '(lambda () (cond (#t => identity)))))))
580
581 (with-test-prefix "bad or missing clauses"
582
583 (pass-if-exception "(cond)"
584 exception:missing-clauses
585 (eval '(cond)
586 (interaction-environment)))
587
588 (pass-if-exception "(cond #t)"
589 exception:bad-cond-clause
590 (eval '(cond #t)
591 (interaction-environment)))
592
593 (pass-if-exception "(cond 1)"
594 exception:bad-cond-clause
595 (eval '(cond 1)
596 (interaction-environment)))
597
598 (pass-if-exception "(cond 1 2)"
599 exception:bad-cond-clause
600 (eval '(cond 1 2)
601 (interaction-environment)))
602
603 (pass-if-exception "(cond 1 2 3)"
604 exception:bad-cond-clause
605 (eval '(cond 1 2 3)
606 (interaction-environment)))
607
608 (pass-if-exception "(cond 1 2 3 4)"
609 exception:bad-cond-clause
610 (eval '(cond 1 2 3 4)
611 (interaction-environment)))
612
613 (pass-if-exception "(cond ())"
614 exception:bad-cond-clause
615 (eval '(cond ())
616 (interaction-environment)))
617
618 (pass-if-exception "(cond () 1)"
619 exception:bad-cond-clause
620 (eval '(cond () 1)
621 (interaction-environment)))
622
623 (pass-if-exception "(cond (1) 1)"
624 exception:bad-cond-clause
625 (eval '(cond (1) 1)
626 (interaction-environment))))
627
628 (with-test-prefix "wrong number of arguments"
629
630 (pass-if-exception "=> (lambda (x y) #t)"
631 exception:wrong-num-args
632 (cond (1 => (lambda (x y) #t))))))
633
634 (with-test-prefix "case"
635
636 (pass-if "clause with empty labels list"
637 (case 1 (() #f) (else #t)))
638
639 (with-test-prefix "case is hygienic"
640
641 (pass-if-exception "bound 'else is handled correctly"
642 exception:bad-case-labels
643 (eval '(let ((else #f)) (case 1 (else #f)))
644 (interaction-environment))))
645
646 (with-test-prefix "unmemoization"
647
648 (pass-if "normal clauses"
649 (let ((foo (lambda (x) (case x ((1) 'bar) ((2) 'baz) (else 'foobar)))))
650 (foo 1) ; make sure, memoization has been performed
651 (foo 2) ; make sure, memoization has been performed
652 (foo 3) ; make sure, memoization has been performed
653 (equal? (procedure-source foo)
654 '(lambda (x) (case x ((1) 'bar) ((2) 'baz) (else 'foobar))))))
655
656 (pass-if "empty labels"
657 (let ((foo (lambda (x) (case x ((1) 'bar) (() 'baz) (else 'foobar)))))
658 (foo 1) ; make sure, memoization has been performed
659 (foo 2) ; make sure, memoization has been performed
660 (foo 3) ; make sure, memoization has been performed
661 (equal? (procedure-source foo)
662 '(lambda (x) (case x ((1) 'bar) (() 'baz) (else 'foobar)))))))
663
664 (with-test-prefix "bad or missing clauses"
665
666 (pass-if-exception "(case)"
667 exception:missing-clauses
668 (eval '(case)
669 (interaction-environment)))
670
671 (pass-if-exception "(case . \"foo\")"
672 exception:bad-expression
673 (eval '(case . "foo")
674 (interaction-environment)))
675
676 (pass-if-exception "(case 1)"
677 exception:missing-clauses
678 (eval '(case 1)
679 (interaction-environment)))
680
681 (pass-if-exception "(case 1 . \"foo\")"
682 exception:bad-expression
683 (eval '(case 1 . "foo")
684 (interaction-environment)))
685
686 (pass-if-exception "(case 1 \"foo\")"
687 exception:bad-case-clause
688 (eval '(case 1 "foo")
689 (interaction-environment)))
690
691 (pass-if-exception "(case 1 ())"
692 exception:bad-case-clause
693 (eval '(case 1 ())
694 (interaction-environment)))
695
696 (pass-if-exception "(case 1 (\"foo\"))"
697 exception:bad-case-clause
698 (eval '(case 1 ("foo"))
699 (interaction-environment)))
700
701 (pass-if-exception "(case 1 (\"foo\" \"bar\"))"
702 exception:bad-case-labels
703 (eval '(case 1 ("foo" "bar"))
704 (interaction-environment)))
705
706 (pass-if-exception "(case 1 ((2) \"bar\") . \"foo\")"
707 exception:bad-expression
708 (eval '(case 1 ((2) "bar") . "foo")
709 (interaction-environment)))
710
711 (pass-if-exception "(case 1 ((2) \"bar\") (else))"
712 exception:bad-case-clause
713 (eval '(case 1 ((2) "bar") (else))
714 (interaction-environment)))
715
716 (pass-if-exception "(case 1 (else #f) . \"foo\")"
717 exception:bad-expression
718 (eval '(case 1 (else #f) . "foo")
719 (interaction-environment)))
720
721 (pass-if-exception "(case 1 (else #f) ((1) #t))"
722 exception:misplaced-else-clause
723 (eval '(case 1 (else #f) ((1) #t))
724 (interaction-environment)))))
725
726 (with-test-prefix "top-level define"
727
728 (pass-if "binding is created before expression is evaluated"
729 (= (eval '(begin
730 (define foo
731 (begin
732 (set! foo 1)
733 (+ foo 1)))
734 foo)
735 (interaction-environment))
736 2))
737
738 (with-test-prefix "currying"
739
740 (pass-if "(define ((foo)) #f)"
741 (eval '(begin
742 (define ((foo)) #t)
743 ((foo)))
744 (interaction-environment))))
745
746 (with-test-prefix "missing or extra expressions"
747
748 (pass-if-exception "(define)"
749 exception:missing-expr
750 (eval '(define)
751 (interaction-environment)))))
752
753 (with-test-prefix "internal define"
754
755 (pass-if "internal defines become letrec"
756 (eval '(let ((a identity) (b identity) (c identity))
757 (define (a x) (if (= x 0) 'a (b (- x 1))))
758 (define (b x) (if (= x 0) 'b (c (- x 1))))
759 (define (c x) (if (= x 0) 'c (a (- x 1))))
760 (and (eq? 'a (a 0) (a 3))
761 (eq? 'b (a 1) (a 4))
762 (eq? 'c (a 2) (a 5))))
763 (interaction-environment)))
764
765 (pass-if "internal defines with begin"
766 (false-if-exception
767 (eval '(let ((a identity) (b identity) (c identity))
768 (define (a x) (if (= x 0) 'a (b (- x 1))))
769 (begin
770 (define (b x) (if (= x 0) 'b (c (- x 1)))))
771 (define (c x) (if (= x 0) 'c (a (- x 1))))
772 (and (eq? 'a (a 0) (a 3))
773 (eq? 'b (a 1) (a 4))
774 (eq? 'c (a 2) (a 5))))
775 (interaction-environment))))
776
777 (pass-if "internal defines with empty begin"
778 (false-if-exception
779 (eval '(let ((a identity) (b identity) (c identity))
780 (define (a x) (if (= x 0) 'a (b (- x 1))))
781 (begin)
782 (define (b x) (if (= x 0) 'b (c (- x 1))))
783 (define (c x) (if (= x 0) 'c (a (- x 1))))
784 (and (eq? 'a (a 0) (a 3))
785 (eq? 'b (a 1) (a 4))
786 (eq? 'c (a 2) (a 5))))
787 (interaction-environment))))
788
789 (pass-if "internal defines with macro application"
790 (false-if-exception
791 (eval '(begin
792 (defmacro my-define forms
793 (cons 'define forms))
794 (let ((a identity) (b identity) (c identity))
795 (define (a x) (if (= x 0) 'a (b (- x 1))))
796 (my-define (b x) (if (= x 0) 'b (c (- x 1))))
797 (define (c x) (if (= x 0) 'c (a (- x 1))))
798 (and (eq? 'a (a 0) (a 3))
799 (eq? 'b (a 1) (a 4))
800 (eq? 'c (a 2) (a 5)))))
801 (interaction-environment))))
802
803 (pass-if-exception "missing body expression"
804 exception:missing-body-expr
805 (eval '(let () (define x #t))
806 (interaction-environment)))
807
808 (pass-if "unmemoization"
809 (eval '(begin
810 (define (foo)
811 (define (bar)
812 'ok)
813 (bar))
814 (foo)
815 (equal?
816 (procedure-source foo)
817 '(lambda () (letrec ((bar (lambda () (quote ok)))) (bar)))))
818 (interaction-environment))))
819
820 (with-test-prefix "do"
821
822 (with-test-prefix "unmemoization"
823
824 (pass-if "normal case"
825 (let ((foo (lambda () (do ((i 1 (+ i 1)) (j 2))
826 ((> i 9) (+ i j))
827 (identity i)))))
828 (foo) ; make sure, memoization has been performed
829 (equal? (procedure-source foo)
830 '(lambda () (do ((i 1 (+ i 1)) (j 2))
831 ((> i 9) (+ i j))
832 (identity i))))))
833
834 (pass-if "reduced case"
835 (let ((foo (lambda () (do ((i 1 (+ i 1)) (j 2 j)) ; redundant step for j
836 ((> i 9) (+ i j))
837 (identity i)))))
838 (foo) ; make sure, memoization has been performed
839 (equal? (procedure-source foo)
840 '(lambda () (do ((i 1 (+ i 1)) (j 2)) ; no redundancy here
841 ((> i 9) (+ i j))
842 (identity i))))))))
843
844 (with-test-prefix "set!"
845
846 (with-test-prefix "unmemoization"
847
848 (pass-if "normal set!"
849 (let ((foo (lambda (x) (set! x (+ 1 x)))))
850 (foo 1) ; make sure, memoization has been performed
851 (equal? (procedure-source foo)
852 '(lambda (x) (set! x (+ 1 x)))))))
853
854 (with-test-prefix "missing or extra expressions"
855
856 (pass-if-exception "(set!)"
857 exception:missing/extra-expr
858 (eval '(set!)
859 (interaction-environment)))
860
861 (pass-if-exception "(set! 1)"
862 exception:missing/extra-expr
863 (eval '(set! 1)
864 (interaction-environment)))
865
866 (pass-if-exception "(set! 1 2 3)"
867 exception:missing/extra-expr
868 (eval '(set! 1 2 3)
869 (interaction-environment))))
870
871 (with-test-prefix "bad variable"
872
873 (pass-if-exception "(set! \"\" #t)"
874 exception:bad-variable
875 (eval '(set! "" #t)
876 (interaction-environment)))
877
878 (pass-if-exception "(set! 1 #t)"
879 exception:bad-variable
880 (eval '(set! 1 #t)
881 (interaction-environment)))
882
883 (pass-if-exception "(set! #t #f)"
884 exception:bad-variable
885 (eval '(set! #t #f)
886 (interaction-environment)))
887
888 (pass-if-exception "(set! #f #t)"
889 exception:bad-variable
890 (eval '(set! #f #t)
891 (interaction-environment)))
892
893 (pass-if-exception "(set! #\\space #f)"
894 exception:bad-variable
895 (eval '(set! #\space #f)
896 (interaction-environment)))))
897
898 (with-test-prefix "quote"
899
900 (with-test-prefix "missing or extra expression"
901
902 (pass-if-exception "(quote)"
903 exception:missing/extra-expr
904 (eval '(quote)
905 (interaction-environment)))
906
907 (pass-if-exception "(quote a b)"
908 exception:missing/extra-expr
909 (eval '(quote a b)
910 (interaction-environment)))))
911
912 (with-test-prefix "while"
913
914 (define (unreachable)
915 (error "unreachable code has been reached!"))
916
917 ;; Return a new procedure COND which when called (COND) will return #t the
918 ;; first N times, then #f, then any further call is an error. N=0 is
919 ;; allowed, in which case #f is returned by the first call.
920 (define (make-iterations-cond n)
921 (lambda ()
922 (cond ((not n)
923 (error "oops, condition re-tested after giving false"))
924 ((= 0 n)
925 (set! n #f)
926 #f)
927 (else
928 (set! n (1- n))
929 #t))))
930
931
932 (pass-if-exception "too few args" exception:wrong-num-args
933 (eval '(while) (interaction-environment)))
934
935 (with-test-prefix "empty body"
936 (do ((n 0 (1+ n)))
937 ((> n 5))
938 (pass-if n
939 (let ((cond (make-iterations-cond n)))
940 (while (cond)))
941 #t)))
942
943 (pass-if "initially false"
944 (while #f
945 (unreachable))
946 #t)
947
948 (with-test-prefix "in empty environment"
949
950 ;; an environment with no bindings at all
951 (define empty-environment
952 (make-module 1))
953
954 (pass-if "empty body"
955 (eval `(,while #f)
956 empty-environment)
957 #t)
958
959 (pass-if "initially false"
960 (eval `(,while #f
961 #f)
962 empty-environment)
963 #t)
964
965 (pass-if "iterating"
966 (let ((cond (make-iterations-cond 3)))
967 (eval `(,while (,cond)
968 123 456)
969 empty-environment))
970 #t))
971
972 (with-test-prefix "iterations"
973 (do ((n 0 (1+ n)))
974 ((> n 5))
975 (pass-if n
976 (let ((cond (make-iterations-cond n))
977 (i 0))
978 (while (cond)
979 (set! i (1+ i)))
980 (= i n)))))
981
982 (with-test-prefix "break"
983
984 (pass-if-exception "too many args" exception:wrong-num-args
985 (while #t
986 (break 1)))
987
988 (with-test-prefix "from cond"
989 (pass-if "first"
990 (while (begin
991 (break)
992 (unreachable))
993 (unreachable))
994 #t)
995
996 (do ((n 0 (1+ n)))
997 ((> n 5))
998 (pass-if n
999 (let ((cond (make-iterations-cond n))
1000 (i 0))
1001 (while (if (cond)
1002 #t
1003 (begin
1004 (break)
1005 (unreachable)))
1006 (set! i (1+ i)))
1007 (= i n)))))
1008
1009 (with-test-prefix "from body"
1010 (pass-if "first"
1011 (while #t
1012 (break)
1013 (unreachable))
1014 #t)
1015
1016 (do ((n 0 (1+ n)))
1017 ((> n 5))
1018 (pass-if n
1019 (let ((cond (make-iterations-cond n))
1020 (i 0))
1021 (while #t
1022 (if (not (cond))
1023 (begin
1024 (break)
1025 (unreachable)))
1026 (set! i (1+ i)))
1027 (= i n)))))
1028
1029 (pass-if "from nested"
1030 (while #t
1031 (let ((outer-break break))
1032 (while #t
1033 (outer-break)
1034 (unreachable)))
1035 (unreachable))
1036 #t)
1037
1038 (pass-if "from recursive"
1039 (let ((outer-break #f))
1040 (define (r n)
1041 (while #t
1042 (if (eq? n 'outer)
1043 (begin
1044 (set! outer-break break)
1045 (r 'inner))
1046 (begin
1047 (outer-break)
1048 (unreachable))))
1049 (if (eq? n 'inner)
1050 (error "broke only from inner loop")))
1051 (r 'outer))
1052 #t))
1053
1054 (with-test-prefix "continue"
1055
1056 (pass-if-exception "too many args" exception:wrong-num-args
1057 (while #t
1058 (continue 1)))
1059
1060 (with-test-prefix "from cond"
1061 (do ((n 0 (1+ n)))
1062 ((> n 5))
1063 (pass-if n
1064 (let ((cond (make-iterations-cond n))
1065 (i 0))
1066 (while (if (cond)
1067 (begin
1068 (set! i (1+ i))
1069 (continue)
1070 (unreachable))
1071 #f)
1072 (unreachable))
1073 (= i n)))))
1074
1075 (with-test-prefix "from body"
1076 (do ((n 0 (1+ n)))
1077 ((> n 5))
1078 (pass-if n
1079 (let ((cond (make-iterations-cond n))
1080 (i 0))
1081 (while (cond)
1082 (set! i (1+ i))
1083 (continue)
1084 (unreachable))
1085 (= i n)))))
1086
1087 (pass-if "from nested"
1088 (let ((cond (make-iterations-cond 3)))
1089 (while (cond)
1090 (let ((outer-continue continue))
1091 (while #t
1092 (outer-continue)
1093 (unreachable)))))
1094 #t)
1095
1096 (pass-if "from recursive"
1097 (let ((outer-continue #f))
1098 (define (r n)
1099 (let ((cond (make-iterations-cond 3))
1100 (first #t))
1101 (while (begin
1102 (if (and (not first)
1103 (eq? n 'inner))
1104 (error "continued only to inner loop"))
1105 (cond))
1106 (set! first #f)
1107 (if (eq? n 'outer)
1108 (begin
1109 (set! outer-continue continue)
1110 (r 'inner))
1111 (begin
1112 (outer-continue)
1113 (unreachable))))))
1114 (r 'outer))
1115 #t)))