racket/collects/tests/mzscheme/stx.ss
2009-12-06 05:15:20 +00:00

1441 lines
50 KiB
Scheme

(load-relative "loadtest.ss")
(Section 'stx)
(test #t syntax? (datum->syntax #f 'hello #f))
(test #f syntax-line (datum->syntax #f 10 '(aha #f #f 19 #f)))
(test #f syntax-column (datum->syntax #f 10 '(aha #f #f 19 #f)))
(test 19 syntax-position (datum->syntax #f 10 '(aha #f #f 19 #f)))
(test 'aha syntax-source (datum->syntax #f 10 '(aha #f #f 19 #f)))
(test #f syntax-span (datum->syntax #f 10 '(aha #f #f 19 #f)))
(test 88 syntax-span (datum->syntax #f 10 '(aha #f #f 19 88)))
(test 7 syntax-line (datum->syntax #f 10 '(aha 7 88 999 #f)))
(test 88 syntax-column (datum->syntax #f 10 '(aha 7 88 999 #f)))
(test 999 syntax-position (datum->syntax #f 10 '(aha 7 88 999 #f)))
(test 'aha syntax-source (datum->syntax #f 10 '(aha 7 88 999 #f)))
(test #f syntax-span (datum->syntax #f 10 '(aha 7 88 999 #f)))
(test 22 syntax-span (datum->syntax #f 10 '(aha 7 88 999 22)))
(test 0 syntax-span (datum->syntax #f 10 '(aha 1 1 1 0)))
(test 0 syntax-column (datum->syntax #f 10 '(aha 1 0 1 0)))
(err/rt-test (datum->syntax #f 10 10))
(err/rt-test (datum->syntax #f 10 '(10)))
(err/rt-test (datum->syntax #f 10 '(10 11)))
(err/rt-test (datum->syntax #f 10 '(10 11 12)))
(err/rt-test (datum->syntax #f 10 '(10 11 12 13)))
(err/rt-test (datum->syntax #f 10 '(10 11 12 13 14 15)))
(err/rt-test (datum->syntax #f 10 '(a 11.0 12 13 14)))
(err/rt-test (datum->syntax #f 10 '(a 11 12 -13 14)))
(err/rt-test (datum->syntax #f 10 '(a 11 12 -13 14)))
(err/rt-test (datum->syntax #f 10 '(a 11 12 13 -1)))
(err/rt-test (datum->syntax #f 10 '(a 0 12 13 0)))
(err/rt-test (datum->syntax #f 10 '(a 11 -1 13 0)))
(err/rt-test (datum->syntax #f 10 '(a 11 12 0 0)))
(syntax-test #'quote-syntax)
(syntax-test #'(quote-syntax))
(syntax-test #'(quote-syntax . 7))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; some syntax-case patterns
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(test 17 'syntax-case (syntax-case '(1 1 1) () [(1 ...) 17]))
(define-syntax sd (syntax-rules () [(_ v) (syntax->datum (syntax v))]))
(test '(3 1 2) 'syntax-case (syntax-case '(1 2 3) () [(a ... b) (sd (b a ...))]))
(test '(3 1 2) 'syntax-case (syntax-case '(1 2 3) () [(a ... b . c) (sd (b a ...))]))
(test '(3 1 2) 'syntax-case (syntax-case '(1 2 3) () [(a ... 3 . c) (sd (3 a ...))]))
(test 5 'syntax-case (syntax-case '(1 2 3 4) () [(a ... 3 . c) (sd (3 a ... c))][_else 5]))
(test '(3 1 2 4) 'syntax-case (syntax-case '(1 2 3 . 4) () [(a ... b . c) (sd (b a ... c))][_else 5]))
(test '(3 1 2 4) 'syntax-case (syntax-case '(1 2 (3 . 4)) () [(a ... (b . c)) (sd (b a ... c))][_else 5]))
(test '((3) 1 2 4) 'syntax-case (syntax-case '(1 2 (3 . 4)) () [(a ... (b ... . c)) (sd ((b ...) a ... c))][_else 5]))
(test '(3 1 2 4) 'syntax-case (syntax-case '(1 2 (3 . 4)) () [(a ... (b ... . c)) (sd (b ... a ... c))][_else 5]))
(test '((3) 1 2 4) 'syntax-case (syntax-case '(1 2 ((3) . 4)) () [(a ... ((b ...) ... . c)) (sd ((b ...) ... a ... c))][_else 5]))
(test '(3 1 2 4) 'syntax-case (syntax-case '(1 2 ((3) . 4)) () [(a ... ((b ...) ... . c)) (sd (b ... ... a ... c))][_else 5]))
(syntax-test (quote-syntax (syntax-case 0 () [(a ... b c ...) 1][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [(a ... b . (c ...)) 1][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [(a ... ...) 1][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [(a ...) #'a][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [(a ...) #'((a ...) ...)][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [(a ...) #'(a ... ...)][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [((a ...) ...) #'a][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [((a ...) ...) #'(a ...)][_else 5])))
(syntax-test (quote-syntax (syntax-case 0 () [((a ...) ...) #'(a ... ... ...)][_else 5])))
(test 'no 'dot-literal (syntax-case #'(1 2) () [(_ . #t) 'yes] [_ 'no]))
(test 'yes 'dot-literal (syntax-case #'(1 . #t) () [(_ . #t) 'yes] [_ 'no]))
(test '(((x 3) (y 3) (z 3)) ;; each line should be x y z, not x x x...
((x 4) (y 4) (z 4))
((x 5) (y 5) (z 5)))
'ellipses
(syntax->datum (syntax-case '(_ 1 (x y z) ((3 3 3) (4 4 4) (5 5 5))) ()
[(_ x (a ...) ((b ...) ...)) #'(((a b) ...) ...)])))
(test '(((x y z 3) (x y z 3) (x y z 3))
((x y z 4) (x y z 4) (x y z 4))
((x y z 5) (x y z 5) (x y z 5)))
'ellipses
(syntax->datum (syntax-case '(_ 1 (x y z) ((3 3 3) (4 4 4) (5 5 5))) ()
[(_ x (a ...) ((b ...) ...)) #'(((a ... b) ...) ...)])))
(test '((1 z) (2 w) (x z) (y w))
'ellipses
(syntax->datum (syntax-case '(((1 2) (x y)) (z w)) ()
[(((a ...) ...) (b ...)) #'((a b) ... ...)])))
(test '(#(1) #(2 3))
'ellipses+vector
(syntax->datum
(syntax-case '((1) (2 3)) ()
[((a ...) ...) #'(#(a ...) ...)])))
(test '(1 2 3 6 8 9 0 1 2 3)
syntax->datum
(syntax-case '(((1) (2 3)) ((6)) ((8 9 0) (1 2 3))) ()
[(((a ...) ...) ...) #'(a ... ... ...)]))
(test '((1 2 3) (6) (8 9 0 1 2 3))
syntax->datum
(syntax-case '(((1) (2 3)) ((6)) ((8 9 0) (1 2 3))) ()
[(((a ...) ...) ...) #'((a ... ...) ...)]))
(test '((1) (2 3) (6) (8 9 0) (1 2 3))
syntax->datum
(syntax-case '(((1) (2 3)) ((6)) ((8 9 0) (1 2 3))) ()
[(((a ...) ...) ...) #'((a ...) ... ...)]))
(test (syntax-case #'((([n 1] [m 2]) ([p 10] [q 20]))
(([nn -1] [mm -2]) ([pp -10] [qq -20]))) ()
[((([x y] ...) ...) ...)
(syntax->datum #'(ell ((ull (+ x ...)
((- x ... y ...) ...))
...)
...))])
'fancy-ellipses
'(ell ((ull (+ n m) ((- n m 1 2) (- p q 10 20)))
(ull (+ p q) ((- nn mm -1 -2) (- pp qq -10 -20))))
((ull (+ nn mm) ((- n m 1 2) (- p q 10 20)))
(ull (+ pp qq) ((- nn mm -1 -2) (- pp qq -10 -20))))))
(test (syntax-case #'((([n 1] [m 2]) ([p 10] [q 20]))
(([nn -1] [mm -2]) ([pp -10] [qq -20]))) ()
[((([x y] ...) ...) ...)
(syntax->datum #'(ell ((ull (+ x ...)
((- x ...) ...))
...)
...))])
'fancy-ellipses
'(ell ((ull (+ n m) ((- n m) (- p q)))
(ull (+ p q) ((- nn mm) (- pp qq))))
((ull (+ nn mm) ((- n m) (- p q)))
(ull (+ pp qq) ((- nn mm) (- pp qq))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test basic expansion and property propagation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (tree-map f)
(lambda (l)
(if (pair? l)
(cons ((tree-map f) (car l))
((tree-map f) (cdr l)))
(if (null? l)
null
(f l)))))
(define-syntax mcr
(lambda (stx)
(syntax-case stx ()
[(_ x) (syntax (begin x))])))
(define s (quote-syntax (mcr 5)))
(define se (expand-once s))
(syntax-case se ()
[(bg five)
(let ([bg (syntax bg)]
[five (syntax five)])
(test 'begin syntax-e bg)
(test 5 syntax-e five)
(test #t syntax-original? five)
(test #f syntax-original? bg)
'ok)])
(test #f syntax-property s 'testing)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Plain s, se derived from part of s
(define s (syntax-property (quote-syntax (mcr 5)) 'testing 10))
(define se (expand-once s))
(test 10 syntax-property s 'testing)
(test 10 syntax-property se 'testing)
(test '(mcr) (tree-map syntax-e) (syntax-property se 'origin))
(test 10 syntax-property (datum->syntax #f 0 #f s) 'testing)
(test #t syntax-original? s)
(test #f syntax-original? se)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Plain s, se is part of s
(define-syntax mcr2
(lambda (stx)
(syntax-case stx ()
[(_ x) (syntax x)])))
(define s (syntax-property (quote-syntax (mcr2 5)) 'testing 10))
(define se (expand-once s))
(test (syntax-e (cadr (syntax-e s))) syntax-e se)
(test 10 syntax-property s 'testing)
(test 10 syntax-property se 'testing)
(test '(mcr2) (tree-map syntax-e) (syntax-property se 'origin))
(test #t syntax-original? s)
(test #t syntax-original? se)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constructed s, se is part of s, part of s tagged
(define s
(syntax-property
(with-syntax ([five (syntax-property (quote-syntax 5) 'testing 12)])
(syntax (mcr2 five)))
'testing 10))
(define se (expand-once s))
(test (syntax-e (cadr (syntax-e s))) syntax-e se)
(test 10 syntax-property s 'testing)
(test '(12 . 10) syntax-property se 'testing)
(test '(mcr2) (tree-map syntax-e) (syntax-property se 'origin))
(test #f syntax-original? s)
(test #t syntax-original? se)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; paren-shape:
(let ([s (with-syntax ([a (quote-syntax [x y])])
#'[a 10])])
(test #f syntax-property #'(x) 'paren-shape)
(test #\[ syntax-property #'[x] 'paren-shape)
(test #\[ syntax-property s 'paren-shape)
(test #\[ syntax-property (syntax-case s () [(b _) #'b]) 'paren-shape))
(let ([s (with-syntax ([(a ...) '(1 2 3)])
#'[a ...])])
(test #\[ syntax-property s 'paren-shape))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Two-step macro chain
(define-syntax mcr5
(lambda (stx)
(syntax-case stx ()
[(_ x) (syntax x)])))
(define s (quote-syntax (mcr5 (mcr2 5))))
(define se (expand-once (expand-once s)))
(test (syntax-e (cadr (syntax-e (cadr (syntax-e s))))) syntax-e se)
(test '(mcr2 mcr5)
(tree-map syntax-e)
(syntax-property se 'origin))
(test #t syntax-original? s)
(test #t syntax-original? se)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Two-step macro chain with expansion
(define-syntax mcr7
(lambda (stx)
(syntax-case stx ()
[(_ x) (local-expand (syntax x) '(internal-define) (list (quote-syntax #%datum)))])))
(define s (quote-syntax (mcr7 (mcr2 5))))
(define se (expand-once s))
(test (syntax-e (cadr (syntax-e (cadr (syntax-e s))))) syntax-e se)
(test '((mcr2) mcr7)
(tree-map syntax-e)
(syntax-property se 'origin))
(test #t syntax-original? s)
(test #t syntax-original? se)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Three-step macro chain, with one expansion
(define s (quote-syntax (mcr5 (mcr7 (mcr2 5)))))
(define se (expand-once (expand-once s)))
(test '((mcr2) mcr7 mcr5)
(tree-map syntax-e)
(syntax-property se 'origin))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Three-step macro chain, with other expansion
(define s (quote-syntax (mcr7 (mcr5 (mcr2 5)))))
(define se (expand-once s))
(test '((mcr2 mcr5) mcr7)
(tree-map syntax-e)
(syntax-property se 'origin))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; #%app, etc.
(define s (syntax-property (quote-syntax (add1 5)) 'testing 10))
(test 10 syntax-property (expand s) 'testing)
(define s (syntax-property (quote-syntax 5) 'testing 10))
(test 10 syntax-property (expand s) 'testing)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check tracking of (formerly) primitive expanders
(test '(let) (tree-map syntax-e) (syntax-property (expand #'(let ([x 10]) x)) 'origin))
(test '(let*-values let*) (tree-map syntax-e) (syntax-property (expand #'(let* ([x 10]) x)) 'origin))
(test '(let) (tree-map syntax-e) (syntax-property (expand #'(let loop ([x 10]) x)) 'origin))
(test '(letrec) (tree-map syntax-e) (syntax-property (expand #'(letrec ([x 10]) x)) 'origin))
(test '(let*-values) (tree-map syntax-e) (syntax-property (expand #'(let*-values ([(x) 10]) x)) 'origin))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Symbol Keys
(test null syntax-property-symbol-keys #'a)
(let ([ssort (lambda (l)
(if (equal? l '(yep aha))
'(aha yep)
l))])
(test '(aha) syntax-property-symbol-keys (syntax-property #'a 'aha 1))
(test '(aha yep) ssort (syntax-property-symbol-keys (syntax-property (syntax-property #'a 'aha 1) 'yep 2)))
(test '(aha yep) ssort (syntax-property-symbol-keys
(syntax-property
(syntax-property
(syntax-property #'a 'aha 1)
'yep 2)
'aha 3))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test free-identifier=? on different phases via syntax-case*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module mta scheme/base
(define mtax 10)
(provide mtax))
(module mtb scheme/base
(define mtby 10)
(provide mtby))
(module mt1 scheme/base
(require (prefix-in a: 'mta))
(require (for-syntax (prefix-in b: 'mtb)
scheme/base))
(require (prefix-in mz: scheme/base))
(define-syntax ck
(lambda (stx)
(syntax-case stx ()
[(_ id et?)
(with-syntax ([cmp (if (syntax-e (syntax et?))
(syntax free-transformer-identifier=?)
(syntax free-identifier=?))])
(syntax
(lambda (x)
(syntax-case* x (id) cmp
[(_ id) #t]
[else #f]))))])))
(define has-lam? (ck case-lambda #f))
(define has-mz:lam? (ck mz:case-lambda #f))
(define has-mtax? (ck a:mtax #f))
(define has-mtby? (ck b:mtby #f))
(define has-et-lam? (ck case-lambda #t))
(define has-et-mz:lam? (ck mz:case-lambda #t))
(define has-et-mtax? (ck a:mtax #t))
(define has-et-mtby? (ck b:mtby #t))
(provide has-lam? has-mz:lam? has-mtax? has-mtby?
has-et-lam? has-et-mz:lam? has-et-mtax? has-et-mtby?))
(require 'mt1)
(require (for-syntax 'mtb))
(test #t has-lam? #'(any case-lambda))
(test #f has-lam? #'(any case-lambada))
(test #t has-et-lam? #'(any case-lambda))
(test #f has-et-lam? #'(any case-lambada))
;; mz: prefix is there in normal environment:
(test #t has-mz:lam? #'(any case-lambda))
(test #f has-et-mz:lam? #'(any case-lambda))
(test #f has-mz:lam? #'(any mz:case-lambda))
(test #t has-et-mz:lam? #'(any mz:case-lambda))
;; No mtax anywhere:
(test #f has-mtax? #'(any mtax))
(test #f has-mtax? #'(any a:mtax))
(test #f has-et-mtax? #'(any mtax))
(test #t has-et-mtax? #'(any a:mtax))
;; mtby (without prefix) in trans env
(test #f has-mtby? #'(any mtby))
(test #t has-mtby? #'(any b:mtby))
(test #t has-et-mtby? #'(any mtby))
(test #f has-et-mtby? #'(any b:mtby))
(module mt2 '#%kernel
(#%require (for-syntax '#%kernel))
(#%require 'mt1)
(#%require 'mta)
;; For #':
(define-syntaxes (syntax)
(lambda (stx)
(datum->syntax
stx
(cons
(quote-syntax quote-syntax)
(cdr (syntax-e stx)))
stx)))
(define-values (run-mt2-test)
(lambda (test)
(test #t has-lam? #'(any case-lambda))
(test #f has-lam? #'(any case-lambada))
(test #t has-et-lam? #'(any case-lambda))
(test #f has-et-lam? #'(any case-lambada))
;; mz: prefix is there in normal environment:
(test #t has-mz:lam? #'(any case-lambda))
(test #f has-et-mz:lam? #'(any case-lambda))
(test #f has-mz:lam? #'(any mz:case-lambda))
(test #t has-et-mz:lam? #'(any mz:case-lambda))
;; mtax in both places normal env:
(test #t has-mtax? #'(any mtax))
(test #f has-mtax? #'(any a:mtax))
(test #f has-et-mtax? #'(any mtax))
(test #t has-et-mtax? #'(any a:mtax))
;; no mtby here
(test #f has-mtby? #'(any mtby))
(test #t has-mtby? #'(any b:mtby))
(test #f has-et-mtby? #'(any mtby))
(test #f has-et-mtby? #'(any b:mtby))))
(#%provide run-mt2-test))
(require 'mt2)
(run-mt2-test test)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(test '(1 2 3) syntax->datum (syntax (1 2 3)))
(test '(1 ... 2 3) syntax->datum (syntax (... (1 ... 2 3))))
(syntax-test #'(syntax (a (... ...))))
(syntax-test #'(syntax (... ...)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; identifier-binding
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (identifier-binding* s)
(let ([b (identifier-binding s)])
(if (list? b)
(list* (let-values ([(name base) (module-path-index-split (car b))])
(fprintf (current-error-port) ">>>>base = ~s\n" base)
name)
(cadr b)
(let-values ([(name base) (module-path-index-split (caddr b))])
name)
(cdddr b))
b)))
(test '('#%kernel case-lambda (lib "scheme/init") case-lambda 0 0 0)
identifier-binding* #'case-lambda)
(test '("private/promise.ss" delay* (lib "scheme/init") delay 0 0 0)
identifier-binding* #'delay)
(test '('#%kernel #%module-begin (lib "scheme/init") #%plain-module-begin 0 0 0)
identifier-binding* #'#%plain-module-begin)
(require (only-in scheme/base [#%plain-module-begin #%pmb]))
(test '('#%kernel #%module-begin scheme/base #%plain-module-begin 0 0 0)
identifier-binding* #'#%pmb)
(let ([b (identifier-binding
(syntax-case (expand #'(module m scheme/base
(require (only-in (lib "lang/htdp-intermediate.ss") [cons bcons]))
bcons)) ()
[(mod m mz (#%mod-beg req (app call-with-values (lambda () cons) print)))
(let ([s (syntax cons)])
(test 'bcons syntax-e s)
s)]))])
(let-values ([(real real-base) (module-path-index-split (car b))]
[(nominal nominal-base) (module-path-index-split (caddr b))])
(test '"teachprims.ss" values real)
(test 'beginner-cons cadr b)
(test '(lib "lang/htdp-intermediate.ss") values nominal)
(test 'cons cadddr b)))
(let ([b (identifier-binding
(syntax-case (expand #'(module m (lib "lang/htdp-intermediate.ss")
cons)) ()
[(mod m beg (#%mod-beg (app call-w-vals (lam () cons) prnt)))
(let ([s (syntax cons)])
(test 'cons syntax-e s)
s)]))])
(let-values ([(real real-base) (module-path-index-split (car b))]
[(nominal nominal-base) (module-path-index-split (caddr b))])
(test '"teachprims.ss" values real)
(test 'beginner-cons cadr b)
(test '(lib "lang/htdp-intermediate.ss") values nominal)
(test 'cons cadddr b)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; eval versus eval-syntax, etc.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless building-flat-tests?
(test eval eval 'eval)
(test eval eval eval)
(test eval eval #'eval)
(test eval eval (datum->syntax #f 'eval))
(err/rt-test (eval-syntax 'eval))
(err/rt-test (eval-syntax eval))
(test eval eval-syntax #'eval)
(test #t
'eval-syntax
(with-handlers ([exn:fail:syntax? (lambda (x) #t)])
(eval-syntax (datum->syntax #f 'eval))))
(test eval (current-eval) 'eval)
(test eval (current-eval) eval)
(test eval (current-eval) #'eval)
(test #t
'current-eval-syntax
(with-handlers ([exn:fail:syntax? (lambda (x) #t)])
((current-eval) (datum->syntax #f 'eval))))
(test eval 'compile (eval (compile 'eval)))
(test eval 'compile (eval (compile eval)))
(test eval 'compile (eval (compile #'eval)))
(test eval 'compile (eval (compile (datum->syntax #f 'eval))))
(err/rt-test (compile-syntax 'eval))
(err/rt-test (compile-syntax eval))
(test eval 'compile (eval (compile-syntax #'eval)))
(test #t
'compile-syntax
(with-handlers ([exn:fail:syntax? (lambda (x) #t)])
(compile-syntax (datum->syntax #f 'eval))))
(test eval 'expand (eval (expand 'eval)))
(test eval 'expand (eval (expand eval)))
(test eval 'expand (eval (expand #'eval)))
(test eval 'expand (eval (expand (datum->syntax #f 'eval))))
(err/rt-test (expand-syntax 'eval))
(err/rt-test (expand-syntax eval))
(test eval 'expand (eval (expand-syntax #'eval)))
(test #t
'expand-syntax
(with-handlers ([exn:fail:syntax? (lambda (x) #t)])
(expand-syntax (datum->syntax #f 'eval))))
(test eval 'expand-once (eval (expand-once 'eval)))
(test eval 'expand-once (eval (expand-once eval)))
(test eval 'expand-once (eval (expand-once #'eval)))
(test eval 'expand-once (eval (expand-once (datum->syntax #f 'eval))))
(err/rt-test (expand-syntax-once 'eval))
(err/rt-test (expand-syntax-once eval))
(test eval 'expand-once (eval (expand-syntax-once #'eval)))
(test #t
'expand-syntax-once
(with-handlers ([exn:fail:syntax? (lambda (x) #t)])
(expand-syntax-once (datum->syntax #f 'eval))))
(test eval 'expand-to-top-form (eval (expand-to-top-form 'eval)))
(test eval 'expand-to-top-form (eval (expand-to-top-form eval)))
(test eval 'expand-to-top-form (eval (expand-to-top-form #'eval)))
(test eval 'expand-to-top-form (eval (expand-to-top-form (datum->syntax #f 'eval))))
(err/rt-test (expand-syntax-to-top-form 'eval))
(err/rt-test (expand-syntax-to-top-form eval))
(test eval 'expand-to-top-form (eval (expand-syntax-to-top-form #'eval)))
(test #t syntax? (expand-syntax-to-top-form (datum->syntax #f 'eval))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; origin tracking
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Checks whether stx includes an mapping for
;; a `where' form (indicated by a symbol) going back to
;; a `what' form (another symbol)
;; If `where' is #f, look for the annotation on a let...-values
;; binding clause
(define (has-stx-property? stx where what prop)
(define (has-p? stx)
(let ([p (syntax-property stx prop)])
(and p
(let loop ([p p])
(cond
[(pair? p) (or (loop (car p))
(loop (cdr p)))]
[else (and (identifier? p)
(eq? what (syntax-e p)))])))))
(let loop ([stx stx])
(or (and (has-p? stx)
(or (eq? #t where)
(eq? (syntax-e stx) where)
(and (pair? (syntax-e stx))
(eq? (syntax-e (car (syntax-e stx)))
where))))
(syntax-case stx (#%plain-lambda case-lambda begin begin0
set! with-continuation-mark
if #%plain-app module #%plain-module-begin
define-values)
[(#%plain-lambda formals expr ...)
(ormap loop (syntax->list #'(expr ...)))]
[(case-lambda [formals expr ...] ...)
(ormap (lambda (l)
(ormap loop (syntax->list l)))
(syntax->list #'((expr ...) ...)))]
[(let ([(id ...) rhs] ...) expr ...)
(or (free-identifier=? #'let #'let-values)
(free-identifier=? #'let #'letrec-values))
(or (and (boolean? where)
(syntax-case stx ()
[(let [clause ...] expr)
(ormap has-p? (syntax->list #'(clause ...)))]))
(ormap loop (syntax->list #'(expr ...)))
(ormap loop (syntax->list #'(rhs ...))))]
[(begin expr ...)
(ormap loop (syntax->list #'(expr ...)))]
[(begin0 expr ...)
(ormap loop (syntax->list #'(expr ...)))]
[(set! id expr)
(loop #'expr)]
[(with-continuation-mark key val expr)
(or (loop #'key) (loop #'val) (loop #'expr))]
[(if test then else)
(or (loop #'test) (loop #'then) (loop #'else))]
[(#%plain-app expr ...)
(ormap loop (syntax->list #'(expr ...)))]
[(module name init body)
(loop #'body)]
[(#%plain-module-begin expr ...)
(ormap loop (syntax->list #'(expr ...)))]
[(define-values (id ...) expr)
(loop #'expr)]
[_ #f]))))
(test #t has-stx-property? (expand #'(let ([x 1]) 2)) 'let-values 'let 'origin)
;; The define-struct macro expands to begin,
(test #t has-stx-property? (expand #'(define-struct x (a))) 'begin 'define-struct 'origin)
(test #t has-stx-property? (expand #'(module m scheme/base (define-struct x (a)))) 'define-values 'define-struct 'origin)
(test #t has-stx-property? (expand #'(module m scheme/base (define-struct x (a)))) 'define-syntaxes 'define-struct 'origin)
;; The s macro also expands to begin:
(test #t has-stx-property? (expand #'(module m scheme/base
(require (for-syntax scheme/base))
(define-syntax (s stx)
#'(begin
(+ 1 10)
14))
s))
'#%app 's 'origin)
(test #t has-stx-property? (expand #'(module m scheme/base
(require (for-syntax scheme/base))
(define-syntax (s stx)
#'(begin
(+ 1 10)
14))
(let ()
s)))
'#%app 's 'origin)
;; Check per-clause origin from internal-defn conversion
(test #t has-stx-property? (expand #'(let () (define x 1) x)) #f 'define 'origin)
(test #t has-stx-property? (expand #'(let () (define-struct x (a)) 12)) #f 'define-struct 'origin)
;; Disappearing syntax decls:
(test #t has-stx-property? (expand #'(let () (define-syntax x 1) (define y 12) 10)) 'letrec-values 'x 'disappeared-binding)
(test #t has-stx-property? (expand #'(let () (define-struct s (x)) 10)) 'letrec-values 's 'disappeared-binding)
(test #t has-stx-property? (expand #'(let () (define-syntax x 1) 10)) 'let-values 'x 'disappeared-binding)
(test #f has-stx-property? (expand #'(fluid-let-syntax ([x 1]) 10)) 'let-values 'x 'disappeared-binding)
;; Disappearing use:
(test #t has-stx-property? (expand #'(let () (define-struct a (x)) (define-struct (b a) (z)) 10))
#f 'a 'disappeared-use)
;; Check that origin is bound by disappeared binding:
(test #t has-stx-property? (expand #'(let () (define-syntax (x stx) #'(quote y)) x)) 'quote 'x 'origin)
(let ([check-expr
(lambda (expr)
(let ([e (expand expr)])
(syntax-case e ()
[(lv (bind ...) beg)
(let ([db (syntax-property #'beg 'disappeared-binding)])
(let-values ([(bg e)
(syntax-case #'beg (#%plain-app list)
[(bg () (#%plain-app list e))
(values #'bg #'e)]
[(bg () e)
(values #'bg #'e)])])
(let ([o (syntax-property e 'origin)])
(test #t (lambda (db o)
(and (list? db)
(list? o)
(<= 1 (length db) 2)
(= 1 (length o))
(andmap identifier? db)
(identifier? (car o))
(ormap (lambda (db) (bound-identifier=? db (car o))) db)))
db o))))])))])
(check-expr #'(let () (letrec-syntaxes+values ([(x) (lambda (stx) #'(quote y))]) () x)))
(check-expr #'(let () (letrec-syntaxes+values ([(x) (lambda (stx) #'(quote y))]) () (list x))))
(check-expr #'(let-values () (define-syntax (x stx) #'(quote y)) x))
(check-expr #'(let-values () (define-syntax (x stx) #'(quote y)) (list x)))
(check-expr #'(let-values ([(y) 2]) (define-syntax (x stx) #'(quote y)) x))
(check-expr #'(let-values ([(y) 2]) (define-syntax (x stx) #'(quote y)) (list x)))
(check-expr #'(let () (define-syntax (x stx) #'(quote y)) x))
(check-expr #'(let () (define-syntax (x stx) #'(quote y)) (list x)))
(check-expr #'(let ([z 45]) (define-syntax (x stx) #'(quote y)) x))
(check-expr #'(let ([z 45]) (define-syntax (x stx) #'(quote y)) (list x))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; protected identifiers
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module ++p scheme/base
(require (for-syntax scheme/base))
(define ++c 12)
(define-syntax (++goo stx) #'++c)
(provide ++goo))
(module ++q scheme/base
(require (for-syntax '++p
scheme/base))
(define ++d 11)
(define-syntax (++o stx) #'++d)
(define-syntax (++s stx)
(syntax-case stx ()
[(_ id) #'(define-syntax (id stx)
(datum->syntax #'here (++goo)))]))
(define-syntax (++t stx) (syntax-case stx () [(_ id) #'(define-values (id) ++d)]))
(define-syntax (++t2 stx) #'(begin ++d))
(define-syntax (++t3 stx) (syntax-property #'(begin0 ++d) 'certify-mode 'transparent))
(define-syntax (++t4 stx) (syntax-case stx () [(_ id) #'(define id ++d)]))
(define-syntax (++v stx) #'(begin0 ++d))
(define-syntax (++v2 stx) #'(++d))
(define-syntax (++v3 stx) (syntax-property #'(begin ++d) 'certify-mode 'opaque))
(define-syntax ++ds 17)
(define-syntax (++check-val stx)
(syntax-case stx ()
[(_ id) (datum->syntax #'here (add1 (syntax-local-value #'id)))]))
(define-syntax (++o2 stx) #'(++check-val ++ds))
(define-syntax (++apply-to-ds stx)
(syntax-case stx ()
[(_ id) #'(id ++ds)]))
(define-syntax (++apply-to-d stx)
(syntax-case stx ()
[(_ id) #'(id ++d)]))
(provide ++o ++o2 ++s ++t ++t2 ++t3 ++t4 ++v ++v2 ++v3
++apply-to-d ++apply-to-ds))
(require '++q)
(++s ++ack)
(test 12 values ++ack)
(test 11 values ++v)
(test 11 values ++o)
(test 18 values ++o2)
(test 13 values (let () (++t id) 13))
(let-syntax ([goo (lambda (stx)
(syntax-case stx ()
[(_ id) (datum->syntax #'here (sub1 (syntax-local-value #'id)))]))])
(test 16 'goo (++apply-to-ds goo)))
(unless building-flat-tests?
(test 11 eval-syntax (expand-syntax #'++o))
(test 11 eval-syntax (syntax-case (expand-syntax #'++t2) ()
[(_ x) #'x]))
(test 11 eval-syntax (syntax-case (expand #'(++t z)) ()
[(d-v (_) x) #'x]))
(test 11 eval-syntax (syntax-case (expand-syntax #'++t3) ()
[(_ x) #'x]))
(test 11 eval-syntax (syntax-case (expand #'(++t4 z)) ()
[(d-v (_) x) #'x]))
(err/rt-test (teval (syntax-case (expand #'++v) ()
[(_ x) #'x]))
exn:fail:syntax?)
(err/rt-test (teval (syntax-case (expand #'++v2) ()
[(_ x) #'x]))
exn:fail:syntax?)
(err/rt-test (teval (syntax-case (expand #'++v3) ()
[(_ x) #'x]))
exn:fail:syntax?))
(let ([expr (expand-syntax #'++v)])
(test expr syntax-recertify expr expr (current-inspector) #f)
(let ([new (syntax-recertify #'no-marks expr (current-inspector) #f)])
(test #t syntax? new)
(test 'no-marks syntax-e new))
(test #t syntax? (syntax-recertify (syntax-case expr ()
[(beg id) #'beg])
expr (current-inspector) #f))
;; we'd prefer this to fail, but it's defined to succeed:
(test #t syntax? (syntax-recertify (syntax-case expr ()
[(beg id) #'id])
expr (current-inspector) #f))
(test #t syntax? (syntax-recertify (datum->syntax expr (syntax-e expr))
expr (current-inspector) #f))
;; we'd prefer this to fail, but it's defined to succeed:
(test #t syntax? (syntax-recertify (syntax-case expr ()
[(beg id) #'(ack id)])
expr (current-inspector) #f)))
(let ([expr (expand-syntax #'(++apply-to-d ack))])
(test '(#%app (#%top . ack) ++d) syntax->datum expr)
(let ([try (lambda (cvt? other)
(syntax-recertify (datum->syntax
expr
(cons (car (syntax-e expr))
((if cvt?
(lambda (x) (datum->syntax
(cdr (syntax-e expr))
x))
values)
(cons
other
(cdr (syntax-e (cdr (syntax-e expr))))))))
expr
(current-inspector)
#f))])
(test #t syntax? (try #f #'other!))
(let ([new (try #t #'other!)])
(test #t syntax? new)
(test '(#%app other! ++d) syntax->datum new))
;; we'd prefer this to fail, but it's defined to succeed:
(test #t syntax? (try #t (syntax-case expr ()
[(ap _ d) #'d])))))
;; ----------------------------------------
(module ++m scheme/base
(require (for-syntax scheme/base))
(define ++x 10)
(define-syntax (++xm stx) #'100)
(provide (protect-out ++x ++xm)))
(module ++n scheme/base
(require (for-syntax scheme/base)
'++m)
(define ++y ++x)
(define-syntax (++y-macro stx) #'++x)
(define-syntax (++y-macro2 stx) (datum->syntax stx '++x))
(define-syntax (++u-macro stx) #'++u)
(define-syntax ++u2 (make-rename-transformer #'++u))
(define ++u 8) ; unexported
(provide ++y ++y-macro ++y-macro2 ++u-macro ++u2))
(require '++n)
(test 10 values ++y)
(test 10 values ++y-macro)
(test 8 values ++u-macro)
(test 8 values ++u2)
(require '++m)
(test 10 values ++x)
(test 100 values ++xm)
(test 10 values ++y-macro2)
(let ()
(define n (current-namespace))
(define n2 (make-base-empty-namespace))
(define i (make-inspector))
(parameterize ([current-namespace n2])
(namespace-attach-module n ''++n))
(parameterize ([current-code-inspector i]
[current-namespace n2])
(namespace-require 'scheme/base)
(teval '(require '++n))
(test 10 teval '++y)
(test 10 teval '++y-macro)
(test 8 teval '++u-macro)
(test 8 teval '++u2)
(err/rt-test (teval '++y-macro2) exn:fail:contract:variable?)
(err/rt-test (teval '++x) exn:fail:contract:variable?)
(err/rt-test (teval '++xm) exn:fail:contract:variable?)
(teval '(require '++m))
(err/rt-test (teval '++x) exn:fail:syntax?)
(err/rt-test (teval '++xm) exn:fail:syntax?)
(err/rt-test (teval '++y-macro2) exn:fail:syntax?)
(teval '(module zrt scheme/base
(require '++n)
(define (vy) ++y)
(define (vy2) ++y-macro)
(define (vu) ++u-macro)
(define (vu2) ++u2)
(provide vy vy2 vu vu2)))
(teval '(module zct scheme/base
(require (for-syntax scheme/base
'++n))
(define-syntax (wy stx) (datum->syntax #'here ++y))
(let-syntax ([goo ++y-macro]) 10)
(define-syntax (wy2 stx) (datum->syntax #'here ++y-macro))
(define-syntax (wu stx) (datum->syntax #'here ++u-macro))
(provide wy wy2 wu)))
(teval '(require 'zct))
(test 10 teval 'wy)
(test 10 teval 'wy2)
(test 8 teval 'wu)
(teval '(require 'zrt))
(test 10 teval '(vy))
(test 10 teval '(vy2))
(test 8 teval '(vu))
(test 8 teval '(vu2)))
(let ([old-insp (current-code-inspector)])
(parameterize ([current-code-inspector i]
[current-namespace n2])
(namespace-unprotect-module old-insp ''++m)))
(parameterize ([current-code-inspector i]
[current-namespace n2])
(test 10 teval '++y-macro)
(test 10 teval '++y-macro2)))
(module ++/n scheme/base
(require (for-syntax scheme/base))
(provide ++/get-foo)
(define-syntax foo #'10)
(define-syntax (++/get-foo stx)
(syntax-local-value #'foo)))
(require '++/n)
(test 10 values ++/get-foo)
(module ++//n scheme/base
(require (for-syntax scheme/base))
(provide ++//def)
(define-syntax foo #'17)
(define-syntax ++//def
(syntax-rules ()
[(_ get-foo)
(define-syntax (get-foo stx)
(syntax-local-value #'foo))])))
(require '++//n)
(++//def ++//get-foo)
(test 17 values ++//get-foo)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; lifting expressions
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax (@@foo stx)
(syntax-case stx ()
[(_ n)
(if (zero? (syntax-e #'n))
#'(list #f 0)
(with-syntax ([m (sub1 (syntax-e #'n))])
#`(list '#,(syntax-local-lift-context)
#,(syntax-local-lift-expression #'(add1 (cadr (@@foo m)))))))]))
(define lifted-output #f)
(define-syntax (@@goo stx)
(syntax-case stx ()
[(_)
(with-syntax ([id (syntax-local-lift-expression #'(set! lifted-output "lifted!"))])
#'(list lifted-output id))]))
(test (list #f 2) '@@foo (@@foo 2))
(test (list #f 2) eval-syntax #'(@@foo 2))
(test (list #f 2) eval (expand-once #'(@@foo 2)))
(test (list #f 2) eval (expand-syntax-once #'(@@foo 2)))
(test (list #f 2) eval (expand #'(@@foo 2)))
(test (list #f 2) eval (expand-syntax #'(@@foo 2)))
(test (list #f 2) eval (expand-to-top-form #'(@@foo 2)))
(test (list #f 2) eval (expand-syntax-to-top-form #'(@@foo 2)))
(test (list "lifted!" (void)) '@@goo (@@goo))
(set! lifted-output #f)
(test (list "lifted!" (void)) eval (expand-once #'(@@goo)))
(test (list "lifted!" (void)) eval (expand #'(@@goo)))
(test (list "lifted!" (void)) eval (expand-to-top-form #'(@@goo)))
(module @@n scheme/base
(require (for-syntax scheme/base))
(define-syntax (@@foo stx)
(syntax-case stx ()
[(_ n)
(if (zero? (syntax-e #'n))
#'0
(with-syntax ([m (sub1 (syntax-e #'n))])
(syntax-local-lift-expression #'(add1 (@@foo m)))))]))
(define-syntax (@@foox stx)
(syntax-case stx ()
[(_ n)
(syntax-local-lift-expression #'n)]))
(provide @@foo @@foox))
(require (for-syntax '@@n))
(test (void) eval (expand #'(define-syntax (@@x stx) #`(list #,(@@foo 1) #,(@@foo 2) #,(@@foo 3)))))
(test (list 1 2 3) '@@x @@x)
(test (void) eval (expand #'(define-syntax (@@x stx) #`(list #,(@@foox 1) #,(@@foox 2) #,(@@foox 3)))))
(test (list 1 2 3) '@@x @@x)
(define-syntax (@@x stx) #`(list #,(@@foox 1) #,(@@foox 2) #,(@@foox 3)))
(test (list 1 2 3) '@@x @@x)
(define-syntax (@@x stx) #`(list #,(@@foo 1) #,(@@foo 2) #,(@@foo 3)))
(test (list 1 2 3) '@@x @@x)
(define-syntax (@@x stx) #`#,(@@foo 2))
(test 2 '@@x @@x)
(test 3
'ls-foo
(let-syntax ([z (lambda (stx) #`#,(@@foo 3))])
z))
(test (void) eval (expand #'(begin-for-syntax (define @@zoo (@@foo 2)))))
(define-syntax (@@x stx) #`#, @@zoo)
(test 2 '@@x/@@zoo @@x)
(begin-for-syntax (define @@zoo2 (@@foo 2)))
(define-syntax (@@x stx) #`#, @@zoo2)
(test 2 '@@x/@@zoo @@x)
(begin-for-syntax (@@foo 1))
(test (void) eval (expand #'(begin-for-syntax (@@foo 1))))
(module @@p scheme/base
(require (for-syntax scheme/base
'@@n))
(provide @@goo)
(define-syntax (@@goo stx) #`#,(@@foo 10)))
(require '@@p)
(test 10 '@@goo (@@goo))
(module @@m scheme/base
(require (for-syntax scheme/base))
(define-for-syntax prev-ctx #f)
(define-syntax (@@foo stx)
(syntax-case stx ()
[(_ n)
(if (zero? (syntax-e #'n))
#'(list #f 0)
(with-syntax ([m (sub1 (syntax-e #'n))])
(let ([prev prev-ctx])
(if prev
(unless (eq? prev (syntax-local-lift-context))
(error 'context
"mismatch: ~s vs.: ~s"
prev
(syntax-local-lift-context)))
(set! prev-ctx (syntax-local-lift-context))))
#`(list '#,(syntax-local-lift-context)
#,(syntax-local-lift-expression #'(add1 (cadr (@@foo m)))))))]))
(define @@local #f)
(define (set-local v)
(set! @@local v))
(set-local (@@foo 2))
(provide @@local))
(require '@@m)
(test 2 '@@local (cadr @@local))
(test #t '@@local (symbol? (car @@local)))
(define-syntaxes (@@local-top @@local-top2 @@local-top3)
(let ([mk
(lambda (stops)
(lambda (stx)
(syntax-case stx ()
[(_ expr)
(let ([v (local-expand/capture-lifts #'expr
(list (gensym))
stops
#f
'the-key)])
;; make sure that it's a `begin' form:
(syntax-case v (begin)
[(begin e ... e0) v]))])))])
(values
(mk (list #'begin #'#%top))
(mk null)
(mk #f))))
(test '(#f 1) 'let-foo (let ([x 5]) (@@foo 1)))
(test '(#f 1) eval (expand #'(let ([x 5]) (@@foo 1))))
(test '(the-key 1) 'local-foo (let ([x 5]) (@@local-top (@@foo 1))))
(test '(the-key 1) eval (expand #'(let ([x 5]) (@@local-top (@@foo 1)))))
(test '(the-key 1) eval (expand #'(@@local-top (@@foo 1))))
(test '(the-key 1) eval (expand #'(@@local-top2 (@@foo 1))))
(test '(the-key 1) eval (expand #'(@@local-top3 (@@foo 1))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check interaction of macro-introduced/lifted names and
;; module->namespace
(let ([go-once
(lambda (eval)
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module mm scheme/base
(require (for-syntax scheme/base))
(define-syntax (define$ stx)
(syntax-case stx ()
[(_ id val)
(with-syntax ([x (datum->syntax #f 'x)])
#'(begin
(define x val)
(define-syntax (id stx) #'x)))]))
(define$ a 1)
(define$ b 2)
(printf "~a ~a~n" a b)))
(eval '(require 'mm))
(eval '(current-namespace (module->namespace ''mm)))
(eval '(define$ c 7))
(test '(1 2 7) eval '(list a b c))
(eval '(define$ d 8))
(test '(1 2 7 8) eval '(list a b c d)))
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module mm scheme/base
(require (for-syntax scheme/base))
(define-syntax (define$ stx)
(syntax-case stx ()
[(_ id val)
(with-syntax ([x (syntax-local-lift-expression #'val)])
#'(define-syntax (id stx) #'x))]))
(define$ a 1)
(define$ b 2)
(printf "~a ~a~n" a b)))
(eval '(require 'mm))
(eval '(current-namespace (module->namespace ''mm)))
(eval '(define$ c 7))
(test '(1 2 7) eval '(list a b c))
(eval '(define$ d 8))
(test '(1 2 7 8) eval '(list a b c d))))])
(go-once eval)
(go-once (lambda (e) (eval (expand e)))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; layers of lexical binding
(test '(1 2) 'macro-nested-lexical
(let ()
(define-syntax (m stx)
(with-syntax ([x1 (let ([x 0]) #'x)]
[x2 (let ([x 0]) #'x)])
#'(begin
(define x1 1)
(define x2 2)
(list x1 x2))))
(m)))
(module @!$m scheme/base
(require (for-syntax scheme/base))
(define-syntax (d stx)
(syntax-case stx ()
[(_ id)
(with-syntax ([x1 (let ([x 0]) #'x)]
[x2 (let ([x 0]) #'x)])
#'(begin
(define x1 10)
(define x2 20)
(define id (list x1 x2
(list? (identifier-binding (quote-syntax x1)))))))]))
(d @!$get)
(provide @!$get))
(require '@!$m)
(test '(10 20 #t) '@!$get @!$get)
(unless building-flat-tests?
(test '(12)
eval
(expand
#'(let ([b 12])
(let-syntax ([goo (lambda (stx)
#`(let ()
(define #,(syntax-local-introduce #'b) 1)
(define z (list b))
z))])
(goo))))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test lazy unmarshaling of renamings and module-name resolution
(let ([load-ok? #t]
[old (current-module-name-resolver)])
(parameterize ([current-namespace (make-base-namespace)]
[current-module-name-resolver
(case-lambda
[(name)
(if (equal? name "a")
(void)
(old name))]
[(name _ __) (make-resolved-module-path 'huh?)]
[(name base stx load?)
(if (equal? name "a")
(begin
(unless load-ok?
(test #f 'load-ok load?))
(make-resolved-module-path 'a))
(old name base stx load?))])])
(let ([a-code '(module a scheme/base
(provide x y)
(define x 1)
(define y #'x))])
(eval a-code)
(let ([b-code (let ([p (open-output-bytes)])
(write (compile
'(module b scheme/base
(require "a")
(provide f)
(define (f) #'x)))
p)
(lambda ()
(parameterize ([read-accept-compiled #t])
(read (open-input-bytes (get-output-bytes p))))))]
[x-id (parameterize ([current-namespace (make-base-namespace)])
(printf "here\n")
(eval a-code)
(eval '(require 'a))
(eval '#'x))])
(eval (b-code))
(eval '(require 'b))
(set! load-ok? #f)
(test #f eval '(free-identifier=? (f) #'x))
(test #t eval `(free-identifier=? (f) (quote-syntax ,x-id)))
(eval '(require 'a))
(test #t eval '(free-identifier=? (f) #'x))
(test #t eval `(free-identifier=? (f) (quote-syntax ,x-id)))
(parameterize ([current-namespace (make-base-namespace)])
(eval '(module a scheme/base
(provide y)
(define y 3)))
(set! load-ok? #t)
(eval (b-code))
(eval '(require 'b))
(set! load-ok? #f)
(test #t eval '(free-identifier=? (f) #'x))
(test #f eval `(free-identifier=? (f) (quote-syntax ,x-id))))))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; certification example from the manual
(module @-m scheme/base
(require (for-syntax scheme/base))
(provide def-go)
(define (unchecked-go n x)
(+ n 17))
(define-syntax (def-go stx)
(syntax-case stx ()
[(_ go)
#'(define-syntax (go stx)
(syntax-case stx ()
[(_ x)
#'(unchecked-go 8 x)]))])))
(module @-n scheme/base
(require '@-m)
(def-go go)
(go 10)) ; access to unchecked-go is allowed
(require '@-n)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Propagating inactive certificates through a transparent macro-expansion
;; result:
(module @!m scheme/base
(require (for-syntax scheme/base))
(provide define-x)
(define-syntax (define-x stx)
(syntax-case stx ()
[(_ x)
#'(define-syntax (x stx)
#'(begin
(define-y y 10)))]))
(define-syntax define-y
(syntax-rules ()
[(_ id v)
(define id v)])))
(module @!n scheme/base
(require '@!m)
(define-x def-y)
(def-y))
;; If we get here, then macro expansion didn't fail.
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check that the free-identifier=? cache doesn't kick in too eagerly.
(module @w@ scheme/base
(define add '+)
(provide (rename-out [add plus])))
(module @q@ scheme/base
(require (for-syntax scheme/base))
(provide result)
(define-for-syntax a #'plus)
(define-for-syntax b #'plus)
(define-for-syntax accum null)
(begin-for-syntax
(set! accum (cons (free-identifier=? a #'plus)
accum)))
(require '@w@)
(begin-for-syntax
(set! accum (list*
(free-identifier=? a #'plus)
(free-identifier=? b #'plus)
accum)))
(define-syntax (accumulated stx)
(datum->syntax stx `',accum))
(define result (accumulated)))
(require '@q@)
(test '(#t #t #t) values result)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test namespace-attach with phase-levels -2 and 2
(module tn scheme/base
(require scheme/file)
(define tmp10 (make-temporary-file))
(provide tmp10)
)
(module @!a scheme/base
(require 'tn)
(provide x)
(with-output-to-file tmp10
#:exists 'append
(lambda ()
(printf "a\n")))
(define x 5))
(module @!b scheme/base
(provide get-x)
(require (for-meta -2 '@!a))
(define (get-x) #'x))
(module @!c scheme/base
(require 'tn)
(require (for-meta 2 '@!b)
(for-syntax scheme/base
(for-syntax scheme/base)))
(define-syntax (foo stx)
(let-syntax ([ref-x (lambda (stx)
#`(quote-syntax #,(get-x)))])
(ref-x)))
(with-output-to-file tmp10
#:exists 'append
(lambda ()
(printf "~s\n" (foo)))))
(require 'tn)
(define (check-tmp10 s)
(test s with-input-from-file tmp10 (lambda () (read-string 1000))))
(require '@!c)
(check-tmp10 "a\n5\n")
(let ()
(define n (make-base-namespace))
(namespace-attach-module (current-namespace) ''@!c n)
(test 5
'use-a
(parameterize ([current-namespace n])
;; Shouldn't instantiate new:
(namespace-require ''@!a)
;; Should see `x' from @!a:
(eval 'x)))
(check-tmp10 "a\n5\n"))
(when (file-exists? tmp10)
(delete-file tmp10))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure post-ex renames aren't simplied away too soon:
(module @simp@ scheme/base
(require (for-syntax scheme/base))
(define-syntax-rule (foo)
(begin
(define-for-syntax goo #'intro)
(define intro 5)
(define-syntax (extract stx)
#`(quote #,(identifier-binding goo)))
(define @simp@tst (extract))
(provide @simp@tst)))
(foo))
(require '@simp@)
(test #t list? @simp@tst)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)