Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol.

Similar presentations


Presentation on theme: "1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol."— Presentation transcript:

1 1 Continue Evaluator

2 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol procedure symbol + symbol x

3 3 Representing the Environment (eval ‘(twice 4)) (extend-environment '(x) '(4) GE) GE x: 10 +: (primitive...) twice: (procedure..) E1 x: 4 Abstractly Concretely GE list of values list of variables frame x4 E1 x 10 + twice primitive

4 4 Representing the Environment (eval ‘(twice 5)) (extend-environment '(x) '(5) GE) GE list of values list of variables frame x4 E1 x 10 + twice primitive x5 E2

5 5 (define (lookup-variable-value var env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) (error "Unbound variable" var) (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env)) (define (frame-variables frame) (car frame)) (define (frame-values frame) (cdr frame)) (define (enclosing-environment env) (cdr env)) (define (first-frame env) (car env))

6 6 (define (define-variable! var val env) (let ((frame (first-frame env))) (define (scan vars vals) (cond ((null? vars) (add-binding-to-frame! var val frame)) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (scan (frame-variables frame) (frame-values frame)))) (define (eval-definition exp env) (let ((name (cadr exp)) (defined-to-be (eval (caddr exp) env))) (define-variable! name defined-to-be env) ‘undefined))

7 Assignments (define (eval-assignment exp env) (set-variable-value! (assignment-variable exp) (eval (assignment-value exp) env) env) 'ok) (define (assignment? exp) (tagged-list? exp 'set!)) (define (assignment-variable exp) (cadr exp)) (define (assignment-value exp) (caddr exp))

8 set-variable-value! (define (set-variable-value! var val env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) (error "Unbound variable -- SET!" var) (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))( (env-loop env))

9 9 Initialization primitives and initial env. (define the-empty-environment '()) (define the-global-environment (setup-environment)) (define (setup-environment) (let ((initial-env (extend-environment (primitive-procedure-names) (primitive-procedure-objects) the-empty-environment))) (define-variable! 'true #t initial-env) (define-variable! 'false #f initial-env) initial-env))

10 10 (define primitive-procedure (list (list 'car car) (list 'cdr cdr) (list 'cons cons) (list 'null? null?) (list '+ +) ;; more primitives )) (define (primitive-procedure-names) (map car primitive-procedures)) (define (primitive-procedure-objects) (map (lambda (proc) (list 'primitive (cadr proc))) primitive-procedures))

11 11 Read-Eval-Print Loop (define input-prompt ";;; M-Eval input:") (define output-prompt ";;; M-Eval value:") (define (prompt-for-input string) (newline) (newline) (display string) (newline)) (define (announce-output string) (newline) (display string) (newline)) (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-env))) (announce-output output-prompt) (user-print output))) (driver-loop))

12 12 SICP’s version of eval (define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (eval (cond->if exp) env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp))))

13 Apply (reminder) (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-env procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))

14 14 Note some minor differences like (define (self-evaluating? exp) (cond ((number? exp) true) ((string? exp) true) (else false))) (define (variable? exp) (symbol? exp)) (define (list-of-values exps env) (if (no-operands? exps) '() (cons (eval (first-operand exps) env) (list-of-values (rest-operands exps) env)))) (define (quoted? exp) (tagged-list? exp 'quote)) (define (text-of-quotation exp) (cadr exp))

15 15 Execution Examples An iterative algorithm in scheme (eval '(define odd (lambda (n) (odd (- n 2)))) GE) A recursive algorithm in scheme (eval '(define sum (lambda (n) (+ n (sum (- n 1))))) GE) Base case and if check omitted from both algorithms to simplify the example

16 16 (eval '(define odd (lambda (n) (odd (- n 2)))) GE) (eval '(odd 4) GE) [call apply, which creates E1: n = 4, then eval body of odd] (eval '(odd (- n 2)) E1) (apply (eval 'odd E1) (list (eval '(- n 2) E1))) [skip some steps in which (- n 2) ==> 2] (apply (list ’procedure '(n) '(odd (- n 2)) GE) '(2)) [apply creates E2: n = 2, then eval body of odd] (eval '(odd (- n 2)) E2)) No pending operations on the recursive call to eval

17 17 (eval '(define sum (lambda (n) (+ n (sum (- n 1))))) GE) (eval '(sum 4) GE) [call apply, which creates E1: n = 4, then eval body of sum] (eval '(+ n (sum (- n 1))) E1) (apply '(primitive #[add]) (list (eval 'n E1) (eval '(sum (- n 1)) E1))) [skip some steps in which (- n 1) ==> 3] (apply '(primitive #[add]) (list 4 (apply (eval 'sum E1) '(3)))) [apply creates E2: n = 3, then eval body of sum] (apply '(primitive #[add]) (list 4 (eval '(+ n (sum (- n 1))) E2)) There are pending operations on the recursive call to eval

18 18 Summary Cycle between eval and apply is the core of the evaluator eval calls apply with operator and argument values apply calls eval with expression and environment What is still missing from scheme ? Some special forms data types other than numbers and booleans

19 19 Note: Syntactic Abstraction Semantics What the language means Model of computation Syntax Particulars of writing expressions E.g. how to signal different expressions Separation of syntax and semantics: allows one to easily alter syntax eval/apply syntax procedures

20 20 Basic Syntax Routines to detect expressions (define (if? exp) (tagged-list? exp 'if)) (define (lambda? exp) (tagged-list? exp 'lambda)) (define (application? exp) (pair? exp)) Routines to get information out of expressions (define (operator app) (car app)) (define (operands app) (cdr app)) (define (first-operand args) (car args)) (define (rest-operands args) (cdr args)) Routines to build expressions (define (make-if predicate consequent alternative) (list 'if predicate consequent alternative))

21 21 Example – Changing Syntax Suppose you wanted a "verbose" application syntax: (CALL ARGS...) Changes – only in the syntax routines! (define (application? exp) (tagged-list? 'CALL)) (define (operator app) (cadr app)) (define (operands app) (cdddr app))

22 22 Implementing "Syntactic Sugar" Idea: Implement a simple fundamental "core" in the evaluator Easy way to add alternative/convenient syntax? "let" as sugared procedure application: (let (( ) ( )) ) ((lambda ( ) ) )

23 23 Detect and Transform the Alternative Syntax (define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp))... ((cond? exp) (eval (cond->if exp) env)) ((let? exp) (eval (let->combination exp) env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression" exp))))

24 24 Implementing cond: Syntax procedures (define (cond-clauses exp) (cdr exp)) (define (cond-else-clause? clause) (eq? (cond-predicate clause) 'else)) (define (cond-predicate clause) (car clause)) (define (cond-actions clause) (cdr clause)) (cond ((= x 23) (+ x 1)) (else (- x 1))) (if (= x 23) (+ x 1) (- x 1))

25 25 Cond syntax (cond ((= x 23) (+ x 1)) (else (- x 1))) cond else 23x = 1x+ 1 x -

26 26 Transforming sequence of expression to an expression (define (sequence->exp seq) (cond ((null? seq) seq) ((last-exp? seq) (first-exp seq)) (else (make-begin seq)))) (define (make-begin seq) (cons 'begin seq)) 2x * car y begin

27 27 Implementing cond (Cont.) (cond ((= x 23) (+ x 1)) (else (- x 1))) (if (= x 23) (+ x 1) (- x 1))

28 28 Implementing cond (define (cond->if exp) (expand-clauses (cond-clauses exp))) (define (expand-clauses clauses) (if (null? clauses) 'false ; no else clause (let ((first (car clauses)) (rest (cdr clauses))) (if (cond-else-clause? first) (if (null? rest) (sequence->exp (cond-actions first)) (error "ELSE clause isn't last -- COND->IF" clauses)) (make-if (cond-predicate first) (sequence->exp (cond-actions first)) (expand-clauses rest))))))

29 29 Details of cond syntax transformation (cond ((= x 23) (+ x 1)) (else (- x 1))) cond else 23x = 1x + 1x -

30 30 Details of cond syntax transformation ( expand-clauses else 23x = 1x + 1x - )

31 31 Details of cond syntax transformation first else 23x = 1x + 1x - rest

32 32 Details of cond syntax transformation 23x = 1x + else 1x - (make-if (expand-clauses ))

33 33 Details of cond syntax transformation 23x = 1x + 1 x - (make-if )

34 34 Details of cond syntax transformation 23x = 1x + 1 x - if

35 35 Named Procedures Support (define (foo ) ) (define (eval-definition exp env) (define-variable! (definition-variable exp) (eval (definition-value exp) env) env)) (define (definition-variable exp) (if (symbol? (cadr exp)) (cadr exp) (caadr exp))) (define (definition-value exp) (if (symbol? (cadr exp)) (caddr exp) (make-lambda (cdadr exp) ;formal params (cddr exp)))) ;body

36 Different frame implementation (define make-frame (lambda (variables values) (lambda (var) (cond ((empty? variables) empty) ((eq? var (car variables)) (make-binding (car variables) (car values))) (else (apply (make-frame (cdr variables) (cdr values)) (list var)))) )) New ADT: Box (whose implementation is a black box) for mutable objects! Details omitted 36

37 Substitution Model Instead of the Env. Model What changes to the evaluator are required? 37

38 Substitution Model Instead of the Env. Model Main changes: No generation (and passing as parameters) of environments (only global environment is generated) –Scoping is handled differently (see next) No support of assignment –Assignment does not fit well in the functional programming framework Besides application, support of other operations stays almost intact –Omit the environment parameter, and use global env. Instead Application requires some work 38

39 (define applicative-eval (lambda (exp) (cond ((atomic? exp) (eval-atomic exp)) … ((application? exp) (let ((renamed-exp (rename exp))) (apply-procedure (applicative-eval (operator renamed-exp)) (list-of-values (operands renamed-exp))))) (else (error "Unknown expression type -- EVAL" exp))))) 39

40 (define apply-procedure (lambda (procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (substitute (procedure-body procedure) (procedure-parameters procedure) arguments))) (else (error "Unknown procedure type -- APPLY" procedure))))) 40

41 substitute (define substitute (letrec ((substitute-var-val (lambda (exp var val) (cond ((variable? exp) (if (eq? exp var) val exp)) ((or (number? exp) (boolean? exp) (quoted? exp) ) exp) ((value? exp) (substitute-var-val-in-value exp var val)) (else (map (lambda(e) (substitute-var-val e var val)) exp)))) ) 41

42 rename 42 Implementation can be found in lecture notes Idea: rename the formal arguments of the closure as well as all occurrences of them in the body To distinguish from other variables with the same name that are e.g. in the global scope

43 Auxiliary function (define (make-new-names old-names) (if (null? old-names) ‘() (cons (gensym) (make-new-names (cdr old-names))))))) This should be inside the code of rename, put as external for clarification! 43

44 One more auxiliary function (define (replace val-exp) (cond ((or (evaluator-symbol? val-exp) (primitive-procedure? val-exp)) val-exp) ((evaluator-list? val-exp) (make-list (map rename (list-content val-exp)))) ((compound-procedure? val-exp) (let* ((params (procedure-parameters val-exp)) (new-params (make-new-names params)) (renamed-subs-body (map rename (procedure-body val- exp))) (renamed-body (substitute renamed-subs- body params new-params))) (make-procedure new-params renamed-body)))) 44

45 Finally- rename (define (rename exp) (cond ((atomic? exp) exp) ((lambda? exp) (let* ((params (lambda-parameters exp)) (new-params (make-new-names params)) (renamed-subs (map rename exp))) (substitute renamed-subs params new- params)) ) ((evaluator-value? exp) (replace exp)) (else (map rename exp)) 45

46 Lists (define (evaluator-value? val) (or (evaluator-symbol? val) (evaluator-list? val) (primitive-procedure? val) (compound-procedure? val)))) (define (list-form? exp) (or (tagged-list? exp ’cons) (tagged-list? exp ’list) (tagged-list? exp ’append)))) (define (eval-list lst) (make-list (apply-primitive-procedure (eval (operator lst)) (list-of-values (operands lst)))))) 46

47 Compilation vs. Interpretation In the interpreter all analysis is done at run-time Including syntax checks Some of it can be done “statically”, before evaluation More efficient in some sense. 47

48 The Analyzer Main idea: separate the syntactic analysis from evaluation Main observation: this corresponds to separating the management of expressions from those of the enviornments Simplest analysis: (define (analyze-self-evaluating exp) (lambda (env) exp)) 48

49 The Analyzer (cont.) (define (analyze-quoted exp) (let ((qval (text-of-quotation exp))) (lambda (env) qval))) (define (analyze-definition exp) (let ((var (definition-variable exp)) (val (analyze (definition-value exp)))) (lambda (env) (if (not (eq? env the-global-environment)) (error ’eval "non global definition: ~s" exp) (begin (add-binding! (make-binding var (val the-global-environment))) ’ok)))))) 49

50 The Analyzer (cont.) (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)))))) And so on… 50


Download ppt "1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol."

Similar presentations


Ads by Google