~ chicken-core (master) /tests/syntax-tests.scm


   1;;;; syntax-tests.scm - various macro tests
   2
   3(import-for-syntax chicken.pretty-print)
   4(import chicken.gc chicken.pretty-print chicken.port)
   5(import (only (scheme base) call/cc))
   6
   7(define-syntax t
   8  (syntax-rules ()
   9    ((_ r x)
  10     (let ((tmp x))
  11       (if (not (equal? r tmp))
  12	   (error "test failed" r tmp 'x)
  13	   (pp tmp))))))
  14
  15(define-syntax f
  16  (syntax-rules ()
  17    ((_ x)
  18     (let ((got-error #f))
  19      (handle-exceptions ex (set! got-error #t) x)
  20      (unless got-error
  21        (error "test returned, but should have failed" 'x) )))))
  22
  23(t 3 3)
  24
  25(f abc)
  26(f (t 3 4))
  27
  28;; test syntax-rules
  29
  30(define-syntax test
  31  (syntax-rules ()
  32    ((_ x form)
  33     (let ((tmp x))
  34       (if (number? tmp)
  35	   form
  36	   (error "not a number" tmp))))))
  37
  38(t 100 (test 2 100))
  39
  40
  41;; Keywords are not symbols; don't attempt to bind them
  42(t 1 (let-syntax ((foo (syntax-rules () ((foo bar: qux) qux))))
  43       (foo bar: 1)))
  44
  45;; some basic contrived testing
  46
  47(define (fac n)
  48  (let-syntax ((m1
  49		(er-macro-transformer
  50		 (lambda (n r c)
  51		   (pp `(M1: ,n))
  52		   (list (r 'sub1) (cadr n))))))
  53    (define (sub1 . _)			; ref. transp.? (should not be used here)
  54      (error "argh.") )
  55    #;(print "fac: " n)
  56    (if (test n (zero? n))
  57	1
  58	(* n (fac (m1 n))))))
  59
  60(t 3628800 (fac 10))
  61
  62;; letrec-syntax
  63
  64(t 34
  65(letrec-syntax ((foo (syntax-rules () ((_ x) (bar x))))
  66		(bar (syntax-rules () ((_ x) (+ x 1)))))
  67  (foo 33))
  68)
  69
  70;; letrec-values
  71
  72(t '(0 1 2 3 (4) (5 6))
  73   (letrec-values ((() (values))
  74                   ((a) (values 0))
  75                   ((b c) (values 1 2))
  76                   ((d . e) (values 3 4))
  77                   (f (values 5 6)))
  78     (list a b c d e f)))
  79
  80;; from r5rs:
  81
  82(t 45
  83(let ((x 5))
  84  (define foo (lambda (y) (bar x y)))
  85  (define bar (lambda (a b) (+ (* a b) a)))
  86  (foo (+ x 3)))
  87)
  88
  89;; an error, according to r5rs - here it treats foo as defining a toplevel binding
  90
  91#;(let-syntax
  92  ((foo (syntax-rules ()
  93          ((foo (proc args ...) body ...)
  94           (define proc
  95             (lambda (args ...)
  96               body ...))))))
  97  (let ((x 3))
  98    (foo (plus x y) (+ x y))
  99    (define foo x)
 100    (print (plus foo x))))
 101
 102(t 'now
 103(let-syntax ((when (syntax-rules ()
 104                     ((when test stmt1 stmt2 ...)
 105                      (if test
 106                          (begin stmt1
 107                                 stmt2 ...))))))
 108  (let ((if #t))
 109    (when if (set! if 'now))
 110    if))
 111)
 112
 113(t 'outer
 114(let ((x 'outer))
 115  (let-syntax ((m (syntax-rules () ((m) x))))
 116    (let ((x 'inner))
 117      (m))))
 118)
 119
 120(t 7
 121(letrec-syntax
 122  ((my-or (syntax-rules ()
 123            ((my-or) #f)
 124            ((my-or e) e)
 125            ((my-or e1 e2 ...)
 126             (let ((temp e1))
 127               (if temp
 128                   temp
 129                   (my-or e2 ...)))))))
 130  (let ((x #f)
 131        (y 7)
 132        (temp 8)
 133        (let odd?)
 134        (if even?))
 135    (my-or x
 136           (let temp)
 137           (if y)
 138           y)))
 139)
 140
 141;; From Al* Petrofsky's "An Advanced Syntax-Rules Primer for the Mildly Insane"
 142(let ((a 1))
 143  (letrec-syntax
 144      ((foo (syntax-rules ()
 145              ((_ b)
 146               (bar a b))))
 147       (bar (syntax-rules ()
 148              ((_ c d)
 149               (cons c (let ((c 3))
 150                         (list d c 'c)))))))
 151    (let ((a 2))
 152      (t '(1 2 3 a) (foo a)))))
 153
 154;; ER equivalent
 155(let ((a 1))
 156  (letrec-syntax
 157      ((foo (er-macro-transformer
 158             (lambda (x r c)
 159               `(,(r 'bar) ,(r 'a) ,(cadr x)))))
 160       (bar (er-macro-transformer
 161             (lambda (x r c)
 162               (let ((c (cadr x))
 163                     (d (caddr x)))
 164                `(,(r 'cons) ,c
 165                  (,(r 'let) ((,c 3))
 166                   (,(r 'list) ,d ,c ',c))))))))
 167    (let ((a 2))
 168      (t '(1 2 3 a) (foo a)))))
 169
 170;; IR equivalent
 171(let ((a 1))
 172  (letrec-syntax
 173      ((foo (ir-macro-transformer
 174             (lambda (x i c)
 175               `(bar a ,(cadr x)))))
 176       (bar (ir-macro-transformer
 177             (lambda (x i c)
 178               (let ((c (cadr x))
 179                     (d (caddr x)))
 180                 `(cons ,c
 181                        (let ((,c 3))
 182                          (list ,d ,c ',c))))))))
 183    (let ((a 2))
 184      (t '(1 2 3 a) (foo a)))))
 185
 186;; Strip-syntax on vectors:
 187(let-syntax
 188    ((foo (syntax-rules ()
 189            ((_)
 190             '#(b)))))
 191  (t '#(b) (foo)))
 192
 193(define-syntax kw
 194  (syntax-rules (baz)
 195    ((_ baz) "baz")
 196    ((_ any) "no baz")))
 197
 198(t "baz" (kw baz))
 199(t "no baz" (kw xxx))
 200
 201(let ((baz 100))
 202  (t "no baz" (kw baz)))
 203
 204;; Optimisation to rewrite constants with =>, reported by Michele La Monaca
 205(t 2 (cond (1 2)))
 206(f (cond (1 => string-length)))
 207(t #t (cond (1 => odd?)))
 208
 209(t 'ok
 210(let ((=> #f))
 211  (cond (#t => 'ok)))
 212)
 213
 214(t 1 (let ((=> 1))
 215       (cond (#f 'false)
 216             (#t =>))))
 217
 218(t 3 (let ((=> 1))
 219       (cond (#f 'false)
 220             (#t => 2 3))))
 221
 222(t '(3 4)
 223(let ((foo 3))
 224  (let-syntax ((bar (syntax-rules () ((_ x) (list foo x)))))
 225    (let ((foo 4))
 226      (bar foo))))
 227)
 228
 229;;; strip-syntax cuts across multiple levels of syntax
 230;;; reported by Matthew Flatt
 231(define-syntax c
 232  (syntax-rules ()
 233    [(_)
 234     (let ([x 10])
 235       (let-syntax ([z (syntax-rules ()
 236                         [(_) (quote x)])])
 237         (z)))]))
 238
 239(t "x" (symbol->string (c)))
 240
 241(define-syntax c2
 242   (syntax-rules ()
 243     [(_)
 244      (let ([x 10])
 245        (let-syntax ([z (syntax-rules ()
 246                          [(_) (let-syntax ([w (syntax-rules ()
 247                                                 [(_) (quote x)])])
 248                                 (w))])])
 249          (z)))]))
 250
 251(t "x" (symbol->string (c2)))
 252
 253;;; strip-syntax on renamed module identifiers, as well as core identifiers
 254(module foo (bar)
 255  (import scheme)
 256
 257  (define bar 1))
 258
 259(import foo)
 260
 261(define-syntax baz
 262  (er-macro-transformer
 263   (lambda (e r c)
 264     `',(strip-syntax (r 'bar)))))
 265
 266(t "bar" (symbol->string (baz bar)))
 267(t "bar" (symbol->string (baz void)))
 268
 269;; Fully qualified symbols are not mangled - these names are internal
 270;; and not documented, but shouldn't be messed with by the expander
 271
 272(t "foo#bar" (symbol->string 'foo#bar))
 273(t "foo#bar" (symbol->string (strip-syntax 'foo#bar)))
 274
 275(t "#!rest" (symbol->string '#!rest))
 276(t "#!rest" (symbol->string '|#!rest|))
 277(t "#!rest" (symbol->string (strip-syntax '#!rest)))
 278
 279;; Read-write invariance of "special" symbols
 280
 281(t '#!rest (with-input-from-string "#!rest" read))
 282(t '#!rest (with-input-from-string "|#!rest|" read))
 283(t "#!rest" (with-output-to-string (lambda () (write '#!rest))))
 284
 285;; Non-special symbols starting with shebang
 286(f (with-input-from-string "#!foo" read))
 287(t '|#!foo| (with-input-from-string "|#!foo|" read))
 288(t "|#!foo|" (with-output-to-string (lambda () (write '|#!foo|))))
 289
 290;; Namespaced symbols
 291(t "foo#bar" (with-output-to-string (lambda () (write 'foo#bar))))
 292(t "##foo#bar" (with-output-to-string (lambda () (write '##foo#bar))))
 293
 294;; These used to be treated specially, but now they just trigger an
 295;; "invalid sharp-sign read syntax" error.
 296(t "|#%foo|" (with-output-to-string (lambda () (write '|#%foo|))))
 297(f (with-input-from-string "#%foo" read))
 298
 299;;; alternative ellipsis test (SRFI-46)
 300
 301(define-syntax foo
 302  (syntax-rules
 303      ___ ()
 304      ((_ vals ___) (list '... vals ___))))
 305
 306(t '(... 1 2 3)
 307   (foo 1 2 3)
 308)
 309
 310(define-syntax defalias
 311  (syntax-rules ___ ()
 312    ((_ new old)
 313     (define-syntax new
 314       (syntax-rules ()
 315	 ((_ args ...) (old args ...)))))))
 316
 317(defalias inc add1)
 318
 319(t 3 (inc 2))
 320
 321;;; Rest patterns after ellipsis (SRFI-46)
 322
 323(define-syntax foo
 324  (syntax-rules ()
 325    ((_ (a ... b) ... (c d))
 326     (list (list (list a ...) ... b ...) c d))
 327    ((_ #(a ... b) ... #(c d) #(e f))
 328     (list (list (vector a ...) ... b ...) c d e f))
 329    ((_ #(a ... b) ... #(c d))
 330     (list (list (vector a ...) ... b ...) c d))))
 331
 332(t '(() 1 2)
 333   (foo (1 2)))
 334
 335(t '(((1) 2) 3 4)
 336   (foo (1 2) (3 4)))
 337
 338(t '(((1 2) (4) 3 5) 6 7)
 339   (foo (1 2 3) (4 5) (6 7)))
 340
 341(t '(() 1 2)
 342   (foo #(1 2)))
 343
 344(t '((#() 1) 2 3)
 345   (foo #(1) #(2 3)))
 346
 347(t '((#(1 2) 3) 4 5)
 348   (foo #(1 2 3) #(4 5)))
 349
 350(t '((#(1 2) 3) 4 5 6 7)
 351   (foo #(1 2 3) #(4 5) #(6 7)))
 352
 353(t '(() 1 2 3 4)
 354   (foo #(1 2) #(3 4)))
 355
 356(t '((#(1) 2) 3 4 5 6)
 357   (foo #(1 2) #(3 4) #(5 6)))
 358
 359(t '((#(1 2) #(4) 3 5) 6 7 8 9)
 360   (foo #(1 2 3) #(4 5) #(6 7) #(8 9)))
 361
 362;;; Bug discovered during implementation of SRFI-46 rest patterns:
 363
 364(define-syntax foo
 365  (syntax-rules ()
 366    ((_ #((a) ...)) (list a ...))))
 367
 368(t '(1)
 369   (foo #((1))))
 370
 371;;;
 372
 373(define-syntax usetmp
 374  (syntax-rules ()
 375    ((_ var)
 376     (list var))))
 377
 378(define-syntax withtmp
 379  (syntax-rules ()
 380    ((_ val exp)
 381     (let ((tmp val))
 382       (exp tmp)))))
 383
 384(t '(99)
 385   (withtmp 99 usetmp)
 386)
 387
 388(t 7
 389(letrec-syntax
 390    ((my-or (syntax-rules ()
 391	      ((my-or) #f)
 392	      ((my-or e) e)
 393	      ((my-or e1 e2 ...)
 394	       (let ((temp e1))
 395		 (if temp
 396		     temp
 397		     (my-or e2 ...)))))))
 398  (let ((x #f)
 399        (y 7)
 400        (temp 8)
 401        (let odd?)
 402        (if even?))
 403    (my-or x
 404           (let temp)
 405           (if y)
 406           y)))
 407)
 408
 409(define-syntax foo
 410  (syntax-rules ()
 411    ((_ #(a ...)) (list a ...))))
 412
 413(t '(1 2 3)
 414   (foo #(1 2 3))
 415)
 416
 417
 418(define-syntax loop
 419  (er-macro-transformer
 420   (lambda (x r c)
 421     (let ((body (cdr x)))
 422       `(,(r 'call/cc)
 423	 (,(r 'lambda) (exit)
 424	  (,(r 'let) ,(r 'f) () ,@body (,(r 'f)))))))))
 425
 426(let ((n 10))
 427  (loop
 428   (print* n " ")
 429   (set! n (sub1 n))
 430   (when (zero? n) (exit #f)))
 431  (newline))
 432
 433(define-syntax while0
 434  (syntax-rules ()
 435    ((_ t b ...)
 436     (loop (if (not t) (exit #f))
 437	   b ...))))
 438
 439(f (while0 #f (print "no.")))
 440
 441(define-syntax while
 442  (er-macro-transformer
 443   (lambda (x r c)
 444     `(,(r 'loop)
 445       (,(r 'if) (,(r 'not) ,(cadr x)) (exit #f))
 446       ,@(cddr x)))))
 447
 448(let ((n 10))
 449  (while (not (zero? n))
 450	 (print* n " ")
 451	 (set! n (- n 1)) )
 452  (newline))
 453
 454;;; found by Jim Ursetto
 455
 456(let ((lambda 0)) (define (foo) 1) (foo))
 457
 458
 459;;; define-macro implementation (only usable in a module-free environment)
 460
 461(define-syntax define-macro
 462  (syntax-rules ()
 463    ((_ (name . llist) body ...)
 464     (define-syntax name
 465       (er-macro-transformer
 466	(lambda (x r c)
 467	  (apply (lambda llist body ...) (strip-syntax (cdr x)))))))))
 468
 469(define-macro (loop . body)
 470  (let ((loop (gensym)))
 471    `(call/cc
 472      (lambda (exit)
 473	(let ,loop () ,@body (,loop))))))
 474
 475(let ((i 1))
 476  (loop (when (> i 10) (exit #f))
 477	(print* i " ")
 478	(set! i (add1 i))))
 479(newline)
 480
 481
 482;;;; exported macro would override original name (fixed in rev. 13351)
 483
 484(module xfoo (xbaz xbar)
 485  (import scheme)
 486  (define-syntax xbar
 487    (syntax-rules ()
 488      ((_ 1) (xbaz))
 489      ((_) 'xbar)))
 490  (define-syntax xbaz
 491    (syntax-rules ()
 492      ((_ 1) (xbar))
 493      ((_) 'xbazz))))
 494
 495(import xfoo)
 496(assert (eq? 'xbar (xbaz 1)))
 497(assert (eq? 'xbazz (xbar 1)))
 498(assert (eq? 'xbar (xbar)))
 499
 500
 501;;;; ellipsis pattern element wasn't matched - reported by Jim Ursetto (fixed rev. 13582)
 502
 503(define-syntax foo
 504  (syntax-rules ()
 505    ((_ (a b) ...)
 506     (list '(a b) ...))
 507    ((_ a ...)
 508     (list '(a) ...))))
 509
 510(assert (equal? (foo (1 2) (3 4) (5 6)) '((1 2) (3 4) (5 6))))
 511(assert (equal? (foo (1 2) (3) (5 6)) '(((1 2)) ((3)) ((5 6))))) ; failed
 512(assert (equal? (foo 1) '((1))))
 513
 514
 515;;; incorrect lookup for keyword variables in DSSSL llists
 516
 517(module broken-keyword-var ()
 518  (import scheme (chicken base))
 519  ((lambda (#!key string) (assert (not string))))) ; refered to R5RS `string'
 520
 521;;; Missing check for keyword and optional variable types in DSSSL llists
 522
 523(f (eval '(lambda (foo #!key (0 1)) x)))
 524(f (eval '(lambda (foo #!optional (0 1)) x)))
 525
 526;;; compiler didn't resolve expansion into local variable
 527;;; (reported by Alex Shinn, #15)
 528
 529(module unresolve-local (foo)
 530  (import scheme)
 531  (define (foo)
 532    (let ((qux 3))
 533      (let-syntax ((bar (syntax-rules () ((bar) qux))))
 534	(bar))))
 535
 536  (display (foo))
 537  (newline)
 538)
 539
 540
 541;;; incorrect expansion when assigning to something marked '##core#primitive (rev. 14613)
 542
 543(define x 99)
 544
 545(module primitive-assign ()
 546  (import scheme (chicken base))
 547  (let ((x 100)) (set! x 20) (assert (= x 20)))
 548  (set! setter 123))
 549
 550(assert (= x 99))
 551(assert (= 123 setter))
 552
 553
 554;;; prefixed import from `chicken' module with indirect reference to imported syntax
 555;;; (reported by Jack Trades)
 556
 557(module prefixed-self-reference1 (a b c)
 558  (import scheme (prefix chicken.base c:))
 559  (c:define-values (a b c) (values 1 2 3)) )
 560
 561(module prefixed-self-reference2 ()
 562  (import scheme (prefix (chicken base) c:) (prefix (chicken condition) c:))
 563  (c:define-values (a b c) (values 1 2 3))
 564  (c:print "ok")
 565  (c:condition-case
 566   (c:abort "ugh")
 567   (ex () (c:print "caught"))))
 568
 569(module prefixed-self-reference3 (a)
 570  ;; TODO: Switch this around when plain "chicken" has been removed
 571  (import (prefix scheme s.) (prefix (chicken condition) c.))
 572  (s.define (a x y)
 573	    (c.condition-case (s.+ x y) ((exn) "not numbers")))
 574  )
 575
 576(module prefixed-self-reference4 (a)
 577  (import (prefix scheme s.))
 578  (s.define (a x y) (s.and x y)))
 579
 580
 581;;; canonicalization of body captures 'begin (reported by Abdulaziz Ghuloum)
 582
 583(let ((begin (lambda (x y) (bomb)))) 1 2)
 584
 585
 586;;; redefinition of defining forms
 587
 588(module m0001 (foo bar)
 589  (import (prefix scheme s:))
 590  (s:define-syntax foo (syntax-rules () ((_ x) (s:list x))))
 591  (s:define bar 99))
 592
 593(module m0002 ()
 594  (import scheme m0001 chicken.pretty-print)
 595  (pp (foo bar)))
 596
 597
 598;;; renaming of arbitrary structures
 599
 600(module m1 (s1 s2)
 601
 602  (import scheme)
 603
 604  (define-syntax s1 (syntax-rules () ((_ x) (list x))))
 605
 606  (define-syntax s2
 607    (er-macro-transformer
 608     (lambda (x r c)
 609       (r `(vector (s1 ,(cadr x))))))) )	; without renaming the local version of `s1'
 610					; below will be captured
 611
 612(import m1)
 613
 614(let-syntax ((s1 (syntax-rules () ((_ x) x))))
 615  (assert (equal? '#((99)) (s2 99))))
 616
 617;; IR macros
 618
 619(define-syntax loop2
 620  (ir-macro-transformer
 621   (lambda (x i c)
 622     (let ((body (cdr x)))
 623       `(call/cc
 624         (lambda (,(i 'exit))
 625           (let f () ,@body (f))))))))
 626
 627(let ((n 10))
 628  (loop2
 629   (print* n " ")
 630   (set! n (sub1 n))
 631   (when (zero? n) (exit #f)))
 632  (newline))
 633
 634(define-syntax while20
 635  (syntax-rules ()
 636    ((_ t b ...)
 637     (loop2 (if (not t) (exit #f))
 638	    b ...))))
 639
 640(f (while20 #f (print "no.")))
 641
 642(define-syntax while2
 643  (ir-macro-transformer
 644   (lambda (x i c)
 645     `(loop
 646       (if (not ,(cadr x)) (,(i 'exit) #f))
 647       ,@(cddr x)))))
 648
 649(let ((n 10))
 650  (while2 (not (zero? n))
 651          (print* n " ")
 652          (set! n (- n 1)) )
 653  (newline))
 654
 655(module m2 (s3 s4)
 656
 657  (import scheme)
 658
 659  (define-syntax s3 (syntax-rules () ((_ x) (list x))))
 660
 661  (define-syntax s4
 662    (ir-macro-transformer
 663     (lambda (x r c)
 664       `(vector (s3 ,(cadr x)))))) ) ; without implicit renaming the local version
 665                                     ; of `s3' below would be captured
 666
 667(import m2)
 668
 669(let-syntax ((s3 (syntax-rules () ((_ x) x))))
 670  (t '#((99)) (s4 99)))
 671
 672(let ((vector list))
 673  (t '#((one)) (s4 'one)))
 674
 675(define-syntax nest-me
 676  (ir-macro-transformer
 677   (lambda (x i c)
 678     `(let ((,(i 'captured) 1))
 679        ,@(cdr x)))))
 680
 681(t '(1 #(1 #(1)))
 682   (nest-me (list captured
 683                  (let ((captured 2)
 684                        (let 'not-captured)
 685                        (list vector))
 686                    (nest-me (list captured
 687                                   (nest-me (list captured))))))))
 688
 689(define-syntax cond-test
 690  (ir-macro-transformer
 691   (lambda (x i c)
 692     (let lp ((exprs (cdr x)))
 693       (cond
 694        ((null? exprs) '(void))
 695        ((c (caar exprs) 'else)
 696         `(begin ,@(cdar exprs)))
 697        ((c (cadar exprs) '=>)
 698         `(let ((tmp ,(caar exprs)))
 699            (if tmp
 700                (,(caddar exprs) tmp)
 701                ,(lp (cdr exprs)))))
 702        ((c (cadar exprs) (i '==>)) ;; ==> is an Unhygienic variant of =>
 703         `(let ((tmp ,(caar exprs)))
 704            (if tmp
 705                (,(caddar exprs) tmp)
 706                ,(lp (cdr exprs)))))
 707        (else
 708         `(if ,(caar exprs)
 709              (begin ,@(cdar exprs))
 710              ,(lp (cdr exprs)))))))))
 711
 712(t 'yep
 713   (cond-test
 714    (#f 'false)
 715    (else 'yep)))
 716
 717(t 1
 718   (cond-test
 719    (#f 'false)
 720    (1 => (lambda (x) x))
 721    (else 'yep)))
 722
 723(let ((=> #f))
 724  (t 'a-procedure
 725     (cond-test
 726      (#f 'false)
 727      (1 => 'a-procedure)
 728      (else 'yep))))
 729
 730(let ((else #f))
 731  (t (void)
 732     (cond-test
 733      (#f 'false)
 734      (else 'nope))))
 735
 736(t 1
 737   (cond-test
 738    (#f 'false)
 739    (1 ==> (lambda (x) x))
 740    (else 'yep)))
 741
 742(let ((==> #f))
 743  (t 1
 744     (cond-test
 745      (#f 'false)
 746      (1 ==> (lambda (x) x))
 747      (else 'yep))))
 748
 749;; Undefined value (but no compiler error) on empty `else' clauses
 750(t (void) (cond (else)))
 751(t (void) (case 1 (else)))
 752
 753;; Literal quotation of a symbol, injected or not, should always result in that symbol
 754(module ir-se-test (run)
 755  (import scheme chicken.base)
 756  (define-syntax run
 757    (ir-macro-transformer
 758     (lambda (e i c)
 759       `(quote ,(i 'void))))))
 760
 761(import ir-se-test)
 762(t 'void (run))
 763
 764;;; local definitions
 765
 766(define-syntax s2
 767  (syntax-rules ()
 768    ((_) 1)))
 769
 770(define (f1) 3)
 771(define-values (v1 v2) (values 9 10))
 772(define-values (v3 . v4) (values 11 12))
 773(define-values v56 (values 13))
 774
 775(let ()
 776  (define-syntax s2
 777    (syntax-rules ()
 778      ((_) 2)))
 779  42
 780  (define-values (v1 v2) (values 1 2))
 781  (define-values (v3 . v4) (values 3 4))
 782  (define-values v56 (values 5 6))
 783  (define v56-again v56) ; ordering of assignments was broken #1274
 784  43
 785  (define (f1) 4)
 786  (define ((f2)) 4)
 787  (assert (= 4 (f1)))
 788  (assert (= 4 ((f2))))
 789  (assert (= 2 (s2)))
 790  (assert (= 1 v1))
 791  (assert (= 2 v2))
 792  (assert (= 3 v3))
 793  (assert (equal? (list 4) v4))
 794  (assert (equal? (list 5 6) v56))
 795  (assert (equal? (list 5 6) v56-again)))
 796
 797(assert (= 1 (s2)))
 798(assert (= 3 (f1)))
 799(assert (= 9 v1))
 800(assert (= 10 v2))
 801(assert (= 11 v3))
 802(assert (equal? (list 12) v4))
 803(assert (equal? (list 13) v56))
 804
 805;;; redefining definition forms (disabled, since we can not catch this error easily)
 806
 807#|
 808(module m0a () (import chicken.module) (reexport (only scheme define)))
 809(module m0b () (import chicken.module) (reexport (only scheme define-syntax)))
 810
 811(module m1 ()
 812(import (prefix scheme s:) (prefix m0b m:))
 813;(s:define m:define 1)
 814(s:define-syntax s:define-syntax (syntax-rules ()))
 815)
 816|#
 817
 818;;; Definitions of non-identifiers
 819
 820(f (eval '(define foo: 1)))
 821(f (eval '(define-syntax foo: (syntax-rules () ((_) 1)))))
 822(f (eval '(let foo: () 1)))
 823(f (eval '(let ((foo: 1)) 1)))
 824
 825
 826;;; Definitions in expression contexts are rejected (#1309)
 827
 828(f (eval '(+ 1 2 (begin (define x 3) x) 4)))
 829(f (eval '(+ 1 2 (begin (define-values (x y) (values 3 4)) x) 4)))
 830(f (eval '(display (define x 1))))
 831;; Some tests for nested but valid definition expressions:
 832(t 2 (eval '(begin (define x 1) 2)))
 833(t 2 (eval '(module _ () (import scheme) (define x 1) 2)))
 834(t 1 (eval '(let ()
 835	      (define-record-type foo (make-foo bar) foo? (bar foo-bar))
 836	      (foo-bar (make-foo 1)))))
 837
 838;; Nested begins inside definitions were not treated correctly
 839(t 3 (eval '(let () (begin 1 (begin 2 (define internal-def 3) internal-def)))))
 840;; Macros that expand to "define" should not cause a letrec barrier
 841(t 1 (eval '(let-syntax ((my-define (syntax-rules ()
 842				      ((_ var val) (define var val)))))
 843	      (let () (define (run-it) foo) (my-define foo 1) (run-it)))))
 844;; Begin should not cause a letrec barrier
 845(t 1 (eval '(let () (define (run-it) foo) (begin (define foo 1) (run-it)))))
 846(f (eval '(let () internal-def)))
 847
 848;;; renaming of keyword argument (#277)
 849
 850(define-syntax foo1
 851  (syntax-rules ()
 852    ((_ procname)
 853     (define (procname #!key (who "world"))
 854       (string-append "hello, " who)))))
 855
 856(foo1 bar)
 857
 858(assert (string=? "hello, XXX" (bar who: "XXX")))
 859
 860;;; DSSSL keyword arguments in various combinations with optional and rest args
 861;;; reported on IRC by R. Winkler
 862
 863(define (test-optional&rest x y #!optional z #!rest r)
 864  (list x y z r))
 865
 866(assert (equal? '(3 4 5 (6 7)) (test-optional&rest 3 4 5 6 7)))
 867
 868(define (test-optional&rest-cdrs x y #!optional z #!rest r)
 869  (list x y z (cdr (cdr r))))
 870
 871(assert (equal? '(3 4 5 ()) (test-optional&rest-cdrs 3 4 5 6 7)))
 872
 873(define (test-optional&key x y #!optional z #!key i (j 1))
 874  (list x y z i: i j: j))
 875
 876(assert (equal? '(3 4 5 i: 6 j: 7) (test-optional&key 3 4 5 i: 6 j: 7 8)))
 877;; Unfortunate but correct (missing optional arg)
 878(assert (equal? '(3 4 i: i: #f j: 1) (test-optional&key 3 4 i: 6 j: 7 8)))
 879
 880(define (test-key&rest x y #!rest r #!key i (j 1))
 881  (list x y i: i j: j r))
 882
 883(assert (equal? '(3 4 i: 5 j: 1 (i: 5 6 7)) (test-key&rest 3 4 i: 5 6 7)))
 884(assert (equal? '(3 4 i: 5 j: 6 (i: 5 j: 6 7 8))
 885                (test-key&rest 3 4 i: 5 j: 6 7 8)))
 886
 887(define (test-optional-key&rest x y #!optional z #!rest r #!key i (j 1))
 888  (list x y z i: i j: j r))
 889
 890(assert (equal? '(3 4 5 i: 6 j: 7 (i: 6 j: 7 8))
 891                (test-optional-key&rest 3 4 5 i: 6 j: 7 8)))
 892
 893;;; Miscellaneous DSSSL tests
 894
 895;; DSSSL annotations may each appear only once
 896(f (eval '(lambda (x #!optional o1 #!optional o2) 'foo)))
 897(f (eval '(lambda (x #!rest r1 #!rest r1) 'foo)))
 898(f (eval '(lambda (x #!key k1 #!key k2) 'foo)))
 899
 900;; DSSSL annotations must occur in order (optional, rest, key)
 901(f (eval '(lambda (x #!rest r1 #!optional o1) 'foo)))
 902(f (eval '(lambda (x #!key k1 #!optional o1) 'foo)))
 903(f (eval '(lambda (x #!key r1 #!rest k1) 'foo)))
 904
 905;; #!rest limited to 1 arg
 906(f (eval '(lambda (x #!rest r1 r2) 'foo)))
 907
 908;; list arguments invalid for required and rest parameters
 909(f (eval '(lambda ((x 0) #!rest r1) 'foo)))
 910(f (eval '(lambda (x #!rest (r1 0)) 'foo)))
 911
 912;; "optional" expansion should not rely on user imports (hygiene)
 913(t '(1 2)
 914   (eval '(module x ()
 915	    (import (only scheme lambda list))
 916	    ((lambda (x #!optional (y 0)) (list x y)) 1 2))))
 917
 918;; Dotted list syntax can be mixed in
 919(t '(1 2 3 4 (5 6))
 920   ((lambda (x y #!optional o1 o2 . r) (list x y o1 o2 r))
 921    1 2 3 4 5 6))
 922
 923;; More DSSSL hygiene issues, from #806
 924(module dsssl-extended-lambda-list-hygiene ()
 925  (import (prefix scheme s/))
 926  (s/define (foo #!optional bar #!rest qux #!key baz)
 927	    (s/list bar baz qux)))
 928
 929;;; import not seen, if explicitly exported and renamed:
 930
 931(module rfoo (rbar rbaz)
 932(import scheme)
 933
 934(define (rbaz x)
 935  (display x)
 936  (newline) )
 937
 938(define-syntax rbar
 939  (syntax-rules ()
 940    ((_ x) (rbaz x))))
 941
 942)
 943
 944(import (prefix rfoo f:))
 945(f:rbar 1)
 946
 947;;; SRFI-2 (and-let*)
 948
 949(t 1 (and-let* ((a 1)) a))
 950(f (eval '(and-let* ((a 1 2 3)) a)))
 951(t 2 (and-let* ((a 1) (b (+ a 1))) b))
 952(t 3 (and-let* (((or #f #t))) 3))
 953(f (eval '(and-let* ((or #f #t)) 1)))
 954(t 4 (and-let* ((c 4) ((equal? 4 c))) c))
 955(t #f (and-let* ((c 4) ((equal? 5 c))) (error "not reached")))
 956(t #f (and-let* (((= 4 5)) ((error "not reached 1"))) (error "not reached 2")))
 957(t 'foo (and-let* (((= 4 4)) (a 'foo)) a))
 958(t #f (and-let* ((a #f) ((error "not reached 1"))) (error "not reached 2")))
 959
 960(t  (and-let* () 1) 1)
 961(t  (and-let* () 1 2) 2)
 962(t  (and-let* () ) #t)
 963
 964(t (let ((x #f)) (and-let* (x))) #f)
 965(t (let ((x 1)) (and-let* (x))) 1)
 966(t (and-let* ((x #f)) ) #f)
 967(t (and-let* ((x 1)) ) 1)
 968(f (eval '(and-let* ( #f (x 1))) ))
 969(t (and-let* ( (#f) (x 1)) ) #f)
 970(f (eval '(and-let* (2 (x 1))) ))
 971(t (and-let* ( (2) (x 1)) ) 1)
 972(t (and-let* ( (x 1) (2)) ) 2)
 973(t (let ((x #f)) (and-let* (x) x)) #f)
 974(t (let ((x "")) (and-let* (x) x)) "")
 975(t (let ((x "")) (and-let* (x)  )) "")
 976(t (let ((x 1)) (and-let* (x) (+ x 1))) 2)
 977(t (let ((x #f)) (and-let* (x) (+ x 1))) #f)
 978(t (let ((x 1)) (and-let* (((positive? x))) (+ x 1))) 2)
 979(t (let ((x 1)) (and-let* (((positive? x))) )) #t)
 980(t (let ((x 0)) (and-let* (((positive? x))) (+ x 1))) #f)
 981(t (let ((x 1)) (and-let* (((positive? x)) (x (+ x 1))) (+ x 1)))  3)
 982; The uniqueness of the bindings isn't enforced
 983(t (let ((x 1)) (and-let* (((positive? x)) (x (+ x 1)) (x (+ x 1))) (+ x 1))) 4)
 984
 985(t (let ((x 1)) (and-let* (x ((positive? x))) (+ x 1))) 2)
 986(t (let ((x 1)) (and-let* ( ((begin x)) ((positive? x))) (+ x 1))) 2)
 987(t (let ((x 0)) (and-let* (x ((positive? x))) (+ x 1))) #f)
 988(t (let ((x #f)) (and-let* (x ((positive? x))) (+ x 1))) #f)
 989(t (let ((x #f)) (and-let* ( ((begin x)) ((positive? x))) (+ x 1))) #f)
 990
 991(t  (let ((x 1)) (and-let* (x (y (- x 1)) ((positive? y))) (/ x y))) #f)
 992(t  (let ((x 0)) (and-let* (x (y (- x 1)) ((positive? y))) (/ x y))) #f)
 993(t  (let ((x #f)) (and-let* (x (y (- x 1)) ((positive? y))) (/ x y))) #f)
 994(t  (let ((x 3)) (and-let* (x (y (- x 1)) ((positive? y))) (/ x y))) 3/2)
 995
 996;;; SRFI-26
 997
 998;; Cut
 999(t '() ((cut list)))
 1000(t '() ((cut list <...>)))
1001(t '(1) ((cut list 1)))
1002(t '(1) ((cut list <>) 1))
1003(t '(1) ((cut list <...>) 1))
1004(t '(1 2) ((cut list 1 2)))
1005(t '(1 2) ((cut list 1 <>) 2))
1006(t '(1 2) ((cut list 1 <...>) 2))
1007(t '(1 2 3 4) ((cut list 1 <...>) 2 3 4))
1008(t '(1 2 3 4) ((cut list 1 <> 3 <>) 2 4))
1009(t '(1 2 3 4 5 6) ((cut list 1 <> 3 <...>) 2 4 5 6))
1010(t '(ok) (let* ((x 'wrong)
1011                (y (cut list x)))
1012           (set! x 'ok)
1013           (y)))
1014(t 2 (let ((a 0))
1015       (map (cut + (begin (set! a (+ a 1)) a) <>)
1016            '(1 2))
1017       a))
1018(f (eval '((cut + <...> 1) 1)))
1019
1020;; Cute
1021(t '() ((cute list)))
1022(t '() ((cute list <...>)))
1023(t '(1) ((cute list 1)))
1024(t '(1) ((cute list <>) 1))
1025(t '(1) ((cute list <...>) 1))
1026(t '(1 2) ((cute list 1 2)))
1027(t '(1 2) ((cute list 1 <>) 2))
1028(t '(1 2) ((cute list 1 <...>) 2))
1029(t '(1 2 3 4) ((cute list 1 <...>) 2 3 4))
1030(t '(1 2 3 4) ((cute list 1 <> 3 <>) 2 4))
1031(t '(1 2 3 4 5 6) ((cute list 1 <> 3 <...>) 2 4 5 6))
1032(t 1 (let ((a 0))
1033       (map (cute + (begin (set! a (+ a 1)) a) <>)
1034            '(1 2))
1035       a))
1036(f (eval '((cute + <...> 1) 1)))
1037
1038;;; (quasi-)quotation
1039
1040(f (eval '(let ((a 1)) (unquote a))))
1041(t 'unquote (quasiquote unquote))
1042(f (eval '(quasiquote (a unquote . 1)))) ; "Bad syntax". Also ok: '(a unquote . 1)
1043(t 'a (quasiquote a))
1044(f (eval '(quasiquote a b)))
1045(f (eval '(quote a b)))
1046(f (eval '(quasiquote)))
1047(f (eval '(quote)))
1048(f (eval '(quasiquote . a)))
1049(f (eval '(quote . a)))
1050(t '(foo . 1) (let ((bar 1))
1051                (quasiquote (foo . (unquote bar)))))
1052(f (eval '(let ((a 1)
1053                (b 2))
1054            (quasiquote (unquote a b))))) ; > 1 arg
1055
1056(t '(quasiquote (unquote a)) (quasiquote (quasiquote (unquote a))))
1057(t '(quasiquote x y) (quasiquote (quasiquote x y)))
1058
1059(t '(unquote-splicing a) (quasiquote (unquote-splicing a)))
1060(t '(1 2) (let ((a (list 2))) (quasiquote (1 (unquote-splicing a)))))
1061(f (eval '(let ((a 1))                  ; a is not a list
1062            (quasiquote (1 (unquote-splicing a) 2)))))
1063(f (eval '(let ((a (list 1))
1064                (b (list 2)))
1065            (quasiquote (1 (unquote-splicing a b)))))) ; > 1 arg
1066
1067;; level counting
1068(define x (list 1 2))
1069
1070;; Testing R5RS-compliance:
1071(t '(quasiquote (unquote (1 2)))
1072   (quasiquote (quasiquote (unquote (unquote x)))))
1073(t '(quasiquote (unquote-splicing (1 2)))
1074   (quasiquote (quasiquote (unquote-splicing (unquote x)))))
1075(t '(quasiquote (unquote 1 2))
1076   (quasiquote (quasiquote (unquote (unquote-splicing x)))))
1077(t 'x
1078   (quasiquote (unquote (quasiquote x))))
1079(t '(quasiquote (unquote-splicing (quasiquote (unquote x))))
1080   (quasiquote (quasiquote (unquote-splicing (quasiquote (unquote x))))))
1081(t '(quasiquote (unquote (quasiquote (unquote-splicing x))))
1082   (quasiquote (quasiquote (unquote (quasiquote (unquote-splicing x))))))
1083(t '(quasiquote (unquote (quasiquote (unquote (1 2)))))
1084   (quasiquote (quasiquote (unquote (quasiquote (unquote (unquote x)))))))
1085
1086;; The following are explicitly left undefined by R5RS. For consistency
1087;; we define any unquote-(splicing) or quasiquote that occurs in the CAR of
1088;; a pair to decrease, respectively increase the level count by one.
1089
1090(t '(quasiquote . #(1 (unquote x) 3))   ; cdr is not a pair
1091   (quasiquote (quasiquote . #(1 (unquote x) 3))))
1092(t '(quasiquote #(1 (unquote x) 3))     ; cdr is a list of one
1093   (quasiquote (quasiquote #(1 (unquote x) 3))))
1094(t '(quasiquote a #(1 (unquote x) 3) b) ; cdr is longer
1095   (quasiquote (quasiquote a #(1 (unquote x) 3) b)))
1096
1097(t '(quasiquote (unquote . #(1 (1 2) 3))) ; cdr is not a pair
1098   (quasiquote (quasiquote (unquote . #(1 (unquote x) 3)))))
1099(t '(quasiquote (unquote #(1 (1 2) 3))) ; cdr is a list of one
1100   (quasiquote (quasiquote (unquote #(1 (unquote x) 3)))))
1101(t '(quasiquote (unquote a #(1 (1 2) 3) b)) ; cdr is longer
1102   (quasiquote (quasiquote (unquote a #(1 (unquote x) 3) b))))
1103
1104(t '(quasiquote (unquote-splicing . #(1 (1 2) 3))) ; cdr is not a pair
1105   (quasiquote (quasiquote (unquote-splicing . #(1 (unquote x) 3)))))
1106(t '(quasiquote (unquote-splicing #(1 (1 2) 3))) ; cdr is a list of one
1107   (quasiquote (quasiquote (unquote-splicing #(1 (unquote x) 3)))))
1108(t '(quasiquote (unquote-splicing a #(1 (1 2) 3) b)) ; cdr is longer
1109   (quasiquote (quasiquote (unquote-splicing a #(1 (unquote x) 3) b))))
1110
1111(t 'quasiquote (quasiquote quasiquote))
1112(t 'unquote (quasiquote unquote))
1113(t 'unquote-splicing (quasiquote unquote-splicing))
1114(t '(x quasiquote) (quasiquote (x quasiquote)))
1115; (quasiquote (x unquote)) is identical to (quasiquote (x . (unquote)))....
1116;; It's either this (error) or make all calls to unquote with more or less
1117;; than one argument resolve to a literal unquote.
1118(f (eval '(quasiquote (x unquote))))
1119(t '(x unquote-splicing) (quasiquote (x unquote-splicing)))
1120;; Let's internal defines properly compared to core define procedure when renamed
1121(f (eval '(let-syntax ((foo (syntax-rules () ((_ x) (begin (define x 1))))))
1122            (let () (foo a))
1123            (print "1: " a))))
1124
1125(t '(a 1) (letrec-syntax ((define (syntax-rules () ((_ x y) (list 'x y))))
1126                          (foo (syntax-rules () ((_ x) (define x 1)))))
1127            (let () (foo a))))
1128
1129(t '(1) (let-syntax ((define (syntax-rules () ((_ x) (list x)))))
1130          (let () (define 1))))
1131
1132;; Local override: not a macro
1133(t '(1) (let ((define list)) (define 1)))
1134
1135;; Toplevel (no SE)
1136(define-syntax foo (syntax-rules () ((_ x) (begin (define x 1)))))
1137(foo a)
1138(t 1 a)
1139
1140
1141;; ,@ in tail pos with circular object - found in trav2 benchmark and
1142;; reported by syn:
1143
1144(let ((a '(1)))
1145  (set-cdr! a a)
1146  `(1 ,@a))
1147
1148
1149;; ##sys#alias-global-hook, when invoked via eval/meta, did resolve identifiers
1150;; used during evaluation of an expander body in the wrong environment and mapped
1151;; an identifier to something imported for the runtime environment
1152
1153(module foonumbers (+)
1154  (import (except scheme +) (only (chicken base) error))
1155  (define (+ . _) (error "failed.")))
1156
1157(import foonumbers)
1158
1159(define-syntax foo
1160  (er-macro-transformer
1161   (lambda (x r c)
1162     `(print ,(+ (cadr x) 1)))))
1163
1164(foo 3)
1165
1166
1167;; #578: import with specifier has no effect for internal modules on csi's top-level
1168
1169(import srfi-4)
1170(import (prefix srfi-4 other-))
1171u8vector
1172other-u8vector
1173
1174(import (prefix scheme other-))
1175eval
1176other-eval
1177
1178
1179;; #805: case-lambda is unhygienic (see 4706afb4 and bc5cc698)
1180(module case-lambda-and-ensure-hygiene ()
1181  (import (prefix (scheme case-lambda) c/) (prefix scheme s/))
1182  (c/case-lambda ((a) a)))
1183
1184
1185;; #816: compiler-syntax should obey hygiene in its rewrites
1186(module foo ()
1187  (import (prefix (only scheme map lambda list) ~))
1188  (~map (~lambda (y) y) (~list 1)))
1189
1190;; #852: renamed macros should not be returned as first-class
1191;;       objects in the interpreter
1192(module renamed-macros (renamed-macro-not-firstclassed)
1193  (import scheme chicken.base)
1194  (define-syntax renamed-macro-not-firstclassed
1195    (er-macro-transformer
1196     (lambda (e r c)
1197       `(,(r 'list) ,(r 'define))))))
1198
1199(f (eval '(begin (import renamed-macros) (renamed-macro-not-firstclassed))))
1200
1201;; #893: implicitly renamed variables shouldn't be resolved to core
1202;;       builtins (#%xyz), but go through a level of indirection, so
1203;;       strip-syntax can still access the original symbol.
1204(module rename-builtins
1205 (strip-syntax-on-*)
1206 (import scheme chicken.base)
1207 (define-syntax strip-syntax-on-*
1208   (ir-macro-transformer
1209    (lambda (e r c) '(quote *)))))
1210
1211(import rename-builtins)
1212(assert (eq? '* (strip-syntax-on-*)))
1213
1214;; #1362: Double rename would cause "renamed" var to be restored to
1215;; the original macro aliased name (resulting in a plain symbol)
1216(let-syntax ((wrapper/should-do-nothing
1217              (er-macro-transformer
1218               (lambda (e r c)
1219                 (let* ((%x (r 'x))
1220                        (%%x (r %x)))
1221                   `(let ((,%x 1)
1222                          (,%%x 2))
1223                      ,(cadr e)))))))
1224  (print (let ((x 1)) (wrapper/should-do-nothing x))))
1225
1226;; Same net effect as above, but more complex by the use of IR macros.
1227(letrec-syntax ((bind-pair
1228                 (ir-macro-transformer
1229                  (lambda (e i c)
1230                    (let* ((b (cadr e))
1231                           (exp (caddr e))
1232                           (body (cdddr e)))
1233                      `(let* ((x ,exp)
1234                              (,(car b) (car x))
1235                              (,(cadr b) (cdr x)))
1236                         ,@body)))))
1237                (foo
1238                 (ir-macro-transformer
1239                  (lambda (e i c)
1240                    `(bind-pair (x y) (cons 'foo-car 'foo-cdr) y)))))
1241  (assert (eq? 'second (bind-pair (x y) (cons 'first 'second) y)))
1242  (assert (eq? 'foo-cdr (foo))))
1243
1244;; #944: macro-renamed defines mismatch with the names recorded in module
1245;;       definitions, causing the module to be unresolvable.
1246
1247(module foo ()
1248  (import scheme)
1249  (define-syntax bar
1250    (syntax-rules ()
1251      ((_) (begin (define req 1) (display req) (newline)))))
1252  (bar))
1253
1254;; The fix for the above bug causes the req to be defined at toplevel,
1255;; unhygienically.  The test below should probably be enabled and this
1256;; behavior fixed.  R5RS seems to allow the current behavior though (?),
1257;; and some Schemes (at least Gauche) behave the same way.  I think it's
1258;; broken, since it's unhygienic.
1259#;(module foo ()
1260  (import scheme)
1261  (define req 1)
1262  (define-syntax bar
1263    (syntax-rules ()
1264      ((_) (begin (define req 2) (display req) (newline)))))
1265  (bar)
1266  (assert (eq? req 1)))
1267
1268
1269;; Includes should be spliced into the surrounding body context:
1270
1271(begin-for-syntax
1272  (with-output-to-file "x.out" (cut pp '(define x 2))))
1273
1274(let ()
1275  (define x 1)
1276  (include "x.out")
1277  (t 2 x))
1278
1279(let ()
1280  (define x 1)
1281  (let ()
1282    (include "x.out"))
1283  (t 1 x))
1284
1285;; letrec vs. letrec*
1286
1287;;XXX this fails - the optimizer substitutes "foo" for it's known constant value
1288#;(t (void) (letrec ((foo 1)
1289		   (bar foo))
1290	    bar))
1291
1292;; Obscure letrec issue #1068
1293(t 1 (letrec ((foo (lambda () 1))
1294	      (bar (let ((tmp (lambda (x) (if x (foo) (bar #t)))))
1295		     tmp)))
1296       (bar #f)))
1297
1298;; Deeper issue uncovered by fixing the above issue
1299(t 1 (letrec ((bar (lambda (x) (if x 1 (bar bar)))))
1300       (bar #f)))
1301
1302;; Just to verify (this has always worked)
1303(t 1 (letrec* ((foo (lambda () 1))
1304	       (bar (let ((tmp (lambda (x) (if x (foo) (bar #t)))))
1305		      tmp)))
1306       (bar #f)))
1307
1308(t 1 (letrec* ((foo 1)
1309	       (bar foo))
1310       bar))
1311
1312
1313;; This would crash in nasty ways (see #1493, reported by megane)
1314(module self-redefinition (foo)
1315  (import scheme (chicken base))
1316
1317  (define-syntax foo
1318    (ir-macro-transformer
1319     (lambda (e i c)
1320       (apply
1321	(lambda (name)
1322	  `(begin
1323	     (define-syntax ,(strip-syntax name)
1324	       (syntax-rules () ((_ . _) 'new)))
1325	     'old))
1326	(cdr e))))))
1327
1328(import (rename self-redefinition (foo imported-foo)))
1329(import (rename self-redefinition (foo reimported-foo)))
1330
1331(t 'old (imported-foo imported-foo))
1332(t 'new (imported-foo imported-foo))
1333
1334;; Like any normal redefinition, the underlying exported identifier
1335;; changes, and any other imports are simply aliases.
1336;;(t 'old (reimported-foo reimported-foo))
1337(t 'new (reimported-foo reimported-foo))
1338
1339;; #1166
1340(module val-vs-syn1 *
1341  (import scheme)
1342  (define-syntax bar (syntax-rules () ((_) 'bar)))
1343  (define (bar) 99)
1344)
1345
1346(module test-val-vs-syn1 ()
1347   (import scheme (chicken base) val-vs-syn1)
1348   (assert (eq? 99 (bar))))
1349
1350(module val-vs-syn2 *
1351  (import scheme)
1352  (define (bar) 99)
1353  (define-syntax bar (syntax-rules () ((_) 'bar)))
1354)
1355
1356(module test-val-vs-syn2 ()
1357   (import scheme (chicken base) val-vs-syn2)
1358   (assert (eq? 'bar (bar))))
1359
1360(define begin -)
1361(assert (eq? -1 (begin 0 1)))
1362
1363;; #1736 - dotted pairs after ellipsis
1364
1365(define-syntax match-ellipsis-and-dotted-tail1
1366  (syntax-rules ()
1367    ((_ a ... . b)
1368     '(a ... b))))
1369
1370(t '(x y z) (match-ellipsis-and-dotted-tail1 x y . z))
1371
1372(define-syntax match-ellipsis-and-dotted-tail2
1373  (syntax-rules ()
1374    ((_ (a) ... . (b))
1375     '(a ... b))))
1376
1377(t '(x y z) (match-ellipsis-and-dotted-tail2 (x) (y) z))
1378
1379;; from SRFI-46 document:
1380(define-syntax fake-begin
1381  (syntax-rules ()
1382    ((fake-begin ?body ... ?tail)
1383     (let* ((ignored ?body) ...) ?tail))))
1384
1385(t 3 (fake-begin 1 2 3))
1386
1387;; #1793
1388
1389(let ([x 'outer])
1390   (define-syntax m
1391     (syntax-rules ()
1392       ((m a)
1393        (let ([a 'inner]) x))))
1394   (t 'outer (m x)))
1395
1396; fails with error when compiled ("toplevel def. in non-toplevel context")
1397#;(let ([x 'outer])
1398   (define-syntax m
1399     (syntax-rules ()
1400       ((m a)
1401        (begin
1402          (define a 'inner)
1403          x))))
1404   (m x)
1405   (t 'inner x))
Trap