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