730 likes | 833 Views
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.
E N D
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
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.
Substitution model: a single global environment Environment Table Name Value score 23 The Environments Model Environments model: many environments.
Example: xis bound to 15 in frame Ay is bound to (1 2) in frame A the value of the variable x in frame A is 15 A x: 15 y: 1 2 Binding: a pairing of a name and a value Frame: a table of bindings
B z: 10 E2 A x: 15 E1 y: 1 2 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) this arrow is calledthe enclosingenvironment pointer
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
The environment data structure frame 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
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.
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. B1 B2
(lambda (x) (* x x)) print Environmentpointer #[proc-...] evallambda-rule A compound procthat squares itsargument Code pointer parameters: xbody: (* x x) Double bubble: how to draw a procedure
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
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.
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)
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
Example 4.6. • Not all evaluation algorithms are equivalent! dynamic-eval != env-eval(compute the same function, have the same domain)
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] ==> 6 dynamic-env-eval[(g*3),GE] ==> 9
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)))] ==> 0 dynamic-env-eval[(f (lambda (x) (* x x)))] ==> 2
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)))
evaluator structure evaluator Scheme expression (Global) Environment Value Chapter 4 - Evaluators for Functional Programming
Files Racket-Evaluators\env-functional-interpreter-compiler>dir analyzer-core.rkt analyzer-tests.rkt env-ds.rkt interpreter-core.rkt interpreter-tests.rkt
4.4.2 Data Structures Package4.4.2.1 Procedure ADTs and their implementation • Primitive procedure: same as in applicative-eval.
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
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
4.4.2.2 Environment related ADTs and their implementations: • The interpreter holds a "DrRacket" variable the-global-environment * Bindings, Frames, Environments.
4.4.2.2 Environment related ADTs and their implementations:The Binding ADT and its implementation: binding var val Alternative definition: (define make-binding cons) (define binding-variable car) (define binding-value cdr) What is the difference?
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 …)))))
4.4.2.2 Environment implementation • An environment is implemented as a list of boxed (mutable) frames. • Racket box operations • box(x) • unbox(b) • set-box!(b, y) environment box frame substitution frame substitution frame substitution variable->value lookup function * in implementation language
(define lookup-variable-value (lambda (envvar) (letrec ((defined-in-env (lambda (varenv) (if (empty-env? env) env (let ((b (get-value-of-variable (first-frameenv) var))) (if (eq? b '_not-found) (defined-in-envvar (enclosing-envenv)) b)))))) (let ((b (defined-in-envvarenv))) (if (empty? b) (error 'lookup "variable not found: ~s\n env = ~s" varenv) b)))))
(define get-value-of-variable (lambda (sub var) (letrec ((lookup (lambda (varsvals) (cond ((or (empty-sub? sub) (not (member varvars))) '_not-found) ((eq? var (car vars)) (car vals)) (else (lookup (cdrvars) (cdrvals))))))) (lookup (get-variables sub) (get-values sub)))))
; 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)))))