(define value-of
(lambda (exp env)
(match exp
[`,n #:when (number? n) n]
[`,y #:when (symbol? y) (env y)]
[`(lambda (,x) ,body)
(lambda (arg)
(value-of body
(lambda (y)
(if (eqv? y x)
arg
(env y)))))]
[`(,rator ,rand)
((value-of rator env)
(value-of rand env))])))
(define empty-env
(lambda ()
(lambda (y)
(error 'empty-env "unbound var ~s" y))))
(define extend-env
(lambda (x arg env)
(lambda (y)
(if (eqv? y x)
arg
(env y)))))
(define apply-env
(lambda (env y)
(env y)))
(define make-closure
(lambda (body x env)
(lambda (arg)
(value-of-fn body
(extend-env x arg env)))))
(define apply-closure
(lambda (c a)
(c a)))
(define value-of-fn
(lambda (exp env)
(match exp
[`,n #:when (number? n) n]
[`,y #:when (symbol? y) (apply-env env y)]
[`(lambda (,x) ,body)
(make-closure x body env)]
[`(,rator ,rand)
(apply-closure (value-of rator env)
(value-of rand env))])))
(define empty-env-ds
(lambda () `(empty-env-ds)))
(define extend-env-ds
(lambda (x arg env)
`(extended-env ,x ,arg ,env)))
(define apply-env-ds
(lambda (env y)
(match env
[`(empty-env-ds)
(error `empty-env-ds "unbound var ~s" y)]
[`(extended-env ,x ,arg ,env)
(if (eqv? x y) arg (apply-env-ds env y))]
[else (env y)])))
(define make-closure-ds
(lambda (x body env)
`(closure ,x ,body ,env)))
(define apply-closure-ds
(lambda (c a)
(match c
[`(closure ,x ,body ,env)
(value-of-ds body
(extend-env-ds x a env))])))
(define value-of-ds
(lambda (exp env)
(match exp
[`,n #:when (number? n) n]
[`,y #:when (symbol? y) (apply-env-ds env y)]
[`(lambda (,x) ,body)
(make-closure-ds x body env)]
[`(,rator ,rand)
(apply-closure-ds (value-of-ds rator env)
(value-of-ds rand env))])))