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:zero-expression-sequence
86 "sequence of zero expressions")
89 ;; (put 'pass-if-syntax-error 'scheme-indent-function 1)
90 (define-syntax pass-if-syntax-error
95 (lambda () exp (error "expected syntax-error exception"))
96 (lambda (k who what where form . maybe-subform)
98 (and (eq? who (car pat))
99 (string-match (cdr pat) what))
100 (string-match pat what))
102 (error "unexpected syntax-error exception" what pat))))))))
104 (with-test-prefix "expressions"
106 (with-test-prefix "Bad argument list"
108 (pass-if-syntax-error "improper argument list of length 1"
109 exception:generic-syncase-error
110 (eval '(let ((foo (lambda (x y) #t)))
112 (interaction-environment)))
114 (pass-if-syntax-error "improper argument list of length 2"
115 exception:generic-syncase-error
116 (eval '(let ((foo (lambda (x y) #t)))
118 (interaction-environment))))
120 (with-test-prefix "missing or extra expression"
123 ;; *Note:* In many dialects of Lisp, the empty combination, (),
124 ;; is a legitimate expression. In Scheme, combinations must
125 ;; have at least one subexpression, so () is not a syntactically
129 (pass-if-syntax-error "empty parentheses \"()\""
130 exception:unexpected-syntax
132 (interaction-environment)))))
134 (with-test-prefix "quote"
137 (with-test-prefix "quasiquote"
139 (with-test-prefix "unquote"
141 (pass-if "repeated execution"
142 (let ((foo (let ((i 0)) (lambda () (set! i (+ i 1)) `(,i)))))
143 (and (equal? (foo) '(1)) (equal? (foo) '(2))))))
145 (with-test-prefix "unquote-splicing"
147 (pass-if "extra arguments"
148 (equal? (eval '(quasiquote ((unquote-splicing (list 1 2) (list 3 4))))
149 (interaction-environment))
152 (with-test-prefix "begin"
154 (pass-if "valid (begin)"
155 (eval '(begin (begin) #t) (interaction-environment)))
157 (if (not (include-deprecated-features))
158 (pass-if-syntax-error "invalid (begin)"
159 exception:zero-expression-sequence
160 (eval '(begin (if #t (begin)) #t) (interaction-environment)))))
162 (define-syntax matches?
164 ((_ (op arg ...) pat) (let ((x (op arg ...)))
167 ((_ x (a . b)) (and (pair? x)
169 (matches? (cdr x) b)))
171 ((_ x pat) (equal? x 'pat))))
173 (with-test-prefix "lambda"
175 (with-test-prefix "bad formals"
177 (pass-if-syntax-error "(lambda)"
180 (interaction-environment)))
182 (pass-if-syntax-error "(lambda . \"foo\")"
184 (eval '(lambda . "foo")
185 (interaction-environment)))
187 (pass-if-syntax-error "(lambda \"foo\")"
189 (eval '(lambda "foo")
190 (interaction-environment)))
192 (pass-if-syntax-error "(lambda \"foo\" #f)"
193 exception:bad-formals
194 (eval '(lambda "foo" #f)
195 (interaction-environment)))
197 (pass-if-syntax-error "(lambda (x 1) 2)"
198 exception:bad-formals
199 (eval '(lambda (x 1) 2)
200 (interaction-environment)))
202 (pass-if-syntax-error "(lambda (1 x) 2)"
203 exception:bad-formals
204 (eval '(lambda (1 x) 2)
205 (interaction-environment)))
207 (pass-if-syntax-error "(lambda (x \"a\") 2)"
208 exception:bad-formals
209 (eval '(lambda (x "a") 2)
210 (interaction-environment)))
212 (pass-if-syntax-error "(lambda (\"a\" x) 2)"
213 exception:bad-formals
214 (eval '(lambda ("a" x) 2)
215 (interaction-environment))))
217 (with-test-prefix "duplicate formals"
220 (pass-if-syntax-error "(lambda (x x) 1)"
221 exception:duplicate-formals
222 (eval '(lambda (x x) 1)
223 (interaction-environment)))
226 (pass-if-syntax-error "(lambda (x x x) 1)"
227 exception:duplicate-formals
228 (eval '(lambda (x x x) 1)
229 (interaction-environment))))
231 (with-test-prefix "bad body"
233 (pass-if-syntax-error "(lambda ())"
236 (interaction-environment)))))
238 (with-test-prefix "let"
240 (with-test-prefix "bindings"
242 (pass-if-exception "late binding"
243 exception:unbound-var
244 (let ((x 1) (y x)) y)))
246 (with-test-prefix "bad bindings"
248 (pass-if-syntax-error "(let)"
251 (interaction-environment)))
253 (pass-if-syntax-error "(let 1)"
256 (interaction-environment)))
258 (pass-if-syntax-error "(let (x))"
261 (interaction-environment)))
263 (pass-if-syntax-error "(let ((x)))"
266 (interaction-environment)))
268 (pass-if-syntax-error "(let (x) 1)"
271 (interaction-environment)))
273 (pass-if-syntax-error "(let ((x)) 3)"
276 (interaction-environment)))
278 (pass-if-syntax-error "(let ((x 1) y) x)"
280 (eval '(let ((x 1) y) x)
281 (interaction-environment)))
283 (pass-if-syntax-error "(let ((1 2)) 3)"
285 (eval '(let ((1 2)) 3)
286 (interaction-environment))))
288 (with-test-prefix "duplicate bindings"
290 (pass-if-syntax-error "(let ((x 1) (x 2)) x)"
291 exception:duplicate-binding
292 (eval '(let ((x 1) (x 2)) x)
293 (interaction-environment))))
295 (with-test-prefix "bad body"
297 (pass-if-syntax-error "(let ())"
300 (interaction-environment)))
302 (pass-if-syntax-error "(let ((x 1)))"
305 (interaction-environment)))))
307 (with-test-prefix "named let"
309 (with-test-prefix "initializers"
311 (pass-if "evaluated in outer environment"
313 (eqv? (let f ((n (f 1))) n) -1))))
315 (with-test-prefix "bad bindings"
317 (pass-if-syntax-error "(let x (y))"
320 (interaction-environment))))
322 (with-test-prefix "bad body"
324 (pass-if-syntax-error "(let x ())"
327 (interaction-environment)))
329 (pass-if-syntax-error "(let x ((y 1)))"
331 (eval '(let x ((y 1)))
332 (interaction-environment)))))
334 (with-test-prefix "let*"
336 (with-test-prefix "bindings"
338 (pass-if "(let* ((x 1) (x 2)) ...)"
342 (pass-if "(let* ((x 1) (x x)) ...)"
346 (pass-if "(let ((x 1) (y 2)) (let* () ...))"
349 (and (= x 1) (= y 2))))))
351 (with-test-prefix "bad bindings"
353 (pass-if-syntax-error "(let*)"
354 exception:generic-syncase-error
356 (interaction-environment)))
358 (pass-if-syntax-error "(let* 1)"
359 exception:generic-syncase-error
361 (interaction-environment)))
363 (pass-if-syntax-error "(let* (x))"
364 exception:generic-syncase-error
366 (interaction-environment)))
368 (pass-if-syntax-error "(let* (x) 1)"
369 exception:generic-syncase-error
371 (interaction-environment)))
373 (pass-if-syntax-error "(let* ((x)) 3)"
374 exception:generic-syncase-error
375 (eval '(let* ((x)) 3)
376 (interaction-environment)))
378 (pass-if-syntax-error "(let* ((x 1) y) x)"
379 exception:generic-syncase-error
380 (eval '(let* ((x 1) y) x)
381 (interaction-environment)))
383 (pass-if-syntax-error "(let* x ())"
384 exception:generic-syncase-error
386 (interaction-environment)))
388 (pass-if-syntax-error "(let* x (y))"
389 exception:generic-syncase-error
391 (interaction-environment)))
393 (pass-if-syntax-error "(let* ((1 2)) 3)"
394 exception:generic-syncase-error
395 (eval '(let* ((1 2)) 3)
396 (interaction-environment))))
398 (with-test-prefix "bad body"
400 (pass-if-syntax-error "(let* ())"
401 exception:generic-syncase-error
403 (interaction-environment)))
405 (pass-if-syntax-error "(let* ((x 1)))"
406 exception:generic-syncase-error
407 (eval '(let* ((x 1)))
408 (interaction-environment)))))
410 (with-test-prefix "letrec"
412 (with-test-prefix "bindings"
414 (pass-if-syntax-error "initial bindings are undefined"
415 exception:used-before-defined
417 ;; FIXME: the memoizer does initialize the var to undefined, but
418 ;; the Scheme evaluator has no way of checking what's an
419 ;; undefined value. Not sure how to do this.
421 (letrec ((x 1) (y x)) y))))
423 (with-test-prefix "bad bindings"
425 (pass-if-syntax-error "(letrec)"
428 (interaction-environment)))
430 (pass-if-syntax-error "(letrec 1)"
433 (interaction-environment)))
435 (pass-if-syntax-error "(letrec (x))"
438 (interaction-environment)))
440 (pass-if-syntax-error "(letrec (x) 1)"
442 (eval '(letrec (x) 1)
443 (interaction-environment)))
445 (pass-if-syntax-error "(letrec ((x)) 3)"
447 (eval '(letrec ((x)) 3)
448 (interaction-environment)))
450 (pass-if-syntax-error "(letrec ((x 1) y) x)"
452 (eval '(letrec ((x 1) y) x)
453 (interaction-environment)))
455 (pass-if-syntax-error "(letrec x ())"
458 (interaction-environment)))
460 (pass-if-syntax-error "(letrec x (y))"
462 (eval '(letrec x (y))
463 (interaction-environment)))
465 (pass-if-syntax-error "(letrec ((1 2)) 3)"
467 (eval '(letrec ((1 2)) 3)
468 (interaction-environment))))
470 (with-test-prefix "duplicate bindings"
472 (pass-if-syntax-error "(letrec ((x 1) (x 2)) x)"
473 exception:duplicate-binding
474 (eval '(letrec ((x 1) (x 2)) x)
475 (interaction-environment))))
477 (with-test-prefix "bad body"
479 (pass-if-syntax-error "(letrec ())"
482 (interaction-environment)))
484 (pass-if-syntax-error "(letrec ((x 1)))"
486 (eval '(letrec ((x 1)))
487 (interaction-environment)))))
489 (with-test-prefix "letrec*"
491 (with-test-prefix "bindings"
493 (pass-if-syntax-error "initial bindings are undefined"
494 exception:used-before-defined
496 ;; FIXME: the memoizer does initialize the var to undefined, but
497 ;; the Scheme evaluator has no way of checking what's an
498 ;; undefined value. Not sure how to do this.
500 (letrec* ((x y) (y 1)) y))))
502 (with-test-prefix "bad bindings"
504 (pass-if-syntax-error "(letrec*)"
505 exception:bad-letrec*
507 (interaction-environment)))
509 (pass-if-syntax-error "(letrec* 1)"
510 exception:bad-letrec*
512 (interaction-environment)))
514 (pass-if-syntax-error "(letrec* (x))"
515 exception:bad-letrec*
517 (interaction-environment)))
519 (pass-if-syntax-error "(letrec* (x) 1)"
520 exception:bad-letrec*
521 (eval '(letrec* (x) 1)
522 (interaction-environment)))
524 (pass-if-syntax-error "(letrec* ((x)) 3)"
525 exception:bad-letrec*
526 (eval '(letrec* ((x)) 3)
527 (interaction-environment)))
529 (pass-if-syntax-error "(letrec* ((x 1) y) x)"
530 exception:bad-letrec*
531 (eval '(letrec* ((x 1) y) x)
532 (interaction-environment)))
534 (pass-if-syntax-error "(letrec* x ())"
535 exception:bad-letrec*
536 (eval '(letrec* x ())
537 (interaction-environment)))
539 (pass-if-syntax-error "(letrec* x (y))"
540 exception:bad-letrec*
541 (eval '(letrec* x (y))
542 (interaction-environment)))
544 (pass-if-syntax-error "(letrec* ((1 2)) 3)"
545 exception:bad-letrec*
546 (eval '(letrec* ((1 2)) 3)
547 (interaction-environment))))
549 (with-test-prefix "duplicate bindings"
551 (pass-if-syntax-error "(letrec* ((x 1) (x 2)) x)"
552 exception:duplicate-binding
553 (eval '(letrec* ((x 1) (x 2)) x)
554 (interaction-environment))))
556 (with-test-prefix "bad body"
558 (pass-if-syntax-error "(letrec* ())"
559 exception:bad-letrec*
561 (interaction-environment)))
563 (pass-if-syntax-error "(letrec* ((x 1)))"
564 exception:bad-letrec*
565 (eval '(letrec* ((x 1)))
566 (interaction-environment))))
568 (with-test-prefix "referencing previous values"
569 (pass-if (equal? (letrec ((a (cons 'foo 'bar))
573 (pass-if (equal? (let ()
574 (define a (cons 'foo 'bar))
579 (with-test-prefix "if"
581 (with-test-prefix "missing or extra expressions"
583 (pass-if-syntax-error "(if)"
584 exception:generic-syncase-error
586 (interaction-environment)))
588 (pass-if-syntax-error "(if 1 2 3 4)"
589 exception:generic-syncase-error
591 (interaction-environment)))))
593 (with-test-prefix "cond"
595 (with-test-prefix "cond is hygienic"
597 (pass-if "bound 'else is handled correctly"
598 (eq? (let ((else 'ok)) (cond (else))) 'ok))
600 (with-test-prefix "bound '=> is handled correctly"
604 (eq? (cond (#t => 'ok)) 'ok)))
608 (eq? (cond (else =>)) 'foo)))
610 (pass-if "else => identity"
612 (eq? (cond (else => identity)) identity)))))
614 (with-test-prefix "SRFI-61"
616 (pass-if "always available"
617 (cond-expand (srfi-61 #t) (else #f)))
619 (pass-if "single value consequent"
620 (eq? 'ok (cond (#t identity => (lambda (x) 'ok)) (else #f))))
622 (pass-if "single value alternate"
623 (eq? 'ok (cond (#t not => (lambda (x) #f)) (else 'ok))))
625 (pass-if-exception "doesn't affect standard =>"
626 exception:wrong-num-args
627 (cond ((values 1 2) => (lambda (x y) #t))))
629 (pass-if "multiple values consequent"
630 (equal? '(2 1) (cond ((values 1 2)
632 (and (= 1 one) (= 2 two))) =>
633 (lambda (one two) (list two one)))
636 (pass-if "multiple values alternate"
637 (eq? 'ok (cond ((values 2 3 4)
638 (lambda args (equal? '(1 2 3) args)) =>
642 (pass-if "zero values"
643 (eq? 'ok (cond ((values) (lambda () #t) => (lambda () 'ok))
646 (pass-if "bound => is handled correctly"
648 (eq? 'ok (cond (#t identity =>) (else #f)))))
650 (pass-if-syntax-error "missing recipient"
651 '(cond . "wrong number of receiver expressions")
652 (eval '(cond (#t identity =>))
653 (interaction-environment)))
655 (pass-if-syntax-error "extra recipient"
656 '(cond . "wrong number of receiver expressions")
657 (eval '(cond (#t identity => identity identity))
658 (interaction-environment))))
660 (with-test-prefix "bad or missing clauses"
662 (pass-if-syntax-error "(cond)"
663 exception:generic-syncase-error
665 (interaction-environment)))
667 (pass-if-syntax-error "(cond #t)"
668 '(cond . "invalid clause")
670 (interaction-environment)))
672 (pass-if-syntax-error "(cond 1)"
673 '(cond . "invalid clause")
675 (interaction-environment)))
677 (pass-if-syntax-error "(cond 1 2)"
678 '(cond . "invalid clause")
680 (interaction-environment)))
682 (pass-if-syntax-error "(cond 1 2 3)"
683 '(cond . "invalid clause")
685 (interaction-environment)))
687 (pass-if-syntax-error "(cond 1 2 3 4)"
688 '(cond . "invalid clause")
689 (eval '(cond 1 2 3 4)
690 (interaction-environment)))
692 (pass-if-syntax-error "(cond ())"
693 '(cond . "invalid clause")
695 (interaction-environment)))
697 (pass-if-syntax-error "(cond () 1)"
698 '(cond . "invalid clause")
700 (interaction-environment)))
702 (pass-if-syntax-error "(cond (1) 1)"
703 '(cond . "invalid clause")
705 (interaction-environment)))
707 (pass-if-syntax-error "(cond (else #f) (#t #t))"
708 '(cond . "else must be the last clause")
709 (eval '(cond (else #f) (#t #t))
710 (interaction-environment))))
712 (with-test-prefix "wrong number of arguments"
714 (pass-if-exception "=> (lambda (x y) #t)"
715 exception:wrong-num-args
716 (cond (1 => (lambda (x y) #t))))))
718 (with-test-prefix "case"
720 (pass-if "clause with empty labels list"
721 (case 1 (() #f) (else #t)))
723 (with-test-prefix "case handles '=> correctly"
725 (pass-if "(1 2 3) => list"
726 (equal? (case 1 ((1 2 3) => list))
729 (pass-if "else => list"
735 (with-test-prefix "bound '=> is handled correctly"
737 (pass-if "(1) => 'ok"
739 (eq? (case 1 ((1) => 'ok)) 'ok)))
743 (eq? (case 1 (else =>)) 'foo)))
745 (pass-if "else => list"
747 (eq? (case 1 (else => identity)) identity))))
749 (pass-if-syntax-error "missing recipient"
750 '(case . "wrong number of receiver expressions")
751 (eval '(case 1 ((1) =>))
752 (interaction-environment)))
754 (pass-if-syntax-error "extra recipient"
755 '(case . "wrong number of receiver expressions")
756 (eval '(case 1 ((1) => identity identity))
757 (interaction-environment))))
759 (with-test-prefix "case is hygienic"
761 (pass-if-syntax-error "bound 'else is handled correctly"
762 '(case . "invalid clause")
763 (eval '(let ((else #f)) (case 1 (else #f)))
764 (interaction-environment))))
766 (with-test-prefix "bad or missing clauses"
768 (pass-if-syntax-error "(case)"
769 exception:generic-syncase-error
771 (interaction-environment)))
773 (pass-if-syntax-error "(case . \"foo\")"
774 exception:generic-syncase-error
775 (eval '(case . "foo")
776 (interaction-environment)))
778 (pass-if-syntax-error "(case 1)"
779 exception:generic-syncase-error
781 (interaction-environment)))
783 (pass-if-syntax-error "(case 1 . \"foo\")"
784 exception:generic-syncase-error
785 (eval '(case 1 . "foo")
786 (interaction-environment)))
788 (pass-if-syntax-error "(case 1 \"foo\")"
789 '(case . "invalid clause")
790 (eval '(case 1 "foo")
791 (interaction-environment)))
793 (pass-if-syntax-error "(case 1 ())"
794 '(case . "invalid clause")
796 (interaction-environment)))
798 (pass-if-syntax-error "(case 1 (\"foo\"))"
799 '(case . "invalid clause")
800 (eval '(case 1 ("foo"))
801 (interaction-environment)))
803 (pass-if-syntax-error "(case 1 (\"foo\" \"bar\"))"
804 '(case . "invalid clause")
805 (eval '(case 1 ("foo" "bar"))
806 (interaction-environment)))
808 (pass-if-syntax-error "(case 1 ((2) \"bar\") . \"foo\")"
809 exception:generic-syncase-error
810 (eval '(case 1 ((2) "bar") . "foo")
811 (interaction-environment)))
813 (pass-if-syntax-error "(case 1 ((2) \"bar\") (else))"
814 '(case . "invalid clause")
815 (eval '(case 1 ((2) "bar") (else))
816 (interaction-environment)))
818 (pass-if-syntax-error "(case 1 (else #f) . \"foo\")"
819 exception:generic-syncase-error
820 (eval '(case 1 (else #f) . "foo")
821 (interaction-environment)))
823 (pass-if-syntax-error "(case 1 (else #f) ((1) #t))"
824 '(case . "else must be the last clause")
825 (eval '(case 1 (else #f) ((1) #t))
826 (interaction-environment)))))
828 (with-test-prefix "top-level define"
830 (pass-if "redefinition"
831 (let ((m (make-module)))
832 (beautify-user-module! m)
834 ;; The previous value of `round' must still be visible at the time the
835 ;; new `round' is defined. According to R5RS (Section 5.2.1), `define'
836 ;; should behave like `set!' in this case (except that in the case of
837 ;; Guile, we respect module boundaries).
838 (eval '(define round round) m)
839 (eq? (module-ref m 'round) round)))
841 (with-test-prefix "missing or extra expressions"
843 (pass-if-syntax-error "(define)"
844 exception:generic-syncase-error
846 (interaction-environment))))
848 (pass-if "module scoping"
852 (define-module (top-level-define/module-scoping-1)
853 #:export (define-10))
854 (define-syntax-rule (define-10 name)
858 (define-module (top-level-define/module-scoping-2)
859 #:use-module (top-level-define/module-scoping-1))
865 (pass-if "module scoping, same symbolic name"
869 (define-module (top-level-define/module-scoping-3))
871 (define-module (top-level-define/module-scoping-4)
872 #:use-module (top-level-define/module-scoping-3))
873 (define a (@@ (top-level-define/module-scoping-3) a))
878 (pass-if "module scoping, introduced names"
882 (define-module (top-level-define/module-scoping-5)
883 #:export (define-constant))
884 (define-syntax-rule (define-constant name val)
888 (define-module (top-level-define/module-scoping-6)
889 #:use-module (top-level-define/module-scoping-5))
890 (define-constant foo 10)
891 (define-constant bar 20)
896 (pass-if "module scoping, duplicate introduced name"
900 (define-module (top-level-define/module-scoping-7)
901 #:export (define-constant))
902 (define-syntax-rule (define-constant name val)
906 (define-module (top-level-define/module-scoping-8)
907 #:use-module (top-level-define/module-scoping-7))
908 (define-constant foo 10)
909 (define-constant foo 20)
914 (with-test-prefix "internal define"
916 (pass-if "internal defines become letrec"
917 (eval '(let ((a identity) (b identity) (c identity))
918 (define (a x) (if (= x 0) 'a (b (- x 1))))
919 (define (b x) (if (= x 0) 'b (c (- x 1))))
920 (define (c x) (if (= x 0) 'c (a (- x 1))))
921 (and (eq? 'a (a 0) (a 3))
923 (eq? 'c (a 2) (a 5))))
924 (interaction-environment)))
926 (pass-if "binding is created before expression is evaluated"
927 ;; Internal defines are equivalent to `letrec' (R5RS, Section 5.2.2).
934 (interaction-environment))
937 (pass-if "internal defines with begin"
939 (eval '(let ((a identity) (b identity) (c identity))
940 (define (a x) (if (= x 0) 'a (b (- x 1))))
942 (define (b x) (if (= x 0) 'b (c (- x 1)))))
943 (define (c x) (if (= x 0) 'c (a (- x 1))))
944 (and (eq? 'a (a 0) (a 3))
946 (eq? 'c (a 2) (a 5))))
947 (interaction-environment))))
949 (pass-if "internal defines with empty begin"
951 (eval '(let ((a identity) (b identity) (c identity))
952 (define (a x) (if (= x 0) 'a (b (- x 1))))
954 (define (b x) (if (= x 0) 'b (c (- x 1))))
955 (define (c x) (if (= x 0) 'c (a (- x 1))))
956 (and (eq? 'a (a 0) (a 3))
958 (eq? 'c (a 2) (a 5))))
959 (interaction-environment))))
961 (pass-if "internal defines with macro application"
964 (defmacro my-define forms
965 (cons 'define forms))
966 (let ((a identity) (b identity) (c identity))
967 (define (a x) (if (= x 0) 'a (b (- x 1))))
968 (my-define (b x) (if (= x 0) 'b (c (- x 1))))
969 (define (c x) (if (= x 0) 'c (a (- x 1))))
970 (and (eq? 'a (a 0) (a 3))
972 (eq? 'c (a 2) (a 5)))))
973 (interaction-environment))))
975 (pass-if-syntax-error "missing body expression"
976 exception:missing-body-expr
977 (eval '(let () (define x #t))
978 (interaction-environment))))
980 (with-test-prefix "set!"
982 (with-test-prefix "missing or extra expressions"
984 (pass-if-syntax-error "(set!)"
987 (interaction-environment)))
989 (pass-if-syntax-error "(set! 1)"
992 (interaction-environment)))
994 (pass-if-syntax-error "(set! 1 2 3)"
997 (interaction-environment))))
999 (with-test-prefix "bad variable"
1001 (pass-if-syntax-error "(set! \"\" #t)"
1004 (interaction-environment)))
1006 (pass-if-syntax-error "(set! 1 #t)"
1009 (interaction-environment)))
1011 (pass-if-syntax-error "(set! #t #f)"
1014 (interaction-environment)))
1016 (pass-if-syntax-error "(set! #f #t)"
1019 (interaction-environment)))
1021 (pass-if-syntax-error "(set! #\\space #f)"
1023 (eval '(set! #\space #f)
1024 (interaction-environment)))))
1026 (with-test-prefix "quote"
1028 (with-test-prefix "missing or extra expression"
1030 (pass-if-syntax-error "(quote)"
1033 (interaction-environment)))
1035 (pass-if-syntax-error "(quote a b)"
1038 (interaction-environment)))))
1040 (with-test-prefix "while"
1042 (define (unreachable)
1043 (error "unreachable code has been reached!"))
1045 ;; Return a new procedure COND which when called (COND) will return #t the
1046 ;; first N times, then #f, then any further call is an error. N=0 is
1047 ;; allowed, in which case #f is returned by the first call.
1048 (define (make-iterations-cond n)
1051 (error "oops, condition re-tested after giving false"))
1060 (pass-if-syntax-error "too few args" exception:generic-syncase-error
1061 (eval '(while) (interaction-environment)))
1063 (with-test-prefix "empty body"
1067 (eval `(letrec ((make-iterations-cond
1071 (error "oops, condition re-tested after giving false"))
1078 (let ((cond (make-iterations-cond ,n)))
1081 (interaction-environment)))))
1083 (pass-if "initially false"
1088 (with-test-prefix "iterations"
1092 (let ((cond (make-iterations-cond n))
1098 (with-test-prefix "break"
1100 (pass-if "normal return"
1101 (not (while #f (error "not reached"))))
1106 (pass-if "multiple values"
1109 (lambda () (while #t (break 1 2 3)))
1112 (with-test-prefix "from cond"
1123 (let ((cond (make-iterations-cond n))
1133 (with-test-prefix "from body"
1143 (let ((cond (make-iterations-cond n))
1153 (pass-if "from nested"
1155 (let ((outer-break break))
1162 (pass-if "from recursive"
1163 (let ((outer-break #f))
1168 (set! outer-break break)
1174 (error "broke only from inner loop")))
1178 (with-test-prefix "continue"
1180 (pass-if-syntax-error "too many args" exception:too-many-args
1183 (interaction-environment)))
1185 (with-test-prefix "from cond"
1189 (let ((cond (make-iterations-cond n))
1200 (with-test-prefix "from body"
1204 (let ((cond (make-iterations-cond n))
1212 (pass-if "from nested"
1213 (let ((cond (make-iterations-cond 3)))
1215 (let ((outer-continue continue))
1221 (pass-if "from recursive"
1222 (let ((outer-continue #f))
1224 (let ((cond (make-iterations-cond 3))
1227 (if (and (not first)
1229 (error "continued only to inner loop"))
1234 (set! outer-continue continue)
1242 (with-test-prefix "syntax-rules"
1244 (pass-if-equal "custom ellipsis within normal ellipsis"
1245 '((((a x) (a y) (a …))
1247 ((c x) (c y) (c …)))
1248 (((a x) (b x) (c x))
1250 ((a …) (b …) (c …))))
1258 (((x y) …) ...)))))))
1259 (define-syntax bar (foo x y …))
1262 (pass-if-equal "normal ellipsis within custom ellipsis"
1263 '((((a x) (a y) (a z))
1265 ((c x) (c y) (c z)))
1266 (((a x) (b x) (c x))
1268 ((a z) (b z) (c z))))
1276 (((x y) ...) …)))))))
1277 (define-syntax bar (foo x y z))
1280 ;; This test is given in SRFI-46.
1281 (pass-if-equal "custom ellipsis is handled hygienically"
1284 ((f (syntax-rules ()
1287 ((g (syntax-rules --- ()
1288 ((g (??x ?e) (??y ---))
1289 '((??x) ?e (??y) ---)))))
1290 (g (1 2) (3 4)))))))
1293 (with-test-prefix "syntax-error"
1295 (pass-if-syntax-error "outside of macro without args"
1297 (eval '(syntax-error "test error")
1298 (interaction-environment)))
1300 (pass-if-syntax-error "outside of macro with args"
1301 "test error x \\(y z\\)"
1302 (eval '(syntax-error "test error" x (y z))
1303 (interaction-environment)))
1305 (pass-if-equal "within macro"
1307 "expected an identifier but got (z1 z2)"
1308 (simple-let ((y (* x x))
1309 ((z1 z2) (values x x)))
1311 (catch 'syntax-error
1314 (define-syntax simple-let
1316 ((_ (head ... ((x . y) val) . tail)
1319 "expected an identifier but got"
1321 ((_ ((name val) ...) body1 body2 ...)
1322 ((lambda (name ...) body1 body2 ...)
1325 (simple-let ((y (* x x))
1326 ((z1 z2) (values x x)))
1329 (interaction-environment))
1330 (error "expected syntax-error exception"))
1331 (lambda (k who what where form . maybe-subform)
1332 (list who what form)))))
1334 (with-test-prefix "syntax-case"
1336 (pass-if-syntax-error "duplicate pattern variable"
1337 '(syntax-case . "duplicate pattern variable")
1340 ((a b c d e d f) #f)))
1341 (interaction-environment)))
1343 (with-test-prefix "misplaced ellipses"
1345 (pass-if-syntax-error "bare ellipsis"
1346 '(syntax-case . "misplaced ellipsis")
1350 (interaction-environment)))
1352 (pass-if-syntax-error "ellipsis singleton"
1353 '(syntax-case . "misplaced ellipsis")
1357 (interaction-environment)))
1359 (pass-if-syntax-error "ellipsis in car"
1360 '(syntax-case . "misplaced ellipsis")
1364 (interaction-environment)))
1366 (pass-if-syntax-error "ellipsis in cdr"
1367 '(syntax-case . "misplaced ellipsis")
1371 (interaction-environment)))
1373 (pass-if-syntax-error "two ellipses in the same list"
1374 '(syntax-case . "misplaced ellipsis")
1377 ((x ... y ...) #f)))
1378 (interaction-environment)))
1380 (pass-if-syntax-error "three ellipses in the same list"
1381 '(syntax-case . "misplaced ellipsis")
1384 ((x ... y ... z ...) #f)))
1385 (interaction-environment)))))
1387 (with-test-prefix "with-ellipsis"
1389 (pass-if-equal "simple"
1392 (define-syntax define-quotation-macros
1395 ((_ (macro-name head-symbol) ...)
1396 #'(begin (define-syntax macro-name
1401 #'(quote (head-symbol x …)))))))
1403 (define-quotation-macros (quote-a a) (quote-b b))
1406 (pass-if-equal "disables normal ellipsis"
1414 #'(quote (a ...)))))))
1417 (pass-if-equal "doesn't affect ellipsis for generated code"
1420 (define-syntax quotation-macro
1428 #'(quote (x ...))))))))))
1429 (define-syntax kwote (quotation-macro))
1432 (pass-if-equal "propagates into syntax binders"
1436 (define-syntax kwote
1443 (pass-if-equal "works with local-eval"
1445 (let ((env (with-ellipsis … (the-environment))))
1446 (local-eval '(syntax-case #'(a b c d e) ()
1451 ;;; Local Variables:
1452 ;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
1453 ;;; eval: (put 'with-ellipsis 'scheme-indent-function 1)