git.fiddlerwoaroof.com
Browse code

feat: Lisp in Small Pieces exercises

Edward authored on 27/04/2021 05:26:42
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,896 @@
1
+(defpackage :fwoar.lisp-sandbox.1
2
+  (:use :cl )
3
+  (:export ))
4
+(in-package :fwoar.lisp-sandbox.1)
5
+(defvar *trace-depth* 0)
6
+
7
+(defclass bool () ())
8
+(progn
9
+  (defvar true (make-instance 'bool))
10
+  (defmethod print-object ((o (eql true)) s)
11
+    (format s "#.~s" 'true)))
12
+(progn
13
+  (defvar false (make-instance 'bool))
14
+  (defmethod print-object ((o (eql false)) s)
15
+    (format s "#.~s" 'false)))
16
+
17
+(defmacro define ((name &rest args) &body body)
18
+  `(progn (defun ,name (,@args)
19
+            ,@body)
20
+          (defparameter ,name (function ,name))))
21
+
22
+(declaim (inline atom? symbol? string? number? char? boolean? vector?))
23
+(define (atom? exp)
24
+  (atom exp))
25
+(define (null? it)
26
+  (null it))
27
+(define (symbol? exp)
28
+  (symbolp exp))
29
+(define (number? exp)
30
+  (numberp exp))
31
+(define (string? exp)
32
+  (stringp exp))
33
+(define (char? exp)
34
+  (characterp exp))
35
+(define (boolean? exp)
36
+  (or (eq exp false)
37
+      (eq exp true)))
38
+(define (vector? exp)
39
+  (vectorp exp))
40
+(define (eq? a b)
41
+  (eq a b))
42
+(define (pair? it)
43
+  (consp it))
44
+(define (set-cdr! it value)
45
+  (rplacd it value))
46
+
47
+(defvar empty-begin 813)
48
+(define (eprogn exps env)
49
+  (if (pair? exps)
50
+      (if (pair? (cdr exps))
51
+          (progn (evaluate (car exps) env)
52
+                 (eprogn (cdr exps)
53
+                         env))
54
+          (evaluate (car exps)
55
+                    env))
56
+      empty-begin))
57
+
58
+(define (evlis exps env)
59
+  (if (pair? exps)
60
+      (cons (evaluate (car exps) env)
61
+            (evlis (cdr exps) env))
62
+      ()))
63
+
64
+(define (wrong &rest args)
65
+  (error "~{~a~^ ~}" args))
66
+
67
+(defvar env.init ())
68
+(defvar env.global (cons nil env.init))
69
+
70
+
71
+(defun key-eql (key)
72
+  (lambda (a b)
73
+    (eql (funcall key a)
74
+         (funcall key b))))
75
+
76
+(defun do-adjoin (list item &rest r)
77
+  (cons item
78
+        (apply #'remove item list r)))
79
+(define-modify-macro adjoinf (item &rest r) do-adjoin)
80
+
81
+(defmacro definitial (name &optional (value nil value-p))
82
+  (if value-p
83
+      `(progn (adjoinf (cdr env.global)
84
+                       (cons ',name ,value)
85
+                       :test (key-eql #'car))
86
+              ',name)
87
+      `(progn (adjoinf (cdr env.global)
88
+                       (cons ',name '#:uninit)
89
+                       :test (key-eql #'car))
90
+              ',name)))
91
+
92
+(defmacro defprimitive (name value arity)
93
+  `(definitial ,name
94
+       (lambda (values &optional env)
95
+         (if (= ,arity (length values))
96
+             (apply ',value values)
97
+             (wrong "incorrect arity" ',name ,arity values)))))
98
+
99
+(defmacro defprimitive-bool (name value arity)
100
+  `(definitial ,name
101
+       (lambda (values &optional env)
102
+         (if (= ,arity (length values))
103
+             (if (apply ',value values)
104
+                 true
105
+                 false)
106
+             (wrong "incorrect arity" ',name ,arity values)))))
107
+
108
+(define (extend env variables values)
109
+  (cond ((pair? variables)
110
+         (if (pair? values)
111
+             (cons (cons (car variables) (car values))
112
+                   (extend env (cdr variables) (cdr values)))
113
+             (wrong "Too less values")))
114
+        ((null? variables)
115
+         (if (null? values)
116
+             env
117
+             (wrong "Too much values")))
118
+        ((symbol? variables) (cons (cons variables values) env))))
119
+
120
+(define (invoke fn args)
121
+  (if (functionp fn)
122
+      (funcall fn args)
123
+      (wrong "Not a function" fn)))
124
+
125
+(define (lookup id env)
126
+  (if (pair? env)
127
+      (if (eq? (caar env) id)
128
+          (cdar env)
129
+          (lookup id (cdr env)))
130
+      (wrong "No such binding" id)))
131
+
132
+(define (make-function variables body env)
133
+  (lambda (values)
134
+    (eprogn body
135
+            (extend env
136
+                    variables
137
+                    values))))
138
+
139
+(define (update! id env value)
140
+  (if (pair? env)
141
+      (if (eq? (caar env) id)
142
+          (progn (set-cdr! (car env) value)
143
+                 value)
144
+          (update! id (cdr env) value))
145
+      (wrong "No such binding" id)))
146
+
147
+(define (evaluate e env)
148
+  (if (atom? e)
149
+      (cond ((eq? e 't) true)
150
+            ((eq? e 'f) false)
151
+            ((or (number? e)
152
+                 (string? e)
153
+                 (char? e)
154
+                 (boolean? e)
155
+                 (vector? e))
156
+             e)
157
+            ((symbol? e) (lookup e env)))
158
+      (case (car e)
159
+        ((quote) (cadr e))
160
+        ((if) (if (not (eq? (evaluate (cadr e) env) false))
161
+                  (evaluate (caddr e) env)
162
+                  (evaluate (cadddr e) env)))
163
+        ((begin) (eprogn (cdr e)
164
+                         env))
165
+        ((set!) (update! (cadr e) env (evaluate (caddr e) env)))
166
+        ((lambda) (make-function (cadr e) (cddr e) env))
167
+        (t (invoke (evaluate (car e) env)
168
+                   (evlis (cdr e) env))))))
169
+
170
+
171
+
172
+
173
+
174
+(defvar *depth-var* '#:depth)
175
+
176
+
177
+(define (eprogn.trace exps env)
178
+  (if (pair? exps)
179
+      (if (pair? (cdr exps))
180
+          (progn (evaluate.trace (car exps) env)
181
+                 (eprogn.trace (cdr exps)
182
+                               env))
183
+          (evaluate.trace (car exps)
184
+                          env))
185
+      ()))
186
+
187
+(define (evlis.trace exps env)
188
+  (if (pair? exps)
189
+      (cons (evaluate.trace (car exps) env)
190
+            (evlis.trace (cdr exps) env))
191
+      ()))
192
+
193
+(define (make-function.trace variables body env)
194
+  (lambda (values)
195
+    (eprogn.trace body
196
+                  (extend env
197
+                          variables
198
+                          values))))
199
+
200
+(define (evaluate.trace e env)
201
+  (let ((*trace-depth* (1+ *trace-depth*)))
202
+    (prog1 (if (atom? e)
203
+               (cond ((eq? e 't) true)
204
+                     ((eq? e 'f) false)
205
+                     ((or (number? e)
206
+                          (string? e)
207
+                          (char? e)
208
+                          (boolean? e)
209
+                          (vector? e))
210
+                      e)
211
+                     ((symbol? e) (lookup e env)))
212
+               (progn
213
+                 (format *trace-output*
214
+                         "~&~v,2@t=> (~{~s~^ ~})~%"
215
+                         (* 2 *trace-depth*)
216
+                         e)
217
+                 (let ((result (case (car e)
218
+                                 ((quote) (cadr e))
219
+                                 ((if) (if (not (eq? (evaluate.trace (cadr e) env) false))
220
+                                           (evaluate.trace (caddr e) env)
221
+                                           (evaluate.trace (cadddr e) env)))
222
+                                 ((begin) (eprogn.trace (cdr e)
223
+                                                        env))
224
+                                 ((set!) (update! (cadr e) env (evaluate.trace (caddr e) env)))
225
+                                 ((lambda) (make-function.trace (cadr e) (cddr e) env))
226
+                                 (t (invoke (evaluate.trace (car e) env)
227
+                                            (evlis.trace (cdr e) env))))))
228
+                   (format *trace-output* "~&~v,2@t<= ~s~%" (* 2 *trace-depth*) result)
229
+                   result))))))
230
+
231
+(defparameter def.extend
232
+  (make-function '(env variables values)
233
+                 '((if (pair? variables)
234
+                       (if (pair? values)
235
+                           (cons (cons (car variables) (car values))
236
+                                 (extend env (cdr variables) (cdr values)))
237
+                           (wrong "Too less values"))
238
+                       (if (null? variables)
239
+                           (if (null? values)
240
+                               env
241
+                               (wrong "Too much values"))
242
+                           (if (symbol? variables)
243
+                               (cons (cons variables values) env)
244
+                               nil))))
245
+                 env.global))
246
+
247
+(defun scheme-atom? (it)
248
+  (if (atom it)
249
+      true
250
+      false))
251
+(defun scheme-not (it)
252
+  (if (eq it true) false true))
253
+(defun scheme-eq? (a b)
254
+  (if (eq a b)
255
+      true
256
+      false))
257
+(defun display (it)
258
+  (format *trace-output* "~&~v,2@t ===> ~s~%" (* 2 *trace-depth*) it)
259
+  it)
260
+
261
+(define (chapter1-scheme)
262
+  (definitial apply
263
+      (lambda (values)
264
+        (apply (car values) (cdr values))))
265
+
266
+  (definitial t true)
267
+  (definitial f false)
268
+  (definitial nil '())
269
+  (definitial foo)
270
+  (definitial bar)
271
+  (definitial fib)
272
+  (definitial fact)
273
+  (definitial evaluate)
274
+  (definitial evlis)
275
+  (definitial eprogn)
276
+  (definitial lookup)
277
+  (definitial wrong)
278
+  (definitial update!)
279
+  (definitial make-function)
280
+  (definitial invoke)
281
+  (definitial foldl
282
+      (make-function '(fn init list)
283
+                     '((if (null? list)
284
+                           init
285
+                           (fn (foldl fn init (cdr list))
286
+                               (car list))))
287
+                     env.global))
288
+
289
+  (definitial extend def.extend)
290
+  (definitial env.global env.global)
291
+  (defprimitive atom? scheme-atom? 1)
292
+  (defprimitive-bool number? number? 1)
293
+  (defprimitive-bool vector? vector? 1)
294
+  (defprimitive-bool char? char? 1)
295
+  (defprimitive-bool boolean? boolean? 1)
296
+  (defprimitive-bool string? string? 1)
297
+  (defprimitive-bool symbol? symbol? 1)
298
+  (defprimitive-bool pair? pair? 1)
299
+  (defprimitive-bool function? functionp 1)
300
+  (defprimitive-bool null? null? 1)
301
+  (defprimitive not scheme-not 1)
302
+  (defprimitive cons cons 2)
303
+
304
+  (defprimitive car car 1)
305
+  (defprimitive cdr cdr 1)
306
+
307
+  (defprimitive caar caar 1)
308
+  (defprimitive cadr cadr 1)
309
+  (defprimitive cdar cdar 1)
310
+  (defprimitive cddr cddr 1)
311
+
312
+  (defprimitive #1=caaar #1# 1)
313
+  (defprimitive #2=caadr #2# 1)
314
+  (defprimitive #3=cadar #3# 1)
315
+  (defprimitive #4=caddr #4# 1)
316
+  (defprimitive #5=cdaar #5# 1)
317
+  (defprimitive #6=cdadr #6# 1)
318
+  (defprimitive #7=cddar #7# 1)
319
+  (defprimitive #8=cdddr #8# 1)
320
+
321
+  (defprimitive #9=caaaar #9# 1)
322
+  (defprimitive #10=caaadr #10# 1)
323
+  (defprimitive #11=caadar #11# 1)
324
+  (defprimitive #12=caaddr #12# 1)
325
+  (defprimitive #13=cadaar #13# 1)
326
+  (defprimitive #14=cadadr #14# 1)
327
+  (defprimitive #15=caddar #15# 1)
328
+  (defprimitive #16=cadddr #16# 1)
329
+  (defprimitive #17=cdaaar #17# 1)
330
+  (defprimitive #18=cdaadr #18# 1)
331
+  (defprimitive #19=cdadar #19# 1)
332
+  (defprimitive #20=cdaddr #20# 1)
333
+  (defprimitive #21=cddaar #21# 1)
334
+  (defprimitive #22=cddadr #22# 1)
335
+  (defprimitive #23=cdddar #23# 1)
336
+  (defprimitive #24=cddddr #24# 1)
337
+
338
+  (defprimitive set-cdr! rplacd 2)
339
+  (defprimitive + + 2)
340
+  (defprimitive * * 2)
341
+  (defprimitive-bool = = 2)
342
+  (defprimitive eq? scheme-eq? 2)
343
+  (defprimitive < < 2)
344
+  (defprimitive eql eql 2)
345
+  (defprimitive display display 1)
346
+  (definitial list
347
+      (make-function 'v
348
+                     '((if (null? v)
349
+                           ()
350
+                           (cons (car v)
351
+                                 (list (cdr v)))))
352
+                     env.global))
353
+  (setf (cdr (assoc 'invoke env.global))
354
+        (make-function '(fn args)
355
+                       '((if (function? fn)
356
+                             (apply fn args)
357
+                             (wrong "Not a function" fn)))
358
+                       env.global)
359
+
360
+        (cdr (assoc 'make-function env.global))
361
+        (make-function '(variables body env)
362
+                       '((lambda (values)
363
+                           (eprogn body
364
+                                   (extend env variables values))))
365
+                       env.global)
366
+
367
+        (cdr (assoc 'update! env.global))
368
+        (make-function '(id env value)
369
+                       '((if (pair? env)
370
+                             (if (eq? (caar env) id)
371
+                                 (begin (set-cdr! (car env) value)
372
+                                        value)
373
+                                 (update! id (cdr env) value))
374
+                             (wrong "No such binding" id)))
375
+                       env.global)
376
+
377
+        (cdr (assoc 'wrong env.global))
378
+        (make-function '(a b)
379
+                       '((display (cons a b)))
380
+                       env.global)
381
+
382
+        (cdr (assoc 'lookup env.global))
383
+        (make-function '(id env)
384
+                       '((if (pair? env)
385
+                             (if (eq? (caar env) id)
386
+                                 (cdar env)
387
+                                 (lookup id (cdr env)))
388
+                             (wrong "No such binding" id)))
389
+                       env.global)
390
+
391
+        (cdr (assoc 'evaluate env.global))
392
+        (make-function '(e env)
393
+                       '((if (atom? e)
394
+                             (if (eq? e 't)
395
+                                 t
396
+                                 (if (eq? e 'f)
397
+                                     f
398
+                                     (if (if (number? e) t
399
+                                             (if (string? e) t
400
+                                                 (if (char? e) t
401
+                                                     (if (boolean? e) t
402
+                                                         (vector? e)))))
403
+                                         e
404
+                                         (if (symbol? e)
405
+                                             (lookup e env)
406
+                                             nil))))
407
+                             ((lambda (case-var)
408
+                                (if (eq? case-var 'quote)
409
+                                    (begin nil (cadr e))
410
+                                    (if (eq? case-var 'if)
411
+                                        (if (not (eq? (evaluate (cadr e) env) f))
412
+                                            (evaluate (caddr e) env)
413
+                                            (evaluate (cadddr e) env))
414
+                                        (if (eq? case-var 'begin)
415
+                                            (eprogn (cdr e) env)
416
+                                            (if (eq? case-var 'set!)
417
+                                                (update! (cadr e) env (evaluate (caddr e) env))
418
+                                                (if (eq? case-var 'lambda)
419
+                                                    (make-function (cadr e) (cddr e) env)
420
+                                                    (invoke (evaluate (car e) env)
421
+                                                            (evlis (cdr e) env))))))))
422
+                              (car e))))
423
+                       env.global)
424
+
425
+        (cdr (assoc 'evlis env.global))
426
+        (make-function '(exps env)
427
+                       '((if (pair? exps)
428
+                             (cons (evaluate (car exps) env)
429
+                                   (evlis (cdr exps) env))
430
+                             ()))
431
+                       env.global)
432
+
433
+        (cdr (assoc 'eprogn env.global))
434
+        (make-function '(exps env)
435
+                       '((if (pair? exps)
436
+                             (if (pair? (cdr exps))
437
+                                 (begin (evaluate (car exps) env)
438
+                                        (eprogn (cdr exps)
439
+                                                env))
440
+                                 (evaluate (car exps)
441
+                                           env))
442
+                             ()))
443
+                       env.global))
444
+
445
+  (labels ((toplevel ()
446
+             (fresh-line)
447
+             (princ "> ")
448
+             (princ (evaluate (let ((it (read)))
449
+                                (case it
450
+                                  (:quit (return-from toplevel))
451
+                                  (t it)))
452
+                              env.global))
453
+             (terpri)
454
+             (toplevel)))
455
+    (toplevel)))
456
+
457
+(define (chapter1-scheme.trace)
458
+  (definitial apply
459
+      (lambda (values)
460
+        (apply (car values) (cdr values))))
461
+
462
+  (definitial t true)
463
+  (definitial f false)
464
+  (definitial nil '())
465
+  (definitial foo)
466
+  (definitial bar)
467
+  (definitial fib)
468
+  (definitial fact)
469
+  (definitial evaluate)
470
+  (definitial evlis)
471
+  (definitial eprogn)
472
+  (definitial lookup)
473
+  (definitial wrong)
474
+  (definitial update!)
475
+  (definitial make-function)
476
+  (definitial invoke)
477
+  (definitial foldl
478
+      (make-function '(fn init list)
479
+                     '((if (null? list)
480
+                           init
481
+                           (fn (foldl fn init (cdr list))
482
+                               (car list))))
483
+                     env.global))
484
+
485
+  (definitial extend def.extend)
486
+  (definitial env.global env.global)
487
+  (defprimitive atom? scheme-atom? 1)
488
+  (defprimitive-bool number? number? 1)
489
+  (defprimitive-bool vector? vector? 1)
490
+  (defprimitive-bool char? char? 1)
491
+  (defprimitive-bool boolean? boolean? 1)
492
+  (defprimitive-bool string? string? 1)
493
+  (defprimitive-bool symbol? symbol? 1)
494
+  (defprimitive-bool pair? pair? 1)
495
+  (defprimitive-bool function? functionp 1)
496
+  (defprimitive-bool null? null? 1)
497
+  (defprimitive not scheme-not 1)
498
+  (defprimitive cons cons 2)
499
+
500
+  (defprimitive car car 1)
501
+  (defprimitive cdr cdr 1)
502
+
503
+  (defprimitive caar caar 1)
504
+  (defprimitive cadr cadr 1)
505
+  (defprimitive cdar cdar 1)
506
+  (defprimitive cddr cddr 1)
507
+
508
+  (defprimitive #1=caaar #1# 1)
509
+  (defprimitive #2=caadr #2# 1)
510
+  (defprimitive #3=cadar #3# 1)
511
+  (defprimitive #4=caddr #4# 1)
512
+  (defprimitive #5=cdaar #5# 1)
513
+  (defprimitive #6=cdadr #6# 1)
514
+  (defprimitive #7=cddar #7# 1)
515
+  (defprimitive #8=cdddr #8# 1)
516
+
517
+  (defprimitive #9=caaaar #9# 1)
518
+  (defprimitive #10=caaadr #10# 1)
519
+  (defprimitive #11=caadar #11# 1)
520
+  (defprimitive #12=caaddr #12# 1)
521
+  (defprimitive #13=cadaar #13# 1)
522
+  (defprimitive #14=cadadr #14# 1)
523
+  (defprimitive #15=caddar #15# 1)
524
+  (defprimitive #16=cadddr #16# 1)
525
+  (defprimitive #17=cdaaar #17# 1)
526
+  (defprimitive #18=cdaadr #18# 1)
527
+  (defprimitive #19=cdadar #19# 1)
528
+  (defprimitive #20=cdaddr #20# 1)
529
+  (defprimitive #21=cddaar #21# 1)
530
+  (defprimitive #22=cddadr #22# 1)
531
+  (defprimitive #23=cdddar #23# 1)
532
+  (defprimitive #24=cddddr #24# 1)
533
+
534
+  (defprimitive set-cdr! rplacd 2)
535
+  (defprimitive + + 2)
536
+  (defprimitive * * 2)
537
+  (defprimitive-bool = = 2)
538
+  (defprimitive eq? scheme-eq? 2)
539
+  (defprimitive < < 2)
540
+  (defprimitive eql eql 2)
541
+  (defprimitive display display 1)
542
+  (definitial list
543
+      (make-function 'v
544
+                     '((if (null? v)
545
+                           ()
546
+                           (cons (car v)
547
+                                 (list (cdr v)))))
548
+                     env.global))
549
+  (setf (cdr (assoc 'invoke env.global))
550
+        (make-function '(fn args)
551
+                       '((if (function? fn)
552
+                             (apply fn args)
553
+                             (wrong "Not a function" fn)))
554
+                       env.global)
555
+
556
+        (cdr (assoc 'make-function env.global))
557
+        (make-function '(variables body env)
558
+                       '((lambda (values)
559
+                           (eprogn body
560
+                                   (extend env variables values))))
561
+                       env.global)
562
+
563
+        (cdr (assoc 'update! env.global))
564
+        (make-function '(id env value)
565
+                       '((if (pair? env)
566
+                             (if (eq? (caar env) id)
567
+                                 (begin (set-cdr! (car env) value)
568
+                                        value)
569
+                                 (update! id (cdr env) value))
570
+                             (wrong "No such binding" id)))
571
+                       env.global)
572
+
573
+        (cdr (assoc 'wrong env.global))
574
+        (make-function '(a b)
575
+                       '((display (cons a b)))
576
+                       env.global)
577
+
578
+        (cdr (assoc 'lookup env.global))
579
+        (make-function '(id env)
580
+                       '((if (pair? env)
581
+                             (if (eq? (caar env) id)
582
+                                 (cdar env)
583
+                                 (lookup id (cdr env)))
584
+                             (wrong "No such binding" id)))
585
+                       env.global)
586
+
587
+        (cdr (assoc 'evaluate env.global))
588
+        (make-function '(e env)
589
+                       '((if (atom? e)
590
+                             (if (eq? e 't)
591
+                                 t
592
+                                 (if (eq? e 'f)
593
+                                     f
594
+                                     (if (if (number? e) t
595
+                                             (if (string? e) t
596
+                                                 (if (char? e) t
597
+                                                     (if (boolean? e) t
598
+                                                         (vector? e)))))
599
+                                         e
600
+                                         (if (symbol? e)
601
+                                             (lookup e env)
602
+                                             nil))))
603
+                             ((lambda (case-var)
604
+                                (if (eq? case-var 'quote)
605
+                                    (begin nil (cadr e))
606
+                                    (if (eq? case-var 'if)
607
+                                        (if (not (eq? (evaluate (cadr e) env) f))
608
+                                            (evaluate (caddr e) env)
609
+                                            (evaluate (cadddr e) env))
610
+                                        (if (eq? case-var 'begin)
611
+                                            (eprogn (cdr e) env)
612
+                                            (if (eq? case-var 'set!)
613
+                                                (update! (cadr e) env (evaluate (caddr e) env))
614
+                                                (if (eq? case-var 'lambda)
615
+                                                    (make-function (cadr e) (cddr e) env)
616
+                                                    (invoke (evaluate (car e) env)
617
+                                                            (evlis (cdr e) env))))))))
618
+                              (car e))))
619
+                       env.global)
620
+
621
+        (cdr (assoc 'evlis env.global))
622
+        (make-function '(exps env)
623
+                       '((if (pair? exps)
624
+                             (cons (evaluate (car exps) env)
625
+                                   (evlis (cdr exps) env))
626
+                             ()))
627
+                       env.global)
628
+
629
+        (cdr (assoc 'eprogn env.global))
630
+        (make-function '(exps env)
631
+                       '((if (pair? exps)
632
+                             (if (pair? (cdr exps))
633
+                                 (begin (evaluate (car exps) env)
634
+                                        (eprogn (cdr exps)
635
+                                                env))
636
+                                 (evaluate (car exps)
637
+                                           env))
638
+                             ()))
639
+                       env.global))
640
+
641
+  (labels ((toplevel ()
642
+             (fresh-line)
643
+             (princ (evaluate.trace (let ((it (read)))
644
+                                      (case it
645
+                                        (:quit (return-from toplevel))
646
+                                        (t it)))
647
+                                    env.global))
648
+             (terpri)
649
+             (toplevel)))
650
+    (toplevel)))
651
+
652
+
653
+(define (d.make-function variables body env)
654
+  (declare (ignore env))
655
+  (lambda (values current.env)
656
+    (d.eprogn body
657
+              (extend current.env
658
+                      variables
659
+                      values))))
660
+
661
+(define (d.invoke fn args env)
662
+  (if (functionp fn)
663
+      (funcall fn args env)
664
+      (wrong "Not a function" fn)))
665
+
666
+(define (d.eprogn exps env)
667
+  (if (pair? exps)
668
+      (if (pair? (cdr exps))
669
+          (progn (d.evaluate (car exps) env)
670
+                 (d.eprogn (cdr exps)
671
+                           env))
672
+          (d.evaluate (car exps)
673
+                      env))
674
+      ()))
675
+
676
+(define (d.evlis exps env)
677
+  (if (pair? exps)
678
+      (cons (d.evaluate (car exps) env)
679
+            (d.evlis (cdr exps) env))
680
+      ()))
681
+
682
+(define (d.evaluate e env)
683
+  (if (atom? e)
684
+      (cond ((or (number? e)
685
+                 (string? e)
686
+                 (char? e)
687
+                 (boolean? e)
688
+                 (vector? e))
689
+             e)
690
+            ((symbol? e) (lookup e env)))
691
+      (case (car e)
692
+        ((quote) (cadr e))
693
+        ((if) (if (not (eq? (d.evaluate (cadr e) env) false))
694
+                  (d.evaluate (caddr e) env)
695
+                  (d.evaluate (cadddr e) env)))
696
+        ((begin) (d.eprogn (cdr e)
697
+                           env))
698
+        ((set!) (update! (cadr e) env (d.evaluate (caddr e) env)))
699
+        ((lambda) (d.make-function (cadr e) (cddr e) nil))
700
+        (t (d.invoke (d.evaluate (car e) env)
701
+                     (d.evlis (cdr e) env)
702
+                     env)))))
703
+(define (d.chapter1-scheme)
704
+  (definitial apply
705
+      (lambda (values)
706
+        (apply (car values) (cdr values))))
707
+
708
+  (definitial t true)
709
+  (definitial f false)
710
+  (definitial nil '())
711
+  (definitial foo)
712
+  (definitial bar)
713
+  (definitial fib)
714
+  (definitial fact)
715
+  (definitial evaluate)
716
+  (definitial evlis)
717
+  (definitial eprogn)
718
+  (definitial lookup)
719
+  (definitial wrong)
720
+  (definitial update!)
721
+  (definitial make-function)
722
+  (definitial invoke)
723
+  (definitial foldl
724
+      (make-function '(fn init list)
725
+                     '((if (null? list)
726
+                           init
727
+                           (fn (foldl fn init (cdr list))
728
+                               (car list))))
729
+                     env.global))
730
+
731
+  (definitial extend def.extend)
732
+  (definitial env.global env.global)
733
+  (defprimitive atom? scheme-atom? 1)
734
+  (defprimitive-bool number? number? 1)
735
+  (defprimitive-bool vector? vector? 1)
736
+  (defprimitive-bool char? char? 1)
737
+  (defprimitive-bool boolean? boolean? 1)
738
+  (defprimitive-bool string? string? 1)
739
+  (defprimitive-bool symbol? symbol? 1)
740
+  (defprimitive-bool pair? pair? 1)
741
+  (defprimitive-bool function? functionp 1)
742
+  (defprimitive-bool null? null? 1)
743
+  (defprimitive not scheme-not 1)
744
+  (defprimitive cons cons 2)
745
+
746
+  (defprimitive car car 1)
747
+  (defprimitive cdr cdr 1)
748
+
749
+  (defprimitive caar caar 1)
750
+  (defprimitive cadr cadr 1)
751
+  (defprimitive cdar cdar 1)
752
+  (defprimitive cddr cddr 1)
753
+
754
+  (defprimitive #1=caaar #1# 1)
755
+  (defprimitive #2=caadr #2# 1)
756
+  (defprimitive #3=cadar #3# 1)
757
+  (defprimitive #4=caddr #4# 1)
758
+  (defprimitive #5=cdaar #5# 1)
759
+  (defprimitive #6=cdadr #6# 1)
760
+  (defprimitive #7=cddar #7# 1)
761
+  (defprimitive #8=cdddr #8# 1)
762
+
763
+  (defprimitive #9=caaaar #9# 1)
764
+  (defprimitive #10=caaadr #10# 1)
765
+  (defprimitive #11=caadar #11# 1)
766
+  (defprimitive #12=caaddr #12# 1)
767
+  (defprimitive #13=cadaar #13# 1)
768
+  (defprimitive #14=cadadr #14# 1)
769
+  (defprimitive #15=caddar #15# 1)
770
+  (defprimitive #16=cadddr #16# 1)
771
+  (defprimitive #17=cdaaar #17# 1)
772
+  (defprimitive #18=cdaadr #18# 1)
773
+  (defprimitive #19=cdadar #19# 1)
774
+  (defprimitive #20=cdaddr #20# 1)
775
+  (defprimitive #21=cddaar #21# 1)
776
+  (defprimitive #22=cddadr #22# 1)
777
+  (defprimitive #23=cdddar #23# 1)
778
+  (defprimitive #24=cddddr #24# 1)
779
+
780
+  (defprimitive set-cdr! rplacd 2)
781
+  (defprimitive + + 2)
782
+  (defprimitive * * 2)
783
+  (defprimitive = = 2)
784
+  (defprimitive eq? scheme-eq? 2)
785
+  (defprimitive < < 2)
786
+  (defprimitive eql eql 2)
787
+  (defprimitive display display 1)
788
+  (definitial list
789
+      (d.make-function 'v
790
+                       '((if (null? v)
791
+                             ()
792
+                             (cons (car v)
793
+                                   (list (cdr v)))))
794
+                       env.global))
795
+  (setf (cdr (assoc 'invoke env.global))
796
+        (d.make-function '(fn args)
797
+                         '((if (function? fn)
798
+                               (apply fn args)
799
+                               (wrong "Not a function" fn)))
800
+                         env.global)
801
+
802
+        (cdr (assoc 'make-function env.global))
803
+        (d.make-function '(variables body env)
804
+                         '((lambda (values)
805
+                             (eprogn body
806
+                                     (extend env variables values))))
807
+                         env.global)
808
+
809
+        (cdr (assoc 'update! env.global))
810
+        (d.make-function '(id env value)
811
+                         '((if (pair? env)
812
+                               (if (eq? (caar env) id)
813
+                                   (begin (set-cdr! (car env) value)
814
+                                          value)
815
+                                   (update! id (cdr env) value))
816
+                               (wrong "No such binding" id)))
817
+                         env.global)
818
+
819
+        (cdr (assoc 'wrong env.global))
820
+        (d.make-function '(a b)
821
+                         '((display (cons a b)))
822
+                         env.global)
823
+
824
+        (cdr (assoc 'lookup env.global))
825
+        (d.make-function '(id env)
826
+                         '((if (pair? env)
827
+                               (if (eq? (caar env) id)
828
+                                   (cdar env)
829
+                                   (lookup id (cdr env)))
830
+                               (wrong "No such binding" id)))
831
+                         env.global)
832
+
833
+        (cdr (assoc 'evaluate env.global))
834
+        (d.make-function '(e env)
835
+                         '((if (atom? e)
836
+                               (if (eq? e 't)
837
+                                   t
838
+                                   (if (eq? e 'f)
839
+                                       f
840
+                                       (if (if (number? e) t
841
+                                               (if (string? e) t
842
+                                                   (if (char? e) t
843
+                                                       (if (boolean? e) t
844
+                                                           (vector? e)))))
845
+                                           e
846
+                                           (if (symbol? e)
847
+                                               (lookup e env)
848
+                                               nil))))
849
+                               ((lambda (case-var)
850
+                                  (if (eq? case-var 'quote)
851
+                                      (begin nil (cadr e))
852
+                                      (if (eq? case-var 'if)
853
+                                          (if (not (eq? (evaluate (cadr e) env) f))
854
+                                              (evaluate (caddr e) env)
855
+                                              (evaluate (cadddr e) env))
856
+                                          (if (eq? case-var 'begin)
857
+                                              (eprogn (cdr e) env)
858
+                                              (if (eq? case-var 'set!)
859
+                                                  (update! (cadr e) env (evaluate (caddr e) env))
860
+                                                  (if (eq? case-var 'lambda)
861
+                                                      (d.make-function (cadr e) (cddr e) env)
862
+                                                      (invoke (evaluate (car e) env)
863
+                                                              (evlis (cdr e) env))))))))
864
+                                (car e))))
865
+                         env.global)
866
+
867
+        (cdr (assoc 'evlis env.global))
868
+        (d.make-function '(exps env)
869
+                         '((if (pair? exps)
870
+                               (cons (evaluate (car exps) env)
871
+                                     (evlis (cdr exps) env))
872
+                               ()))
873
+                         env.global)
874
+
875
+        (cdr (assoc 'eprogn env.global))
876
+        (d.make-function '(exps env)
877
+                         '((if (pair? exps)
878
+                               (if (pair? (cdr exps))
879
+                                   (begin (evaluate (car exps) env)
880
+                                          (eprogn (cdr exps)
881
+                                                  env))
882
+                                   (evaluate (car exps)
883
+                                             env))
884
+                               ()))
885
+                         env.global))
886
+
887
+  (labels ((toplevel ()
888
+             (fresh-line)
889
+             (princ (d.evaluate (let ((it (read)))
890
+                                  (case it
891
+                                    (:quit (return-from toplevel))
892
+                                    (t it)))
893
+                                env.global))
894
+             (terpri)
895
+             (toplevel)))
896
+    (toplevel)))
0 897
new file mode 100644
... ...
@@ -0,0 +1,497 @@
1
+(defpackage :fwoar.lisp-sandbox.2
2
+  (:use :cl )
3
+  (:export ))
4
+(in-package :fwoar.lisp-sandbox.2)
5
+(defvar *trace-depth* 0)
6
+
7
+(defclass bool () ())
8
+(progn
9
+  (defvar true (make-instance 'bool))
10
+  (defmethod print-object ((o (eql true)) s)
11
+    (format s "#.~s" 'true)))
12
+(progn
13
+  (defvar false (make-instance 'bool))
14
+  (defmethod print-object ((o (eql false)) s)
15
+    (format s "#.~s" 'false)))
16
+
17
+(defmacro define ((name &rest args) &body body)
18
+  `(progn (defun ,name (,@args)
19
+            ,@body)
20
+          (defparameter ,name (function ,name))))
21
+
22
+(declaim (inline atom? symbol? string? number? char? boolean? vector?))
23
+(define (atom? exp)
24
+  (atom exp))
25
+(define (null? it)
26
+  (null it))
27
+(define (symbol? exp)
28
+  (symbolp exp))
29
+(define (number? exp)
30
+  (numberp exp))
31
+(define (string? exp)
32
+  (stringp exp))
33
+(define (char? exp)
34
+  (characterp exp))
35
+(define (boolean? exp)
36
+  (or (eq exp false)
37
+      (eq exp true)))
38
+(define (vector? exp)
39
+  (vectorp exp))
40
+(define (eq? a b)
41
+  (eq a b))
42
+(define (pair? it)
43
+  (consp it))
44
+(define (set-cdr! it value)
45
+  (rplacd it value))
46
+
47
+(define (->cl bool)
48
+  (if (eq bool true) t nil))
49
+
50
+(defvar empty-begin 813)
51
+
52
+(define (wrong &rest args)
53
+  (error "~{~a~^ ~}" args))
54
+
55
+(defvar env.init ())
56
+(defvar env.global (cons nil env.init))
57
+(defvar fenv.global (cons nil env.init))
58
+
59
+(defun key-eql (key)
60
+  (lambda (a b)
61
+    (eql (funcall key a)
62
+         (funcall key b))))
63
+
64
+(defun do-adjoin (list item &rest r)
65
+  (cons item
66
+        (apply #'remove item list r)))
67
+(define-modify-macro adjoinf (item &rest r) do-adjoin)
68
+
69
+(defmacro definitial (name &optional (value nil value-p))
70
+  (if value-p
71
+      `(progn (adjoinf (cdr env.global)
72
+                       (cons ',name ,value)
73
+                       :test (key-eql #'car))
74
+              ',name)
75
+      `(progn (adjoinf (cdr env.global)
76
+                       (cons ',name '#:uninit)
77
+                       :test (key-eql #'car))
78
+              ',name)))
79
+
80
+(defmacro definitial-function (name &optional (value nil value-p))
81
+  (if value-p
82
+      `(progn (adjoinf (cdr fenv.global)
83
+                       (cons ',name ,value)
84
+                       :test (key-eql #'car))
85
+              ',name)
86
+      `(progn (adjoinf (cdr fenv.global)
87
+                       (cons ',name '#:uninit)
88
+                       :test (key-eql #'car))
89
+              ',name)))
90
+
91
+(defmacro defprimitive (name value arity)
92
+  `(definitial-function ,name
93
+       (lambda (values &optional env)
94
+         (declare (ignore env))
95
+         (if (= ,arity (length values))
96
+             (apply ',value values)
97
+             (wrong "incorrect arity" ',name ,arity values)))))
98
+
99
+(defmacro defprimitive-bool (name value arity)
100
+  `(definitial-function ,name
101
+       (lambda (values &optional env)
102
+         (declare (ignore env))
103
+         (if (= ,arity (length values))
104
+             (if (apply ',value values)
105
+                 true
106
+                 false)
107
+             (wrong "incorrect arity" ',name ,arity values)))))
108
+
109
+(define (extend env variables values)
110
+  (cond ((pair? variables)
111
+         (if (pair? values)
112
+             (cons (cons (car variables) (car values))
113
+                   (extend env (cdr variables) (cdr values)))
114
+             (wrong "Too less values")))
115
+        ((null? variables)
116
+         (if (null? values)
117
+             env
118
+             (wrong "Too much values")))
119
+        ((symbol? variables) (cons (cons variables values) env))))
120
+
121
+(define (invoke fn args)
122
+  (if (functionp fn)
123
+      (funcall fn args)
124
+      (wrong "Not a function" fn)))
125
+
126
+(define (lookup id env)
127
+  (if (pair? env)
128
+      (if (eq? (caar env) id)
129
+          (cdar env)
130
+          (lookup id (cdr env)))
131
+      (wrong "No such binding" id)))
132
+
133
+(define (f.make-function variables body env fenv)
134
+  (lambda (values)
135
+    (f.eprogn body
136
+              (extend env
137
+                      variables
138
+                      values)
139
+              fenv)))
140
+
141
+(define (update! id env value)
142
+  (if (pair? env)
143
+      (if (eq? (caar env) id)
144
+          (progn (set-cdr! (car env) value)
145
+                 value)
146
+          (update! id (cdr env) value))
147
+      (wrong "No such binding" id)))
148
+
149
+(define (f.evaluate e env fenv)
150
+  (if (atom? e)
151
+      (cond ((eq? e 't) true)
152
+            ((eq? e 'f) false)
153
+            ((or (number? e)
154
+                 (string? e)
155
+                 (char? e)
156
+                 (boolean? e)
157
+                 (vector? e))
158
+             e)
159
+            ((symbol? e) (lookup e env))
160
+            ((wrong "Cannot evaluate" e)))
161
+      (case (car e)
162
+        ((quote) (cadr e))
163
+        ((if) (if (->cl (f.evaluate (cadr e)
164
+                                    env fenv))
165
+                  (f.evaluate (caddr e)
166
+                              env fenv)
167
+                  (f.evaluate (cadddr e)
168
+                              env fenv)))
169
+        ((begin) (f.eprogn (cdr e)
170
+                           env
171
+                           fenv))
172
+        ((set!) (update! (cadr e)
173
+                         env
174
+                         (f.evaluate (caddr e)
175
+                                     env
176
+                                     fenv)))
177
+        ((function) (cond ((symbol? (cadr e))
178
+                           (f.lookup (cadr e)
179
+                                     fenv))
180
+                          ((and (pair? (cadr e))
181
+                                (eq? (cadr e)
182
+                                     'lambda))
183
+                           (f.make-function (cadr (cadr e))
184
+                                            (cddr (cadr e))
185
+                                            env fenv))
186
+                          ((wrong "Incorrect function" (cadr e)))))
187
+        ((lambda) (make-function (cadr e)
188
+                                 (cddr e)
189
+                                 env))
190
+        ((flet)
191
+         (f.eprogn (cddr e)
192
+                   env
193
+                   (extend fenv
194
+                           (mapcar 'car (cadr e))
195
+                           (mapcar (lambda (def)
196
+                                     (f.make-function (cadr def)
197
+                                                      (cddr def)
198
+                                                      env fenv))
199
+                                   (cadr e)))))
200
+        ((labels)
201
+         (let ((new-fenv (extend fenv
202
+                                 (mapcar 'car
203
+                                         (cadr e))
204
+                                 (mapcar (lambda (def)
205
+                                           'void)
206
+                                         (cadr e)))))
207
+           (mapc (lambda (def)
208
+                   (update! (car def)
209
+                            new-fenv
210
+                            (f.make-function (cadr def)
211
+                                             (cddr def)
212
+                                             env new-fenv)))
213
+                 (cadr e))
214
+           (f.eprogn (cddr e)
215
+                     env new-fenv)))
216
+        (t (f.evaluate-application (car e)
217
+                                   (f.evlis (cdr e)
218
+                                            env fenv)
219
+                                   env fenv)))))
220
+(define (f.eprogn exps env fenv)
221
+  (if (pair? exps)
222
+      (if (pair? (cdr exps))
223
+          (progn (f.evaluate (car exps) env fenv)
224
+                 (eprogn (cdr exps)
225
+                         env))
226
+          (f.evaluate (car exps)
227
+                      env fenv))
228
+      empty-begin))
229
+
230
+(define (f.evlis exps env fenv)
231
+  (if (pair? exps)
232
+      (cons (f.evaluate (car exps) env fenv)
233
+            (f.evlis (cdr exps) env fenv))
234
+      ()))
235
+
236
+(define (f.evaluate-application fn args env fenv)
237
+  (cond ((symbol? fn)
238
+         (funcall (f.lookup fn fenv) args))
239
+        ((and (pair? fn)
240
+              (eq? (car fn)
241
+                   'ambda))
242
+         (f.eprogn (cddr fn)
243
+                   (extend env
244
+                           (cadr fn)
245
+                           args)
246
+                   fenv))
247
+        ((wrong "Incorrect functional term" fn))))
248
+
249
+(define (f.lookup id fenv)
250
+  (if (pair? fenv)
251
+      (if (eq? (caar fenv)
252
+               id)
253
+          (cdar fenv)
254
+          (f.lookup id
255
+                    (cdr fenv)))
256
+      (lambda (values)
257
+        (declare (ignore values))
258
+        (wrong "No such functional binding" id))))
259
+
260
+(defparameter def.extend
261
+  (f.make-function '(env variables values)
262
+                   '((if (pair? variables)
263
+                         (if (pair? values)
264
+                             (cons (cons (car variables) (car values))
265
+                                   (extend env (cdr variables) (cdr values)))
266
+                             (wrong "Too less values"))
267
+                         (if (null? variables)
268
+                             (if (null? values)
269
+                                 env
270
+                                 (wrong "Too much values"))
271
+                             (if (symbol? variables)
272
+                                 (cons (cons variables values) env)
273
+                                 nil))))
274
+                   env.global
275
+                   fenv.global))
276
+
277
+(defun scheme-atom? (it)
278
+  (if (atom it)
279
+      true
280
+      false))
281
+(defun scheme-not (it)
282
+  (if (eq it true) false true))
283
+(defun scheme-eq? (a b)
284
+  (if (eq a b)
285
+      true
286
+      false))
287
+(defun display (it)
288
+  (format *trace-output* "~&~v,2@t ===> ~s~%" (* 2 *trace-depth*) it)
289
+  it)
290
+
291
+(define (chapter2-scheme)
292
+  (definitial apply
293
+      (lambda (values)
294
+        (apply (car values) (cdr values))))
295
+
296
+  (definitial t true)
297
+  (definitial f false)
298
+  (definitial nil '())
299
+  (definitial foo)
300
+  (definitial bar)
301
+  (definitial-function fib)
302
+  (definitial-function fact)
303
+  (definitial-function evaluate)
304
+  (definitial-function evlis)
305
+  (definitial-function eprogn)
306
+  (definitial-function lookup)
307
+  (definitial-function wrong)
308
+  (definitial-function update!)
309
+  (definitial-function make-function)
310
+  (definitial-function invoke)
311
+  (definitial-function foldl
312
+      (f.make-function '(fn init list)
313
+                       '((if (null? list)
314
+                             init
315
+                             (fn (foldl fn init (cdr list))
316
+                                 (car list))))
317
+                       env.global
318
+                       fenv.global))
319
+
320
+  (definitial-function extend def.extend)
321
+  (definitial env.global env.global)
322
+  (defprimitive atom? scheme-atom? 1)
323
+  (defprimitive-bool number? number? 1)
324
+  (defprimitive-bool vector? vector? 1)
325
+  (defprimitive-bool char? char? 1)
326
+  (defprimitive-bool boolean? boolean? 1)
327
+  (defprimitive-bool string? string? 1)
328
+  (defprimitive-bool symbol? symbol? 1)
329
+  (defprimitive-bool pair? pair? 1)
330
+  (defprimitive-bool function? functionp 1)
331
+  (defprimitive-bool null? null? 1)
332
+  (defprimitive not scheme-not 1)
333
+  (defprimitive cons cons 2)
334
+
335
+  (defprimitive car car 1)
336
+  (defprimitive cdr cdr 1)
337
+
338
+  (defprimitive caar caar 1)
339
+  (defprimitive cadr cadr 1)
340
+  (defprimitive cdar cdar 1)
341
+  (defprimitive cddr cddr 1)
342
+
343
+  (defprimitive #1=caaar #1# 1)
344
+  (defprimitive #2=caadr #2# 1)
345
+  (defprimitive #3=cadar #3# 1)
346
+  (defprimitive #4=caddr #4# 1)
347
+  (defprimitive #5=cdaar #5# 1)
348
+  (defprimitive #6=cdadr #6# 1)
349
+  (defprimitive #7=cddar #7# 1)
350
+  (defprimitive #8=cdddr #8# 1)
351
+
352
+  (defprimitive #9=caaaar #9# 1)
353
+  (defprimitive #10=caaadr #10# 1)
354
+  (defprimitive #11=caadar #11# 1)
355
+  (defprimitive #12=caaddr #12# 1)
356
+  (defprimitive #13=cadaar #13# 1)
357
+  (defprimitive #14=cadadr #14# 1)
358
+  (defprimitive #15=caddar #15# 1)
359
+  (defprimitive #16=cadddr #16# 1)
360
+  (defprimitive #17=cdaaar #17# 1)
361
+  (defprimitive #18=cdaadr #18# 1)
362
+  (defprimitive #19=cdadar #19# 1)
363
+  (defprimitive #20=cdaddr #20# 1)
364
+  (defprimitive #21=cddaar #21# 1)
365
+  (defprimitive #22=cddadr #22# 1)
366
+  (defprimitive #23=cdddar #23# 1)
367
+  (defprimitive #24=cddddr #24# 1)
368
+
369
+  (defprimitive set-cdr! rplacd 2)
370
+  (defprimitive + + 2)
371
+  (defprimitive * * 2)
372
+  (defprimitive-bool = = 2)
373
+  (defprimitive eq? scheme-eq? 2)
374
+  (defprimitive < < 2)
375
+  (defprimitive eql eql 2)
376
+  (defprimitive display display 1)
377
+  (definitial list
378
+      (f.make-function 'v
379
+                       '((if (null? v)
380
+                             ()
381
+                             (cons (car v)
382
+                                   (list (cdr v)))))
383
+                       env.global
384
+                       fenv.global))
385
+  (setf (cdr (assoc 'invoke fenv.global))
386
+        (f.make-function '(fn args)
387
+                         '((if (function? fn)
388
+                               (apply fn args)
389
+                               (wrong "Not a function" fn)))
390
+                         env.global
391
+                         fenv.global)
392
+
393
+        (cdr (assoc 'make-function fenv.global))
394
+        (f.make-function '(variables body env)
395
+                         '((lambda (values)
396
+                             (eprogn body
397
+                                     (extend env variables values))))
398
+                         env.global
399
+                         fenv.global)
400
+
401
+        (cdr (assoc 'update! fenv.global))
402
+        (f.make-function '(id env value)
403
+                         '((if (pair? env)
404
+                               (if (eq? (caar env) id)
405
+                                   (begin (set-cdr! (car env) value)
406
+                                          value)
407
+                                   (update! id (cdr env) value))
408
+                               (wrong "No such binding" id)))
409
+                         env.global
410
+                         fenv.global)
411
+
412
+        (cdr (assoc 'wrong fenv.global))
413
+        (f.make-function '(a b)
414
+                         '((display (cons a b)))
415
+                         env.global
416
+                         fenv.global)
417
+
418
+        (cdr (assoc 'lookup fenv.global))
419
+        (f.make-function '(id env)
420
+                         '((if (pair? env)
421
+                               (if (eq? (caar env) id)
422
+                                   (cdar env)
423
+                                   (lookup id (cdr env)))
424
+                               (wrong "No such binding" id)))
425
+                         env.global
426
+                         fenv.global)
427
+
428
+        (cdr (assoc 'evaluate fenv.global))
429
+        (f.make-function '(e env)
430
+                         '((if (atom? e)
431
+                               (if (eq? e 't)
432
+                                   t
433
+                                   (if (eq? e 'f)
434
+                                       f
435
+                                       (if (if (number? e) t
436
+                                               (if (string? e) t
437
+                                                   (if (char? e) t
438
+                                                       (if (boolean? e) t
439
+                                                           (vector? e)))))
440
+                                           e
441
+                                           (if (symbol? e)
442
+                                               (lookup e env)
443
+                                               nil))))
444
+                               ((lambda (case-var)
445
+                                  (if (eq? case-var 'quote)
446
+                                      (begin nil (cadr e))
447
+                                      (if (eq? case-var 'if)
448
+                                          (if (not (eq? (evaluate (cadr e) env) f))
449
+                                              (evaluate (caddr e) env)
450
+                                              (evaluate (cadddr e) env))
451
+                                          (if (eq? case-var 'begin)
452
+                                              (eprogn (cdr e) env)
453
+                                              (if (eq? case-var 'set!)
454
+                                                  (update! (cadr e) env (evaluate (caddr e) env))
455
+                                                  (if (eq? case-var 'lambda)
456
+                                                      (f.make-function (cadr e) (cddr e) env)
457
+                                                      (invoke (evaluate (car e) env)
458
+                                                              (evlis (cdr e) env))))))))
459
+                                (car e))))
460
+                         env.global
461
+                         fenv.global)
462
+
463
+        (cdr (assoc 'evlis fenv.global))
464
+        (f.make-function '(exps env)
465
+                         '((if (pair? exps)
466
+                               (cons (evaluate (car exps) env)
467
+                                     (evlis (cdr exps) env))
468
+                               ()))
469
+                         env.global
470
+                         fenv.global)
471
+
472
+        (cdr (assoc 'eprogn fenv.global))
473
+        (f.make-function '(exps env)
474
+                         '((if (pair? exps)
475
+                               (if (pair? (cdr exps))
476
+                                   (begin (evaluate (car exps) env)
477
+                                          (eprogn (cdr exps)
478
+                                                  env))
479
+                                   (evaluate (car exps)
480
+                                             env))
481
+                               ()))
482
+                         env.global
483
+                         fenv.global))
484
+
485
+  (labels ((toplevel ()
486
+             (fresh-line)
487
+             (princ "> ")
488
+             (with-simple-restart (continue "continue scheme repl")
489
+               (princ (f.evaluate (let ((it (read)))
490
+                                    (case it
491
+                                      (:quit (return-from toplevel))
492
+                                      (t it)))
493
+                                  env.global
494
+                                  fenv.global)))
495
+             (terpri)
496
+             (toplevel)))
497
+    (toplevel)))