27
1 nv 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..)

The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

Embed Size (px)

Citation preview

Page 1: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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..)

Page 2: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 3: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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) … >

Page 4: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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) … >

Page 5: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 6: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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) … >

Page 7: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 8: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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))

Page 9: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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)

Page 10: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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)

Page 11: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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)

Page 12: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 13: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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)

Page 14: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 15: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 16: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 17: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 18: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 19: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 20: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 21: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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

Page 22: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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>)))

Page 23: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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?

Page 24: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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.

Page 25: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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:

Page 26: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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!

Page 27: The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using

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