3 (require (rename-in racket/base
4 (apply apply-in-underlying-scheme)
5 (eval eval-in-underlying-scheme)))
7 (provide (all-defined-out))
9 (define (self-evaluating? expr)
16 (define (variable? expr) (symbol? expr))
20 (define (eval-sequence exps env)
21 (cond ((last-exp? exps) (eval (first-exp exps) env))
22 (else (eval (first-exp exps) env)
23 (eval-sequence (rest-exps exps) env))))
26 (define (last-exp? seq) (null? (cdr seq)))
27 (define (first-exp seq) (car seq))
28 (define (rest-exps seq) (cdr seq))
31 (define (make-lambda parameters body)
32 (cons 'lambda (cons parameters body)))
34 (define (analyze-sequence exps)
35 (define (sequentially proc1 proc2)
36 (lambda (env) (proc1 env) (proc2 env)))
37 (define (loop first-proc rest-procs)
38 (if (null? rest-procs)
40 (loop (sequentially first-proc (car rest-procs))
42 (let ((procs (map analyze exps)))
44 (error "Empty sequence -- ANALYZE")
45 (loop (car procs) (cdr procs)))))
47 ;; environment data structures
48 (define (enclosing-environment env) (cdr env))
49 (define (first-frame env) (car env))
50 (define the-empty-environment '())
52 (define (make-frame variables values)
53 (let ([ht (make-hash)])
54 (for-each (lambda (var val)
55 (hash-set! ht var val))
60 (define (frame-variables frame)
63 (define (frame-values frame)
66 (define (add-binding-to-frame! var val frame)
67 (hash-set! frame var val))
69 ;; environment is a list of frames, most recent being the last
70 ;; one consed into the list
71 (define (extend-environment vars vals base-env)
72 (let ([frame (make-frame vars vals)])
73 (cons frame base-env)))
75 (define (lookup-variable-value var env)
76 (if (eq? env the-empty-environment)
77 (error "unbound variable: " var)
78 (let ([frame (first-frame env)])
79 (let ([value (hash-ref frame var (lambda () (lookup-variable-value var (enclosing-environment env))))])
80 (if (eq? value '*unassigned*)
81 (error "evaluating a variable that is not assigned a value -- " var)
84 (define (set-variable-value! var val env)
85 (if (eq? env the-empty-environment)
86 (error "unbound variable: " var)
87 (let ([frame (first-frame env)])
88 (if (hash-has-key? frame var)
89 (hash-set! frame var val)
90 (set-variable-value! var val (enclosing-environment env))))))
92 (define (define-variable! var val env)
93 (let ([frame (first-frame env)])
94 (if (hash-has-key? frame var)
95 (hash-set! frame var val)
96 (add-binding-to-frame! var val frame))))
98 ;; primitive procedure
99 (define (primitive-implementation proc) (cadr proc))
101 (define primitive-procedures
102 (list (list 'car car)
115 (define (primitive-procedure-names)
116 (map car primitive-procedures))
118 (define (primitive-procedure-objects)
119 (map (lambda (proc) (list 'primitive (cadr proc)))
120 primitive-procedures))
122 (define (apply-primitive-procedure proc args)
123 (apply-in-underlying-scheme
124 (primitive-implementation proc) args))
127 (define (make-environment)
129 (extend-environment (primitive-procedure-names)
130 (primitive-procedure-objects)
131 the-empty-environment)))
132 (define-variable! 'true true initial-env)
133 (define-variable! 'false false initial-env)
136 (define the-global-environment (make-environment))
139 (define (list-of-values exps env)
140 (if (no-operands? exps)
142 (cons (eval (first-operand exps) env)
143 (list-of-values (rest-operands exps) env))))
145 (define (no-operands? ops) (null? ops))
146 (define (first-operand ops) (car ops))
147 (define (rest-operands ops) (cdr ops))
149 ;; compound procedure
150 (define (make-procedure params body env)
151 (list 'procedure params (scan-out-definitions body) env))
153 (define (procedure-parameters p) (cadr p))
154 (define (procedure-body p) (scan-out-definitions (caddr p)))
155 (define (procedure-environment p) (cadddr p))
157 (define (execute-application procedure arguments)
159 [`(primitive ,f ...) (apply-primitive-procedure procedure arguments)]
160 [`(procedure ,f ...) ((procedure-body procedure)
162 (procedure-parameters procedure)
164 (procedure-environment procedure)))]
165 [_ (error "Unknown procedure type -- APPLY" procedure)]))
175 (define (cond->if clauses)
176 (define (seq->exp actions)
177 (if (empty? (cdr actions))
182 (let ([clause (car clauses)])
184 [`(else ,action ...) (seq->exp action)]
185 [`(,pred ,action ...) `(if ,pred
187 ,(cond->if (cdr clauses)))]))))
190 (define (let->combination lexpr)
191 (match-let* ([`(let ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) lexpr]
192 [`((,var ,val) ...) bindings])
193 `((lambda ,var ,@body) ,@val)))
196 (define (named-let->combination lexpr)
197 (match-let* ([`(let ,(? symbol? name) ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) lexpr]
198 [`((,var ,val) ...) bindings])
199 `(begin (define ,name (lambda ,var ,@body))
203 (define (let*->nested-lets lexpr)
205 [`(let* (,first-binding ,rest-bindings ...) ,body ..1)
206 `(let (,first-binding) ,(let*->nested-lets `(let* ,rest-bindings ,@body)))]
207 [`(let* () ,body ..1) `(let () ,@body)]))
209 ;; internal definitions
210 (define (scan-out-definitions body)
212 [`((define ,var ,e) ..1 ,rest)
213 `((let ,(map (lambda (v) (list (car v) ''*unassigned*)) var)
214 ,@(map (lambda (v e) `(set! ,(car v) (lambda ,(cdr v) ,e))) var e)
219 (define (letrec->combination lexpr)
221 [`(letrec (,bindings ...) ,body ..1)
222 `(let ,(map (lambda (v) (list (car v) ''*unassigned*)) bindings)
223 ,@(map (lambda (binding)
224 (let ([name (car binding)]
225 [value (cadr binding)])
226 `(set! ,name ,value)))
230 (define (analyze exp)
231 ;; use this display statement to visualize the recursive evaluation process
232 ;;(display (format "~s~%" exp))
234 [(? self-evaluating? exp) (lambda (env) exp)]
235 [(? variable? exp) (lambda (env) (lookup-variable-value exp env))]
236 [`(quote ,x) (lambda (env) x)]
237 [`(set! ,var ,val) (let ([vproc (analyze val)])
239 (set-variable-value! var (vproc env) env)))]
240 [`(define ,(? (lambda (x) (not (pair? x))) var) ,b) (let ([vproc (analyze b)])
242 (define-variable! var (vproc env) env)))]
243 [`(define ,(? pair? var) ,b ..1) (let ([pproc (analyze (make-lambda (cdr var) b))]
246 (define-variable! pname (pproc env) env)))]
247 [`(if ,pred ,consequent ,alternative) (let ([pproc (analyze pred)]
248 [cproc (analyze consequent)]
249 [aproc (analyze alternative)])
251 (if (true? (pproc env))
254 [`(lambda ,parameters ,body ..1) (let ([bproc (analyze-sequence body)])
256 (make-procedure parameters bproc env)))]
257 [`(begin ,exp ...) (analyze-sequence exp)]
258 [`(cond ,clauses ...) (analyze (cond->if clauses))]
259 [`(let ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) (analyze (let->combination exp))]
260 [`(let ,(? symbol? name) ,bindings ,body ..1) (analyze (named-let->combination exp))]
261 [`(let* ,bindings ,body ..1) (analyze (let*->nested-lets exp))]
262 [`(letrec ,bindings ,body ..1) (analyze (letrec->combination exp))]
263 [(list f x ...) (let ([fproc (analyze f)]
264 [aprocs (map analyze x)])
266 (execute-application (fproc env)
270 [_ (error "unable to evaluate expression -- EVAL " exp)]))
273 (define (eval exp env)
277 (let loop ([input (read)]
278 [env the-global-environment])
279 (let ([output (eval input env)])
284 (let ([t1 (current-inexact-milliseconds)])
285 (eval expr the-global-environment)
286 (displayln (- (current-inexact-milliseconds) t1))))