115 lines
3.4 KiB
Scheme
115 lines
3.4 KiB
Scheme
#lang scheme/base
|
|
(require (planet "test.ss" ("schematics" "schemeunit.plt" 2))
|
|
mzlib/serialize
|
|
mzlib/match
|
|
(lib "define-closure.ss" "web-server" "private"))
|
|
(provide define-closure-tests)
|
|
|
|
(define-closure id (x) () x)
|
|
|
|
(define-closure add-y (x) (y) (+ x y))
|
|
(define-closure even-p (n) (odd-p) (or (zero? n)
|
|
(odd-p (sub1 n))))
|
|
(define-closure odd-p (n) (even-p) (or (= 1 n)
|
|
(even-p (sub1 n))))
|
|
|
|
(define even-p (make-even-p (lambda () odd-p)))
|
|
(define odd-p (make-odd-p (lambda () even-p)))
|
|
|
|
;; an interpreter
|
|
|
|
(define-closure the-empty-env (var) ()
|
|
(error "unbound symbol: " var))
|
|
|
|
(define-closure extended-env (v) (env var val)
|
|
(if (eqv? v var) val
|
|
(env v)))
|
|
|
|
(define-serializable-struct proc (var body env))
|
|
|
|
(define-closure clsr:evaluate (expr env) (evaluate eval-app)
|
|
(match expr
|
|
[('lambda (var) body) (make-proc var body env)]
|
|
[(expr1 expr2)
|
|
(let ([val1 (evaluate expr1 env)]
|
|
[val2 (evaluate expr2 env)])
|
|
(eval-app val1 val2))]
|
|
[(? number? n) n]
|
|
[var (env var)]))
|
|
|
|
(define-closure clsr:eval-app (val1 val2) (evaluate)
|
|
(cond
|
|
[(proc? val1)
|
|
(evaluate (proc-body val1)
|
|
(make-extended-env
|
|
(lambda () (values (proc-env val1) (proc-var val1) val2))))]
|
|
[else
|
|
(error "stuck term: " (list val1 val2))]))
|
|
|
|
(define evaluate (make-clsr:evaluate (lambda () (values evaluate eval-app))))
|
|
(define eval-app (make-clsr:eval-app (lambda () evaluate)))
|
|
|
|
(define define-closure-tests
|
|
(test-suite
|
|
"Define Closure"
|
|
|
|
(test-case
|
|
"serialize id procedure"
|
|
(check = 7 ((deserialize (serialize (make-id))) 7)))
|
|
|
|
(test-case
|
|
"id procedure"
|
|
(check = 7 ((make-id) 7)))
|
|
|
|
(test-case
|
|
"add-y procedure"
|
|
(check = 2 ((make-add-y (lambda () 1)) 1)))
|
|
|
|
(test-case
|
|
"serialize the add-y procedure"
|
|
(check = 2 ((deserialize (serialize (make-add-y (lambda () 1)))) 1)))
|
|
|
|
(test-case
|
|
"even-p procedure"
|
|
(check-true (even-p 8)))
|
|
|
|
(test-case
|
|
"serialize the even-p procedure"
|
|
(check-true ((deserialize (serialize even-p)) 64)))
|
|
|
|
(test-case
|
|
"simple interpreter case"
|
|
(check = 3 (evaluate 3 (make-the-empty-env))))
|
|
|
|
(test-case
|
|
"serialize simple interpreter case"
|
|
(check = 3 ((deserialize (serialize evaluate))
|
|
3
|
|
(deserialize (serialize (make-the-empty-env))))))
|
|
|
|
(test-case
|
|
"apply identity"
|
|
(check = 3 (evaluate '((lambda (x) x) 3) (make-the-empty-env))))
|
|
|
|
(test-case
|
|
"serialize environments"
|
|
(let* ([e0 (make-the-empty-env)]
|
|
[e1 (make-extended-env (lambda () (values e0 'x 1)))]
|
|
[e2 (make-extended-env (lambda () (values e1 'y 2)))]
|
|
[e3 (make-extended-env (lambda () (values e2 'z 3)))]
|
|
[e4 (make-extended-env (lambda () (values e3 'x 4)))]
|
|
[e5 (make-extended-env (lambda () (values e4 'y 5)))]
|
|
[e6 (make-extended-env (lambda () (values e5 'z 6)))]
|
|
[env3 (deserialize (serialize e3))]
|
|
[env5 (deserialize (serialize e5))]
|
|
[env6 (deserialize (serialize e6))])
|
|
(check = 1 (env3 'x))
|
|
(check = 2 (env3 'y))
|
|
(check = 3 (env3 'z))
|
|
(check = 4 (env5 'x))
|
|
(check = 5 (env5 'y))
|
|
(check = 3 (env5 'z))
|
|
(check = 4 (env6 'x))
|
|
(check = 5 (env6 'y))
|
|
(check = 6 (env6 'z))))))
|