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