;; (Skip down to "the interpreter" for your HW5 additions.) ;; An expval is ;; * number, or ;; * closure ;; A denval is an expval ;; The language: ;; = ;; a number ;; | @ ;; looks up a value in the env ;; | [] ;; creates a closure (1 arg) ;; | call(, ) ;; applies a closure (1 arg) ;; | ifzero(, , ) ;; branch ;; | +(, ) ;; add ;; | -(, ) ;; subtract ;;;;;;;; grammatical specification (don't modify) ;;;;;;;;;;;;;;;; (define the-lexical-spec '((whitespace (whitespace) skip) (id (letter (arbno (or letter digit "?"))) make-symbol) (number ((or "" "-" "+") digit (arbno digit)) make-number))) (define the-grammar '((expression (number) lit-exp) (expression ("@" number) lookup-exp) (expression ("[" expression "]") proc-exp) (expression ("call" "(" expression "," expression ")") app-exp) (expression ("ifzero" "(" expression "," expression "," expression ")") ifzero-exp) (expression ("+" "(" expression "," expression ")") add-exp) (expression ("-" "(" expression "," expression ")") subtract-exp))) (sllgen:make-define-datatypes the-lexical-spec the-grammar) (define-datatype closure closure? (a-closure (env environment?) (body expression?))) ;;;;;;;;;;;;;;;; top level (don't modify) ;;;;;;;;;;;;;;;; ; read-eval-print : -> [loops forever] (define read-eval-print (lambda () ((sllgen:make-rep-loop "-->" (lambda (x) (eval-expression x (empty-env))) (sllgen:make-stream-parser the-lexical-spec the-grammar))))) ; run : string -> expval ; ; Takes a string respresting concrete syntax and ; evaluates it, returning the result. ; ; (run "5") = 5 ; (run "[1]") = _(a-closure (empty-env-rec) (lit-exp 1))_ ; (run "call([@0], 1)") = 1 ; (run "call([call(call(@0, @0), 10)], [[ifzero(@0,0,+(@0,call(call(@1, @1),-(@0,1))))]])") = 55 ; (define run (lambda (string) (eval-expression (scan&parse string) (empty-env)))) (define scan&parse (sllgen:make-string-parser the-lexical-spec the-grammar)) ;;;;;;;;;;;;;;;;;;;; the interpreter ;;;;;;;;;;;;;;;; ;;; >>>>> This is the part you implement <<<<<<< ;;;; ; eval-expression : expression env -> expval ; ; Evaluates an expression in the given environment. ; ; (eval-expression (lit-exp 5) (empty-env)) = 5 ; (eval-expression (lookup-exp 1) ; (extend-env 42 (extend-env 43 (empty-env)))) = 43 ; (eval-expression (app-exp (proc-exp (lookup-exp 0)) ; (lit-exp 42)) ; (empty-env)) = 42 ; (define eval-expression ... ) ;;;;;;;;;;;;;;;; environments (don't modify) ;;;;;;;;;;;;;;;; ;; Abstract envrionment datatype implementation (define (denval? x) (or (number? x) (closure? x))) (define-datatype environment environment? (empty-env-rec) (extended-env-rec (val denval?) (env environment?))) ; empty-env : -> env (define empty-env (lambda () (empty-env-rec))) ; extend-env : denval env -> env (define extend-env (lambda (val env) (extended-env-rec val env))) ; apply-env : env num -> denval (define apply-env (lambda (env cn) (cases environment env (empty-env-rec () (eopl:error 'apply-env "lookup too deep")) (extended-env-rec (val env) (if (zero? cn) val (apply-env env (- cn 1)))))))