Download presentation
Presentation is loading. Please wait.
Published byBertha Craig Modified over 9 years ago
1
1 The metacircular evaluator (Cont.)
2
2 6. Defining new procedures (define (lambda? e) (tag-check e 'lambda)) (define (eval exp env) (cond ((number? exp) exp) ((symbol? exp) (lookup exp env)) ((define? exp) (eval-define exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (eval-lambda exp env)) ((application? exp) (apply (eval (car exp) env) (map (lambda (e) (eval e env)) (cdr exp)))) (else (error "unknown expression " exp)))) (define (eval-lambda exp env) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) (define (lambda-parameters exp) (cadr exp)) (define (lambda-body exp) (cddr exp)) (define (make-procedure parameters body env) (list 'procedure parameters body env))
3
3 (eval '(define twice (lambda (x) (+ x x))) GE)
4
4 Implementation of lambda (eval '(lambda (x) (+ x x)) GE) (eval-lambda '(lambda (x) (+ x x)) GE) (make-procedure '(x) ’((+ x x)) GE) (list ’procedure '(x) ’((+ x x)) GE) symbol procedure symbol + symbol x GE This data structure is a procedure!
5
5 Naming the procedure (eval '(define twice (lambda (x) (+ x x))) GE) names values z 9 true #t + twice symbol primitive scheme procedure + symbol procedure symbol + symbol x
6
6 6. Defining new procedures (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)))) (define (compound-procedure? exp) (tag-check exp ‘procedure)) (define (procedure-parameters compound) (cadr compound)) (define (procedure-body compound) (caddr compound)) (define (procedure-env compound) (cadddr compound))
7
7 (define (eval-sequence exps env) (cond ((last-exp? exps) (eval (first-exp exps) env)) (else (eval (first-exp exps) env) (eval-sequence (rest-exps exps) env)))) (define (last-exp? seq) (null? (cdr seq))) (define (first-exp seq) (car seq)) (define (rest-exps seq) (cdr seq))
8
8 How the Environment Works Abstractly – in our environment diagrams: Concretely – our implementation (as in SICP) E2 x: 10 plus: (procedure...) E1 environment manipulation 3. list of values enclosing- environment list of variables frame xplus 10 E2 procedure
9
9 Extending the Environment (extend-environment '(x y) (list 4 5) E2) E1 E2 x: 10 plus: (procedure...) E3 x: 4 y: 5 Abstractly Concretely E2 list of values list of variables frame xy4 E3 5 E1
10
10 (define (extend-environment vars vals base-env) (if (= (length vars) (length vals)) (cons (make-frame vars vals) base-env) (if (< (length vars) (length vals)) (error "Too many arguments supplied" vars vals) (error "Too few arguments supplied" vars vals))))
11
11 (eval '(twice 4) GE)
12
12 Implementation of apply (1) (eval '(twice 4) GE) (apply (eval 'twice GE) (map (lambda (e) (eval e GE)) '(4))) (apply (list 'procedure '(x) ’((+ x x)) GE) '(4)) (eval-seq ’((+ x x)) (extend-environment '(x) '(4) GE)) (eval '(+ x x) E1) name value x 4 GE E1 A
13
13 Implementation of apply (2) (eval '(+ x x) E1) (apply (eval + E1) (map (lambda (e) (eval e E1)) '(x x))) (apply '(primitive #[add]) (list (eval 'x E1) (eval 'x E1))) (apply '(primitive #[add]) '(4 4)) (scheme-apply #[add] '(4 4)) 8 name value x 4 GE E1 A
14
14 "Scanning" the environment Look for a variable in the environment... Look for a variable in a frame... –loop through the list of vars and list of vals in parallel –detect if the variable is found in the frame If not found in frame (out of variables in the frame), look in enclosing environment
15
15 (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))
16
16 (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-define exp env) (let ((name (cadr exp)) (defined-to-be (eval (caddr exp) env))) (define-variable! name defined-to-be env) ‘undefined))
17
17 The Initial (Global) Environment primitives and initial env. 4. (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))
18
18 Is eval an iterative or recursive algorithm? It depends on the scheme program being evaluated 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
19
19 (eval '(define odd (lambda (n) (odd (- n 2)))) GE) ==> undefined (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
20
20 (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
21
21 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
22
22 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))))
23
23 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))))
24
24 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
25
25 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))
26
26 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))
27
27 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 ( ) ) )
28
28 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))))
29
29 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))
30
30 Cond syntax (cond ((= x 23) (+ x 1)) (else (- x 1))) cond else 23 x = 1 x + 1 x -
31
31 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
32
32 Implementing cond (Cont.) (cond ((= x 23) (+ x 1)) (else (- x 1))) (if (= x 23) (+ x 1) (- x 1))
33
33 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))))))
34
34 Details of cond syntax transformation (cond ((= x 23) (+ x 1)) (else (- x 1))) cond else 23 x = 1 x + 1 x -
35
35 Details of cond syntax transformation ( expand-clauses else 23 x = 1 x + 1 x - )
36
36 Details of cond syntax transformation first else 23 x = 1 x + 1 x - rest
37
37 Details of cond syntax transformation 23x = 1x + else 1 x - (make-if (expand-clauses ))
38
38 Details of cond syntax transformation 23x = 1x + 1 x - (make-if )
39
39 Details of cond syntax transformation 23x = 1x + 1 x - if
40
40 Named Procedures – Syntax vs. Semantics (define (foo ) ) Semantic implementation – just another define: (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
41
41 Read-Eval-Print Loop (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)) (define (prompt-for-input string) (newline) (newline) (display string) (newline)) (define (announce-output string) (newline) (display string) (newline)) (define (user-print object) (if (compound-procedure? object) (display (list 'compound-procedure (procedure-parameters object) (procedure-body object) ' )) (display object))) (define input-prompt ";;; M-Eval input:") (define output-prompt ";;; M-Eval value:")
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.