מבוא מורחב למדעי המחשב Scheme בשפת
13תרגול
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
3
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))
Top Related