1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; Mandatory SICP Metacircular Evaluator ;;
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5 (define apply-in-underlying-scheme apply)
9 ;; Verbatim code from SICP
11 (display "eval and apply\n")
13 (define (eval exp env)
14 (cond ((self-evaluating? exp)
17 (lookup-variable-value exp env))
19 (text-of-quotation exp))
21 (eval-assignment exp env))
23 (eval-definition exp env))
28 (lambda-parameters exp)
36 (eval (cond->if exp) env))
38 (apply (eval (operator exp) env)
43 (error "Unknown expression type: EVAL" exp))))
45 (define (apply procedure arguments)
46 (cond ((primitive-procedure? procedure)
47 (apply-primitive-procedure
50 ((compound-procedure? procedure)
52 (procedure-body procedure)
57 (procedure-environment
60 (error "Unknown procedure type: APPLY"
63 (define (list-of-values exps env)
64 (if (no-operands? exps)
66 (cons (eval (first-operand exps) env)
71 (define (eval-if exp env)
72 (if (true? (eval (if-predicate exp) env))
73 (eval (if-consequent exp) env)
74 (eval (if-alternative exp) env)))
76 (define (eval-sequence exps env)
77 (cond ((last-exp? exps)
78 (eval (first-exp exps) env))
80 (eval (first-exp exps) env)
81 (eval-sequence (rest-exps exps)
84 (define (eval-assignment exp env)
86 (assignment-variable exp)
87 (eval (assignment-value exp) env)
91 (define (self-evaluating? exp)
92 (cond ((number? exp) true)
96 (define (variable? exp) (symbol? exp))
99 (tagged-list? exp 'quote))
101 (define (text-of-quotation exp)
104 (define (tagged-list? exp tag)
109 (define (assignment? exp)
110 (tagged-list? exp 'set!))
112 (define (assignment-variable exp)
115 (define (assignment-value exp) (caddr exp))
117 (define (definition? exp)
118 (tagged-list? exp 'define))
120 (define (definition-variable exp)
121 (if (symbol? (cadr exp))
125 (define (definition-value exp)
126 (if (symbol? (cadr exp))
129 (cdadr exp) ; formal parameters
133 (display "lambda... \n")
135 (define (lambda? exp)
136 (tagged-list? exp 'lambda))
137 (define (lambda-parameters exp) (cadr exp))
138 (define (lambda-body exp) (cddr exp))
140 (define (make-lambda parameters body)
141 (cons 'lambda (cons parameters body)))
143 (define (if? exp) (tagged-list? exp 'if))
144 (define (if-predicate exp) (cadr exp))
145 (define (if-consequent exp) (caddr exp))
146 (define (if-alternative exp)
147 (if (not (null? (cdddr exp)))
151 (define (make-if predicate
160 (tagged-list? exp 'begin))
161 (define (begin-actions exp) (cdr exp))
162 (define (last-exp? seq) (null? (cdr seq)))
163 (define (first-exp seq) (car seq))
164 (define (rest-exps seq) (cdr seq))
166 (define (sequence->exp seq)
167 (cond ((null? seq) seq)
168 ((last-exp? seq) (first-exp seq))
169 (else (make-begin seq))))
171 (define (make-begin seq) (cons 'begin seq))
173 (define (application? exp) (pair? exp))
174 (define (operator exp) (car exp))
175 (define (operands exp) (cdr exp))
176 (define (no-operands? ops) (null? ops))
177 (define (first-operand ops) (car ops))
178 (define (rest-operands ops) (cdr ops))
181 (display "cond... \n")
184 (tagged-list? exp 'cond))
185 (define (cond-clauses exp) (cdr exp))
186 (define (cond-else-clause? clause)
187 (eq? (cond-predicate clause) 'else))
188 (define (cond-predicate clause)
190 (define (cond-actions clause)
192 (define (cond->if exp)
193 (expand-clauses (cond-clauses exp)))
194 (define (expand-clauses clauses)
196 'false ; no else clause
197 (let ((first (car clauses))
198 (rest (cdr clauses)))
199 (if (cond-else-clause? first)
202 (cond-actions first))
203 (error "ELSE clause isn't last: COND->IF"
205 (make-if (cond-predicate first)
207 (cond-actions first))
219 (display "make-procedure...\n")
222 (define (make-procedure parameters body env)
223 (list 'procedure parameters body env))
224 (define (compound-procedure? p)
225 (tagged-list? p 'procedure))
226 (define (procedure-parameters p) (cadr p))
227 (define (procedure-body p) (caddr p))
228 (define (procedure-environment p) (cadddr p))
230 (define (enclosing-environment env) (cdr env))
231 (define (first-frame env) (car env))
232 (define the-empty-environment '())
235 (display "make-frame\n")
237 (define (make-frame variables values)
238 (cons variables values))
239 (define (frame-variables frame) (car frame))
240 (define (frame-values frame) (cdr frame))
241 (define (add-binding-to-frame! var val frame)
242 (display "Adding binding to frame... ")
243 (set-car! frame (cons var (car frame)))
244 (set-cdr! frame (cons val (cdr frame))))
246 (display "extend-environment\n")
248 (define (extend-environment vars vals base-env)
249 (if (= (length vars) (length vals))
250 (cons (make-frame vars vals) base-env)
251 (if (< (length vars) (length vals))
252 (error "Too many arguments supplied"
255 (error "Too few arguments supplied"
259 (display "lookup-variable\n")
261 (define (lookup-variable-value var env)
262 (define (env-loop env)
263 (define (scan vars vals)
266 (enclosing-environment env)))
267 ((eq? var (car vars))
269 (else (scan (cdr vars)
271 (if (eq? env the-empty-environment)
272 (error "Unbound variable" var)
273 (let ((frame (first-frame env)))
274 (scan (frame-variables frame)
275 (frame-values frame)))))
278 (display "set-variable\n")
280 (define (set-variable-value! var val env)
281 (define (env-loop env)
282 (define (scan vars vals)
285 (enclosing-environment env)))
286 ((eq? var (car vars))
288 (else (scan (cdr vars)
290 (if (eq? env the-empty-environment)
291 (error "Unbound variable: SET!" var)
292 (let ((frame (first-frame env)))
293 (scan (frame-variables frame)
294 (frame-values frame)))))
297 (display "define-variable\n")
299 (define (define-variable! var val env)
300 (display "Defining a variable...\n")
301 (let ((frame (first-frame env)))
302 (define (scan vars vals)
303 (display "Scanning for ") (display var) (display " in ") (display vars) (display "...\n")
305 (begin (display "adding binding\n")
306 (add-binding-to-frame!
308 ((eq? var (car vars))
309 (begin (display "replacing binding\n")
310 (set-car! vals val)))
313 (display "iterating\n")
316 (scan (frame-variables frame)
317 (frame-values frame))))
319 (display "setup-environment...\n")
321 (define (setup-environment)
324 (primitive-procedure-names)
325 (primitive-procedure-objects)
326 the-empty-environment)))
327 (display "Setting up the environment..\n")
328 (define-variable! 'true true initial-env)
329 (define-variable! 'false false initial-env)
332 (define (primitive-procedure? proc)
333 (tagged-list? proc 'primitive))
335 (define (primitive-implementation proc)
338 (define primitive-procedures
339 (list (list 'car car)
347 (define (primitive-procedure-names)
348 (map car primitive-procedures))
350 (define (primitive-procedure-objects)
352 (list 'primitive (cadr proc)))
353 primitive-procedures))
357 (define (apply-primitive-procedure proc args)
358 (apply-in-underlying-scheme
359 (primitive-implementation proc) args))
361 (define input-prompt ";;; M-Eval input:")
362 (define output-prompt ";;; M-Eval value:")
365 (display "driver-loop...\n")
367 (define (driver-loop)
368 (prompt-for-input input-prompt)
369 (let ((input (read)))
372 the-global-environment)))
373 (announce-output output-prompt)
374 (user-print output)))
377 (define (prompt-for-input string)
379 (display string) (newline))
381 (define (announce-output string)
382 (newline) (display string) (newline))
384 (define (user-print object)
385 (if (compound-procedure? object)
387 (list 'compound-procedure
388 (procedure-parameters object)
389 (procedure-body object)
393 ;; (define the-global-environment (setup-environment))