Upload
kelley-craig
View
217
Download
0
Tags:
Embed Size (px)
Citation preview
1
The environment model evaluator and compilerThe env model evaluator Motivation
In one word: Efficiency
• Saves repeated renaming and substitution: Using new data
structures (frame, environment), explicit substitution is replaced by
variable bindings.
• Can be utilized to gain further improvements that cannot be
achieved using the substitution model (coming up next..)
2
The environment model evaluator and compilerThe env model evaluator Structure & implementation
Data structures
Abstract syntax parser
Core
Derived expressions
Special forms
No changes here!
• New data structures:• A binding• A frame• An environment
•Changed data structures:• A closure
• Additional procedures to handle with these ADTs
• Procedure application and evaluation of expressions is now done with respect to a certain environment.
• No need for renaming & substitution procedures.
Test Utils
The environment model evaluator and compiler
3
The env model evaluator Structure & implementation
Data structures package:
A binding: A pair consisting of a variable and its value.
#<primitive:+>
+
A frame:
• A variable-value mapping. Every variable in a frame is bound to one value only.
• Implemented as a procedure that gets a variable name and returns value or
empty
<procedure (var) … >
4
The environment model evaluator and compilerThe env model evaluator Structure & implementation
An environment:
• A finite sequence of frames in which the last frame is the global environment.
• Implemented as a list of frames.
Data structures package:E2
…
…
E3
E1
<procedure (var) … >
<procedure (var) … >
5
The environment model evaluator and compilerThe env model evaluator Structure & implementation
Data structures package:
A closure: The data structure representing a procedure value includes, in
addition to its params and body, also the env in which the procedure has been
declared. This env is to be extended when applying the procedure.
P:B:
env
6
The environment model evaluator and compilerThe env model evaluator Structure & implementation
“Our” global environment is referenced by a variable in Dr. Racket!
• A finite sequence of frames in which the last frame is the global environment.
• Implemented as a list of frames.
t-g-e
“ Dr.Rackets’s global environment “
<procedure (var) … >
7
(define env-eval (lambda (exp env) (cond ((atomic? exp) (eval-atomic exp env)) ((special-form? exp) (eval-special-form exp env)) ((application? exp) (apply-procedure (env-eval (operator exp) env) (list-of-values (operands exp) env))) (else (error 'eval "unknown expression type: ~s" exp)))))
env-eval (interpreter-core.scm)
The environment model evaluator and compilerThe env model evaluator Structure & implementation
The environment model evaluator and compiler
8
The env model evaluator Example 1
> (env-eval '(define f (lambda (x) (lambda (y) (+ x y)))) t-g-e)
(define eval-special-form (lambda (exp env) (cond ... ((definition? exp) (if (not (eq? env t-g-e)) (error 'eval "non global definition: ~s" exp) (eval-definition exp))) ...)))
(define eval-definition (lambda (exp) (add-binding! (make-binding (definition-variable exp) (env-eval (definition-value exp) t-g-e))) 'ok))
9
The environment model evaluator and compiler
(define eval-special-form (lambda (exp env) (cond ... ((lambda? exp) (eval-lambda exp env)) ... )))
(define eval-lambda (lambda (exp env) (make-procedure (lambda-parameters exp) (lambda-body exp) env)))
The env model evaluator Example 1
> (env-eval '(define f (lambda (x) (lambda (y) (+ x y)))) t-g-e)
10
The environment model evaluator and compiler
(define make-procedure (lambda (parameters body env) (attach-tag (list parameters body env) 'procedure))) P:
B:
env
Q: Why use list and not just return '(procedure (x) (lambda (y) (+ x y)) t-g-e)?
A: If we did, t-g-e would have been quoted, thus producing a symbol instead of
the data structure that represents the global environment used by our evaluator.
The env model evaluator Example 1
> (env-eval '(define f (lambda (x) (lambda (y) (+ x y)))) t-g-e)
11
The environment model evaluator and compiler
Back to the original expression: Bind f with the created closure in our GE.
(add-binding! (make-binding f (list 'procedure '(x) '(lambda (y) (+ x y)) t-g-e)))
(define eval-definition (lambda (exp) (add-binding! (make-binding (definition-variable exp) (env-eval (definition-value exp) t-g-e))) 'ok))
The env model evaluator Example 1
> (env-eval '(define f (lambda (x) (lambda (y) (+ x y)))) t-g-e)
12
The environment model evaluator and compiler
> (env-eval ‘f t-g-e)
(define eval-atomic (lambda (exp env) (if (or (number? exp) (boolean? exp) (null? exp)) exp (lookup-variable-value exp env))))
• We look up f in the given env.
• The result is our representation of a procedure: a tagged list storing the body, the
params and the env where the procedure was defined.
The env model evaluator Example 2
The environment model evaluator and compiler
> (env-eval '(define g (f 1) ) t-g-e)
(apply-procedure (procedure (x) ((lambda (y) (+ x y))) t-g-e) (1))
Create a new frame where x maps to 1
GE
x: 1
13
The env model evaluator Example 3
(make-frame ‘(x) ‘(1))
Extend the envirounment
(extend-env new-frame t-g-e)
Evaluate the body
(eval-sequence body new-env)
The environment model evaluator and compiler
14
What is a let* expression?• Similar to a let, only that every defined variable can be used in the following definitions.
• Can be regarded as a nested let expression.
• The number of variables corresponds to the number of nested let expressions.
>(let* ((a 1) (c (* a 2)))(+ a c))
3
>(let ((a 1) (c (* a 2))) (+ a c))
21
>(define a 10)
>(let ((a 1)) (let ((c (* a 2))) (+ a c)))
>((λ (a) ((λ (c) (+ a c)) (* a 2)) 1)
Supporting a let* expression
The env model evaluator Adding a let* exp
The environment model evaluator and compiler
15
Evaluation rule for let* expressions: The evaluation rule for an expression (let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm), with respect to
an environment E0, is defined as follows:
E1 E0 * make-frame [(v1),(env-eval e1 E0)]E2 E1 * make-frame [(v2),(env-eval e2 E1)]...En En-1* make-frame [(vn),(env-eval en En-1)]
(env-eval b1 En) ... (env-eval bm-1 En)
Return (env-eval bm En)
Q: How would the evaluation rule for let look like?A: There will be only one frame extending E0 and creating a new environment E1.
All of the expressions e1…en will be evaluated with respect to E0.
The env model evaluator Adding a let* expression
The environment model evaluator and compiler
16
Supporting a let* expression: As a special form
1. Add the required ADT procedures to the ASP
ASPASP
Derived expressions
Derived expressions
Core
Special forms
Data Structures(+GE)
(define (let*? exp) (tagged-list? exp 'let*))
(define let*-bindings cadr)
(define let*-body cddr)
(define (let*-variables exp) (map car (let*-bindings exp)))
(define (let*-initial-values exp) (map cadr (let*-bindings exp)))
(define (let*-first-variable exp) (caar (let*-bindings exp)))
(define (let*-first-initial-value exp) (cadar (let*-bindings exp)))
(define (make-let*-bindings vars vals) (map list vars vals))
(define (make-let* bindings body) (append (list 'let* bindings) body))
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
The environment model evaluator and compilerThe env model evaluator Adding let* as a special form
17
2. Add the required changes to identify a let* expression as a special formASP
Derived expressions
Core
Special forms
Data Structures(+GE)
(define (special-form? exp) (or (quoted? exp) (lambda? exp) (definition? exp) (if? exp) (begin? exp) (let*? exp)))
(define (eval-special-form exp env) (cond ((quoted? exp) (text-of-quotation exp)) ((lambda? exp) (eval-lambda exp env)) … ((let*? exp) (eval-let* exp env))))
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
How would eval-let* work?
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model evaluator Adding let* as a special form
18
3. Add the required changes to evaluate a let* expression
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
(define (eval-let* exp env) (let ((body (let*-body exp))) (if (null? (let*-bindings exp)) (eval-sequence body env) (let ((first-var (let*-first-variable exp)) (first-val (let*-first-initial-value exp)) (rest-bindings (let*-rest-bindings exp))) (eval-let* (make-let* rest-bindings body) (extend-env (make-frame (list first-var) (list (env-eval first-val env))) env))))))
Option A: Create a new, smaller let* expression and recursively evaluate it with respect to an extended env.
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model evaluator Adding let* as a special form
19
(define (eval-let*expenv) (let ((vars (let*-variablesexp)) (vals (let*-initial-valuesexp)) (body (let*-bodyexp))) (letrec ((helper (lambda (vars-lst vals-lst env) (if (null? vars-lst) (eval-sequence body env) (helper (cdr vars-lst) (cdr vals-lst) (extend-env (make-frame (list (carvars-lst)) (list (env-eval (car vals-lst) env))) env)))))) (helper vars vals env))))
Option B: Keep extending the given env with new frames. When vars-lst becomes empty, No more extensions are needed. It only remain to evaluate the body.
(let* ((v1 e1) (v2 e2) … (vn en)) b1 b2 … bm)
3. Add the required changes to evaluate a let* expression
Q: How is option B different from option A?A: In option A we create code in run-time (when calling make-let*).
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model evaluator Adding let* as a special form
20
1. Add the required ADT procedures to the ASP: Same as earlier!
ASPASP
Derived expressions
Derived expressions
Core
Special forms
Data Structures(+GE)
2. Add the required changes to identify a let* expression as a derived
expression(define (derived? exp) (or (cond? exp) (function-definition? exp) (let? exp) (let*? exp)))
(define (shallow-derive exp) (cond ((cond? exp) (cond->if exp)) … ((let*? exp) (let*->nested-let exp)) (else "Unhandled derivision" exp)))
3. Support a let* expression in the shallow-derive procedure
How will let*->nested-let work?
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model evaluator Adding let* as a derived exp
21
4. Provide with a procedure to derive a let* expression(define (let*->nested-let exp) (let ( (bindings (let*-bindings exp)) (body (let*-body exp)) ) (if (null? (cdr bindings)) (derive (make-let bindings body)) (derive (make-let (make-let-bindings (list (let*-first-variable exp))
(list (let*-first-initial-value exp))) (list (let*->nested-let (make-let* (cdr bindings) body))))))))
Q1: Why do we use derive in the body of let*->nested-let?A1: We derive let* into nested let expressions, but let is a derived expression itself. We must derive it so the evaluator can handle it.
Q2: In the alternative clause, we enclose the body parameter for make-let in a list. Why?A2: Since the body may include a sequence of expressions, make-let expects a list. let*->nested-let returns a single expression, so we must enclose it within a list to be given as an argument to make-let.
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model evaluator Adding let* as a derived exp
22
• Env-eval combines expression analysis and evaluation in the same process.
• This leads to inefficiency due to repeated analysis (repeated calls for ASP procedures).
• We avoid this by separating analysis from evaluation.
• This could not be achieved in the substitution model, where every application involves
substitution and analysis.
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model compiler What is it good for?
We analyze our code, producing a procedure that is ready for execution, given an
environment argument. The procedure returns the evaluation of the analyzed code with
respect to the given environment. No analysis is performed during the evaluation.
(define env-eval (lambda (exp env) <body>))
(define analyze (lambda (exp) (lambda (env) <analyzed -body>)))
23
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compiler
(define fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1))))))
Compiler:
• To avoids repeated analysis, Takes an exp, performs analysis in static time and returns
a procedure that awaits an environment argument.
• Once the procedure is applied, it evaluates the analyzed exp with respect to the given
environment. No further analysis is performed.
Interpreter:
Each time fact is called, the interpreter repeatedly uses ASP
procedures to identify the body as an if expression and to get
the required components for evaluation.
env-eval:Exp*Env->Scheme-Type
compiler:Exp->[Env->Scheme-Type]
The env model compiler What is it good for?
24
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compiler
(define (analyze exp) (cond ((atomic? exp) (analyze-atomic exp)) ((special-form? exp) (analyze-special-form exp)) ((application? exp) (analyze-application exp)) (else (error "Unknown expression type -- EVAL“ exp))))
The env model compiler Example
(define (eval-if exp env) (if (true? (env-eval (if-predicate exp) env)) (env-eval (if-consequent exp) env) (env-eval (if-alternative exp) env)))
Evaluator code for if-expression
(define (analyze-if exp) (let ((pred (analyze (if-predicate exp))) (consequent (analyze (if-consequent exp))) (alternative (analyze (if-alternative exp)))) (lambda (env) (if (true? (pred env)) (consequent env) (alternative env)))))
Compiler code for if-expression
The analysis of an if expression is performed only once. It saves us the calls for ASP procedure for the evaluation during run-time. The returned procedure performsevaluation only.
25
(define (analyze-special-form exp) (cond ((quoted? exp) (analyze-quoted exp)) ((lambda? exp) (analyze-lambda exp)) … ((let*? exp) (analyze-let* exp))))
How will analyze-let* work?
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model compiler Adding a let* expression
What should be done to add let* as a derived expression?Same thing we did with the evaluator!
How would we support a let* expression as a special form?1. Add the required ADT procedures to the ASP
2. identify a let* expression as a special form
3. Support a let* expression in the analyze-special-form procedure:
26
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model compiler Adding a let* expression
4. Provide with a procedure to analyze a let* expression:• Take an evaluator procedure that evaluates a let* expression.• Curry the env parameter.• inductively apply analyze to all sub expressions.
(define (eval-let* exp env) (let ((body (let*-body exp))) (if (null? (let*-bindings exp)) (eval-sequence body env) (let ((first-var (let*-first-variable exp)) (first-val (let*-first-initial-value exp)) (rest-bindings (let*-rest-bindings exp))) (eval-let* (make-let* rest-bindings body) (extend-env (make-frame (list first-var) (list (env-eval first-val env))) env))))))
Option A: What’s wrong with it?
It produces code on run-time, which we cannot analyze. Analysis is
performed ONLY on static time, before evaluation!
27
The environment model evaluator and compilerSupporting a let* expression: As a special formThe environment model evaluator and compilerThe env model compiler Adding a let* expression
The second version for eval-let* (option B) translated into analyze-let*:(define (analyze-let* exp) (let ( (vars (let*-variables exp)) (vals (map analyze (let*-initial-values exp))) (body (analyze-sequence (let*-body exp))) ) (letrec ((helper (lambda (vars-lst vals-lst env) (if (null? vars-lst) (body env) (helper (cdr vars-lst) (cdr vals-lst) (extend-env (make-frame (list (car vars-lst)) (list ((car vals-lst) env))) env)))))) (lambda (env) ;letrc body – carrying (helper vars vals env)))))
Note: If we were to support let* as a derived expression, we would have used derive-analyze-eval