The environment-based operational semantics

73
The environment-based operational semantics Chapter 4.3 1

description

The environment-based operational semantics. Chapter 4.3. What’s Wrong with Substitution?. On every application we have to: Rename and substitute: heavy operations Analyze the body (ask what kind of expression it is etc ) mixed value/expression. Evaluator value distinction required. - PowerPoint PPT Presentation

Transcript of The environment-based operational semantics

Page 1: The environment-based operational semantics

1

The environment-based operational semantics

Chapter 4.3

Page 2: The environment-based operational semantics

2

What’s Wrong with Substitution?

• On every application we have to:– Rename and substitute: heavy operations– Analyze the body (ask what kind of expression it is

etc)• mixed value/expression. Evaluator value

distinction required

Page 3: The environment-based operational semantics

3

The Environment Based Operational Semantics

• Replace local variable management Substitution with A hierarchical environment structure.

• The env-eval algorithm evaluates an expression with respect to an environment.

• Advantage: – Directly access local variables (procedures are

pure code, no need for evaluator value distinction.– Later: Body of procedure may be analyzed once.

Page 4: The environment-based operational semantics

4

The Environments Model

Name Value

Environment Table

23score

Substitution model: a single global environment

Environments model: many environments.

Page 5: The environment-based operational semantics

5

Binding: a pairing of a name and a valueFrame: a table of bindings

Example: x is bound to 15 in frame A y is bound to (1 2) in frame A the value of the variable x in frame A is 15

21

x: 15

A

y:

Page 6: The environment-based operational semantics

6

Environment: a sequence of frames• Environment E1 consists of frames A and B

• Environment E2 consists of frame B only(A frame may be shared by multiple environments)

z: 10

B

E1

E2

x: 15

A

21

y:

this arrow is calledthe enclosing

environment pointer

Page 7: The environment-based operational semantics

7

Evaluation in the environment model• All evaluations occur with respect to an environment

• The current environment changes when theinterpreter applies a procedure

• The top environment is called the global environment (GE)

• Only the GE has no enclosing environment

Page 8: The environment-based operational semantics

8

The environment data structureframe is a list of bindings, a variable-value mapping: Variable –> Scheme-type.

environment is a finite sequence of frames E=<f1, f2,..., fn>.

environment diagram

Page 9: The environment-based operational semantics

9

Operations on environments and frames:

Page 10: The environment-based operational semantics

10

Operations on environments and frames:

Page 11: The environment-based operational semantics

11

Operations on environments and frames:

Page 12: The environment-based operational semantics

12

The closure data structure• The closure is the value of a lambda expression.<Closure parameters, body, environment>.

• The components of a closure cl are denoted clparameters , clbody , clenvironment .

• The closure carries the environment it was constructed in.

• this enables the evaluator algorithm to have a lexical scoping policy.

Page 13: The environment-based operational semantics

13

The closure data structure• A closure carries an environment - the one containing all local

variables defined when it was created.

>(define f(let ((x 3)) (lambda(y) (+ x y)))

>(f 1)

The interpreter need to know that:• x=3 when evaluating B1.

• This local variable binding needs to be saved for future use of the closure corresponding to (lambda(y) (+ x y)).

• Procedure application involves an extension of that environment.

B2

B1

Page 14: The environment-based operational semantics

14

Double bubble: how to draw a procedure

(lambda (x) (* x x))

eval

lambda-rule

A compound procthat squares its

argument

#[proc-...]pr

int

Environmentpointer

Code pointer

parameters: xbody: (* x x)

Page 15: The environment-based operational semantics

15

The Environment Model Evaluation Algorithm

Page 16: The environment-based operational semantics

16

The Environment Model Evaluation Algorithm - continued

Page 17: The environment-based operational semantics

17

The Environment Model Evaluation Algorithm - continued

Page 18: The environment-based operational semantics

18

The Environment Model Evaluation Algorithm - continued

Page 19: The environment-based operational semantics

19

Notes• The recursive algorithm passes an 'env' parameter• env-eval consults or modify the environment structure in the following

steps:(a) Creation of a compound procedure (closure): Evaluation of a 'lambda'

expression (and 'let').(b) Application of a compound procedure (closure) –

the only way to add a frame (also 'let').(c) Evaluation of 'define' expression – adds a binding to the global

environment.(d) Evaluation of a variable.

• De-allocation of frames: garbage collection...• An environment corresponds to a lexical scope

Page 20: The environment-based operational semantics

20

Example 4.7.>(define member

(lambda (x list)(cond ((null list) (list))

((eq? x (car list)) list)(else (member x (cdr list)))))

>(define a (list ’a ’b ’c))>(member ’b a)

Drawing environment diagrams is a way to represent the computation of the env-eval algorithm.

Page 21: The environment-based operational semantics

21

Example 4.8. Try a "curried" version of member:>(define c_member

(lambda (list)(lambda (el)

(cond ((null list) (list))((eq? el (car list)) list)(else ((c_member (cdr list))

el))))))

>(define a (list ’a ’b ’c))>(define search-a (c_member a))>(search-a 'b)

Page 22: The environment-based operational semantics

22

Example 4.5.

Page 23: The environment-based operational semantics

23

Example 4.6.

Page 24: The environment-based operational semantics

24

Static (Lexical) vs. Dynamic Scoping Policies(Section 4.3.3)

• Policies for interpreting variables (variable scoping) in a program.

• applicative-eval, normal-eval and env-eval algorithms have a Static (lexical) scoping policy. The nesting of lexical blocks determines the variable binding at run-time

• In dynamic scoping, a variable occurrences is bound by the most recent declaration of that variable.

• In dynamic scoping: the access link is defined by the control link and closures do not carry an environment.

• Do not confuse static scoping with static type-inference algorithms! => languages with static scoping policies allow for static type inference

Page 25: The environment-based operational semantics

25

dynamic-env-eval

Page 26: The environment-based operational semantics

26

Example 4.6.

• Not all evaluation algorithms are equivalent! dynamic-eval != env-eval(compute the same function, have the same domain)

Page 27: The environment-based operational semantics

27

Example 4.10.>(define f

(lambda (x) (a x x)))>(define g

(lambda (a x) (f x)))>(define a +)>(g * 3)

env-eval[(g*3),GE] ==> 6dynamic-env-eval[(g*3),GE] ==> 9

Page 28: The environment-based operational semantics

28

Example 4.12.>(define init 0)>(define 1+

(lambda(x)(+ x 1)))>(define f

(lambda (f1)(let ((f2 (lambda () (f1 init))))(let ((f1 1+) (init 1)) (f2) ))))

>(f (lambda (x) (* x x)))

env-eval[(f (lambda (x) (* x x)))] ==> 0dynamic-env-eval[(f (lambda (x) (* x x)))] ==> 2

Page 29: The environment-based operational semantics

29

4.4 The env-eval Evaluator Implementation

1. Abstract Syntax Parser (same as "applicative-eval" implementation) 2. Data structures - environment hierarchy, closures.3. Core ("env-eval" algorithm implementation)

; Type: [<Scheme-exp> -> Scheme-type](define derive-eval

(lambda (exp)(env-eval (derive exp) the-global-environment)))

Page 30: The environment-based operational semantics

Chapter 4 - Evaluators for Functional Programming

30

evaluator structure

Scheme expression

Value

evaluator

(Global) Environment

Page 31: The environment-based operational semantics

31

Files

Racket-Evaluators\env-functional-interpreter-compiler>dir

analyzer-core.rktanalyzer-tests.rktenv-ds.rktinterpreter-core.rktinterpreter-tests.rkt

Page 32: The environment-based operational semantics

32

4.4.2 Data Structures Package4.4.2.1 Procedure ADTs and their implementation

• Primitive procedure: same as in applicative-eval.

Page 33: The environment-based operational semantics

33

4.4.2 Data Structures Package4.4.2.1 Procedure ADTs and their implementation

• A Closure (procedure value) - contains an environment in which is was created

Page 34: The environment-based operational semantics

34

4.4.2 Data Structures Package4.4.2.1 Procedure ADTs and their implementation

• A Closure (procedure value) - contains an environment in which is was created

• Identify procedures in general

Page 35: The environment-based operational semantics

35

4.4.2.2 Environment related ADTs and their implementations:

• The interpreter holds a "DrRacket" variable the-global-environment

* Bindings, Frames, Environments.

Page 36: The environment-based operational semantics

36

4.4.2.2 Environment related ADTs and their implementations:The Binding ADT and its implementation:

Alternative definition:(define make-binding cons)(define binding-variable car)(define binding-value cdr)What is the difference?

var val

binding

Page 37: The environment-based operational semantics

37

4.4.2.2 Environment related ADTs and their implementations:The Frame ADT and its implementation:

(define make-frame (lambda (variables values) (make-sub variables values)))

(define make-sub (lambda (variables values) (let ((sub (list variables values))) (if (sub? sub) sub (error …)))))

Page 38: The environment-based operational semantics

38

4.4.2.2 Environment implementation• An environment is implemented as a list of boxed (mutable) frames.

environment

frame substitution

frame substitution

frame substitution

* in implementation language

box

variable->value lookup function

Racket box operationsbox(x)unbox(b)set-box!(b, y)

Page 39: The environment-based operational semantics

39

4.4.2.2 Global environment construction

Page 40: The environment-based operational semantics

40

Page 41: The environment-based operational semantics

41

(define lookup-variable-value (lambda (env var) (letrec ((defined-in-env (lambda (var env) (if (empty-env? env) env (let ((b (get-value-of-variable (first-frame env) var))) (if (eq? b '_not-found) (defined-in-env var (enclosing-env env)) b)))))) (let ((b (defined-in-env var env))) (if (empty? b) (error 'lookup "variable not found: ~s\n env = ~s" var env) b)))))

Page 42: The environment-based operational semantics

42

(define get-value-of-variable (lambda (sub var) (letrec ((lookup (lambda (vars vals) (cond ((or (empty-sub? sub) (not (member var vars))) '_not-found) ((eq? var (car vars)) (car vals)) (else (lookup (cdr vars) (cdr vals))))))) (lookup (get-variables sub) (get-values sub)))))

Page 43: The environment-based operational semantics

43

; Global environment mutator: ADT type is [Binding -> Unit]; Type: [PAIR(Symbol,T) -> Unit]; Note: Mutation is enabled only for the global environment(define add-binding! (lambda (binding) (let ((frame (first-frame the-global-environment))) (set-box! (first-boxed-frame the-global-environment) (extend-frame binding frame)))))

Page 44: The environment-based operational semantics

44

4.4.1.1 Main evaluator loop:

Page 45: The environment-based operational semantics

45

Page 46: The environment-based operational semantics

46

Page 47: The environment-based operational semantics

47

4.4.1.2 Evaluation of atomic expressions

Page 48: The environment-based operational semantics

48

Page 49: The environment-based operational semantics

49

Page 50: The environment-based operational semantics

50

Page 51: The environment-based operational semantics

4.4.1.4 Evaluation of applications

; Type: [Evaluator-procedure*LIST -> Scheme-type](define apply-procedure (lambda (procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (let* ((parameters (procedure-parameters procedure)) (body (procedure-body procedure)) (env (procedure-environment procedure)) (new-env (extend-env (make-frame parameters arguments) env))) (eval-sequence body new-env))) (else (error 'apply "unknown procedure type: ~s" procedure)))))

Page 52: The environment-based operational semantics

52

Primitive procedure application

Page 53: The environment-based operational semantics

53

Testing(define (app-lambda-tests) (test (derive-eval '((lambda (x) x) 12)) => 12) (test

(derive-eval '((lambda (x y z) (+ x y z)) 12 13 14))

=> 39)...

)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Invoking tests;;;;;;;;;;;;;;;;;;;;;;;;;;;;;(app-lambda-tests)

Page 54: The environment-based operational semantics

54

The Analyzer

So far, no distinction between syntax analysis and evaluation

For example: the kind of an expression (special form, application etc) can be decided statically.

Page 55: The environment-based operational semantics

55

Files

Racket-Evaluators\env-functional-interpreter-compiler>dir

analyzer-core.rktanalyzer-tests.rktenv-ds.rktinterpreter-core.rktinterpreter-tests.rkt

Page 56: The environment-based operational semantics

56

4.5.1 The Analyzer• Compile time (static time):

Things performed first, once if possible. – static syntax analysis

• Run time (dynamic time): Things performed later, as needed – data-structure (environments and closures) related

• Compile time is less expensive than run time.

• Analyzing a procedure body once, independently from its application, means compiling its code into something more efficient/optimal, which is ready for evaluation.

Page 57: The environment-based operational semantics

Chapter 4 - Evaluators for Functional Programming

57

analyzer structure

Scheme expression

Value

(Global) Environment

syntax-analysis(compilation)

run-time evaluation

Program in target

language

code in the implementation language.

Page 58: The environment-based operational semantics

58

4.5 An Environment-based FP Meta-Circular CompilerThe analyzer

• avoid repetition of syntax-analysis in every procedure application.

• Idea: separate static syntax analysis (syntax parsing)from run-time evaluation (closure/environment data-structure manipulation).

• means: curried function style.

Page 59: The environment-based operational semantics

59

An Environment-based FP Meta-Circular Compiler

The analyzer• Use curryingInterpreter: Compiler:(lambda (exp env) (lambda (exp)

syntax analysis+ syntax analysis run-time evaluation (performed once) returns(lambda(env)run-time evaluation

[Expression*Env->T] [Expression->[Env->T]]

• Compiler output is code in the implementation language.

Page 60: The environment-based operational semantics

60

Environment-based compiler(define derive-analyze-eval

(lambda(exp)((analyze (derive exp)) the-global-environment))

(define analyze(lambda (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)))))

Page 61: The environment-based operational semantics

61

Environment-based compiler• Interpreter: (define eval-atomic

(lambda (exp env)(if (or (number? exp) (boolean? exp) (null? exp))exp(lookup-variable-value exp env))))

• Compiler: (define analyze-atomic

(lambda (exp)(if (or (number? exp) (boolean? exp) (null? exp))(lambda (env) exp)(lambda (env) (lookup-variable-value exp env)))))

Page 62: The environment-based operational semantics

62

Environment-based compiler• Interpreter:(define eval-if

(lambda (exp env)(if (true? (env-eval (if-predicate exp) env))(env-eval (if-consequent exp) env)(env-eval (if-alternative exp) env))))

• Compiler:(define analyze-if

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

Page 63: The environment-based operational semantics

63

Environment-based compiler• Interpreter(define eval-lambda

(lambda (exp env)(make-procedure (lambda-parameters exp)

(lambda-body exp) env)))

• Compiler - body is analyzed once!(define analyze-lambda

(lambda (exp)(let ((parameters (lambda-parameters exp)) (body (analyze-sequence (lambda-body exp)))) (lambda (env)

(make-procedure parameters body env))))

Page 64: The environment-based operational semantics

64

Environment-based compiler(define analyze-sequence

(lambda (exps)(let ((procs (map analyze exps)) (last-in-list (lambda (lst) (car (reverse

lst))))) (if (null? procs)

(error "Empty sequence -- ANALYZE"))(lambda (env) (let ((vals (map (lambda (proc)(proc env))

procs))) (last-in-list vals)))))

• relies on the order of map in the underlining (implementation) Scheme.

Page 65: The environment-based operational semantics

65

Environment-based compiler• Interpreter(define eval-special-form

(lambda (exp env)(cond ...

((definition? exp)(if (not (eq? env the-global-

environment)) (error "Non global definition" exp) (eval-definition exp)))

...(define eval-definition

(lambda (exp)(add-binding!

(make-binding (definition-variable exp) (env-eval (definition-value exp)

the-global-environment)))’ok))

Page 66: The environment-based operational semantics

66

Environment-based compiler• Compiler:(define (analyze-definition

(lambda (exp)(let ((var (definition-variable exp)) (val (analyze (definition-value exp)))) (lambda (env)

(if (not (eq? env the-global-environment)) (error "Non global definition" exp) (begin (add-binding!

(make-binding var (val the-global-

environment))) ’ok))))))

Page 67: The environment-based operational semantics

67

• Interpreter:(define env-eval

(lambda (exp env)(cond ... ((application? exp)(apply-procedure (env-eval (operator exp) env) (list-of-values (operands exp) env)))...

Compiler: (define analyze

(lambda (exp)(cond ... ((application? exp) (analyze-application exp))...

(define analyze-application(lambda (exp)(let ((application-operator (analyze (operator exp))) (application-operands (map analyze (operands exp)))) (lambda (env)(apply-procedure(application-operator env)(map (lambda (operand) (operand env)) application-operands))))))

Page 68: The environment-based operational semantics

68

• Interpreter:(define apply-procedure (lambda (procedure args)

(cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure args))

((compound-procedure? procedure) (let

((proc-params (procedure-parameters procedure))

(proc-body (procedure-body procedure))(proc-env (procedure-environment procedure)))

(eval-sequence proc-body

(extend-env (make-frame proc-params args)

proc-env))(else (error ... )))))

Page 69: The environment-based operational semantics

69

• Compiler - evaluation of analyzed operator on extended environment(define apply-procedure

(lambda (procedure args) (cond ((primitive-procedure? procedure)

(apply-primitive-procedure procedure args)) ((compound-procedure? procedure)

(let ((proc-params (procedure-parameters procedure)))

(proc-abody (procedure-body procedure))

(proc-env (procedure-environment procedure)))

(proc-abody (extend-env

(make-frame proc-params args) proc-env))

(else (error ... )))))

Page 70: The environment-based operational semantics

70

No repeated analysis - Tracing example> (require racket/trace) > (trace analyze)> (derive-analyze-eval ’(define (factorial n) (if (= n 1) 1 (*

(factorial (- n 1)) n)))| (analyze (define factorial (lambda(n) (if (= n 1) 1 (* (factorial (- n

1)) n))))| |(analyze (lambda (n) (if (= n 1) 1 (* (factorial (- n 1)) n))))| | (analyze (if (= n 1) 1 (* (factorial (- n 1)) n)))| | |(analyze (= n 1))| | | (analyze =)| | | #<procedure>| | | (analyze n)| | | #<procedure>| | | (analyze 1)| | | #<procedure>| | |#<procedure> // returned from analyze '(= n 1)

Page 71: The environment-based operational semantics

71

| | |(analyze 1)| | |#<procedure>| | |(analyze (* (factorial (- n 1)) n))| | | (analyze *)| | | #<procedure>| | | (analyze (factorial (- n 1)))| | | |(analyze factorial)| | | |#<procedure>| | | |(analyze (- n 1))| | | | (analyze -)| | | | #<procedure>| | | | (analyze n)| | | | #<procedure>| | | | (analyze 1)| | | | #<procedure>| | | |#<procedure> // returned from analyze '(- n 1) | | | #<procedure> // returned from analyze '(factorial (- n 1))| | | (analyze n)

Page 72: The environment-based operational semantics

72

No repeated analysis - example| | | #<procedure>| | |#<procedure> // returned from analyze '( * (factorial...| | #<procedure> // returned from analyze '(if ...| |#<procedure> // returned from analyze '(lambda ...| #<procedure> // returned from analyze '(define ...)|ok // returned from application on the-global-environment

> (derive-analyze-eval ’(factorial 4))|( (analyze (factorial 4)) the-global-environment)| (analyze (factorial 4))| |(analyze factorial)| |#<procedure> // returned from analyze 'factorial| |(analyze 4)| |#<procedure> // returned from analyze 4| #<procedure> // returned from analyze '(factorial 4)|24 // returned from application on the-global-environment

// no recursive analysis when recursive analyzed procedure is applied!!

Page 73: The environment-based operational semantics

73

Chapter 4 Summary• Interpreter algorithms that have a static scoping policy:

applicative-eval, env-eval and normal-eval are functionally equivalent (on the domain conjunction).

• An interpreter algorithm that has a dynamic scoping policy.dynamic-env-eval

• Implementations for applicative-eval, env-eval :use ASP (incl. handling expression derivation), Data structures (environments, procedure and other values), have test modules.

• Analyzer optimization for the environment based interpreter.