racket/collects/tests/eopl/chapter4/mutable-pairs/interp.rkt
David Van Horn 7491e172ea EOPL test suite re-written in Racket-based #lang eopl and rackunit
The eopl language is now racket-based rather than mzscheme-based.  This
test-suite, which was originally distributed on the book's web-site has
been re-written in the new language.  Changes include dropping all
drscheme-init.scm and top.scm files.  Remaining files were renamed to
use the .rkt extension and edited to use the #lang syntax (instead of
modulue).  Require and provide forms were changed to reflect racket's
syntax instead of mzscheme's (eg, only-in vs. only).  Several
occurrences of one-armed ifs were changed to use when and unless.  All
tests have been run successfully.
2012-02-24 14:46:18 -05:00

183 lines
5.9 KiB
Racket
Executable File

#lang eopl
;; interpreter for the MUTABLE-PAIRS language
(require "lang.rkt")
(require "data-structures.rkt")
(require "environments.rkt")
(require "store.rkt")
(require "pairvals.rkt")
(require (only-in racket pretty-print))
(provide value-of-program value-of instrument-let instrument-newref)
;;;;;;;;;;;;;;;; switches for instrument-let ;;;;;;;;;;;;;;;;
(define instrument-let (make-parameter #f))
;; say (instrument-let #t) to turn instrumentation on.
;; (instrument-let #f) to turn it off again.
;;;;;;;;;;;;;;;; the interpreter ;;;;;;;;;;;;;;;;
;; value-of-program : Program -> ExpVal
(define value-of-program
(lambda (pgm)
(initialize-store!)
(cases program pgm
(a-program (body)
(value-of body (init-env))))))
;; value-of : Exp * Env -> ExpVal
;; Page: 126
(define value-of
(lambda (exp env)
(cases expression exp
(const-exp (num) (num-val num))
(var-exp (var) (deref (apply-env env var)))
(diff-exp (exp1 exp2)
(let ((val1
(expval->num
(value-of exp1 env)))
(val2
(expval->num
(value-of exp2 env))))
(num-val
(- val1 val2))))
(zero?-exp (exp1)
(let ((val1 (expval->num (value-of exp1 env))))
(if (zero? val1)
(bool-val #t)
(bool-val #f))))
(if-exp (exp0 exp1 exp2)
(if (expval->bool (value-of exp0 env))
(value-of exp1 env)
(value-of exp2 env)))
;;; Uninstrumented version
;;; (let-exp (id rhs body)
;;; (let ((val (value-of rhs env)))
;;; (value-of body
;;; (extend-env id (newref val) env))))
(let-exp (var exp1 body)
(when (instrument-let)
(eopl:printf "entering let ~s~%" var))
(let ((val (value-of exp1 env)))
(let ((new-env (extend-env var (newref val) env)))
(when (instrument-let)
(eopl:printf "entering body of let ~s with env =~%" var)
(pretty-print (env->list new-env))
(eopl:printf "store =~%")
(pretty-print (store->readable (get-store-as-list)))
(eopl:printf "~%")
)
(value-of body new-env))))
(proc-exp (var body)
(proc-val
(procedure var body env)))
(call-exp (rator rand)
(let ((proc (expval->proc (value-of rator env)))
(arg (value-of rand env)))
(apply-procedure proc arg)))
(letrec-exp (p-names b-vars p-bodies letrec-body)
(value-of letrec-body
(extend-env-rec* p-names b-vars p-bodies env)))
(begin-exp (exp1 exps)
(letrec
((value-of-begins
(lambda (e1 es)
(let ((v1 (value-of e1 env)))
(if (null? es)
v1
(value-of-begins (car es) (cdr es)))))))
(value-of-begins exp1 exps)))
(assign-exp (x e)
(begin
(setref!
(apply-env env x)
(value-of e env))
(num-val 27)))
(newpair-exp (exp1 exp2)
(let ((v1 (value-of exp1 env))
(v2 (value-of exp2 env)))
(mutpair-val (make-pair v1 v2))))
(left-exp (exp1)
(let ((v1 (value-of exp1 env)))
(let ((p1 (expval->mutpair v1)))
(left p1))))
(right-exp (exp1)
(let ((v1 (value-of exp1 env)))
(let ((p1 (expval->mutpair v1)))
(right p1))))
(setleft-exp (exp1 exp2)
(let ((v1 (value-of exp1 env))
(v2 (value-of exp2 env)))
(let ((p (expval->mutpair v1)))
(begin
(setleft p v2)
(num-val 82)))))
(setright-exp (exp1 exp2)
(let ((v1 (value-of exp1 env))
(v2 (value-of exp2 env)))
(let ((p (expval->mutpair v1)))
(begin
(setright p v2)
(num-val 83)))))
)))
;; apply-procedure : Proc * ExpVal -> ExpVal
;; (define apply-procedure
;; (lambda (proc1 arg)
;; (cases proc proc1
;; (procedure (bvar body saved-env)
;; (value-of body
;; (extend-env bvar (newref arg) saved-env))))))
(define apply-procedure
(lambda (proc1 arg)
(cases proc proc1
(procedure (var body saved-env)
(let ((r (newref arg)))
(let ((new-env (extend-env var r saved-env)))
(when (instrument-let)
(eopl:printf
"entering body of proc ~s with env =~%"
var)
(pretty-print (env->list new-env))
(eopl:printf "store =~%")
(pretty-print (store->readable (get-store-as-list)))
(eopl:printf "~%"))
(value-of body new-env)))))))
;; store->readable : Listof(List(Ref,Expval))
;; -> Listof(List(Ref,Something-Readable))
(define store->readable
(lambda (l)
(map
(lambda (p)
(list
(car p)
(expval->printable (cadr p))))
l)))