<<
Home , ENV

CSSE 304 Day 19 Summary (first we will finish the day 19 material on environment representations)

1. What is the result of executing this code? > (define a 0) > (map (lambda (x) (set! a (add1 a)) a) '(a b c d e f g h i j k l m n o p))

2. Main pieces of the initial (code is on daily handout). This is a place for your notes about the procedures. Procedure What it does / how it works (rep)

(apply-env env symbol succeed fail)

(top-level-eval parsed-form)

(eval-exp exp)

(eval-rands rands)

(apply-proc proc-val args)

(apply-prim-proc prim-proc args)

(define init-env …

3. Before adding let and lambda to interpreted language: Add a local env argument to several procedures (especially eval-exp) (code details are in the slides). 4. Do we need to add an env argument to apply-proc? Why or why not?

5. Add let, if, lambda to the interpreted language

(define-datatype environment environment? ; eval-exp is the main component of the interpreter (empty-env-record) (extended-env-record (define eval-exp (syms (list-of symbol?)) (lambda (exp) (vals (list-of scheme-value?)) (cases expression exp (env environment?))) [lit-exp (datum) datum] [var-exp (id) ;; Parsed expression datatypes (apply-env init-env id ; look up its value. (define-datatype expression expression? (lambda (x) x) ; if id is in the environment [var-exp ; variable references (lambda (); procedure to call if id not in env (id symbol?)] (eopl:error 'apply-env [lit-exp ; "Normal" data. "variable not found in environment: ~s" (datum ; Did I leave out any types? id)))] (lambda (x) [app-exp (rator rands) (ormap (let ([proc-value (eval-exp rator)] (lambda (pred) (pred x)) [args (eval-rands rands)]) (list number? vector? boolean? (apply-proc proc-value args))] symbol? string? pair? null?))))] [else [app-exp ; applications (eopl:error 'eval-exp (rator expression?) "Bad abstract syntax: ~a" (rands (list-of expression?))] exp)]))) )

; datatype for procedures. first only one ; evaluate list of operands, putting results into a list ; kind of procedure, kinds added later. (define eval-rands (define-datatype proc-val proc-val? (lambda (rands) [prim-proc (map eval-exp rands))) (name symbol?)]) ; Apply a procedure to its arguments (values, not code). ; Environment definitions. Based on EoPL section 2.3 ; At this point, we only have primitive procedures. (define ; User-defined procedures will be added later. empty-env (lambda () (define apply-proc (empty-env-record))) (lambda (proc-value args)

(cases proc-val proc-value (define extend-env [prim-proc (op) (apply-prim-proc op args)] (lambda (syms vals env) ; You will add other cases (extended-env-record syms vals env))) [else (error 'apply-proc "Attempt to apply bad procedure: ~s" (define list--position proc-value)]))) (lambda (sym los) (list-index (lambda (xsym) (eqv? sym xsym)) los))) (define *prim-proc-names* '(+ - * add1 sub1 cons =))

(define list-index (define init-env ; for now, initial global environment (lambda (pred ) ; only contains procedure names. (cond (extend-env ; Recall that an environment associates ((null? ls) #f) *prim-proc-names* ; a value (not an expression) ((pred (car ls)) 0) ; with an identifier. (else (let ((list-index-r (list-index pred (cdr (map prim-proc ls)))) *prim-proc-names*) (if (number? list-index-r) (empty-env))) (+ 1 list-index-r) #f)))))) ; Usually an interpreter must define each built-in ; procedure individually. Defined using the facilities ; provided by the implementation language. (define apply-env (lambda (env sym succeed fail) ; succeed and fail are (define apply-prim-proc ; applied if the var is or (lambda (prim-proc args) ; isn't found, respectively. (case prim-proc (cases environment env [(+) (+ (1st args) (2nd args))] (empty-env-record () [(-) (- (1st args) (2nd args))] (fail)) [(*) (* (1st args) (2nd args))] (extended-env-record (syms vals env) [(add1) (+ (1st args) 1)] (let ((pos (list-find-position sym syms))) [(sub1) (- (1st args) 1)] (if (number? pos) [(cons) (cons (1st args) (2nd args))] (succeed (list-ref vals pos)) [(=) (= (1st args) (2nd args))] (apply-env env sym succeed fail))))))) [else (error 'apply-prim-proc "Bad primitive procedure name: ~s" ; parse and evaluate a single expression prim-op)]))) ; (non-interactive interface) ; ------interactive interpreter interface ------(define eval-one-exp (define rep ; "read-eval-print" loop. (lambda (x) (top-level-eval (parse-exp x)))) (lambda () (display "--> ") ; top-level-eval evaluates a form in the global ;; note that we don't change the environment yet environment (let ([answer (top-level-eval (parse-exp (read)))]) (define top-level-eval ;; TODO: are there answers that should (lambda (parsed-form) ;; display differently? ; later we may add things that are not expressions. (eopl:pretty-print answer) (eval-exp parsed-form))) (newline) (rep)))) ; -recursive, so stack doesn't grow.