#lang racket
(define valof-lexical
(lambda (exp env)
(match exp
[`,y #:when (symbol? y) (apply-env env y)]
[`,n #:when (number? n) n]
[`(* ,a ,b) (* (valof-lexical a env) (valof-lexical b env))]
[`(lambda (,x) ,b) `(lambda (,x) ,b ,env)]
[`(let ((,x ,val)) ,b)
(valof-lexical b (ext-env x (valof-lexical val env) env))]
[`(,rator ,rand)
(match-let ((`(lambda (,x) ,b ,env) (valof-lexical rator env)) (a (valof-lexical rand env)))
(valof-lexical b (ext-env x a env)))])))
(define valof-dynamic
(lambda (exp env)
(match exp
[`,y #:when (symbol? y) (apply-env env y)]
[`,n #:when (number? n) n]
[`(* ,a ,b) (* (valof-dynamic a env) (valof-dynamic b env))]
[`(lambda (,x) ,b) `(lambda (,x) ,b ,env)]
[`(let ((,x ,val)) ,b)
(valof-dynamic b (ext-env x (valof-dynamic val env) env))]
[`(,rator ,rand)
(match-let ((`(lambda (,x) ,b ,env^) (valof-dynamic rator env)) (a (valof-dynamic rand env)))
(valof-dynamic b (ext-env x a env)))])))
(define apply-env
(lambda (env y)
(env y)))
(define ext-env
(lambda (x a env)
(lambda (e)
(if (eqv? e x)
a
(env e)))))
(define empty-env
(lambda ()
(lambda (x)
(error "unbound ~s" x))))
(valof-lexical '(let ((x 5))
(let ((f (lambda (y) (* x y))))
(let ((x 6))
(f x))))
(empty-env))
(valof-dynamic '(let ((x 5))
(let ((f (lambda (y) (* x y))))
(let ((x 6))
(f x))))
(empty-env))