Fast generic function dispatch without calling `compile' at runtime
[bpt/guile.git] / test-suite / tests / syntax.test
CommitLineData
08c608e1
DH
1;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
2;;;;
f78a1cce 3;;;; Copyright (C) 2001, 2003, 2004, 2005, 2006, 2009, 2010,
2d6a3144 4;;;; 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
f78a1cce 5;;;;
53befeb7
NJ
6;;;; This library is free software; you can redistribute it and/or
7;;;; modify it under the terms of the GNU Lesser General Public
8;;;; License as published by the Free Software Foundation; either
9;;;; version 3 of the License, or (at your option) any later version.
08c608e1 10;;;;
53befeb7 11;;;; This library is distributed in the hope that it will be useful,
08c608e1 12;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
53befeb7
NJ
13;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14;;;; Lesser General Public License for more details.
08c608e1 15;;;;
53befeb7
NJ
16;;;; You should have received a copy of the GNU Lesser General Public
17;;;; License along with this library; if not, write to the Free Software
18;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
08c608e1 19
8aa28a91 20(define-module (test-suite test-syntax)
e75184d5 21 #:use-module (ice-9 regex)
1624e149 22 #:use-module (ice-9 local-eval)
e75184d5 23 #:use-module (test-suite lib))
08c608e1 24
2a6f7afe 25
40b36cfb 26(define exception:generic-syncase-error
e75184d5 27 "source expression failed to match")
40b36cfb 28(define exception:unexpected-syntax
e75184d5 29 "unexpected syntax")
40b36cfb 30
2a6f7afe 31(define exception:bad-expression
e75184d5 32 "Bad expression")
cc56ba80 33
21628685 34(define exception:missing/extra-expr
e75184d5 35 "Missing or extra expression")
cc56ba80 36(define exception:missing-expr
e75184d5 37 "Missing expression")
ced8edb0 38(define exception:missing-body-expr
e75184d5 39 "no expressions in body")
cc56ba80 40(define exception:extra-expr
e75184d5 41 "Extra expression")
89bff2fc 42(define exception:illegal-empty-combination
e75184d5 43 "Illegal empty combination")
cc56ba80 44
dc1eed52 45(define exception:bad-lambda
e75184d5 46 "bad lambda")
dc1eed52 47(define exception:bad-let
e75184d5 48 "bad let$")
dc1eed52 49(define exception:bad-letrec
e75184d5 50 "bad letrec$")
5f8c55ce 51(define exception:bad-letrec*
e75184d5 52 "bad letrec\\*$")
9ecac781 53(define exception:bad-set!
e75184d5 54 "bad set!")
9ecac781 55(define exception:bad-quote
e75184d5 56 '(quote . "bad syntax"))
08c608e1 57(define exception:bad-bindings
e75184d5 58 "Bad bindings")
d6754c23 59(define exception:bad-binding
e75184d5 60 "Bad binding")
d6754c23 61(define exception:duplicate-binding
e75184d5 62 "duplicate bound variable")
08c608e1 63(define exception:bad-body
e75184d5 64 "^bad body")
08c608e1 65(define exception:bad-formals
e75184d5 66 "invalid argument list")
03a3e941 67(define exception:bad-formal
e75184d5 68 "Bad formal")
c89222f8 69(define exception:duplicate-formals
e75184d5 70 "duplicate identifier in argument list")
cc56ba80 71
2a6f7afe 72(define exception:missing-clauses
e75184d5 73 "Missing clauses")
609a8b86 74(define exception:misplaced-else-clause
e75184d5 75 "Misplaced else clause")
2a6f7afe 76(define exception:bad-case-clause
e75184d5 77 "Bad case clause")
2a6f7afe 78(define exception:bad-case-labels
e75184d5 79 "Bad case labels")
609a8b86 80(define exception:bad-cond-clause
e75184d5 81 "Bad cond clause")
cc56ba80 82
10e69149 83(define exception:too-many-args
e75184d5 84 "too many arguments")
b00c9b22
AW
85(define exception:wrong-number-of-values
86 '(wrong-number-of-args . "number of (values)|(arguments)"))
9133716f
LC
87(define exception:zero-expression-sequence
88 "sequence of zero expressions")
e75184d5 89
7974c579 90(define exception:variable-ref
dc33a945 91 '(misc-error . "Unbound variable"))
e75184d5
AW
92
93;; (put 'pass-if-syntax-error 'scheme-indent-function 1)
94(define-syntax pass-if-syntax-error
95 (syntax-rules ()
96 ((_ name pat exp)
97 (pass-if name
98 (catch 'syntax-error
f78a1cce 99 (lambda () exp (error "expected syntax-error exception"))
e75184d5
AW
100 (lambda (k who what where form . maybe-subform)
101 (if (if (pair? pat)
102 (and (eq? who (car pat))
103 (string-match (cdr pat) what))
104 (string-match pat what))
105 #t
106 (error "unexpected syntax-error exception" what pat))))))))
08c608e1
DH
107
108(with-test-prefix "expressions"
109
d6e04e7c
DH
110 (with-test-prefix "Bad argument list"
111
e75184d5 112 (pass-if-syntax-error "improper argument list of length 1"
40b36cfb 113 exception:generic-syncase-error
d6e04e7c
DH
114 (eval '(let ((foo (lambda (x y) #t)))
115 (foo . 1))
116 (interaction-environment)))
117
e75184d5 118 (pass-if-syntax-error "improper argument list of length 2"
40b36cfb 119 exception:generic-syncase-error
d6e04e7c
DH
120 (eval '(let ((foo (lambda (x y) #t)))
121 (foo 1 . 2))
122 (interaction-environment))))
123
08c608e1
DH
124 (with-test-prefix "missing or extra expression"
125
126 ;; R5RS says:
127 ;; *Note:* In many dialects of Lisp, the empty combination, (),
128 ;; is a legitimate expression. In Scheme, combinations must
129 ;; have at least one subexpression, so () is not a syntactically
130 ;; valid expression.
1c54a87c
MV
131
132 ;; Fixed on 2001-3-3
e75184d5 133 (pass-if-syntax-error "empty parentheses \"()\""
40b36cfb 134 exception:unexpected-syntax
d6e04e7c
DH
135 (eval '()
136 (interaction-environment)))))
08c608e1 137
7171f1ab
DH
138(with-test-prefix "quote"
139 #t)
140
141(with-test-prefix "quasiquote"
142
143 (with-test-prefix "unquote"
144
145 (pass-if "repeated execution"
146 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
147 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
148
149 (with-test-prefix "unquote-splicing"
150
36ad2533
AW
151 (pass-if "extra arguments"
152 (equal? (eval '(quasiquote ((unquote-splicing (list 1 2) (list 3 4))))
153 (interaction-environment))
154 '(1 2 3 4)))))
7171f1ab
DH
155
156(with-test-prefix "begin"
157
9133716f 158 (pass-if "valid (begin)"
ce09ee19 159 (eval '(begin (begin) #t) (interaction-environment)))
7171f1ab 160
dc65d1cf 161 (if (not (include-deprecated-features))
9133716f
LC
162 (pass-if-syntax-error "invalid (begin)"
163 exception:zero-expression-sequence
dc65d1cf 164 (eval '(begin (if #t (begin)) #t) (interaction-environment)))))
7171f1ab 165
02604212 166(define-syntax matches?
31fe1202 167 (syntax-rules (<>)
02604212
AW
168 ((_ (op arg ...) pat) (let ((x (op arg ...)))
169 (matches? x pat)))
170 ((_ x ()) (null? x))
171 ((_ x (a . b)) (and (pair? x)
172 (matches? (car x) a)
173 (matches? (cdr x) b)))
31fe1202 174 ((_ x <>) #t)
02604212
AW
175 ((_ x pat) (equal? x 'pat))))
176
08c608e1
DH
177(with-test-prefix "lambda"
178
179 (with-test-prefix "bad formals"
180
e75184d5 181 (pass-if-syntax-error "(lambda)"
dc1eed52 182 exception:bad-lambda
d6e04e7c
DH
183 (eval '(lambda)
184 (interaction-environment)))
ea6c2147 185
e75184d5 186 (pass-if-syntax-error "(lambda . \"foo\")"
dc1eed52 187 exception:bad-lambda
d6e04e7c
DH
188 (eval '(lambda . "foo")
189 (interaction-environment)))
ea6c2147 190
e75184d5 191 (pass-if-syntax-error "(lambda \"foo\")"
dc1eed52 192 exception:bad-lambda
d6e04e7c
DH
193 (eval '(lambda "foo")
194 (interaction-environment)))
ea6c2147 195
e75184d5 196 (pass-if-syntax-error "(lambda \"foo\" #f)"
ea6c2147 197 exception:bad-formals
4dce3c96
DH
198 (eval '(lambda "foo" #f)
199 (interaction-environment)))
ea6c2147 200
e75184d5 201 (pass-if-syntax-error "(lambda (x 1) 2)"
dc1eed52 202 exception:bad-formals
d6e04e7c
DH
203 (eval '(lambda (x 1) 2)
204 (interaction-environment)))
08c608e1 205
e75184d5 206 (pass-if-syntax-error "(lambda (1 x) 2)"
dc1eed52 207 exception:bad-formals
d6e04e7c
DH
208 (eval '(lambda (1 x) 2)
209 (interaction-environment)))
08c608e1 210
e75184d5 211 (pass-if-syntax-error "(lambda (x \"a\") 2)"
dc1eed52 212 exception:bad-formals
d6e04e7c
DH
213 (eval '(lambda (x "a") 2)
214 (interaction-environment)))
08c608e1 215
e75184d5 216 (pass-if-syntax-error "(lambda (\"a\" x) 2)"
dc1eed52 217 exception:bad-formals
d6e04e7c
DH
218 (eval '(lambda ("a" x) 2)
219 (interaction-environment))))
08c608e1 220
1c54a87c
MV
221 (with-test-prefix "duplicate formals"
222
223 ;; Fixed on 2001-3-3
e75184d5 224 (pass-if-syntax-error "(lambda (x x) 1)"
c89222f8 225 exception:duplicate-formals
d6e04e7c
DH
226 (eval '(lambda (x x) 1)
227 (interaction-environment)))
08c608e1 228
1c54a87c 229 ;; Fixed on 2001-3-3
e75184d5 230 (pass-if-syntax-error "(lambda (x x x) 1)"
c89222f8 231 exception:duplicate-formals
d6e04e7c
DH
232 (eval '(lambda (x x x) 1)
233 (interaction-environment))))
7171f1ab
DH
234
235 (with-test-prefix "bad body"
236
e75184d5 237 (pass-if-syntax-error "(lambda ())"
dc1eed52 238 exception:bad-lambda
d6e04e7c
DH
239 (eval '(lambda ())
240 (interaction-environment)))))
08c608e1
DH
241
242(with-test-prefix "let"
243
244 (with-test-prefix "bindings"
245
246 (pass-if-exception "late binding"
247 exception:unbound-var
248 (let ((x 1) (y x)) y)))
249
7171f1ab 250 (with-test-prefix "bad bindings"
08c608e1 251
e75184d5 252 (pass-if-syntax-error "(let)"
dc1eed52 253 exception:bad-let
d6e04e7c
DH
254 (eval '(let)
255 (interaction-environment)))
08c608e1 256
e75184d5 257 (pass-if-syntax-error "(let 1)"
dc1eed52 258 exception:bad-let
d6e04e7c
DH
259 (eval '(let 1)
260 (interaction-environment)))
08c608e1 261
e75184d5 262 (pass-if-syntax-error "(let (x))"
dc1eed52 263 exception:bad-let
d6e04e7c
DH
264 (eval '(let (x))
265 (interaction-environment)))
08c608e1 266
e75184d5 267 (pass-if-syntax-error "(let ((x)))"
dc1eed52 268 exception:bad-let
d6e04e7c
DH
269 (eval '(let ((x)))
270 (interaction-environment)))
08c608e1 271
e75184d5 272 (pass-if-syntax-error "(let (x) 1)"
dc1eed52 273 exception:bad-let
d6e04e7c
DH
274 (eval '(let (x) 1)
275 (interaction-environment)))
08c608e1 276
e75184d5 277 (pass-if-syntax-error "(let ((x)) 3)"
dc1eed52 278 exception:bad-let
d6e04e7c
DH
279 (eval '(let ((x)) 3)
280 (interaction-environment)))
08c608e1 281
e75184d5 282 (pass-if-syntax-error "(let ((x 1) y) x)"
dc1eed52 283 exception:bad-let
d6e04e7c
DH
284 (eval '(let ((x 1) y) x)
285 (interaction-environment)))
08c608e1 286
e75184d5 287 (pass-if-syntax-error "(let ((1 2)) 3)"
dc1eed52 288 exception:bad-let
4dce3c96
DH
289 (eval '(let ((1 2)) 3)
290 (interaction-environment))))
08c608e1 291
c0ed1605
MV
292 (with-test-prefix "duplicate bindings"
293
e75184d5 294 (pass-if-syntax-error "(let ((x 1) (x 2)) x)"
d6754c23 295 exception:duplicate-binding
d6e04e7c
DH
296 (eval '(let ((x 1) (x 2)) x)
297 (interaction-environment))))
7171f1ab
DH
298
299 (with-test-prefix "bad body"
300
e75184d5 301 (pass-if-syntax-error "(let ())"
dc1eed52 302 exception:bad-let
d6e04e7c
DH
303 (eval '(let ())
304 (interaction-environment)))
7171f1ab 305
e75184d5 306 (pass-if-syntax-error "(let ((x 1)))"
dc1eed52 307 exception:bad-let
d6e04e7c
DH
308 (eval '(let ((x 1)))
309 (interaction-environment)))))
08c608e1
DH
310
311(with-test-prefix "named let"
312
7171f1ab
DH
313 (with-test-prefix "initializers"
314
315 (pass-if "evaluated in outer environment"
316 (let ((f -))
317 (eqv? (let f ((n (f 1))) n) -1))))
318
319 (with-test-prefix "bad bindings"
320
e75184d5 321 (pass-if-syntax-error "(let x (y))"
dc1eed52 322 exception:bad-let
d6e04e7c
DH
323 (eval '(let x (y))
324 (interaction-environment))))
7171f1ab 325
08c608e1
DH
326 (with-test-prefix "bad body"
327
e75184d5 328 (pass-if-syntax-error "(let x ())"
dc1eed52 329 exception:bad-let
d6e04e7c
DH
330 (eval '(let x ())
331 (interaction-environment)))
08c608e1 332
e75184d5 333 (pass-if-syntax-error "(let x ((y 1)))"
dc1eed52 334 exception:bad-let
d6e04e7c
DH
335 (eval '(let x ((y 1)))
336 (interaction-environment)))))
08c608e1
DH
337
338(with-test-prefix "let*"
339
e1a7b2ce
DH
340 (with-test-prefix "bindings"
341
342 (pass-if "(let* ((x 1) (x 2)) ...)"
343 (let* ((x 1) (x 2))
344 (= x 2)))
345
346 (pass-if "(let* ((x 1) (x x)) ...)"
347 (let* ((x 1) (x x))
aa498d0c
DH
348 (= x 1)))
349
350 (pass-if "(let ((x 1) (y 2)) (let* () ...))"
351 (let ((x 1) (y 2))
352 (let* ()
353 (and (= x 1) (= y 2))))))
e1a7b2ce 354
7171f1ab 355 (with-test-prefix "bad bindings"
08c608e1 356
e75184d5 357 (pass-if-syntax-error "(let*)"
dc1eed52 358 exception:generic-syncase-error
d6e04e7c
DH
359 (eval '(let*)
360 (interaction-environment)))
08c608e1 361
e75184d5 362 (pass-if-syntax-error "(let* 1)"
dc1eed52 363 exception:generic-syncase-error
d6e04e7c
DH
364 (eval '(let* 1)
365 (interaction-environment)))
08c608e1 366
e75184d5 367 (pass-if-syntax-error "(let* (x))"
dc1eed52 368 exception:generic-syncase-error
d6e04e7c
DH
369 (eval '(let* (x))
370 (interaction-environment)))
08c608e1 371
e75184d5 372 (pass-if-syntax-error "(let* (x) 1)"
dc1eed52 373 exception:generic-syncase-error
d6e04e7c
DH
374 (eval '(let* (x) 1)
375 (interaction-environment)))
08c608e1 376
e75184d5 377 (pass-if-syntax-error "(let* ((x)) 3)"
dc1eed52 378 exception:generic-syncase-error
d6e04e7c
DH
379 (eval '(let* ((x)) 3)
380 (interaction-environment)))
08c608e1 381
e75184d5 382 (pass-if-syntax-error "(let* ((x 1) y) x)"
dc1eed52 383 exception:generic-syncase-error
d6e04e7c
DH
384 (eval '(let* ((x 1) y) x)
385 (interaction-environment)))
08c608e1 386
e75184d5 387 (pass-if-syntax-error "(let* x ())"
dc1eed52 388 exception:generic-syncase-error
4dce3c96
DH
389 (eval '(let* x ())
390 (interaction-environment)))
08c608e1 391
e75184d5 392 (pass-if-syntax-error "(let* x (y))"
dc1eed52 393 exception:generic-syncase-error
4dce3c96
DH
394 (eval '(let* x (y))
395 (interaction-environment)))
08c608e1 396
e75184d5 397 (pass-if-syntax-error "(let* ((1 2)) 3)"
dc1eed52 398 exception:generic-syncase-error
4dce3c96
DH
399 (eval '(let* ((1 2)) 3)
400 (interaction-environment))))
7171f1ab
DH
401
402 (with-test-prefix "bad body"
403
e75184d5 404 (pass-if-syntax-error "(let* ())"
dc1eed52 405 exception:generic-syncase-error
d6e04e7c
DH
406 (eval '(let* ())
407 (interaction-environment)))
7171f1ab 408
e75184d5 409 (pass-if-syntax-error "(let* ((x 1)))"
dc1eed52 410 exception:generic-syncase-error
d6e04e7c
DH
411 (eval '(let* ((x 1)))
412 (interaction-environment)))))
08c608e1
DH
413
414(with-test-prefix "letrec"
415
416 (with-test-prefix "bindings"
417
7974c579
AW
418 (pass-if-exception "initial bindings are undefined"
419 exception:variable-ref
420 (eval '(let ((x 1))
421 (letrec ((x 1) (y x)) y))
422 (interaction-environment))))
08c608e1 423
7171f1ab 424 (with-test-prefix "bad bindings"
08c608e1 425
e75184d5 426 (pass-if-syntax-error "(letrec)"
dc1eed52 427 exception:bad-letrec
d6e04e7c
DH
428 (eval '(letrec)
429 (interaction-environment)))
08c608e1 430
e75184d5 431 (pass-if-syntax-error "(letrec 1)"
dc1eed52 432 exception:bad-letrec
d6e04e7c
DH
433 (eval '(letrec 1)
434 (interaction-environment)))
08c608e1 435
e75184d5 436 (pass-if-syntax-error "(letrec (x))"
dc1eed52 437 exception:bad-letrec
d6e04e7c
DH
438 (eval '(letrec (x))
439 (interaction-environment)))
08c608e1 440
e75184d5 441 (pass-if-syntax-error "(letrec (x) 1)"
dc1eed52 442 exception:bad-letrec
d6e04e7c
DH
443 (eval '(letrec (x) 1)
444 (interaction-environment)))
08c608e1 445
e75184d5 446 (pass-if-syntax-error "(letrec ((x)) 3)"
dc1eed52 447 exception:bad-letrec
d6e04e7c
DH
448 (eval '(letrec ((x)) 3)
449 (interaction-environment)))
08c608e1 450
e75184d5 451 (pass-if-syntax-error "(letrec ((x 1) y) x)"
dc1eed52 452 exception:bad-letrec
d6e04e7c
DH
453 (eval '(letrec ((x 1) y) x)
454 (interaction-environment)))
08c608e1 455
e75184d5 456 (pass-if-syntax-error "(letrec x ())"
dc1eed52 457 exception:bad-letrec
4dce3c96
DH
458 (eval '(letrec x ())
459 (interaction-environment)))
08c608e1 460
e75184d5 461 (pass-if-syntax-error "(letrec x (y))"
dc1eed52 462 exception:bad-letrec
4dce3c96
DH
463 (eval '(letrec x (y))
464 (interaction-environment)))
08c608e1 465
e75184d5 466 (pass-if-syntax-error "(letrec ((1 2)) 3)"
dc1eed52 467 exception:bad-letrec
4dce3c96
DH
468 (eval '(letrec ((1 2)) 3)
469 (interaction-environment))))
08c608e1 470
c0ed1605
MV
471 (with-test-prefix "duplicate bindings"
472
e75184d5 473 (pass-if-syntax-error "(letrec ((x 1) (x 2)) x)"
d6754c23 474 exception:duplicate-binding
d6e04e7c
DH
475 (eval '(letrec ((x 1) (x 2)) x)
476 (interaction-environment))))
7171f1ab
DH
477
478 (with-test-prefix "bad body"
479
e75184d5 480 (pass-if-syntax-error "(letrec ())"
dc1eed52 481 exception:bad-letrec
d6e04e7c
DH
482 (eval '(letrec ())
483 (interaction-environment)))
7171f1ab 484
e75184d5 485 (pass-if-syntax-error "(letrec ((x 1)))"
dc1eed52 486 exception:bad-letrec
d6e04e7c
DH
487 (eval '(letrec ((x 1)))
488 (interaction-environment)))))
08c608e1 489
5f8c55ce
AW
490(with-test-prefix "letrec*"
491
492 (with-test-prefix "bindings"
493
7974c579
AW
494 (pass-if-exception "initial bindings are undefined"
495 exception:variable-ref
496 (eval '(letrec* ((x y) (y 1)) y)
497 (interaction-environment))))
5f8c55ce
AW
498
499 (with-test-prefix "bad bindings"
500
e75184d5 501 (pass-if-syntax-error "(letrec*)"
5f8c55ce
AW
502 exception:bad-letrec*
503 (eval '(letrec*)
504 (interaction-environment)))
505
e75184d5 506 (pass-if-syntax-error "(letrec* 1)"
5f8c55ce
AW
507 exception:bad-letrec*
508 (eval '(letrec* 1)
509 (interaction-environment)))
510
e75184d5 511 (pass-if-syntax-error "(letrec* (x))"
5f8c55ce
AW
512 exception:bad-letrec*
513 (eval '(letrec* (x))
514 (interaction-environment)))
515
e75184d5 516 (pass-if-syntax-error "(letrec* (x) 1)"
5f8c55ce
AW
517 exception:bad-letrec*
518 (eval '(letrec* (x) 1)
519 (interaction-environment)))
520
e75184d5 521 (pass-if-syntax-error "(letrec* ((x)) 3)"
5f8c55ce
AW
522 exception:bad-letrec*
523 (eval '(letrec* ((x)) 3)
524 (interaction-environment)))
525
e75184d5 526 (pass-if-syntax-error "(letrec* ((x 1) y) x)"
5f8c55ce
AW
527 exception:bad-letrec*
528 (eval '(letrec* ((x 1) y) x)
529 (interaction-environment)))
530
e75184d5 531 (pass-if-syntax-error "(letrec* x ())"
5f8c55ce
AW
532 exception:bad-letrec*
533 (eval '(letrec* x ())
534 (interaction-environment)))
535
e75184d5 536 (pass-if-syntax-error "(letrec* x (y))"
5f8c55ce
AW
537 exception:bad-letrec*
538 (eval '(letrec* x (y))
539 (interaction-environment)))
540
e75184d5 541 (pass-if-syntax-error "(letrec* ((1 2)) 3)"
5f8c55ce
AW
542 exception:bad-letrec*
543 (eval '(letrec* ((1 2)) 3)
544 (interaction-environment))))
545
546 (with-test-prefix "duplicate bindings"
547
e75184d5 548 (pass-if-syntax-error "(letrec* ((x 1) (x 2)) x)"
5f8c55ce
AW
549 exception:duplicate-binding
550 (eval '(letrec* ((x 1) (x 2)) x)
551 (interaction-environment))))
552
553 (with-test-prefix "bad body"
554
e75184d5 555 (pass-if-syntax-error "(letrec* ())"
5f8c55ce
AW
556 exception:bad-letrec*
557 (eval '(letrec* ())
558 (interaction-environment)))
559
e75184d5 560 (pass-if-syntax-error "(letrec* ((x 1)))"
5f8c55ce
AW
561 exception:bad-letrec*
562 (eval '(letrec* ((x 1)))
563 (interaction-environment))))
564
565 (with-test-prefix "referencing previous values"
7974c579
AW
566 (pass-if (equal? (letrec* ((a (cons 'foo 'bar))
567 (b a))
5f8c55ce
AW
568 b)
569 '(foo . bar)))
570 (pass-if (equal? (let ()
571 (define a (cons 'foo 'bar))
572 (define b a)
573 b)
574 '(foo . bar)))))
575
08c608e1
DH
576(with-test-prefix "if"
577
578 (with-test-prefix "missing or extra expressions"
579
e75184d5 580 (pass-if-syntax-error "(if)"
dc1eed52 581 exception:generic-syncase-error
4dce3c96
DH
582 (eval '(if)
583 (interaction-environment)))
08c608e1 584
e75184d5 585 (pass-if-syntax-error "(if 1 2 3 4)"
dc1eed52 586 exception:generic-syncase-error
4dce3c96
DH
587 (eval '(if 1 2 3 4)
588 (interaction-environment)))))
08c608e1
DH
589
590(with-test-prefix "cond"
591
aa498d0c
DH
592 (with-test-prefix "cond is hygienic"
593
594 (pass-if "bound 'else is handled correctly"
595 (eq? (let ((else 'ok)) (cond (else))) 'ok))
596
597 (with-test-prefix "bound '=> is handled correctly"
598
599 (pass-if "#t => 'ok"
600 (let ((=> 'foo))
601 (eq? (cond (#t => 'ok)) 'ok)))
602
603 (pass-if "else =>"
604 (let ((=> 'foo))
605 (eq? (cond (else =>)) 'foo)))
606
607 (pass-if "else => identity"
608 (let ((=> 'foo))
609 (eq? (cond (else => identity)) identity)))))
610
9ee0f678
LC
611 (with-test-prefix "SRFI-61"
612
613 (pass-if "always available"
614 (cond-expand (srfi-61 #t) (else #f)))
615
616 (pass-if "single value consequent"
617 (eq? 'ok (cond (#t identity => (lambda (x) 'ok)) (else #f))))
618
619 (pass-if "single value alternate"
620 (eq? 'ok (cond (#t not => (lambda (x) #f)) (else 'ok))))
621
622 (pass-if-exception "doesn't affect standard =>"
623 exception:wrong-num-args
624 (cond ((values 1 2) => (lambda (x y) #t))))
625
626 (pass-if "multiple values consequent"
627 (equal? '(2 1) (cond ((values 1 2)
628 (lambda (one two)
629 (and (= 1 one) (= 2 two))) =>
630 (lambda (one two) (list two one)))
631 (else #f))))
632
633 (pass-if "multiple values alternate"
634 (eq? 'ok (cond ((values 2 3 4)
635 (lambda args (equal? '(1 2 3) args)) =>
636 (lambda (x y z) #f))
637 (else 'ok))))
638
639 (pass-if "zero values"
640 (eq? 'ok (cond ((values) (lambda () #t) => (lambda () 'ok))
641 (else #f))))
642
643 (pass-if "bound => is handled correctly"
644 (let ((=> 'ok))
645 (eq? 'ok (cond (#t identity =>) (else #f)))))
646
e75184d5
AW
647 (pass-if-syntax-error "missing recipient"
648 '(cond . "wrong number of receiver expressions")
e7cf0457
MW
649 (eval '(cond (#t identity =>))
650 (interaction-environment)))
9ee0f678 651
e75184d5
AW
652 (pass-if-syntax-error "extra recipient"
653 '(cond . "wrong number of receiver expressions")
e7cf0457
MW
654 (eval '(cond (#t identity => identity identity))
655 (interaction-environment))))
9ee0f678 656
08c608e1
DH
657 (with-test-prefix "bad or missing clauses"
658
e75184d5 659 (pass-if-syntax-error "(cond)"
dc1eed52 660 exception:generic-syncase-error
d6e04e7c
DH
661 (eval '(cond)
662 (interaction-environment)))
08c608e1 663
e75184d5 664 (pass-if-syntax-error "(cond #t)"
e7cf0457 665 '(cond . "invalid clause")
d6e04e7c
DH
666 (eval '(cond #t)
667 (interaction-environment)))
08c608e1 668
e75184d5 669 (pass-if-syntax-error "(cond 1)"
e7cf0457 670 '(cond . "invalid clause")
d6e04e7c
DH
671 (eval '(cond 1)
672 (interaction-environment)))
08c608e1 673
e75184d5 674 (pass-if-syntax-error "(cond 1 2)"
e7cf0457 675 '(cond . "invalid clause")
d6e04e7c
DH
676 (eval '(cond 1 2)
677 (interaction-environment)))
08c608e1 678
e75184d5 679 (pass-if-syntax-error "(cond 1 2 3)"
e7cf0457 680 '(cond . "invalid clause")
d6e04e7c
DH
681 (eval '(cond 1 2 3)
682 (interaction-environment)))
08c608e1 683
e75184d5 684 (pass-if-syntax-error "(cond 1 2 3 4)"
e7cf0457 685 '(cond . "invalid clause")
d6e04e7c
DH
686 (eval '(cond 1 2 3 4)
687 (interaction-environment)))
08c608e1 688
e75184d5 689 (pass-if-syntax-error "(cond ())"
e7cf0457 690 '(cond . "invalid clause")
d6e04e7c
DH
691 (eval '(cond ())
692 (interaction-environment)))
08c608e1 693
e75184d5 694 (pass-if-syntax-error "(cond () 1)"
e7cf0457 695 '(cond . "invalid clause")
d6e04e7c
DH
696 (eval '(cond () 1)
697 (interaction-environment)))
08c608e1 698
e75184d5 699 (pass-if-syntax-error "(cond (1) 1)"
e7cf0457 700 '(cond . "invalid clause")
d6e04e7c 701 (eval '(cond (1) 1)
e7cf0457
MW
702 (interaction-environment)))
703
704 (pass-if-syntax-error "(cond (else #f) (#t #t))"
705 '(cond . "else must be the last clause")
706 (eval '(cond (else #f) (#t #t))
aa498d0c 707 (interaction-environment))))
b461abe7 708
d6e04e7c 709 (with-test-prefix "wrong number of arguments"
08c608e1 710
d6e04e7c
DH
711 (pass-if-exception "=> (lambda (x y) #t)"
712 exception:wrong-num-args
713 (cond (1 => (lambda (x y) #t))))))
08c608e1 714
27a22666
DH
715(with-test-prefix "case"
716
58a2510b
DH
717 (pass-if "clause with empty labels list"
718 (case 1 (() #f) (else #t)))
719
e7cf0457
MW
720 (with-test-prefix "case handles '=> correctly"
721
722 (pass-if "(1 2 3) => list"
723 (equal? (case 1 ((1 2 3) => list))
724 '(1)))
725
726 (pass-if "else => list"
727 (equal? (case 6
728 ((1 2 3) 'wrong)
729 (else => list))
730 '(6)))
731
732 (with-test-prefix "bound '=> is handled correctly"
733
734 (pass-if "(1) => 'ok"
735 (let ((=> 'foo))
736 (eq? (case 1 ((1) => 'ok)) 'ok)))
737
738 (pass-if "else =>"
739 (let ((=> 'foo))
740 (eq? (case 1 (else =>)) 'foo)))
741
742 (pass-if "else => list"
743 (let ((=> 'foo))
744 (eq? (case 1 (else => identity)) identity))))
745
746 (pass-if-syntax-error "missing recipient"
747 '(case . "wrong number of receiver expressions")
748 (eval '(case 1 ((1) =>))
749 (interaction-environment)))
750
751 (pass-if-syntax-error "extra recipient"
752 '(case . "wrong number of receiver expressions")
753 (eval '(case 1 ((1) => identity identity))
754 (interaction-environment))))
755
2a6f7afe
DH
756 (with-test-prefix "case is hygienic"
757
e75184d5 758 (pass-if-syntax-error "bound 'else is handled correctly"
e7cf0457 759 '(case . "invalid clause")
2a6f7afe
DH
760 (eval '(let ((else #f)) (case 1 (else #f)))
761 (interaction-environment))))
762
27a22666
DH
763 (with-test-prefix "bad or missing clauses"
764
e75184d5 765 (pass-if-syntax-error "(case)"
dc1eed52 766 exception:generic-syncase-error
d6e04e7c
DH
767 (eval '(case)
768 (interaction-environment)))
27a22666 769
e75184d5 770 (pass-if-syntax-error "(case . \"foo\")"
dc1eed52 771 exception:generic-syncase-error
d6e04e7c
DH
772 (eval '(case . "foo")
773 (interaction-environment)))
27a22666 774
e75184d5 775 (pass-if-syntax-error "(case 1)"
dc1eed52 776 exception:generic-syncase-error
d6e04e7c
DH
777 (eval '(case 1)
778 (interaction-environment)))
27a22666 779
e75184d5 780 (pass-if-syntax-error "(case 1 . \"foo\")"
dc1eed52 781 exception:generic-syncase-error
d6e04e7c
DH
782 (eval '(case 1 . "foo")
783 (interaction-environment)))
27a22666 784
e75184d5 785 (pass-if-syntax-error "(case 1 \"foo\")"
e7cf0457 786 '(case . "invalid clause")
d6e04e7c
DH
787 (eval '(case 1 "foo")
788 (interaction-environment)))
27a22666 789
e75184d5 790 (pass-if-syntax-error "(case 1 ())"
e7cf0457 791 '(case . "invalid clause")
d6e04e7c
DH
792 (eval '(case 1 ())
793 (interaction-environment)))
27a22666 794
e75184d5 795 (pass-if-syntax-error "(case 1 (\"foo\"))"
e7cf0457 796 '(case . "invalid clause")
d6e04e7c
DH
797 (eval '(case 1 ("foo"))
798 (interaction-environment)))
27a22666 799
e75184d5 800 (pass-if-syntax-error "(case 1 (\"foo\" \"bar\"))"
e7cf0457 801 '(case . "invalid clause")
d6e04e7c
DH
802 (eval '(case 1 ("foo" "bar"))
803 (interaction-environment)))
27a22666 804
e75184d5 805 (pass-if-syntax-error "(case 1 ((2) \"bar\") . \"foo\")"
dc1eed52 806 exception:generic-syncase-error
d6e04e7c
DH
807 (eval '(case 1 ((2) "bar") . "foo")
808 (interaction-environment)))
27a22666 809
e75184d5 810 (pass-if-syntax-error "(case 1 ((2) \"bar\") (else))"
e7cf0457 811 '(case . "invalid clause")
d6e04e7c
DH
812 (eval '(case 1 ((2) "bar") (else))
813 (interaction-environment)))
27a22666 814
e75184d5 815 (pass-if-syntax-error "(case 1 (else #f) . \"foo\")"
dc1eed52 816 exception:generic-syncase-error
d6e04e7c
DH
817 (eval '(case 1 (else #f) . "foo")
818 (interaction-environment)))
27a22666 819
e75184d5 820 (pass-if-syntax-error "(case 1 (else #f) ((1) #t))"
e7cf0457 821 '(case . "else must be the last clause")
d6e04e7c
DH
822 (eval '(case 1 (else #f) ((1) #t))
823 (interaction-environment)))))
27a22666 824
ced8edb0 825(with-test-prefix "top-level define"
08c608e1 826
3dcf3373
LC
827 (pass-if "redefinition"
828 (let ((m (make-module)))
829 (beautify-user-module! m)
830
831 ;; The previous value of `round' must still be visible at the time the
832 ;; new `round' is defined. According to R5RS (Section 5.2.1), `define'
833 ;; should behave like `set!' in this case (except that in the case of
834 ;; Guile, we respect module boundaries).
835 (eval '(define round round) m)
836 (eq? (module-ref m 'round) round)))
36245b66 837
08c608e1
DH
838 (with-test-prefix "missing or extra expressions"
839
e75184d5 840 (pass-if-syntax-error "(define)"
9ecac781 841 exception:generic-syncase-error
d6e04e7c 842 (eval '(define)
1ce64556
AW
843 (interaction-environment))))
844
845 (pass-if "module scoping"
846 (equal?
847 (eval
848 '(begin
849 (define-module (top-level-define/module-scoping-1)
850 #:export (define-10))
851 (define-syntax-rule (define-10 name)
852 (begin
853 (define t 10)
854 (define (name) t)))
855 (define-module (top-level-define/module-scoping-2)
856 #:use-module (top-level-define/module-scoping-1))
857 (define-10 foo)
858 (foo))
859 (current-module))
ab2d0f8f
AW
860 10))
861
862 (pass-if "module scoping, same symbolic name"
863 (equal?
864 (eval
865 '(begin
866 (define-module (top-level-define/module-scoping-3))
867 (define a 10)
868 (define-module (top-level-define/module-scoping-4)
869 #:use-module (top-level-define/module-scoping-3))
870 (define a (@@ (top-level-define/module-scoping-3) a))
871 a)
872 (current-module))
adf91e1c
AW
873 10))
874
875 (pass-if "module scoping, introduced names"
876 (equal?
877 (eval
878 '(begin
879 (define-module (top-level-define/module-scoping-5)
880 #:export (define-constant))
881 (define-syntax-rule (define-constant name val)
882 (begin
883 (define t val)
884 (define (name) t)))
885 (define-module (top-level-define/module-scoping-6)
886 #:use-module (top-level-define/module-scoping-5))
887 (define-constant foo 10)
888 (define-constant bar 20)
889 (foo))
890 (current-module))
891 10))
892
893 (pass-if "module scoping, duplicate introduced name"
894 (equal?
895 (eval
896 '(begin
897 (define-module (top-level-define/module-scoping-7)
898 #:export (define-constant))
899 (define-syntax-rule (define-constant name val)
900 (begin
901 (define t val)
902 (define (name) t)))
903 (define-module (top-level-define/module-scoping-8)
904 #:use-module (top-level-define/module-scoping-7))
905 (define-constant foo 10)
906 (define-constant foo 20)
907 (foo))
908 (current-module))
909 20)))
08c608e1 910
ced8edb0
DH
911(with-test-prefix "internal define"
912
913 (pass-if "internal defines become letrec"
914 (eval '(let ((a identity) (b identity) (c identity))
915 (define (a x) (if (= x 0) 'a (b (- x 1))))
916 (define (b x) (if (= x 0) 'b (c (- x 1))))
917 (define (c x) (if (= x 0) 'c (a (- x 1))))
918 (and (eq? 'a (a 0) (a 3))
919 (eq? 'b (a 1) (a 4))
920 (eq? 'c (a 2) (a 5))))
921 (interaction-environment)))
922
3dcf3373
LC
923 (pass-if "binding is created before expression is evaluated"
924 ;; Internal defines are equivalent to `letrec' (R5RS, Section 5.2.2).
925 (= (eval '(let ()
926 (define foo
927 (begin
928 (set! foo 1)
929 (+ foo 1)))
930 foo)
931 (interaction-environment))
932 2))
933
c86c440b 934 (pass-if "internal defines with begin"
ced8edb0
DH
935 (false-if-exception
936 (eval '(let ((a identity) (b identity) (c identity))
937 (define (a x) (if (= x 0) 'a (b (- x 1))))
938 (begin
939 (define (b x) (if (= x 0) 'b (c (- x 1)))))
940 (define (c x) (if (= x 0) 'c (a (- x 1))))
941 (and (eq? 'a (a 0) (a 3))
942 (eq? 'b (a 1) (a 4))
943 (eq? 'c (a 2) (a 5))))
944 (interaction-environment))))
945
c86c440b 946 (pass-if "internal defines with empty begin"
ced8edb0
DH
947 (false-if-exception
948 (eval '(let ((a identity) (b identity) (c identity))
949 (define (a x) (if (= x 0) 'a (b (- x 1))))
950 (begin)
951 (define (b x) (if (= x 0) 'b (c (- x 1))))
952 (define (c x) (if (= x 0) 'c (a (- x 1))))
953 (and (eq? 'a (a 0) (a 3))
954 (eq? 'b (a 1) (a 4))
955 (eq? 'c (a 2) (a 5))))
956 (interaction-environment))))
957
c3d94801 958 (pass-if "internal defines with macro application"
560434b3
DH
959 (false-if-exception
960 (eval '(begin
c3d94801 961 (defmacro my-define forms
560434b3 962 (cons 'define forms))
c3d94801
DH
963 (let ((a identity) (b identity) (c identity))
964 (define (a x) (if (= x 0) 'a (b (- x 1))))
965 (my-define (b x) (if (= x 0) 'b (c (- x 1))))
966 (define (c x) (if (= x 0) 'c (a (- x 1))))
967 (and (eq? 'a (a 0) (a 3))
968 (eq? 'b (a 1) (a 4))
969 (eq? 'c (a 2) (a 5)))))
560434b3
DH
970 (interaction-environment))))
971
e75184d5 972 (pass-if-syntax-error "missing body expression"
ced8edb0
DH
973 exception:missing-body-expr
974 (eval '(let () (define x #t))
b7742c6b 975 (interaction-environment))))
aa498d0c 976
48eb9021
MW
977(with-test-prefix "top-level define-values"
978
979 (pass-if "zero values"
980 (eval '(begin (define-values () (values))
981 #t)
982 (interaction-environment)))
983
984 (pass-if-equal "one value"
985 1
986 (eval '(begin (define-values (x) 1)
987 x)
988 (interaction-environment)))
989
990 (pass-if-equal "two values"
991 '(2 3)
992 (eval '(begin (define-values (x y) (values 2 3))
993 (list x y))
994 (interaction-environment)))
995
996 (pass-if-equal "three values"
997 '(4 5 6)
998 (eval '(begin (define-values (x y z) (values 4 5 6))
999 (list x y z))
1000 (interaction-environment)))
1001
1002 (pass-if-equal "one value with tail"
1003 '(a (b c d))
1004 (eval '(begin (define-values (x . y) (values 'a 'b 'c 'd))
1005 (list x y))
1006 (interaction-environment)))
1007
1008 (pass-if-equal "two values with tail"
1009 '(x y (z w))
1010 (eval '(begin (define-values (x y . z) (values 'x 'y 'z 'w))
1011 (list x y z))
1012 (interaction-environment)))
1013
1014 (pass-if-equal "just tail"
1015 '(1 2 3)
1016 (eval '(begin (define-values x (values 1 2 3))
1017 x)
1018 (interaction-environment)))
1019
1020 (pass-if-exception "expected 0 values, got 1"
b00c9b22 1021 exception:wrong-number-of-values
48eb9021
MW
1022 (eval '(define-values () 1)
1023 (interaction-environment)))
1024
1025 (pass-if-exception "expected 1 value, got 0"
b00c9b22 1026 exception:wrong-number-of-values
48eb9021
MW
1027 (eval '(define-values (x) (values))
1028 (interaction-environment)))
1029
1030 (pass-if-exception "expected 1 value, got 2"
b00c9b22 1031 exception:wrong-number-of-values
48eb9021
MW
1032 (eval '(define-values (x) (values 1 2))
1033 (interaction-environment)))
1034
1035 (pass-if-exception "expected 1 value with tail, got 0"
b00c9b22 1036 exception:wrong-number-of-values
48eb9021
MW
1037 (eval '(define-values (x . y) (values))
1038 (interaction-environment)))
1039
1040 (pass-if-exception "expected 2 value with tail, got 1"
b00c9b22 1041 exception:wrong-number-of-values
48eb9021
MW
1042 (eval '(define-values (x y . z) 1)
1043 (interaction-environment)))
1044
1045 (pass-if "redefinition"
1046 (let ((m (make-module)))
1047 (beautify-user-module! m)
1048
1049 ;; The previous values of `floor' and `round' must still be
1050 ;; visible at the time the new `floor' and `round' are defined.
1051 (eval '(define-values (floor round) (values floor round)) m)
1052 (and (eq? (module-ref m 'floor) floor)
1053 (eq? (module-ref m 'round) round))))
1054
1055 (with-test-prefix "missing expression"
1056
1057 (pass-if-syntax-error "(define-values)"
1058 exception:generic-syncase-error
1059 (eval '(define-values)
1060 (interaction-environment)))))
1061
1062(with-test-prefix "internal define-values"
1063
1064 (pass-if "zero values"
1065 (let ()
1066 (define-values () (values))
1067 #t))
1068
1069 (pass-if-equal "one value"
1070 1
1071 (let ()
1072 (define-values (x) 1)
1073 x))
1074
1075 (pass-if-equal "two values"
1076 '(2 3)
1077 (let ()
1078 (define-values (x y) (values 2 3))
1079 (list x y)))
1080
1081 (pass-if-equal "three values"
1082 '(4 5 6)
1083 (let ()
1084 (define-values (x y z) (values 4 5 6))
1085 (list x y z)))
1086
1087 (pass-if-equal "one value with tail"
1088 '(a (b c d))
1089 (let ()
1090 (define-values (x . y) (values 'a 'b 'c 'd))
1091 (list x y)))
1092
1093 (pass-if-equal "two values with tail"
1094 '(x y (z w))
1095 (let ()
1096 (define-values (x y . z) (values 'x 'y 'z 'w))
1097 (list x y z)))
1098
1099 (pass-if-equal "just tail"
1100 '(1 2 3)
1101 (let ()
1102 (define-values x (values 1 2 3))
1103 x))
1104
1105 (pass-if-exception "expected 0 values, got 1"
b00c9b22 1106 exception:wrong-number-of-values
48eb9021
MW
1107 (eval '(let ()
1108 (define-values () 1)
1109 #f)
1110 (interaction-environment)))
1111
1112 (pass-if-exception "expected 1 value, got 0"
b00c9b22 1113 exception:wrong-number-of-values
48eb9021
MW
1114 (eval '(let ()
1115 (define-values (x) (values))
1116 #f)
1117 (interaction-environment)))
1118
1119 (pass-if-exception "expected 1 value, got 2"
b00c9b22 1120 exception:wrong-number-of-values
48eb9021
MW
1121 (eval '(let ()
1122 (define-values (x) (values 1 2))
1123 #f)
1124 (interaction-environment)))
1125
1126 (pass-if-exception "expected 1 value with tail, got 0"
b00c9b22 1127 exception:wrong-number-of-values
48eb9021
MW
1128 (eval '(let ()
1129 (define-values (x . y) (values))
1130 #f)
1131 (interaction-environment)))
1132
1133 (pass-if-exception "expected 2 value with tail, got 1"
b00c9b22 1134 exception:wrong-number-of-values
48eb9021
MW
1135 (eval '(let ()
1136 (define-values (x y . z) 1)
1137 #f)
1138 (interaction-environment)))
1139
1140 (with-test-prefix "missing expression"
1141
1142 (pass-if-syntax-error "(define-values)"
1143 exception:generic-syncase-error
1144 (eval '(let ()
1145 (define-values)
1146 #f)
1147 (interaction-environment)))))
1148
08c608e1
DH
1149(with-test-prefix "set!"
1150
1151 (with-test-prefix "missing or extra expressions"
1152
e75184d5 1153 (pass-if-syntax-error "(set!)"
9ecac781 1154 exception:bad-set!
4dce3c96
DH
1155 (eval '(set!)
1156 (interaction-environment)))
08c608e1 1157
e75184d5 1158 (pass-if-syntax-error "(set! 1)"
9ecac781 1159 exception:bad-set!
4dce3c96
DH
1160 (eval '(set! 1)
1161 (interaction-environment)))
08c608e1 1162
e75184d5 1163 (pass-if-syntax-error "(set! 1 2 3)"
9ecac781 1164 exception:bad-set!
4dce3c96
DH
1165 (eval '(set! 1 2 3)
1166 (interaction-environment))))
08c608e1
DH
1167
1168 (with-test-prefix "bad variable"
1169
e75184d5 1170 (pass-if-syntax-error "(set! \"\" #t)"
9ecac781 1171 exception:bad-set!
4dce3c96
DH
1172 (eval '(set! "" #t)
1173 (interaction-environment)))
08c608e1 1174
e75184d5 1175 (pass-if-syntax-error "(set! 1 #t)"
9ecac781 1176 exception:bad-set!
4dce3c96
DH
1177 (eval '(set! 1 #t)
1178 (interaction-environment)))
08c608e1 1179
e75184d5 1180 (pass-if-syntax-error "(set! #t #f)"
9ecac781 1181 exception:bad-set!
4dce3c96
DH
1182 (eval '(set! #t #f)
1183 (interaction-environment)))
08c608e1 1184
e75184d5 1185 (pass-if-syntax-error "(set! #f #t)"
9ecac781 1186 exception:bad-set!
4dce3c96
DH
1187 (eval '(set! #f #t)
1188 (interaction-environment)))
08c608e1 1189
e75184d5 1190 (pass-if-syntax-error "(set! #\\space #f)"
9ecac781 1191 exception:bad-set!
4dce3c96
DH
1192 (eval '(set! #\space #f)
1193 (interaction-environment)))))
08c608e1 1194
08c608e1
DH
1195(with-test-prefix "quote"
1196
1197 (with-test-prefix "missing or extra expression"
1198
e75184d5 1199 (pass-if-syntax-error "(quote)"
9ecac781 1200 exception:bad-quote
4dce3c96
DH
1201 (eval '(quote)
1202 (interaction-environment)))
08c608e1 1203
e75184d5 1204 (pass-if-syntax-error "(quote a b)"
9ecac781 1205 exception:bad-quote
4dce3c96
DH
1206 (eval '(quote a b)
1207 (interaction-environment)))))
2798ba71
KR
1208
1209(with-test-prefix "while"
1210
1211 (define (unreachable)
1212 (error "unreachable code has been reached!"))
1213
2798ba71
KR
1214 ;; Return a new procedure COND which when called (COND) will return #t the
1215 ;; first N times, then #f, then any further call is an error. N=0 is
1216 ;; allowed, in which case #f is returned by the first call.
1217 (define (make-iterations-cond n)
1218 (lambda ()
1219 (cond ((not n)
1220 (error "oops, condition re-tested after giving false"))
1221 ((= 0 n)
1222 (set! n #f)
1223 #f)
1224 (else
1225 (set! n (1- n))
1226 #t))))
1227
1228
e75184d5 1229 (pass-if-syntax-error "too few args" exception:generic-syncase-error
d6e04e7c 1230 (eval '(while) (interaction-environment)))
2798ba71
KR
1231
1232 (with-test-prefix "empty body"
1233 (do ((n 0 (1+ n)))
1234 ((> n 5))
1235 (pass-if n
ce09ee19
AW
1236 (eval `(letrec ((make-iterations-cond
1237 (lambda (n)
1238 (lambda ()
1239 (cond ((not n)
1240 (error "oops, condition re-tested after giving false"))
1241 ((= 0 n)
1242 (set! n #f)
1243 #f)
1244 (else
1245 (set! n (1- n))
1246 #t))))))
1247 (let ((cond (make-iterations-cond ,n)))
1248 (while (cond))
1249 #t))
1250 (interaction-environment)))))
2798ba71
KR
1251
1252 (pass-if "initially false"
1253 (while #f
1254 (unreachable))
1255 #t)
1256
2798ba71
KR
1257 (with-test-prefix "iterations"
1258 (do ((n 0 (1+ n)))
1259 ((> n 5))
1260 (pass-if n
1261 (let ((cond (make-iterations-cond n))
1262 (i 0))
1263 (while (cond)
1264 (set! i (1+ i)))
1265 (= i n)))))
1266
1267 (with-test-prefix "break"
1268
91956a94
AW
1269 (pass-if "normal return"
1270 (not (while #f (error "not reached"))))
1271
1272 (pass-if "no args"
1273 (while #t (break)))
1274
1275 (pass-if "multiple values"
1276 (equal? '(1 2 3)
1277 (call-with-values
1278 (lambda () (while #t (break 1 2 3)))
1279 list)))
1280
2798ba71
KR
1281 (with-test-prefix "from cond"
1282 (pass-if "first"
1283 (while (begin
1284 (break)
1285 (unreachable))
1286 (unreachable))
1287 #t)
1288
1289 (do ((n 0 (1+ n)))
1290 ((> n 5))
1291 (pass-if n
1292 (let ((cond (make-iterations-cond n))
1293 (i 0))
1294 (while (if (cond)
1295 #t
1296 (begin
1297 (break)
1298 (unreachable)))
1299 (set! i (1+ i)))
1300 (= i n)))))
1301
1302 (with-test-prefix "from body"
1303 (pass-if "first"
1304 (while #t
1305 (break)
1306 (unreachable))
1307 #t)
1308
1309 (do ((n 0 (1+ n)))
1310 ((> n 5))
1311 (pass-if n
1312 (let ((cond (make-iterations-cond n))
1313 (i 0))
1314 (while #t
1315 (if (not (cond))
1316 (begin
1317 (break)
1318 (unreachable)))
1319 (set! i (1+ i)))
1320 (= i n)))))
1321
1322 (pass-if "from nested"
1323 (while #t
1324 (let ((outer-break break))
1325 (while #t
1326 (outer-break)
1327 (unreachable)))
1328 (unreachable))
cc08aafd
KR
1329 #t)
1330
1331 (pass-if "from recursive"
1332 (let ((outer-break #f))
1333 (define (r n)
1334 (while #t
1335 (if (eq? n 'outer)
1336 (begin
1337 (set! outer-break break)
1338 (r 'inner))
1339 (begin
1340 (outer-break)
1341 (unreachable))))
1342 (if (eq? n 'inner)
1343 (error "broke only from inner loop")))
1344 (r 'outer))
2798ba71
KR
1345 #t))
1346
1347 (with-test-prefix "continue"
1348
e75184d5 1349 (pass-if-syntax-error "too many args" exception:too-many-args
9ecac781
AW
1350 (eval '(while #t
1351 (continue 1))
1352 (interaction-environment)))
2798ba71
KR
1353
1354 (with-test-prefix "from cond"
1355 (do ((n 0 (1+ n)))
1356 ((> n 5))
1357 (pass-if n
1358 (let ((cond (make-iterations-cond n))
1359 (i 0))
1360 (while (if (cond)
1361 (begin
1362 (set! i (1+ i))
1363 (continue)
1364 (unreachable))
1365 #f)
1366 (unreachable))
1367 (= i n)))))
1368
1369 (with-test-prefix "from body"
1370 (do ((n 0 (1+ n)))
1371 ((> n 5))
1372 (pass-if n
1373 (let ((cond (make-iterations-cond n))
1374 (i 0))
1375 (while (cond)
1376 (set! i (1+ i))
1377 (continue)
1378 (unreachable))
1379 (= i n)))))
1380
1381 (pass-if "from nested"
1382 (let ((cond (make-iterations-cond 3)))
1383 (while (cond)
1384 (let ((outer-continue continue))
1385 (while #t
1386 (outer-continue)
1387 (unreachable)))))
cc08aafd
KR
1388 #t)
1389
1390 (pass-if "from recursive"
1391 (let ((outer-continue #f))
1392 (define (r n)
1393 (let ((cond (make-iterations-cond 3))
1394 (first #t))
1395 (while (begin
1396 (if (and (not first)
1397 (eq? n 'inner))
1398 (error "continued only to inner loop"))
1399 (cond))
1400 (set! first #f)
1401 (if (eq? n 'outer)
1402 (begin
1403 (set! outer-continue continue)
1404 (r 'inner))
1405 (begin
1406 (outer-continue)
1407 (unreachable))))))
1408 (r 'outer))
2798ba71 1409 #t)))
aa8630ef 1410
1624e149
MW
1411(with-test-prefix "syntax-rules"
1412
1413 (pass-if-equal "custom ellipsis within normal ellipsis"
1414 '((((a x) (a y) (a …))
1415 ((b x) (b y) (b …))
1416 ((c x) (c y) (c …)))
1417 (((a x) (b x) (c x))
1418 ((a y) (b y) (c y))
1419 ((a …) (b …) (c …))))
1420 (let ()
1421 (define-syntax foo
1422 (syntax-rules ()
1423 ((_ y ...)
1424 (syntax-rules … ()
1425 ((_ x …)
1426 '((((x y) ...) …)
1427 (((x y) …) ...)))))))
1428 (define-syntax bar (foo x y …))
1429 (bar a b c)))
1430
1431 (pass-if-equal "normal ellipsis within custom ellipsis"
1432 '((((a x) (a y) (a z))
1433 ((b x) (b y) (b z))
1434 ((c x) (c y) (c z)))
1435 (((a x) (b x) (c x))
1436 ((a y) (b y) (c y))
1437 ((a z) (b z) (c z))))
1438 (let ()
1439 (define-syntax foo
1440 (syntax-rules … ()
1441 ((_ y …)
1442 (syntax-rules ()
1443 ((_ x ...)
1444 '((((x y) …) ...)
1445 (((x y) ...) …)))))))
1446 (define-syntax bar (foo x y z))
2d6a3144
MW
1447 (bar a b c)))
1448
1449 ;; This test is given in SRFI-46.
1450 (pass-if-equal "custom ellipsis is handled hygienically"
1451 '((1) 2 (3) (4))
1452 (let-syntax
1453 ((f (syntax-rules ()
1454 ((f ?e)
1455 (let-syntax
1456 ((g (syntax-rules --- ()
1457 ((g (??x ?e) (??y ---))
1458 '((??x) ?e (??y) ---)))))
1459 (g (1 2) (3 4)))))))
1460 (f ---))))
1624e149 1461
0e181633
MW
1462(with-test-prefix "syntax-error"
1463
1464 (pass-if-syntax-error "outside of macro without args"
1465 "test error"
1466 (eval '(syntax-error "test error")
1467 (interaction-environment)))
1468
1469 (pass-if-syntax-error "outside of macro with args"
1470 "test error x \\(y z\\)"
1471 (eval '(syntax-error "test error" x (y z))
1472 (interaction-environment)))
1473
1474 (pass-if-equal "within macro"
1475 '(simple-let
1476 "expected an identifier but got (z1 z2)"
1477 (simple-let ((y (* x x))
1478 ((z1 z2) (values x x)))
1479 (+ y 1)))
1480 (catch 'syntax-error
1481 (lambda ()
1482 (eval '(let ()
1483 (define-syntax simple-let
1484 (syntax-rules ()
1485 ((_ (head ... ((x . y) val) . tail)
1486 body1 body2 ...)
1487 (syntax-error
1488 "expected an identifier but got"
1489 (x . y)))
1490 ((_ ((name val) ...) body1 body2 ...)
1491 ((lambda (name ...) body1 body2 ...)
1492 val ...))))
1493 (define (foo x)
1494 (simple-let ((y (* x x))
1495 ((z1 z2) (values x x)))
1496 (+ y 1)))
1497 foo)
1498 (interaction-environment))
1499 (error "expected syntax-error exception"))
1500 (lambda (k who what where form . maybe-subform)
1501 (list who what form)))))
1502
aa8630ef
MW
1503(with-test-prefix "syntax-case"
1504
1505 (pass-if-syntax-error "duplicate pattern variable"
1506 '(syntax-case . "duplicate pattern variable")
1507 (eval '(lambda (e)
1508 (syntax-case e ()
1509 ((a b c d e d f) #f)))
1510 (interaction-environment)))
1511
1512 (with-test-prefix "misplaced ellipses"
1513
1514 (pass-if-syntax-error "bare ellipsis"
1515 '(syntax-case . "misplaced ellipsis")
1516 (eval '(lambda (e)
1517 (syntax-case e ()
1518 (... #f)))
1519 (interaction-environment)))
1520
1521 (pass-if-syntax-error "ellipsis singleton"
1522 '(syntax-case . "misplaced ellipsis")
1523 (eval '(lambda (e)
1524 (syntax-case e ()
1525 ((...) #f)))
1526 (interaction-environment)))
1527
1528 (pass-if-syntax-error "ellipsis in car"
1529 '(syntax-case . "misplaced ellipsis")
1530 (eval '(lambda (e)
1531 (syntax-case e ()
1532 ((... . _) #f)))
1533 (interaction-environment)))
1534
1535 (pass-if-syntax-error "ellipsis in cdr"
1536 '(syntax-case . "misplaced ellipsis")
1537 (eval '(lambda (e)
1538 (syntax-case e ()
1539 ((_ . ...) #f)))
1540 (interaction-environment)))
1541
1542 (pass-if-syntax-error "two ellipses in the same list"
1543 '(syntax-case . "misplaced ellipsis")
1544 (eval '(lambda (e)
1545 (syntax-case e ()
1546 ((x ... y ...) #f)))
1547 (interaction-environment)))
1548
1549 (pass-if-syntax-error "three ellipses in the same list"
1550 '(syntax-case . "misplaced ellipsis")
1551 (eval '(lambda (e)
1552 (syntax-case e ()
1553 ((x ... y ... z ...) #f)))
1554 (interaction-environment)))))
1555
1624e149
MW
1556(with-test-prefix "with-ellipsis"
1557
1558 (pass-if-equal "simple"
1559 '(a 1 2 3)
1560 (let ()
1561 (define-syntax define-quotation-macros
1562 (lambda (x)
1563 (syntax-case x ()
1564 ((_ (macro-name head-symbol) ...)
1565 #'(begin (define-syntax macro-name
1566 (lambda (x)
1567 (with-ellipsis …
1568 (syntax-case x ()
1569 ((_ x …)
1570 #'(quote (head-symbol x …)))))))
1571 ...)))))
1572 (define-quotation-macros (quote-a a) (quote-b b))
1573 (quote-a 1 2 3)))
1574
1575 (pass-if-equal "disables normal ellipsis"
1576 '(a ...)
1577 (let ()
1578 (define-syntax foo
1579 (lambda (x)
1580 (with-ellipsis …
1581 (syntax-case x ()
1582 ((_)
1583 #'(quote (a ...)))))))
1584 (foo)))
1585
1586 (pass-if-equal "doesn't affect ellipsis for generated code"
1587 '(a b c)
1588 (let ()
1589 (define-syntax quotation-macro
1590 (lambda (x)
1591 (with-ellipsis …
1592 (syntax-case x ()
1593 ((_)
1594 #'(lambda (x)
1595 (syntax-case x ()
1596 ((_ x ...)
1597 #'(quote (x ...))))))))))
1598 (define-syntax kwote (quotation-macro))
1599 (kwote a b c)))
1600
1601 (pass-if-equal "propagates into syntax binders"
1602 '(a b c)
1603 (let ()
1604 (with-ellipsis …
1605 (define-syntax kwote
1606 (lambda (x)
1607 (syntax-case x ()
1608 ((_ x …)
1609 #'(quote (x …))))))
1610 (kwote a b c))))
1611
1612 (pass-if-equal "works with local-eval"
1613 5
1614 (let ((env (with-ellipsis … (the-environment))))
1615 (local-eval '(syntax-case #'(a b c d e) ()
1616 ((x …)
1617 (length #'(x …))))
1618 env))))
1619
aa8630ef
MW
1620;;; Local Variables:
1621;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
1624e149 1622;;; eval: (put 'with-ellipsis 'scheme-indent-function 1)
aa8630ef 1623;;; End: