מבוא מורחב למדעי המחשב בשפת Scheme
description
Transcript of מבוא מורחב למדעי המחשב בשפת Scheme
מבוא מורחב למדעי המחשב Scheme בשפת
14תרגול
Metacircular Evaluator
4.1, pages 362-398
definitions file on web
2
Overview
1. Eval, apply
2. Change definition
3. Add let, let*
4. Add special forms and, or
5. Abstraction of frame scanning
6. More examples3
4
Evaluator: a program that
determines meaning of expressions
in a programming language.
Metacircular: written in the same language that it evaluates
Read-Eval-Print Loop
(define (driver-loop)1. PRINT PROMPT (prompt-for-input input-prompt)2. READ INPUT EXPRESSION (let ((input (read))) 3. EVALUATE EXPRESSION (let ((output (mc-eval input the-global-environment)))
…4. PRINT RESULT (user-print output)5. LOOP (driver-loop))))))
5
Eval-Apply
Mutual recursion between eval and apply
To evaluate a compound expression means to evaluate the sub-expressions recursively, then apply the operator to the arguments.
To apply a function to arguments means to evaluate the body of the function in a new environment.
6
Eval
Evaluate expression in given environment
(define (mc-eval exp env) (cond ((self-evaluating? exp) exp)… ((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env)))
The name mc-eval is used to differ from the primitive eval
7
Apply
Apply procedure to list of arguments
(define (mc-apply procedure arguments)…(eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure))))
The name mc-apply is used to differ from the primitive apply
8
Change definition
from (define x 7)
to (x := 7)
and
from (define (square x) (* x x))
to ((square x) := (* x x))
9
Change eval case
from:(define (definition? exp) (tagged-list? exp 'define))
(define (tagged-list? exp tag) (if (pair? exp) (eq? (car exp) tag) false))to:(define (definition? exp) (and (pair? exp) (pair? (cdr exp)) (eq? (cadr exp) ':=)))
10
Change selectors
(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) (cddr exp))))
(car(car
(car
(caar
(cdar
11
Adding let, let*
Rearranging as another expression
12
let
(let ((<var1> <exp1>) … (<varn> <expn>)) <body>)
is equivalent to
((lambda (<var1> … <varn>) <body>) <exp1> … <expn>)
add a syntactic transformationlet->combination
13
let - case in eval
((let? exp)
(mc-eval (let->combination exp) env))
(define (let? exp)
(tagged-list? exp ‘let))
let - predicate
14
let - constructors
(define (make-combination
function expressions)
(cons function expressions))
15
let - selectors
(define (let-bindings exp) (cadr exp))
(define (let-body exp) (cddr exp))
(define (let-variables exp) (map car (let-bindings exp)))
(define (let-expressions exp) (map cadr (let-bindings exp)))
16
let - evaluation
(define (let->combination exp)
(make-combination
(make-lambda
(let-variables exp)
(let-body exp))
(let-expressions exp)))
17
let*
The bindings of are performed sequentially.
Each binding is made in an environment inwhich all of the preceding bindings arevisible.
(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z))> 39
18
let*
(let* ((<var1> <exp1>)…(<varn> <expn>))
<body>)
is equivalent to
(let ((<var1> <exp1>)) (let* ((<var2> <exp2>)… (<varn> <expn>)) <body>))
add a syntactic transformationlet*->nested-let
19
let* - example(let* ((<var1> <exp1>) (<var2> <exp2>)) <body>)=(let ((<var1> <exp1>)) (let* (<var2> <exp2>)) <body>))=(let ((<var1> <exp1>)) (let ((<var2> <exp2>)) (let* () <body>)))=(let ((<var1> <exp1>)) (let ((<var2> <exp2>)) (let () <body>)))
20
let* - case in eval
((let*? exp)
(mc-eval (let*->nested-let exp) env))
21
let* - constructors
(define (make-let bindings body)
(cons ‘let (cons bindings body)))
(define (make-let* bindings body)
(cons ‘let* (cons bindings body)))
22
let* - predicates
(define (let*? exp)
(tagged-list exp ‘let*))
(define (no-bindings? bindings)
(null? bindings))
23
let* - selectors
(define (let*-bindings exp) (cadr exp))
(define (let*-body exp) (cddr exp))
(define (let*-first-binding bindings)
(car bindings))
(define (let*-rest-bindings bindings)
(cdr bindings))
24
let* - evaluation
(define (let*->nested-let exp)
(if (no-bindings? (let*-bindings exp))
(make-let
(let*-bindings exp)
(let*-body exp))
(make-let
(list (let*-first-binding
(let*-bindings exp)) ; ((v1 e1))
(make-let*
(let*-rest-bindings (let*-bindings exp))
(let*-body exp))))
25
Special forms: and, or
Direct evaluation
26
and, or - cases in eval
(define (mc-eval exp env) (cond ((self-evaluating? exp) exp)…((and? exp) (eval-and (and-exps exp) env))((or? exp) (eval-or (or-exps exp) env))
((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env)))
27
and, or - predicates
(define (and? exp) (tagged-list? exp ‘and))
(define (or? exp) (tagged-list? exp ‘or))
(define (no-exps? exps) (null? exps))
(define (last-exp? exps) (null? (cdr exps)))
28
and, or - selectors
(define (and-exps exp) (cdr exp))
(define (or-exps exp) (cdr exp))
(define (first-exp exps) (car exps))
(define (rest-exps exps) (cdr exps))
29
and - evaluation
from left to right
Evaluation Return value
Any expression evaluates to false
false
All expressions evaluate to true
value of last expression
No expressions true
and - evaluation
(define (eval-and exps env) (if (no-exps? exps) true (let ((first (mc-eval (first-exp exps) env)))
(if (false? first) false (if (last-exp? exps) first (eval-and (rest-exps exps) env)))))
31
or - evaluation
from left to right
32
Evaluation Return value
Any expression evaluates to true
value of last expression
All expressions evaluate to false
false
No expressions false
or - evaluation
(define (eval-or exps env) (if (no-exps? exps) false (let ((first (mc-eval (first-exp exps) env)))
(if (true? first) first ;(if (last-exp? exps) false (eval-or (rest-exps exps) env)))))
33
Abstraction of frame scanning
Exercise 4.12
34
35
Frames
A frame is a set of bindings, represented as a pair of two lists: variables and values
Constructor(make-frame variables values)Selectors(frame-variables frame)(frame-values frame)Mutator(add-binding-to-frame! var val frame)
36
EnvironmentsAn environment consists of its first frame and an enclosing
environment
Constructor(extend-environment vars vals base-env)Selectors (first-frame env)(enclosing-environment env)Predefined environmentsthe-global-environmentthe-empty-environment
37
Frame Scanning
Performed by:• lookup-variable-value
invoked when evaluating names• set-variable-value!
invoked when evaluating set! expressions• define-value!
invoked when evaluating definitions
38
lookup-variable-value(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))
39
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))
40
define-variable!(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))))
41
All procedures are alike!
• Scan the frame for the variable’s name– If found, success operation
(return value / set value)– If not in frame, failure operation
(continue to next frame / add binding)
• Error on empty environment (if this can happen)
• We can get better abstraction– Capturing common patterns– Hiding frame scanning / mutation
42
Generic frame scan
(define (scan-first-frame var env succeed fail)
(define (scan vars vals)
(cond ((null? vars)
(fail))
((eq? var (car vars))
(succeed 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)))))
43
lookup-variable-value
(define (lookup-variable-value var env)
(define (succeed vals)
(get-binding-value vals))
(define (fail)
(scan-first-frame
var (enclosing-environment env) succeed fail))
(scan-first-frame var env succeed fail))
(define (get-binding-value vals)
(car vals))
44
set-variable-value!
(define (set-variable-value! var val env)
(define (succeed vals)
(set-binding-value! vals val))
(define (fail)
(scan-first-frame
var (enclosing-environment env) succeed fail))
(scan-first-frame var env succeed fail))
(define (set-binding-value! vals val)
(set-car! vals val))
45
define-variable!
(define (define-variable! var val env)
(define (succeed vals)
(set-binding-value! vals val))
(define (fail)
(add-binding-to-frame! var val (first-frame env))) (scan-first-frame var env succeed fail))
46
Example: if>=<
Format: (if>=< exp1 exp2 if> if= if<)
exp1 and exp2 evaluate to numerical values
if exp1>exp2 evaluate and return if>
if exp1=exp2 evaluate and return if=
otherwise, evaluate and return if<
47
Predicate and Selectors
(define (if>=<? exp)
(tagged-list? exp ‘if>=<))
(define (if>=<exp1 exp) (cadr exp))
(define (if>=<exp2 exp) (caddr exp))
(define (if> exp) (cadddr exp))
(define (if= exp) (list-ref exp 4))
(define (if< exp) (list-ref exp 5))
48
mc-eval implementation
(define (eval-if>=< exp env)
(let ((exp1 (mc-eval (if>=<exp1 exp) env))
(exp2 (mc-eval (if>=<exp2 exp) env))
(cond ((> exp1 exp2)
(mc-eval (if> exp) env))
((= exp1 exp2)
(mc-eval (if= exp) env))
(else (mc-eval (if< exp) env)))))
49
Practice Question
• When a procedure with no parameters is applied, an empty frame is opened
• Change the MCE code such that parameter-less procedures will be applied in the parent environment
• Is the modified evaluator equivalent to the original one? Explain or give a contradicting example
50
Modification to apply
(define (mc-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-environment procedure)))) (else (error ….))))
(if (null? (procedure-parameters procedure)) (eval-sequence (procedure-body procedure) (procedure-environment procedure)) )
51
Practice Question
Suppose we can manipulate environments as if they were data types, using the following imaginary special forms:
(this-env)
(get-env proc)
(set-env! proc env)
52
Example
(define x 2)
(define (f y) (+ x y))
(define (make-env x) (this-env))
GE
x:2
f: make-env
p: y
b: (+ x y)
p: x
b: (this-env)
53
(define env1 (make-env 3))
GE
x:2
f: env1 make-env
p: y
b: (+ x y)
p: x
b: (this-env)
E1
x:3
Example (cont.)
54
(set-env! f env1)
GE
x:2
f: env1 make-env
p: y
b: (+ x y)
p: x
b: (this-env)
E1
x:3
Example (cont.)
55
Section A
What will evaluating the following code return?
Apply changes to the env. diagram.
(f 5)
(define (mystery g)
(define (aux x y)
(set-env! g (this-env)))
(aux 1 4))
(mystery f)
(f 5)
56
(f 5)
GE
x:2
f: env1 make-env
p: y
b: (+ x y)
p: x
b: (this-env)
E1
x:3
E2
y:5
Solution
57
(mystery f)
GE
x:2
f: env1 make-env mystery:
E1
x:3
E2
y:5
E3
g:
aux:E4
x:1
y:4
Solution (cont.)
58
(f 5)
GE
x:2
f: env1 make-env mystery:
E1
x:3
E2
y:5
E3
g:
aux:E4
x:1
y:4E5
y:5
Solution (cont.)
59
Section B
Complete(call-from-env proc vars env)
which applies proc on vars from environment env, instead of proc’s original environment
When returning, proc’s environment is restored to its original environment
60
Code
(define (call-from-env proc vars env (let ((original-env ))
? (let ((result )) ?
?)))
(get-env proc) (set-env! proc env)
(apply proc vars)
(set-env! proc original-env)
result
61
Section C,D,E
• Add support for this-env, get-env and set-env! in the mc-eval
• The representation of an environment is the interior data structure inside the evaluator
• Relaxation: In set-env! you may assume that the proc operand is evaluated to a compound (not primitive) procedure
62
mc-eval additions
Add in mc-eval:((this-env? exp) (eval-this-env exp env))
((get-env? exp) (eval-get-env exp env))
((set-env? exp) (eval-set-env exp env))
63
Predicates
(define (this-env? exp) )(define (get-env? exp) ) (define (set-env? exp) )
(tagged-list? exp ‘this-env) (tagged-list? exp ‘get-env) (tagged-list? exp ‘set-env!)
64
Selectors
(this-env)no selectors
(get-env proc)(define (get-env-proc exp) (cadr exp))
(set-env! proc env)(define (set-env-proc exp) (cadr exp))(define (set-env-env exp) (caddr exp))
65
eval-this-env
eval-this-env is simply:(define (eval-this-env exp env) env)
66
eval-get-env
(define (eval-get-env exp env)
(let ((proc _______________________________))
(if (primitive-procedure? proc)
_______________________________
_______________________________ )))
(mc-eval (get-env-proc exp) env)
the-global-environment
(procedure-environment proc)
67
eval-set-env
(define (eval-set-env exp env)
(let ((proc
________________________________ )
(new-env
________________________________ ))
__________________________________ ))
Reminder: a compound procedure is represented by:(list ‘procedure parameters body env)
(mc-eval (set-env-proc exp) env)
(mc-eval (set-env-env exp) env)
(set-car! (cdddr proc) new-env)