CS 61A
Week 12 solutions
HOMEWORK
========
4.3
datadirected eval
The table itself could be done in several ways; perhaps the easiest
is to use the builtin table from chapter 2.
So we say:
(put 'quote 'eval textofquotation)
(put 'define 'eval evaldefinition)
(put 'set! 'eval evalassignment)
Where the original eval does something other than (foo exp env) we
have to write an interface procedure.
For example:
(define (evallambda exp env)
(makeprocedure (lambdaparameters exp) (lambdabody exp) env))
(put 'lambda 'eval evallambda)
(define (eval exp env)
(cond ((selfevaluating? exp) exp)
((variable? exp) (lookupvariablevalue exp env))
(else (let ((form (get (operator exp) 'eval)))
(if form
;; IT'S A SPECIAL FORM
(form exp env)
;; SO form IS THE PROCEDURE TO CALL
(apply (eval (operator exp) env)
(listofvalues (operands exp) env) ))))))
The first two COND clauses deal with atomic expressions: numbers (which
are selfevaluating) and symbols (which represent variables).
If the
expression is neither of those, then it's a list, and we look at its
CAR.
We look that up in the table; if we find it, the expression is a
special form, and we invoke the particular procedure that knows about
that special form.
Otherwise, it's a regular procedure.
We're neglecting various kinds of errors that might occur with malformed
input.
We also have to rewrite textofquotation so that it accepts an extra
input, the environment, even though it doesn't need it:
(define (textofquotation exp env)
(cadr exp))
And we have to write a new "front end" to cond>if:
(define (evalcond exp env)
(eval (cond>if exp) env))
and put that in the table.
It would also be possible to include the atomic expressions in the
general datadirected mechanism by assigning them implicit types just as
we assigned Scheme numbers an implicit type in exercise 2.78, page 193:
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document(define (expressiontype exp)
(cond ((selfevaluating? exp) '(() SELFEVALUATING))
((symbol? exp) '(() SYMBOL))
((pair? exp) (car exp))
(else (error "Unknown expression type" exp))))
(define (eval exp env)
(let ((handler (get (expressiontype exp) 'eval)))
(if handler
(handler exp env)
(apply (eval (operator exp) env)
(listofvalues (operands exp) env)))))
(put '(() selfevaluating) 'eval (lambda (exp env) exp))
(put '(() symbol) 'eval lookupvariablevalue)
The reason for using (() SYMBOL) instead of just SYMBOL as the type tag
is that otherwise we'd get in trouble if an expression tried to call a
procedure named SYMBOL.
These type tags aren't valid Scheme expressions,
so they shouldn't get us in trouble.
4.6
Implementing LET
;; In eval's big cond we put
((let? exp) (eval (let>combination exp) env))
;; Now for the guts of the problem:
(define (let>combination exp)
(cons (makelambda (letformals exp)
(letbody exp))
(letactuals exp)))
;; And now for the data abstraction stuff:
(define (let? exp)
(taggedlist? exp 'let))
(define (letformals exp)
(map car (cadr exp)))
(define (letactuals exp)
(map cadr (cadr exp)))
(define (letbody exp)
This is the end of the preview.
Sign up
to
access the rest of the document.
 Spring '08
 Harvey
 exp env, ASSOC VAR ALIST

Click to edit the document details