Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Evaluators for Functional Programming Evaluators for Functional Programming 1 How to describe (specify) a programming language? 1. Syntax: atoms, primitives, combination and abstraction means. 2. Semantics: values, types. 3. Operational semantics: evaluation rules, evaluator algorithm. Evaluators for Functional Programming 2 Evaluator for Functional Programming • meta-circular : – Interpreted language = our flavor of Scheme –(embedding) language = Scheme • We will see three evaluators for FP: 1. Substitution evaluator (impl. applicativeeval) 2. Environment-based evaluator (uses an environment data structure) 3. Environment-based compiler Evaluators for Functional Programming 3 Evaluator Structure evaluator program in interpreted language eval (Global) Environment substitute reduce Value from interpreted language values written in Implementation (embedding) language Evaluators for Functional Programming 4 common evaluator structure evaluator program in interpreted language (Global) Environment abstract syntax parser parsed expression (parse tree) eval substitute reduce Evaluators for Functional Programming Value from interpreted language values 5 basic compiler structure program in interpreted language Value from target language values compiler abstract syntax parser parsed expression (parse tree) compilation execution/ evaluation program in target language Evaluators for Functional Programming Global Environment 6 evaluator structure evaluator Scheme expression (Global) Environment Code in: Racket-Evaluators\substitution-interpreter\ Evaluators for Functional Programming Value 7 Input • Input: a scheme expression or an already evaluated scheme expression (in case of repeated evaluation). (lambda (lst) (car (car lst)) • Input is accepted in the form of constant lists. '(lambda (lst) (car (car lst))) (list 'lambda (list 'lst) (list 'car (list 'car 'lst)) • uniformity of Scheme expressions and the printed form of lists. Evaluators for Functional Programming 8 Input > (derive-eval '(+ 1 2) ) 3 > (derive-eval (list 'lambda (list 'lst) (list 'car (list 'car 'lst)) )) (procedure (lst) ((car (car lst)))) > (derive-eval '(lambda (lst) (car (car 'lst))) ) (procedure (lst) ((car (car lst)))) > (derive-eval (lambda (lst) (car (car lst)) )) . . ASP.scm:247:31: car: expects argument of type <pair>; given #<procedure> Evaluators for Functional Programming 9 Abstract Syntax Parser (ASP) A tool that 1. Identifies the kind of an input expression (atomic, lambda, application, etc) 2. Select the components of a Scheme expression 3. Construct a Scheme expression from its components Impl. an interface for Scheme Expression, according to Abstract Syntax of Scheme: ADT! Evaluators for Functional Programming 10 Derived Expressions Language expression have two classes: • Kernel (core knows what to do with them) • Derived (rewritten using kernel expressions – more on that later) Evaluators for Functional Programming 11 Tagged-data interface and impl. Evaluators for Functional Programming 12 Tagged-data interface and impl. Evaluators for Functional Programming 13 Parser procedures - atomic exp. Evaluators for Functional Programming 14 Parser procedures - compound exp. Evaluators for Functional Programming 15 Parser procedures - compound exp. Evaluators for Functional Programming 16 Parser procedures - compound exp. Evaluators for Functional Programming 17 Parser procedures - compound exp. Evaluators for Functional Programming 18 Parser procedures - compound exp. Evaluators for Functional Programming 19 Parser procedures - compound exp. Evaluators for Functional Programming 20 Parser procedures - compound exp. Evaluators for Functional Programming 21 Parser procedures - compound exp. letrec - similar functions... Evaluators for Functional Programming 22 Parser procedures - compound exp. Evaluators for Functional Programming 23 Parser procedures - application • The application expression is special compound expression: It does not have a tag. Evaluators for Functional Programming 24 ASP - Derived Expressions 'derived' expression are translated into 'core' expressions (according to syntactic sugar/macro rule), before being evaluated. Derivation procedures are part of the ASP ; Signature: derive(exp) ; Type: [Scheme-exp -> Scheme-exp] Evaluators for Functional Programming 25 ASP - Derived Expressions (let ((x (+ y 2)) (y (- x 3))) (* x y)) ((lambda (x y) (* x y)) (+ y 2) (- x 3)) (define let->combination (lambda (exp) (let ((vars (let-variables exp)) (body (let-body exp)) (initial-vals (let-initial-values exp))) (make-application (make-lambda vars body) initial-vals)))) Evaluators for Functional Programming 26 ASP - Derived Expressions (define (f x y) (display x) (+ x y)) (define f (lambda (x y) (display x) (+ x y))) (define function-define->define (lambda (exp) (let ((var (function-definition-variable exp)) (params (function-definition-parameters exp)) (body (function-definition-body exp))) (make-definition var (make-lambda params body))))) Evaluators for Functional Programming 27 ASP - Derived Expressions (cond ((> x 0) x) ((= x 0) (display ’zero) 0) (else (- x))) (if (> x 0) x (if (= x 0) (begin (display ’zero) 0) (- x))) • cond->if Evaluators for Functional Programming 28 ASP - Derived expressions (cond ((> x 0) x) (else (cond ((= x 0) 0) (else (- x)))))) shallow derivation (if (> x 0) x (cond ((= x 0) 0) (else (- x)))) deep (recursive) derivation (if (> x 0) x (if(= x 0) 0 (- x))) Evaluators for Functional Programming 29 ASP - Derived expressions (let*((x 10) (y (+ x 2)) (+ x y)) shallow derivation (let((x 10)) (let ((y (+ x 2))) (+ x y))) recursive derivation until fixed point achieved ((lambda(x) (let ((y ....)) 10) Evaluators for Functional Programming 30 Evaluators for Functional Programming 31 Evaluators for Functional Programming 32 evaluator structure evaluator Scheme expression (Global) Environment Code in: Racket-Evaluators\substitution-interpreter\ Evaluators for Functional Programming Value 33 Applicative-Eval Evaluator Core data structures: 1. Evaluated values 2. The global environment – managing "global" variable-value bindings. Evaluators for Functional Programming 34 Evaluated Values • Repeated evaluation of compound values: applicative-eval[((λ (lst)(car lst)) (list 1 2 3))] applicative-eval[(λ (lst)(car lst))] <== <Closure (lst)(car lst) > applicative-eval[(list 1 2 3)] <== (1 2 3) // evaluated value of list applicative-eval[ (car (1 2 3)) ] ==> applicative-eval[car] <== Code of car. applicative-eval[(1 2 3)] <== "error: 1 is not a procedure" • Same problem for values of lambda, quote (and other possible compound values) and primitive procedures. • Need to identify (tag), evaluated values. Evaluators for Functional Programming35 Evaluated values ADTs Primitive-procedure Procedure Other make-primitive-procedure [T -> Primitive-procedure] primitive-procedure? [T –> Boolean] primitive-implementation [Primitive-procedure –> T] make-procedure [LIST(Symbol)*LIST –> Procedure] compound-procedure? procedure-parameters [Procedure –> LIST(Symbol)] procedure-body [Procedure –> LIST] make-value value? value-content Evaluators for Functional Programming 36 Primitive procedure - Impl. Evaluators for Functional Programming 37 Procedure - Impl. Evaluators for Functional Programming 38 evaluator structure evaluator Scheme expression (Global) Environment Code in: Racket-Evaluators\substitution-interpreter\ Evaluators for Functional Programming Value 39 The global environment GE procedures: Evaluators for Functional Programming 40 The global environment • mutable binding management. mapping from "global" variables to values. • make-binding • binding-variable • Binding-value Evaluators for Functional Programming 41 evaluator structure evaluator Scheme expression (Global) Environment Code in: Racket-Evaluators\substitution-interpreter\ Evaluators for Functional Programming Value 42 Applicative-Eval Evaluator - core • • • • • • • Implementation of applicative eval algorithm. Derives expressions Special form/Atomic/Application Application: Eval-substitute-reduce (recursive). Has 'rename' and 'substitute' sub-routines Uses: ASP (parser), GE packages Creates Evaluated Values and returns them. Evaluators for Functional Programming 43 Applicative-Eval Evaluator - core Evaluators for Functional Programming 44 Applicative-Eval Evaluator - core Evaluators for Functional Programming 45 Applicative-Eval Evaluator - core Evaluators for Functional Programming 46 Applicative-Eval Evaluator - core atomic exp. Evaluators for Functional Programming 47 Applicative-Eval Evaluator - core special forms Evaluators for Functional Programming 48 Applicative-Eval Evaluator - core special forms Evaluators for Functional Programming 49 Applicative-Eval Evaluator - core special forms Evaluators for Functional Programming 50 Applicative-Eval Evaluator - core application Evaluators for Functional Programming 51 Applicative-Eval Evaluator - core primitive procedure application Evaluators for Functional Programming 52 Applicative-Eval Evaluator - core substitution Evaluators for Functional Programming 53 evaluator structure evaluator Scheme expression (Global) Environment Code in: Racket-Evaluators\substitution-interpreter\ Evaluators for Functional Programming Value 54 Applicative-Eval Evaluator - tests > (derive-eval '(* 3 4)) '(value 12) > (derive-eval '((lambda (f) (f 2 1)) +)) '(value 3) Regression tests: (test (derive-eval '(* 3 4)) => '(value 12)) (test (derive-eval '(cons 3 (cons 4 (list)))) => '(value (3 4))) (test (derive-eval '((lambda (f) (f 2 1)) +)) => '(value 3)) (test (derive-eval '(begin 1 2 3)) => '(value 3)) (test (derive-eval '(begin 1 2 3)) => '(value 3)) (test (derive-eval '(define x 2)) => 'ok) (test (derive-eval '(define (f x) (+ x x))) => 'ok) (test (derive-eval 'x) => '(value 2)) (test (derive-eval '(f x)) => '(value 4)) (test (derive '(let ((x 1)) (+ x 1))) => '( (lambda (x)(+ x 1)) 1)) Evaluators for Functional Programming 55 The environment-based operational semantics 56 Why Substitute? • Because we needed the values of the variables. 57 Ok, So What’s Wrong with Substitution? • On every application we have to: – Rename – Substitute – Analyze the body (ask what kind of expression it is etc) • Mixed value/expression. Evaluator value distinction required 58 New Way to get the Value of a Variable: The Environment Model 59 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. 60 The Environments Model Substitution model: a single global environment Environment Table Name score Value 23 Environments model: many environments. 61 Binding: a pairing of a name and a value Frame: 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 A x: 15 y: 2 1 62 Environment: a finite 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) B E2 z: 10 this arrow is called the enclosing environment pointer A E1 x: 15 y: 1 63 2 Evaluation in the environment model • All evaluations occur with respect to an environment • The current environment changes when the interpreter applies a procedure • The top environment is called the global environment (GE) • Only the GE has no enclosing environment 64 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 65 Operations on environments and frames: 66 Operations on environments and frames: 67 Operations on environments and frames: 68 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. 69 The closure data structure • A closure carries an environment - the one containing all local variables defined when it was created. >(define f B (let ((x 3)) 1 (lambda(y) (+ x y))) >(f 1) B2 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. 70 Double bubble: how to draw a procedure (lambda (x) (* x x)) #[proc-...] Environment pointer A compound proc that squares its argument Code pointer parameters: x body: (* x x) 71 The Environment Model Evaluation Algorithm 72 The Environment Model Evaluation Algorithm continued 73 The Environment Model Evaluation Algorithm continued 74 The Environment Model Evaluation Algorithm continued 75 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` 76 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. 77 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) 78 Example 4.5. 79 Example 4.6. 80 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 runtime • 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 81 dynamic-env-eval 82 Example 4.6. • Not all evaluation algorithms are equivalent! dynamic-eval != env-eval (compute the same function, have the same domain) 83 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 84 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 85 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))) 86 evaluator structure evaluator Scheme expression (Global) Environment Value Chapter 4 - Evaluators for Functional Programming 87 Files Racket-Evaluators\env-functional-interpreter-compiler>dir analyzer-core.rkt analyzer-tests.rkt env-ds.rkt interpreter-core.rkt interpreter-tests.rkt 88 4.4.2 Data Structures Package 4.4.2.1 Procedure ADTs and their implementation • Primitive procedure: same as in applicative-eval. 89 4.4.2 Data Structures Package 4.4.2.1 Procedure ADTs and their implementation • A Closure (procedure value) - contains an environment in which is was created 90 4.4.2 Data Structures Package 4.4.2.1 Procedure ADTs and their implementation • A Closure (procedure value) - contains an environment in which is was created • Identify procedures in general 91 4.4.2.2 Environment related ADTs and their implementations: • The interpreter holds a "DrRacket" variable the-global-environment * Bindings, Frames, Environments. 92 4.4.2.2 Environment related ADTs and their implementations: The Binding ADT and its implementation: binding var val Alternative definition: (define (define (define What is make-binding cons) binding-variable car) binding-value cdr) the difference? 93 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 …))))) 94 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 * in implementation language frame substitution variable->value lookup function 95 4.4.2.2 Global environment construction 96 97 (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))))) 98 (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))))) 99 ; 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))))) 100 4.4.1.1 Main evaluator loop: 101 102 103 4.4.1.2 Evaluation of atomic expressions 104 105 106 107 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)))) Primitive procedure application 109 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) 110 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. 111 Files Racket-Evaluators\env-functional-interpreter-compiler>dir analyzer-core.rkt analyzer-tests.rkt env-ds.rkt interpreter-core.rkt interpreter-tests.rkt 112 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. 113 analyzer structure Scheme expression code in the implementation language. syntax-analysis (compilation) Program in target language (Global) Environment run-time evaluation Value Chapter 4 - Evaluators for Functional Programming 114 4.5 An Environment-based FP Meta-Circular Compiler The analyzer • avoid repetition of syntax-analysis in every procedure application. • Idea: separate static syntax analysis (syntax parsing) from run-time evaluation (closure/environment datastructure manipulation). • means: curried function style. 115 An Environment-based FP Meta-Circular Compiler The analyzer • Use currying Interpreter: Compiler: (lambda (exp env) (lambda (exp) syntax analysis+ run-time evaluation syntax analysis (performed once) returns (lambda(env) [Expression*Env->T] run-time evaluation [Expression->[Env->T]] • Compiler output is code in the implementation language. 116 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 'eval "unknown expression type: ~s" exp))))) 117 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))))) 118 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)))))) 119 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)))) 120 Environment-based compiler (define analyze-sequence (lambda (exps) (let ((procs (map analyze exps))) (lambda (env) (let ((vals (map (lambda (proc) (proc env)) procs))) (last vals)))))) • relies on the order of map in the underlining (implementation) Scheme. 121 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)) 122 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)))))) 123 • 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)))))) 124 • 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 ... ))))) 125 • Compiler - evaluation of analyzed operator on extended environment (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))) (body new-env))) (else (error 'apply "unknown procedure type: ~s" procedure))))) 126 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) 127 | | |(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) | | | #<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 128 No repeated analysis - example > (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-globalenvironment // no recursive analysis when recursive analyzed procedure is applied!! 129 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. 130