1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
;;;"scmactst.scm" test syntactic closures macros
;;; From "sc-macro.doc", A Syntactic Closures Macro Facility by Chris Hanson
(define errs '())
(define test
(lambda (expect fun . args)
(write (cons fun args))
(display " ==> ")
((lambda (res)
(write res)
(newline)
(cond ((not (equal? expect res))
(set! errs (cons (list res expect (cons fun args)) errs))
(display " BUT EXPECTED ")
(write expect)
(newline)
#f)
(else #t)))
(if (procedure? fun) (apply fun args) (car args)))))
(require 'syntactic-closures)
(macro:expand
'(define-syntax push
(syntax-rules ()
((push item list)
(set! list (cons item list))))))
(test '(set! foo (cons bar foo)) 'push (macro:expand '(push bar foo)))
(macro:expand
'(define-syntax push1
(transformer
(lambda (exp env)
(let ((item
(make-syntactic-closure env '() (cadr exp)))
(list
(make-syntactic-closure env '() (caddr exp))))
`(set! ,list (cons ,item ,list)))))))
(test '(set! foo (cons bar foo)) 'push1 (macro:expand '(push1 bar foo)))
(macro:expand
'(define-syntax loop
(transformer
(lambda (exp env)
(let ((body (cdr exp)))
`(call-with-current-continuation
(lambda (exit)
(let f ()
,@(map (lambda (exp)
(make-syntactic-closure env '(exit)
exp))
body)
(f)))))))))
(macro:expand
'(define-syntax let1
(transformer
(lambda (exp env)
(let ((id (cadr exp))
(init (caddr exp))
(exp (cadddr exp)))
`((lambda (,id)
,(make-syntactic-closure env (list id) exp))
,(make-syntactic-closure env '() init)))))))
(test 93 'let1 (macro:eval '(let1 a 90 (+ a 3))))
(macro:expand
'(define-syntax loop-until
(syntax-rules
()
((loop-until id init test return step)
(letrec ((loop
(lambda (id)
(if test return (loop step)))))
(loop init))))))
(test (macro:expand '(letrec ((loop (lambda (foo) (if #t 12 (loop 33)))))
(loop 3)))
'loop
(macro:expand '(loop-until foo 3 #t 12 33)))
(macro:expand
'(define-syntax loop-until1
(transformer
(lambda (exp env)
(let ((id (cadr exp))
(init (caddr exp))
(test (cadddr exp))
(return (cadddr (cdr exp)))
(step (cadddr (cddr exp)))
(close
(lambda (exp free)
(make-syntactic-closure env free exp))))
`(letrec ((loop
,(capture-syntactic-environment
(lambda (env)
`(lambda (,id)
(,(make-syntactic-closure env '() `if)
,(close test (list id))
,(close return (list id))
(,(make-syntactic-closure env '()
`loop)
,(close step (list id)))))))))
(loop ,(close init '()))))))))
(test (macro:expand '(letrec ((loop (lambda (foo) (if #t 12 (loop 33)))))
(loop 3)))
'loop1
(macro:expand '(loop-until1 foo 3 #t 12 33)))
(test '#t 'identifier (identifier? 'a))
;;; this needs to setup ENV.
;;;(test '#t 'identifier
;;; (identifier? (macro:expand (make-syntactic-closure env '() 'a))))
(test #f 'identifier (identifier? "a"))
(test #f 'identifier (identifier? #\a))
(test #f 'identifier (identifier? 97))
(test #f 'identifier (identifier? #f))
(test #f 'identifier (identifier? '(a)))
(test #f 'identifier (identifier? '#(a)))
(test '(#t #f)
'syntax
(macro:eval
'(let-syntax
((foo
(transformer
(lambda (form env)
(capture-syntactic-environment
(lambda (transformer-env)
(identifier=? transformer-env 'x env 'x)))))))
(list (foo)
(let ((x 3))
(foo))))))
(test '(#f #t)
'syntax
(macro:eval
'(let-syntax ((bar foo))
(let-syntax
((foo
(transformer
(lambda (form env)
(capture-syntactic-environment
(lambda (transformer-env)
(identifier=? transformer-env 'foo
env (cadr form))))))))
(list (foo foo)
(foo bar))))))
(newline)
(cond ((null? errs) (display "Passed all tests"))
(else (display "errors were:") (newline)
(display "(got expected (call))") (newline)
(for-each (lambda (l) (write l) (newline)) errs)))
(newline)
|