Title: CS 3015 Lecture 20
1CS 3015 Lecture 20
2Recall Definition of eval
- (define (eval exp env)(cond ((self-evaluating? ex
p) 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) (ev
al-if exp env)) - ((lambda? exp) (make-procedure (l
ambda-parameters exp) (la
mbda-body exp) env))
3Definition of eval contd
- ((begin? exp) (eval-sequence
- (begin-actions exp) env))
((cond? exp) (eval (cond-gtif exp) env)) ((app
lication? exp) (apply (eval (operator exp
) env) (list-of-values - (operands exp) env))) (else (error
"Unknown expression type -- - EVAL" exp))))
4Sequences
- (define (begin? exp)
- (tagged-list? exp 'begin))
- (define (begin-actions exp) (cdr exp))
- (define (last-exp? seq)
- (null? (cdr seq)))
- (define (first-exp seq) (car seq))
- (define (rest-exps seq) (cdr seq))
5A Constructor for sequences
- (define (sequence-gtexp seq)(cond ((null? seq) seq
) ((last-exp? seq) - (first-exp seq)) (else (make-begin seq)))
) - (define (make-begin seq)
- (cons 'begin seq))
- For use in converting cond to if
6Procedure Applications
- (define (application? exp) (pair? exp))
- (define (operator exp) (car exp))
- (define (operands exp) (cdr exp))
- (define (no-operands? ops) (null? ops))
- (define (first-operand ops) (car ops))
- (define (rest-operands ops) (cdr ops))
7Implementing cond
- Rather than implementing cond directly, we can
implement it in terms of if - Example
- (cond ((gt x 0) x) (( x 0) (display 'zero) 0)
(else (- x))) - (if (gt x 0) x (if ( x 0) (begin (display
'zero) 0) (- x)))
8Predicates and Selectors for cond
- (define (cond? exp)
- (tagged-list? exp 'cond))
- (define (cond-clauses exp) (cdr exp))
- (define (cond-else-clause? clause) (eq? (cond-pr
edicate clause) 'else)) - (define (cond-predicate clause) (car clause))
- (define (cond-actions clause) (cdr clause))
- (define (cond-gtif exp) (expand-clauses (cond-cla
uses exp)))
9Translating cond into if
- (define (expand-clauses clauses)
- (if (null? clauses) 'false
- (let((first (car clauses)) (rest (cdr
clauses))) (if (cond-else-clause? first)
(if (null? rest) (sequence-gt
exp - (cond-actions first)) (error "
clauses)) (make-
if (cond-predicate first) (sequ
ence-gtexp - (cond-actions first)) (exp
and-clauses rest))))))
10Evaluator Data Structures
- We need to define data structures for
representing true, false, procedures,
environments, - True and false are easy
- (define (true? x) (not (eq? x false)))
- (define (false? x) (eq? x false))
11Representing Compound Procedures
- (define (make-procedure parameters body env) (li
st 'procedure parameters body env)) - (define (compound-procedure? p) (tagged-list? p
'procedure)) - (define (procedure-parameters p) (cadr p))
- (define (procedure-body p) (caddr p))
- (define (procedure-environment p) (cadddr p))
12Operations on Environments
- (lookup-variable-value ltvargt ltenvgt)returns the
value of ltvargt in the environment ltenvgt, or
signals an error if the variable is unbound - (extend-environment ltvariablesgt ltvaluesgt
ltbase-envgt)returns a new environment, consisting
of a new frame in which the symbols in the list
ltvariablesgt are bound to the corresponding
elements in the list ltvaluesgt, where the
enclosing environment is ltbase-envgt - (define-variable! ltvargt ltvaluegt ltenvgt)adds to
the first frame in ltenvgt a new binding that
associates ltvargt with ltvaluegt - (set-variable-value! ltvargt ltvaluegt ltenvgt)changes
the binding of ltvargt in ltenvgt so that the
variable is now bound to ltvaluegt
13Representing Environments
- Represent environments as lists of frames
- The enclosing environment is the cdr
- The empty environment is just the empty list
- (define (enclosing-environment env)
- (cdr env))
- (define (first-frame env) (car env))
- (define the-empty-environment '())
14Frames
- A frame is represented as a pair of parallel
lists - (define (make-frame variables values) (cons vari
ables values)) - (define (frame-variables frame) (car frame))
- (define (frame-values frame) (cdr frame))
- (define (add-binding-to-frame! var val frame) (s
et-car! frame (cons var (car frame))) (set-cdr!
frame (cons val (cdr frame))))
15Extending an Environment
- (define (extend-environment vars vals base-env)(i
f ( (length vars) (length vals)) (cons (make-
frame vars vals) base-env) (if (lt (length vars
) (length vals)) (error "Too many argument
s supplied" - vars vals) (error "Too few arguments
supplied" - vars vals))))
16Looking up a variable in an environment
- Scan the list of frames
- Find the first frame that contains a binding for
the variable - Return the binding
- If none found, the variable is unbound
17Definition of lookup-variable-value
- (define (lookup-variable-value var env)(define (e
nv-loop env) (define (scan vars vals) (cond
((null? vars) (env-loop (enclosing-envi
ronment - env))) ((eq? var (car vars))
(car vals)) (else (scan (cdr vars)
(cdr vals))))) (if (eq? env the-empty-environme
nt) (error "Unbound variable" var) (le
t ((frame (first-frame env))) (scan (frame
-variables frame) (frame-values fram
e))))) - (env-loop env))
18Definition of set-variable-value!
- (define (set-variable-value! var val env)(define
(env-loop env) (define (scan vars vals) (con
d ((null? vars) (env-loop (enclosing-en
vironment - env))) ((eq? var (car vars))
(set-car! vals val)) (else (scan (cd
r vars) (cdr vals))))) (if (eq? env the-empty-en
vironment) (error "Unbound variable -- SET!"
var) (let ((frame (first-frame env)))
(scan (frame-variables frame) (fr
ame-values frame)))))(env-loop env))
19Definition of define-variable!
- (define (define-variable! var val env)(let ((fram
e (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-var
iables frame) (frame-values frame))))
20Running the evaluator
- Ultimately the evaluator reduces programs to
evaluation of primitive procedures - However, we still have not talked about
evaluating primitive procedures - We need a mechanism that calls the underlying
Scheme system to evaluate primitives
21So we need a global environment
- (define (setup-environment)(let ((initial-env
(extend-environment - (primitive-procedure-names) (prim
itive-procedure-objects) the-empty-enviro
nment))) (define-variable! 'true true initial-env
) (define-variable! 'false false initial-env) in
itial-env)) - (define the-global-environment
- (setup-environment))
22Representing Primitive Procedures
- (define (primitive-procedure? proc)(tagged-list?
proc 'primitive)) - (define (primitive-implementation proc)
- (cadr proc))
23- (define primitive-procedures (list (list 'car ca
r) (list 'cdr cdr) (list 'cons con
s) (list 'null? null?) ltmore primi
tivesgt )) - (define (primitive-procedure-names) (map car
primitive-procedures)) - (define (primitive-procedure-objects) (map (lamb
da (proc) - (list 'primitive (cadr proc))) primitive
-procedures))
24Definition of apply-primitive-procedure
- (define (apply-primitive-procedure
- proc args)(apply-in-underlying-scheme (primi
tive-implementation proc) - args))
- Before the definition of apply
- (define apply-in-underlying-scheme apply)
25Using the evaluator
- A driver loop is provided for convenience
- Models read-eval-print loop in underlying scheme
system - The driver does the following
- prints a prompt
- reads an input expression
- evaluates this expression in the global
environment - prints the result
26The Driver Loop
- (define input-prompt " M-Eval input")
- (define output-prompt " M-Eval value")
- (define (driver-loop)(prompt-for-input input-prom
pt)(let ((input (read))) (let ((output - (eval input the-global-environment))) (anno
unce-output output-prompt) (user-print output)
))(driver-loop))
27- (define (prompt-for-input string)(newline) (newli
ne) (display string) - (newline))
- (define (announce-output string)(newline) (displa
y string) (newline)) - (define (user-print object)(if (compound-procedur
e? object) (display (list 'compound-procedure
(procedure-parameters object)
(procedure-body object)
'ltprocedure-envgt)) (display object)
))
28Example of using the Driver Loop
- (define the-global-environment (setup-environment)
) - (driver-loop)
- M-Eval input
- (define (append x y)
- (if (null? x) y (cons (car x) (a
ppend (cdr x) y)))) - M-Eval value
- Ok
- M-Eval input
- (append '(a b c) '(d e f))
- M-Eval value
- (a b c d e f)