Announcements
Quiz 2 tomorrow
5pm to 7pm xor 7pm to 9pm
Room 4-270 and 4-370
Analyzing Evaluator
(define (eval exp env)
;; First call ANALYZE to build a bag of code
;; from the original EXPression, then call the
;; bag of code with the ENVironment.
((analyze exp) env))
(define (analyze exp)
;; Convert the EXPression into a bag of code
(cond ((self-evaluating? exp)
(analyze-self-evaluating exp))
...
((variable? exp) (analyze-variable exp))
((if? exp) (analyze-if exp))
((lambda? exp) (analyze-lambda exp))
((application? exp) (analyze-application exp))
(else ...)))
IF and LAMBDA, Analyze Style
(define (analyze-if exp)
(let ((pproc (analyze (if-predicate exp)))
(cproc (analyze (if-consequent exp)))
(aproc (analyze (if-alternative exp))))
(lambda (env)
(if (true? (pproc env))
(cproc env)
(aproc env)))))
(define (analyze-lambda exp)
(let ((vars (lambda-parameters exp))
(bproc (analyze-sequence (lambda-body exp))))
(lambda (env) (make-procedure vars bproc env))))
Procedure Application, Analyze Style
(define (analyze-application exp)
(let ((fproc (analyze (operator exp)))
(aprocs (map analyze (operands exp))))
(lambda (env)
(execute-application
(fproc env)
(map (lambda (aproc) (aproc env)) aprocs)))))
(define (execute-application proc args)
(cond ...
((compound-procedure? proc)
((procedure-body proc)
(extend-environment
(procedure-parameters proc)
args
procedure-environment proc))))
...))
CATCH and OOPS
(define (add-up l)
(if (null? l)
0
(+ (car l) (add-up (cdr l)))))
(define (average values)
(catch Divide-by-Zero
(divide (add-up values) (length values))
0))
(define (divide x y)
(if (zero? y)
(oops divide-by-zero)
(/ x y)))
(average (list 10 20)) ==> 15
(average '()) ==> 0
Support: Label Lookup
(define *labels* '())
(define (add-label name procedure)
(set! *labels* (cons (list name procedure) *labels*)))
(define (find-label name)
(let ((entry (assq name *labels*)))
(and entry (second entry))))
Implementing OOPS
(define (analyze-oops exp)
;; (OOPS <name>)
(let ((name (second exp)))
(lambda (env)
(let ((label (find-label name)))
(if label
(label)
(error "No handler for error" name))))))
A Bug in the Code
(catch george (oops george) 'george) ==> george
(catch george (+ 2 3) 'george) ==> 5
(catch george
(begin (oops george) (+ 2 3))
'george) ==> 5 ; Should be GEORGE