1 ;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
3 ;;;; Copyright (C) 2001, 2003, 2004, 2005, 2006, 2009, 2010,
4 ;;;; 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
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.
11 ;;;; This library is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ;;;; Lesser General Public License for more details.
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
20 (define-module (test-suite test-syntax)
21 #:use-module (ice-9 regex)
22 #:use-module (ice-9 local-eval)
23 #:use-module (test-suite lib))
26 (define exception:generic-syncase-error
27 "source expression failed to match")
28 (define exception:unexpected-syntax
31 (define exception:bad-expression
34 (define exception:missing/extra-expr
35 "Missing or extra expression")
36 (define exception:missing-expr
38 (define exception:missing-body-expr
39 "no expressions in body")
40 (define exception:extra-expr
42 (define exception:illegal-empty-combination
43 "Illegal empty combination")
45 (define exception:bad-lambda
47 (define exception:bad-let
49 (define exception:bad-letrec
51 (define exception:bad-letrec*
53 (define exception:bad-set!
55 (define exception:bad-quote
56 '(quote . "bad syntax"))
57 (define exception:bad-bindings
59 (define exception:bad-binding
61 (define exception:duplicate-binding
62 "duplicate bound variable")
63 (define exception:bad-body
65 (define exception:bad-formals
66 "invalid argument list")
67 (define exception:bad-formal
69 (define exception:duplicate-formals
70 "duplicate identifier in argument list")
72 (define exception:missing-clauses
74 (define exception:misplaced-else-clause
75 "Misplaced else clause")
76 (define exception:bad-case-clause
78 (define exception:bad-case-labels
80 (define exception:bad-cond-clause
83 (define exception:too-many-args
85 (define exception:wrong-number-of-values
86 '(wrong-number-of-args . "number of (values)|(arguments)"))
87 (define exception:zero-expression-sequence
88 "sequence of zero expressions")
90 (define exception:variable-ref
91 '(misc-error . "Unbound variable"))
93 ;; (put 'pass-if-syntax-error 'scheme-indent-function 1)
94 (define-syntax pass-if-syntax-error
99 (lambda () exp (error "expected syntax-error exception"))
100 (lambda (k who what where form . maybe-subform)
102 (and (eq? who (car pat))
103 (string-match (cdr pat) what))
104 (string-match pat what))
106 (error "unexpected syntax-error exception" what pat))))))))
108 (with-test-prefix "expressions"
110 (with-test-prefix "Bad argument list"
112 (pass-if-syntax-error "improper argument list of length 1"
113 exception:generic-syncase-error
114 (eval '(let ((foo (lambda (x y) #t)))
116 (interaction-environment)))
118 (pass-if-syntax-error "improper argument list of length 2"
119 exception:generic-syncase-error
120 (eval '(let ((foo (lambda (x y) #t)))
122 (interaction-environment))))
124 (with-test-prefix "missing or extra expression"
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
133 (pass-if-syntax-error "empty parentheses \"()\""
134 exception:unexpected-syntax
136 (interaction-environment)))))
138 (with-test-prefix "quote"
141 (with-test-prefix "quasiquote"
143 (with-test-prefix "unquote"
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))))))
149 (with-test-prefix "unquote-splicing"
151 (pass-if "extra arguments"
152 (equal? (eval '(quasiquote ((unquote-splicing (list 1 2) (list 3 4))))
153 (interaction-environment))
156 (with-test-prefix "begin"
158 (pass-if "valid (begin)"
159 (eval '(begin (begin) #t) (interaction-environment)))
161 (if (not (include-deprecated-features))
162 (pass-if-syntax-error "invalid (begin)"
163 exception:zero-expression-sequence
164 (eval '(begin (if #t (begin)) #t) (interaction-environment)))))
166 (define-syntax matches?
168 ((_ (op arg ...) pat) (let ((x (op arg ...)))
171 ((_ x (a . b)) (and (pair? x)
173 (matches? (cdr x) b)))
175 ((_ x pat) (equal? x 'pat))))
177 (with-test-prefix "lambda"
179 (with-test-prefix "bad formals"
181 (pass-if-syntax-error "(lambda)"
184 (interaction-environment)))
186 (pass-if-syntax-error "(lambda . \"foo\")"
188 (eval '(lambda . "foo")
189 (interaction-environment)))
191 (pass-if-syntax-error "(lambda \"foo\")"
193 (eval '(lambda "foo")
194 (interaction-environment)))
196 (pass-if-syntax-error "(lambda \"foo\" #f)"
197 exception:bad-formals
198 (eval '(lambda "foo" #f)
199 (interaction-environment)))
201 (pass-if-syntax-error "(lambda (x 1) 2)"
202 exception:bad-formals
203 (eval '(lambda (x 1) 2)
204 (interaction-environment)))
206 (pass-if-syntax-error "(lambda (1 x) 2)"
207 exception:bad-formals
208 (eval '(lambda (1 x) 2)
209 (interaction-environment)))
211 (pass-if-syntax-error "(lambda (x \"a\") 2)"
212 exception:bad-formals
213 (eval '(lambda (x "a") 2)
214 (interaction-environment)))
216 (pass-if-syntax-error "(lambda (\"a\" x) 2)"
217 exception:bad-formals
218 (eval '(lambda ("a" x) 2)
219 (interaction-environment))))
221 (with-test-prefix "duplicate formals"
224 (pass-if-syntax-error "(lambda (x x) 1)"
225 exception:duplicate-formals
226 (eval '(lambda (x x) 1)
227 (interaction-environment)))
230 (pass-if-syntax-error "(lambda (x x x) 1)"
231 exception:duplicate-formals
232 (eval '(lambda (x x x) 1)
233 (interaction-environment))))
235 (with-test-prefix "bad body"
237 (pass-if-syntax-error "(lambda ())"
240 (interaction-environment)))))
242 (with-test-prefix "let"
244 (with-test-prefix "bindings"
246 (pass-if-exception "late binding"
247 exception:unbound-var
248 (let ((x 1) (y x)) y)))
250 (with-test-prefix "bad bindings"
252 (pass-if-syntax-error "(let)"
255 (interaction-environment)))
257 (pass-if-syntax-error "(let 1)"
260 (interaction-environment)))
262 (pass-if-syntax-error "(let (x))"
265 (interaction-environment)))
267 (pass-if-syntax-error "(let ((x)))"
270 (interaction-environment)))
272 (pass-if-syntax-error "(let (x) 1)"
275 (interaction-environment)))
277 (pass-if-syntax-error "(let ((x)) 3)"
280 (interaction-environment)))
282 (pass-if-syntax-error "(let ((x 1) y) x)"
284 (eval '(let ((x 1) y) x)
285 (interaction-environment)))
287 (pass-if-syntax-error "(let ((1 2)) 3)"
289 (eval '(let ((1 2)) 3)
290 (interaction-environment))))
292 (with-test-prefix "duplicate bindings"
294 (pass-if-syntax-error "(let ((x 1) (x 2)) x)"
295 exception:duplicate-binding
296 (eval '(let ((x 1) (x 2)) x)
297 (interaction-environment))))
299 (with-test-prefix "bad body"
301 (pass-if-syntax-error "(let ())"
304 (interaction-environment)))
306 (pass-if-syntax-error "(let ((x 1)))"
309 (interaction-environment)))))
311 (with-test-prefix "named let"
313 (with-test-prefix "initializers"
315 (pass-if "evaluated in outer environment"
317 (eqv? (let f ((n (f 1))) n) -1))))
319 (with-test-prefix "bad bindings"
321 (pass-if-syntax-error "(let x (y))"
324 (interaction-environment))))
326 (with-test-prefix "bad body"
328 (pass-if-syntax-error "(let x ())"
331 (interaction-environment)))
333 (pass-if-syntax-error "(let x ((y 1)))"
335 (eval '(let x ((y 1)))
336 (interaction-environment)))))
338 (with-test-prefix "let*"
340 (with-test-prefix "bindings"
342 (pass-if "(let* ((x 1) (x 2)) ...)"
346 (pass-if "(let* ((x 1) (x x)) ...)"
350 (pass-if "(let ((x 1) (y 2)) (let* () ...))"
353 (and (= x 1) (= y 2))))))
355 (with-test-prefix "bad bindings"
357 (pass-if-syntax-error "(let*)"
358 exception:generic-syncase-error
360 (interaction-environment)))
362 (pass-if-syntax-error "(let* 1)"
363 exception:generic-syncase-error
365 (interaction-environment)))
367 (pass-if-syntax-error "(let* (x))"
368 exception:generic-syncase-error
370 (interaction-environment)))
372 (pass-if-syntax-error "(let* (x) 1)"
373 exception:generic-syncase-error
375 (interaction-environment)))
377 (pass-if-syntax-error "(let* ((x)) 3)"
378 exception:generic-syncase-error
379 (eval '(let* ((x)) 3)
380 (interaction-environment)))
382 (pass-if-syntax-error "(let* ((x 1) y) x)"
383 exception:generic-syncase-error
384 (eval '(let* ((x 1) y) x)
385 (interaction-environment)))
387 (pass-if-syntax-error "(let* x ())"
388 exception:generic-syncase-error
390 (interaction-environment)))
392 (pass-if-syntax-error "(let* x (y))"
393 exception:generic-syncase-error
395 (interaction-environment)))
397 (pass-if-syntax-error "(let* ((1 2)) 3)"
398 exception:generic-syncase-error
399 (eval '(let* ((1 2)) 3)
400 (interaction-environment))))
402 (with-test-prefix "bad body"
404 (pass-if-syntax-error "(let* ())"
405 exception:generic-syncase-error
407 (interaction-environment)))
409 (pass-if-syntax-error "(let* ((x 1)))"
410 exception:generic-syncase-error
411 (eval '(let* ((x 1)))
412 (interaction-environment)))))
414 (with-test-prefix "letrec"
416 (with-test-prefix "bindings"
418 (pass-if-exception "initial bindings are undefined"
419 exception:variable-ref
421 (letrec ((x 1) (y x)) y))
422 (interaction-environment))))
424 (with-test-prefix "bad bindings"
426 (pass-if-syntax-error "(letrec)"
429 (interaction-environment)))
431 (pass-if-syntax-error "(letrec 1)"
434 (interaction-environment)))
436 (pass-if-syntax-error "(letrec (x))"
439 (interaction-environment)))
441 (pass-if-syntax-error "(letrec (x) 1)"
443 (eval '(letrec (x) 1)
444 (interaction-environment)))
446 (pass-if-syntax-error "(letrec ((x)) 3)"
448 (eval '(letrec ((x)) 3)
449 (interaction-environment)))
451 (pass-if-syntax-error "(letrec ((x 1) y) x)"
453 (eval '(letrec ((x 1) y) x)
454 (interaction-environment)))
456 (pass-if-syntax-error "(letrec x ())"
459 (interaction-environment)))
461 (pass-if-syntax-error "(letrec x (y))"
463 (eval '(letrec x (y))
464 (interaction-environment)))
466 (pass-if-syntax-error "(letrec ((1 2)) 3)"
468 (eval '(letrec ((1 2)) 3)
469 (interaction-environment))))
471 (with-test-prefix "duplicate bindings"
473 (pass-if-syntax-error "(letrec ((x 1) (x 2)) x)"
474 exception:duplicate-binding
475 (eval '(letrec ((x 1) (x 2)) x)
476 (interaction-environment))))
478 (with-test-prefix "bad body"
480 (pass-if-syntax-error "(letrec ())"
483 (interaction-environment)))
485 (pass-if-syntax-error "(letrec ((x 1)))"
487 (eval '(letrec ((x 1)))
488 (interaction-environment)))))
490 (with-test-prefix "letrec*"
492 (with-test-prefix "bindings"
494 (pass-if-exception "initial bindings are undefined"
495 exception:variable-ref
496 (eval '(letrec* ((x y) (y 1)) y)
497 (interaction-environment))))
499 (with-test-prefix "bad bindings"
501 (pass-if-syntax-error "(letrec*)"
502 exception:bad-letrec*
504 (interaction-environment)))
506 (pass-if-syntax-error "(letrec* 1)"
507 exception:bad-letrec*
509 (interaction-environment)))
511 (pass-if-syntax-error "(letrec* (x))"
512 exception:bad-letrec*
514 (interaction-environment)))
516 (pass-if-syntax-error "(letrec* (x) 1)"
517 exception:bad-letrec*
518 (eval '(letrec* (x) 1)
519 (interaction-environment)))
521 (pass-if-syntax-error "(letrec* ((x)) 3)"
522 exception:bad-letrec*
523 (eval '(letrec* ((x)) 3)
524 (interaction-environment)))
526 (pass-if-syntax-error "(letrec* ((x 1) y) x)"
527 exception:bad-letrec*
528 (eval '(letrec* ((x 1) y) x)
529 (interaction-environment)))
531 (pass-if-syntax-error "(letrec* x ())"
532 exception:bad-letrec*
533 (eval '(letrec* x ())
534 (interaction-environment)))
536 (pass-if-syntax-error "(letrec* x (y))"
537 exception:bad-letrec*
538 (eval '(letrec* x (y))
539 (interaction-environment)))
541 (pass-if-syntax-error "(letrec* ((1 2)) 3)"
542 exception:bad-letrec*
543 (eval '(letrec* ((1 2)) 3)
544 (interaction-environment))))
546 (with-test-prefix "duplicate bindings"
548 (pass-if-syntax-error "(letrec* ((x 1) (x 2)) x)"
549 exception:duplicate-binding
550 (eval '(letrec* ((x 1) (x 2)) x)
551 (interaction-environment))))
553 (with-test-prefix "bad body"
555 (pass-if-syntax-error "(letrec* ())"
556 exception:bad-letrec*
558 (interaction-environment)))
560 (pass-if-syntax-error "(letrec* ((x 1)))"
561 exception:bad-letrec*
562 (eval '(letrec* ((x 1)))
563 (interaction-environment))))
565 (with-test-prefix "referencing previous values"
566 (pass-if (equal? (letrec* ((a (cons 'foo 'bar))
570 (pass-if (equal? (let ()
571 (define a (cons 'foo 'bar))
576 (with-test-prefix "if"
578 (with-test-prefix "missing or extra expressions"
580 (pass-if-syntax-error "(if)"
581 exception:generic-syncase-error
583 (interaction-environment)))
585 (pass-if-syntax-error "(if 1 2 3 4)"
586 exception:generic-syncase-error
588 (interaction-environment)))))
590 (with-test-prefix "cond"
592 (with-test-prefix "cond is hygienic"
594 (pass-if "bound 'else is handled correctly"
595 (eq? (let ((else 'ok)) (cond (else))) 'ok))
597 (with-test-prefix "bound '=> is handled correctly"
601 (eq? (cond (#t => 'ok)) 'ok)))
605 (eq? (cond (else =>)) 'foo)))
607 (pass-if "else => identity"
609 (eq? (cond (else => identity)) identity)))))
611 (with-test-prefix "SRFI-61"
613 (pass-if "always available"
614 (cond-expand (srfi-61 #t) (else #f)))
616 (pass-if "single value consequent"
617 (eq? 'ok (cond (#t identity => (lambda (x) 'ok)) (else #f))))
619 (pass-if "single value alternate"
620 (eq? 'ok (cond (#t not => (lambda (x) #f)) (else 'ok))))
622 (pass-if-exception "doesn't affect standard =>"
623 exception:wrong-num-args
624 (cond ((values 1 2) => (lambda (x y) #t))))
626 (pass-if "multiple values consequent"
627 (equal? '(2 1) (cond ((values 1 2)
629 (and (= 1 one) (= 2 two))) =>
630 (lambda (one two) (list two one)))
633 (pass-if "multiple values alternate"
634 (eq? 'ok (cond ((values 2 3 4)
635 (lambda args (equal? '(1 2 3) args)) =>
639 (pass-if "zero values"
640 (eq? 'ok (cond ((values) (lambda () #t) => (lambda () 'ok))
643 (pass-if "bound => is handled correctly"
645 (eq? 'ok (cond (#t identity =>) (else #f)))))
647 (pass-if-syntax-error "missing recipient"
648 '(cond . "wrong number of receiver expressions")
649 (eval '(cond (#t identity =>))
650 (interaction-environment)))
652 (pass-if-syntax-error "extra recipient"
653 '(cond . "wrong number of receiver expressions")
654 (eval '(cond (#t identity => identity identity))
655 (interaction-environment))))
657 (with-test-prefix "bad or missing clauses"
659 (pass-if-syntax-error "(cond)"
660 exception:generic-syncase-error
662 (interaction-environment)))
664 (pass-if-syntax-error "(cond #t)"
665 '(cond . "invalid clause")
667 (interaction-environment)))
669 (pass-if-syntax-error "(cond 1)"
670 '(cond . "invalid clause")
672 (interaction-environment)))
674 (pass-if-syntax-error "(cond 1 2)"
675 '(cond . "invalid clause")
677 (interaction-environment)))
679 (pass-if-syntax-error "(cond 1 2 3)"
680 '(cond . "invalid clause")
682 (interaction-environment)))
684 (pass-if-syntax-error "(cond 1 2 3 4)"
685 '(cond . "invalid clause")
686 (eval '(cond 1 2 3 4)
687 (interaction-environment)))
689 (pass-if-syntax-error "(cond ())"
690 '(cond . "invalid clause")
692 (interaction-environment)))
694 (pass-if-syntax-error "(cond () 1)"
695 '(cond . "invalid clause")
697 (interaction-environment)))
699 (pass-if-syntax-error "(cond (1) 1)"
700 '(cond . "invalid clause")
702 (interaction-environment)))
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))
707 (interaction-environment))))
709 (with-test-prefix "wrong number of arguments"
711 (pass-if-exception "=> (lambda (x y) #t)"
712 exception:wrong-num-args
713 (cond (1 => (lambda (x y) #t))))))
715 (with-test-prefix "case"
717 (pass-if "clause with empty labels list"
718 (case 1 (() #f) (else #t)))
720 (with-test-prefix "case handles '=> correctly"
722 (pass-if "(1 2 3) => list"
723 (equal? (case 1 ((1 2 3) => list))
726 (pass-if "else => list"
732 (with-test-prefix "bound '=> is handled correctly"
734 (pass-if "(1) => 'ok"
736 (eq? (case 1 ((1) => 'ok)) 'ok)))
740 (eq? (case 1 (else =>)) 'foo)))
742 (pass-if "else => list"
744 (eq? (case 1 (else => identity)) identity))))
746 (pass-if-syntax-error "missing recipient"
747 '(case . "wrong number of receiver expressions")
748 (eval '(case 1 ((1) =>))
749 (interaction-environment)))
751 (pass-if-syntax-error "extra recipient"
752 '(case . "wrong number of receiver expressions")
753 (eval '(case 1 ((1) => identity identity))
754 (interaction-environment))))
756 (with-test-prefix "case is hygienic"
758 (pass-if-syntax-error "bound 'else is handled correctly"
759 '(case . "invalid clause")
760 (eval '(let ((else #f)) (case 1 (else #f)))
761 (interaction-environment))))
763 (with-test-prefix "bad or missing clauses"
765 (pass-if-syntax-error "(case)"
766 exception:generic-syncase-error
768 (interaction-environment)))
770 (pass-if-syntax-error "(case . \"foo\")"
771 exception:generic-syncase-error
772 (eval '(case . "foo")
773 (interaction-environment)))
775 (pass-if-syntax-error "(case 1)"
776 exception:generic-syncase-error
778 (interaction-environment)))
780 (pass-if-syntax-error "(case 1 . \"foo\")"
781 exception:generic-syncase-error
782 (eval '(case 1 . "foo")
783 (interaction-environment)))
785 (pass-if-syntax-error "(case 1 \"foo\")"
786 '(case . "invalid clause")
787 (eval '(case 1 "foo")
788 (interaction-environment)))
790 (pass-if-syntax-error "(case 1 ())"
791 '(case . "invalid clause")
793 (interaction-environment)))
795 (pass-if-syntax-error "(case 1 (\"foo\"))"
796 '(case . "invalid clause")
797 (eval '(case 1 ("foo"))
798 (interaction-environment)))
800 (pass-if-syntax-error "(case 1 (\"foo\" \"bar\"))"
801 '(case . "invalid clause")
802 (eval '(case 1 ("foo" "bar"))
803 (interaction-environment)))
805 (pass-if-syntax-error "(case 1 ((2) \"bar\") . \"foo\")"
806 exception:generic-syncase-error
807 (eval '(case 1 ((2) "bar") . "foo")
808 (interaction-environment)))
810 (pass-if-syntax-error "(case 1 ((2) \"bar\") (else))"
811 '(case . "invalid clause")
812 (eval '(case 1 ((2) "bar") (else))
813 (interaction-environment)))
815 (pass-if-syntax-error "(case 1 (else #f) . \"foo\")"
816 exception:generic-syncase-error
817 (eval '(case 1 (else #f) . "foo")
818 (interaction-environment)))
820 (pass-if-syntax-error "(case 1 (else #f) ((1) #t))"
821 '(case . "else must be the last clause")
822 (eval '(case 1 (else #f) ((1) #t))
823 (interaction-environment)))))
825 (with-test-prefix "top-level define"
827 (pass-if "redefinition"
828 (let ((m (make-module)))
829 (beautify-user-module! m)
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)))
838 (with-test-prefix "missing or extra expressions"
840 (pass-if-syntax-error "(define)"
841 exception:generic-syncase-error
843 (interaction-environment))))
845 (pass-if "module scoping"
849 (define-module (top-level-define/module-scoping-1)
850 #:export (define-10))
851 (define-syntax-rule (define-10 name)
855 (define-module (top-level-define/module-scoping-2)
856 #:use-module (top-level-define/module-scoping-1))
862 (pass-if "module scoping, same symbolic name"
866 (define-module (top-level-define/module-scoping-3))
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))
875 (pass-if "module scoping, introduced names"
879 (define-module (top-level-define/module-scoping-5)
880 #:export (define-constant))
881 (define-syntax-rule (define-constant name val)
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)
893 (pass-if "module scoping, duplicate introduced name"
897 (define-module (top-level-define/module-scoping-7)
898 #:export (define-constant))
899 (define-syntax-rule (define-constant name val)
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)
911 (with-test-prefix "internal define"
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))
920 (eq? 'c (a 2) (a 5))))
921 (interaction-environment)))
923 (pass-if "binding is created before expression is evaluated"
924 ;; Internal defines are equivalent to `letrec' (R5RS, Section 5.2.2).
931 (interaction-environment))
934 (pass-if "internal defines with begin"
936 (eval '(let ((a identity) (b identity) (c identity))
937 (define (a x) (if (= x 0) 'a (b (- x 1))))
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))
943 (eq? 'c (a 2) (a 5))))
944 (interaction-environment))))
946 (pass-if "internal defines with empty begin"
948 (eval '(let ((a identity) (b identity) (c identity))
949 (define (a x) (if (= x 0) 'a (b (- x 1))))
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))
955 (eq? 'c (a 2) (a 5))))
956 (interaction-environment))))
958 (pass-if "internal defines with macro application"
961 (defmacro my-define forms
962 (cons 'define forms))
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))
969 (eq? 'c (a 2) (a 5)))))
970 (interaction-environment))))
972 (pass-if-syntax-error "missing body expression"
973 exception:missing-body-expr
974 (eval '(let () (define x #t))
975 (interaction-environment))))
977 (with-test-prefix "top-level define-values"
979 (pass-if "zero values"
980 (eval '(begin (define-values () (values))
982 (interaction-environment)))
984 (pass-if-equal "one value"
986 (eval '(begin (define-values (x) 1)
988 (interaction-environment)))
990 (pass-if-equal "two values"
992 (eval '(begin (define-values (x y) (values 2 3))
994 (interaction-environment)))
996 (pass-if-equal "three values"
998 (eval '(begin (define-values (x y z) (values 4 5 6))
1000 (interaction-environment)))
1002 (pass-if-equal "one value with tail"
1004 (eval '(begin (define-values (x . y) (values 'a 'b 'c 'd))
1006 (interaction-environment)))
1008 (pass-if-equal "two values with tail"
1010 (eval '(begin (define-values (x y . z) (values 'x 'y 'z 'w))
1012 (interaction-environment)))
1014 (pass-if-equal "just tail"
1016 (eval '(begin (define-values x (values 1 2 3))
1018 (interaction-environment)))
1020 (pass-if-exception "expected 0 values, got 1"
1021 exception:wrong-number-of-values
1022 (eval '(define-values () 1)
1023 (interaction-environment)))
1025 (pass-if-exception "expected 1 value, got 0"
1026 exception:wrong-number-of-values
1027 (eval '(define-values (x) (values))
1028 (interaction-environment)))
1030 (pass-if-exception "expected 1 value, got 2"
1031 exception:wrong-number-of-values
1032 (eval '(define-values (x) (values 1 2))
1033 (interaction-environment)))
1035 (pass-if-exception "expected 1 value with tail, got 0"
1036 exception:wrong-number-of-values
1037 (eval '(define-values (x . y) (values))
1038 (interaction-environment)))
1040 (pass-if-exception "expected 2 value with tail, got 1"
1041 exception:wrong-number-of-values
1042 (eval '(define-values (x y . z) 1)
1043 (interaction-environment)))
1045 (pass-if "redefinition"
1046 (let ((m (make-module)))
1047 (beautify-user-module! m)
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))))
1055 (with-test-prefix "missing expression"
1057 (pass-if-syntax-error "(define-values)"
1058 exception:generic-syncase-error
1059 (eval '(define-values)
1060 (interaction-environment)))))
1062 (with-test-prefix "internal define-values"
1064 (pass-if "zero values"
1066 (define-values () (values))
1069 (pass-if-equal "one value"
1072 (define-values (x) 1)
1075 (pass-if-equal "two values"
1078 (define-values (x y) (values 2 3))
1081 (pass-if-equal "three values"
1084 (define-values (x y z) (values 4 5 6))
1087 (pass-if-equal "one value with tail"
1090 (define-values (x . y) (values 'a 'b 'c 'd))
1093 (pass-if-equal "two values with tail"
1096 (define-values (x y . z) (values 'x 'y 'z 'w))
1099 (pass-if-equal "just tail"
1102 (define-values x (values 1 2 3))
1105 (pass-if-exception "expected 0 values, got 1"
1106 exception:wrong-number-of-values
1108 (define-values () 1)
1110 (interaction-environment)))
1112 (pass-if-exception "expected 1 value, got 0"
1113 exception:wrong-number-of-values
1115 (define-values (x) (values))
1117 (interaction-environment)))
1119 (pass-if-exception "expected 1 value, got 2"
1120 exception:wrong-number-of-values
1122 (define-values (x) (values 1 2))
1124 (interaction-environment)))
1126 (pass-if-exception "expected 1 value with tail, got 0"
1127 exception:wrong-number-of-values
1129 (define-values (x . y) (values))
1131 (interaction-environment)))
1133 (pass-if-exception "expected 2 value with tail, got 1"
1134 exception:wrong-number-of-values
1136 (define-values (x y . z) 1)
1138 (interaction-environment)))
1140 (with-test-prefix "missing expression"
1142 (pass-if-syntax-error "(define-values)"
1143 exception:generic-syncase-error
1147 (interaction-environment)))))
1149 (with-test-prefix "set!"
1151 (with-test-prefix "missing or extra expressions"
1153 (pass-if-syntax-error "(set!)"
1156 (interaction-environment)))
1158 (pass-if-syntax-error "(set! 1)"
1161 (interaction-environment)))
1163 (pass-if-syntax-error "(set! 1 2 3)"
1166 (interaction-environment))))
1168 (with-test-prefix "bad variable"
1170 (pass-if-syntax-error "(set! \"\" #t)"
1173 (interaction-environment)))
1175 (pass-if-syntax-error "(set! 1 #t)"
1178 (interaction-environment)))
1180 (pass-if-syntax-error "(set! #t #f)"
1183 (interaction-environment)))
1185 (pass-if-syntax-error "(set! #f #t)"
1188 (interaction-environment)))
1190 (pass-if-syntax-error "(set! #\\space #f)"
1192 (eval '(set! #\space #f)
1193 (interaction-environment)))))
1195 (with-test-prefix "quote"
1197 (with-test-prefix "missing or extra expression"
1199 (pass-if-syntax-error "(quote)"
1202 (interaction-environment)))
1204 (pass-if-syntax-error "(quote a b)"
1207 (interaction-environment)))))
1209 (with-test-prefix "while"
1211 (define (unreachable)
1212 (error "unreachable code has been reached!"))
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)
1220 (error "oops, condition re-tested after giving false"))
1229 (pass-if-syntax-error "too few args" exception:generic-syncase-error
1230 (eval '(while) (interaction-environment)))
1232 (with-test-prefix "empty body"
1236 (eval `(letrec ((make-iterations-cond
1240 (error "oops, condition re-tested after giving false"))
1247 (let ((cond (make-iterations-cond ,n)))
1250 (interaction-environment)))))
1252 (pass-if "initially false"
1257 (with-test-prefix "iterations"
1261 (let ((cond (make-iterations-cond n))
1267 (with-test-prefix "break"
1269 (pass-if "normal return"
1270 (not (while #f (error "not reached"))))
1275 (pass-if "multiple values"
1278 (lambda () (while #t (break 1 2 3)))
1281 (with-test-prefix "from cond"
1292 (let ((cond (make-iterations-cond n))
1302 (with-test-prefix "from body"
1312 (let ((cond (make-iterations-cond n))
1322 (pass-if "from nested"
1324 (let ((outer-break break))
1331 (pass-if "from recursive"
1332 (let ((outer-break #f))
1337 (set! outer-break break)
1343 (error "broke only from inner loop")))
1347 (with-test-prefix "continue"
1349 (pass-if-syntax-error "too many args" exception:too-many-args
1352 (interaction-environment)))
1354 (with-test-prefix "from cond"
1358 (let ((cond (make-iterations-cond n))
1369 (with-test-prefix "from body"
1373 (let ((cond (make-iterations-cond n))
1381 (pass-if "from nested"
1382 (let ((cond (make-iterations-cond 3)))
1384 (let ((outer-continue continue))
1390 (pass-if "from recursive"
1391 (let ((outer-continue #f))
1393 (let ((cond (make-iterations-cond 3))
1396 (if (and (not first)
1398 (error "continued only to inner loop"))
1403 (set! outer-continue continue)
1411 (with-test-prefix "syntax-rules"
1413 (pass-if-equal "custom ellipsis within normal ellipsis"
1414 '((((a x) (a y) (a …))
1416 ((c x) (c y) (c …)))
1417 (((a x) (b x) (c x))
1419 ((a …) (b …) (c …))))
1427 (((x y) …) ...)))))))
1428 (define-syntax bar (foo x y …))
1431 (pass-if-equal "normal ellipsis within custom ellipsis"
1432 '((((a x) (a y) (a z))
1434 ((c x) (c y) (c z)))
1435 (((a x) (b x) (c x))
1437 ((a z) (b z) (c z))))
1445 (((x y) ...) …)))))))
1446 (define-syntax bar (foo x y z))
1449 ;; This test is given in SRFI-46.
1450 (pass-if-equal "custom ellipsis is handled hygienically"
1453 ((f (syntax-rules ()
1456 ((g (syntax-rules --- ()
1457 ((g (??x ?e) (??y ---))
1458 '((??x) ?e (??y) ---)))))
1459 (g (1 2) (3 4)))))))
1462 (with-test-prefix "syntax-error"
1464 (pass-if-syntax-error "outside of macro without args"
1466 (eval '(syntax-error "test error")
1467 (interaction-environment)))
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)))
1474 (pass-if-equal "within macro"
1476 "expected an identifier but got (z1 z2)"
1477 (simple-let ((y (* x x))
1478 ((z1 z2) (values x x)))
1480 (catch 'syntax-error
1483 (define-syntax simple-let
1485 ((_ (head ... ((x . y) val) . tail)
1488 "expected an identifier but got"
1490 ((_ ((name val) ...) body1 body2 ...)
1491 ((lambda (name ...) body1 body2 ...)
1494 (simple-let ((y (* x x))
1495 ((z1 z2) (values x x)))
1498 (interaction-environment))
1499 (error "expected syntax-error exception"))
1500 (lambda (k who what where form . maybe-subform)
1501 (list who what form)))))
1503 (with-test-prefix "syntax-case"
1505 (pass-if-syntax-error "duplicate pattern variable"
1506 '(syntax-case . "duplicate pattern variable")
1509 ((a b c d e d f) #f)))
1510 (interaction-environment)))
1512 (with-test-prefix "misplaced ellipses"
1514 (pass-if-syntax-error "bare ellipsis"
1515 '(syntax-case . "misplaced ellipsis")
1519 (interaction-environment)))
1521 (pass-if-syntax-error "ellipsis singleton"
1522 '(syntax-case . "misplaced ellipsis")
1526 (interaction-environment)))
1528 (pass-if-syntax-error "ellipsis in car"
1529 '(syntax-case . "misplaced ellipsis")
1533 (interaction-environment)))
1535 (pass-if-syntax-error "ellipsis in cdr"
1536 '(syntax-case . "misplaced ellipsis")
1540 (interaction-environment)))
1542 (pass-if-syntax-error "two ellipses in the same list"
1543 '(syntax-case . "misplaced ellipsis")
1546 ((x ... y ...) #f)))
1547 (interaction-environment)))
1549 (pass-if-syntax-error "three ellipses in the same list"
1550 '(syntax-case . "misplaced ellipsis")
1553 ((x ... y ... z ...) #f)))
1554 (interaction-environment)))))
1556 (with-test-prefix "with-ellipsis"
1558 (pass-if-equal "simple"
1561 (define-syntax define-quotation-macros
1564 ((_ (macro-name head-symbol) ...)
1565 #'(begin (define-syntax macro-name
1570 #'(quote (head-symbol x …)))))))
1572 (define-quotation-macros (quote-a a) (quote-b b))
1575 (pass-if-equal "disables normal ellipsis"
1583 #'(quote (a ...)))))))
1586 (pass-if-equal "doesn't affect ellipsis for generated code"
1589 (define-syntax quotation-macro
1597 #'(quote (x ...))))))))))
1598 (define-syntax kwote (quotation-macro))
1601 (pass-if-equal "propagates into syntax binders"
1605 (define-syntax kwote
1612 (pass-if-equal "works with local-eval"
1614 (let ((env (with-ellipsis … (the-environment))))
1615 (local-eval '(syntax-case #'(a b c d e) ()
1620 ;;; Local Variables:
1621 ;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
1622 ;;; eval: (put 'with-ellipsis 'scheme-indent-function 1)