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))
19 (define (eval-sequence exps env)
21 [(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 ;; environment data structures
35 (define (enclosing-environment env) (cdr env))
36 (define (first-frame env) (car env))
37 (define the-empty-environment '())
39 (define (make-frame variables values)
40 (let ([ht (make-hash)])
41 (for-each (lambda (var val)
42 (hash-set! ht var val))
47 (define (frame-variables frame)
50 (define (frame-values frame)
53 (define (add-binding-to-frame! var val frame)
54 (hash-set! frame var val))
56 ;; environment is a list of frames, most recent being the last
57 ;; one consed into the list
58 (define (extend-environment vars vals base-env)
59 (let ([frame (make-frame vars vals)])
60 (cons frame base-env)))
62 (define (lookup-variable-value var env)
63 (if (eq? env the-empty-environment)
64 (error "unbound variable: " var)
65 (let ([frame (first-frame env)])
66 (let ([value (hash-ref frame var (lambda () (lookup-variable-value var (enclosing-environment env))))])
67 (if (eq? value '*unassigned*)
68 (error "evaluating a variable that is not assigned a value -- " var)
71 (define (set-variable-value! var val env)
72 (if (eq? env the-empty-environment)
73 (error "unbound variable: " var)
74 (let ([frame (first-frame env)])
75 (if (hash-has-key? frame var)
76 (hash-set! frame var val)
77 (set-variable-value! var val (enclosing-environment env))))))
79 (define (define-variable! var val env)
80 (let ([frame (first-frame env)])
81 (if (hash-has-key? frame var)
82 (hash-set! frame var val)
83 (add-binding-to-frame! var val frame))))
85 ;; primitive procedure
86 (define (primitive-implementation proc) (cadr proc))
88 (define primitive-procedures
101 (list 'newline newline)
102 (list 'display display)))
104 (define (primitive-procedure-names)
105 (map car primitive-procedures))
107 (define (primitive-procedure-objects)
108 (map (lambda (proc) (list 'primitive (cadr proc)))
109 primitive-procedures))
111 (define (apply-primitive-procedure proc args)
112 (apply-in-underlying-scheme
113 (primitive-implementation proc) args))
116 (define (make-environment)
118 (extend-environment (primitive-procedure-names)
119 (primitive-procedure-objects)
120 the-empty-environment)))
121 (define-variable! 'true true initial-env)
122 (define-variable! 'false false initial-env)
125 (define the-global-environment (make-environment))
128 (define (list-of-values exps env)
129 (if (no-operands? exps)
131 (cons (eval (first-operand exps) env)
132 (list-of-values (rest-operands exps) env))))
134 (define (no-operands? ops) (null? ops))
135 (define (first-operand ops) (car ops))
136 (define (rest-operands ops) (cdr ops))
138 ;; compound procedure
139 (define (make-procedure params body env)
140 (list 'procedure params (scan-out-definitions body) env))
142 (define (procedure-parameters p) (cadr p))
143 (define (procedure-body p) (scan-out-definitions (caddr p)))
144 (define (procedure-environment p) (cadddr p))
146 (define (apply procedure arguments env)
147 ;;(display (format "~s~%" arguments))
149 [`(primitive ,f ...) (apply-primitive-procedure procedure (list-of-arg-values arguments env))]
150 [`(procedure ,f ...) (eval-sequence
151 (procedure-body procedure)
153 (procedure-parameters procedure)
154 (list-of-delayed-args arguments env)
155 (procedure-environment procedure)))]
156 [_ (error "Unknown procedure type -- APPLY" procedure)]))
158 (define (list-of-arg-values exps env)
159 (if (no-operands? exps)
161 (cons (actual-value (first-operand exps) env)
162 (list-of-arg-values (rest-operands exps) env))))
164 (define (list-of-delayed-args exps env)
165 (if (no-operands? exps)
167 (cons (delay-it (first-operand exps) env)
168 (list-of-delayed-args (rest-operands exps) env))))
178 (define (cond->if clauses)
179 (define (seq->exp actions)
180 (if (empty? (cdr actions))
185 (let ([clause (car clauses)])
187 [`(else ,action ...) (seq->exp action)]
188 [`(,pred ,action ...) `(if ,pred
190 ,(cond->if (cdr clauses)))]))))
193 (define (let->combination lexpr)
194 (match-let* ([`(let ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) lexpr]
195 [`((,var ,val) ...) bindings])
196 `((lambda ,var ,@body) ,@val)))
199 (define (named-let->combination lexpr)
200 (match-let* ([`(let ,(? symbol? name) ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) lexpr]
201 [`((,var ,val) ...) bindings])
202 `(begin (define ,name (lambda ,var ,@body))
206 (define (let*->nested-lets lexpr)
208 [`(let* (,first-binding ,rest-bindings ...) ,body ..1)
209 `(let (,first-binding) ,(let*->nested-lets `(let* ,rest-bindings ,@body)))]
210 [`(let* () ,body ..1) `(let () ,@body)]))
212 ;; internal definitions
213 (define (scan-out-definitions body)
215 [`((define ,var ,e) ..1 ,rest)
216 `((let ,(map (lambda (v) (list (car v) ''*unassigned*)) var)
217 ,@(map (lambda (v e) `(set! ,(car v) (lambda ,(cdr v) ,e))) var e)
222 (define (letrec->combination lexpr)
224 [`(letrec (,bindings ...) ,body ..1)
225 `(let ,(map (lambda (v) (list (car v) ''*unassigned*)) bindings)
226 ,@(map (lambda (binding)
227 (let ([name (car binding)]
228 [value (cadr binding)])
229 `(set! ,name ,value)))
234 (define (actual-value exp env)
235 ;(display (format "eval expr ~s~%" exp))
237 (force-it (eval exp env)))
239 (define (force-it obj)
240 ;; (display (format "~s~%" obj))
242 [`(thunk ,exp ,env) (begin
243 ;(display (format "eval's output ~s~%" obj))
245 (actual-value exp env))]
248 (define (delay-it exp env)
249 (list 'thunk exp env))
252 (define (eval exp env)
253 ;; use this display statement to visualize the recursive evaluation process
254 ;;(display (format "~s~%" exp))
256 [(? self-evaluating? exp) exp]
257 [(? variable? exp) (lookup-variable-value exp env)]
259 [`(set! ,var ,val) (set-variable-value! var (eval val env) env)]
260 [`(define ,(? (lambda (x) (not (pair? x))) var) ,b) (define-variable! var (eval b env) env)]
261 [`(define ,(? pair? var) ,b ..1) (define-variable! (car var) (eval (make-lambda (cdr var) b) env) env)]
262 [`(if ,pred ,consequent ,alternative) (if (true? (actual-value pred env)) (eval consequent env) (eval alternative env))]
263 [`(unless ,condition ,consequent ,alternative) (if (true? (eval condition env)) (eval alternative env) (eval consequent env))]
264 [`(lambda ,parameters ,body ..1) (make-procedure parameters body env)]
265 [`(begin ,exp ...) (eval-sequence exp env)]
266 [`(cond ,clauses ...) (eval (cond->if clauses) env)]
267 [`(let ,(? (lambda (x) (or (pair? x) (empty? x))) bindings) ,body ..1) (eval (let->combination exp) env)]
268 [`(let ,(? symbol? name) ,bindings ,body ..1) (eval (named-let->combination exp) env)]
269 [`(let* ,bindings ,body ..1) (eval (let*->nested-lets exp) env)]
270 [`(letrec ,bindings ,body ..1) (eval (letrec->combination exp) env)]
271 [`(,f ,x ...) (apply (actual-value f env)
274 [_ (error "unable to evaluate expression -- EVAL " exp)]))
278 (let loop ([input (read)]
279 [env the-global-environment])
280 (let ([output (actual-value input env)])
285 (let ([t1 (current-inexact-milliseconds)])
286 (eval expr the-global-environment)
287 (displayln (- (current-inexact-milliseconds) t1))))