git.fiddlerwoaroof.com
Browse code

(init)

Ed Langley authored on 29/10/2020 22:36:50
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+*~
0 2
new file mode 100644
... ...
@@ -0,0 +1,212 @@
1
+(defpackage :fwoar.interp
2
+  (:use :cl )
3
+  (:export ))
4
+(in-package :fwoar.interp)
5
+
6
+;; pseudo-scheme
7
+
8
+(define-condition not-implemented (error)
9
+  ())
10
+(defun not-implemented (&optional (note ""))
11
+  (error 'not-implemented :note note))
12
+
13
+(defstruct true)
14
+(defmethod make-load-form ((o true) &optional environment)
15
+  (declare (ignore environment))
16
+  '(if (boundp true) true (setf true (make-true))))
17
+(defstruct false)
18
+(defmethod make-load-form ((o false) &optional environment)
19
+  (declare (ignore environment))
20
+  '(if (boundp false) false (setf false (make-false))))
21
+
22
+(defparameter true
23
+  (if (boundp 'true)
24
+      true
25
+      (make-true)))
26
+(defparameter false
27
+  (if (boundp 'false)
28
+      false
29
+      (make-false)))
30
+
31
+(defmacro define (what &body body)
32
+  (etypecase what
33
+    (cons (destructuring-bind (name . args) what
34
+            `(progn (defun ,name ,args
35
+                      ,@body)
36
+                    (defparameter ,name ',name))))
37
+    (symbol `(defparameter ,what
38
+               (progn ,@body)))))
39
+
40
+(define (symbol? v) (symbolp v))
41
+(define (string? v) (stringp v))
42
+(define (number? v) (numberp v))
43
+(define (char? v) (characterp v))
44
+(define (boolean? v) (member v (list true false)))
45
+(define (vector? v) (vectorp v))
46
+(define (atom? v) (not (consp v)))
47
+(define (pair? v) (consp v))
48
+(define (null? v) (null v))
49
+(define (procedure? v) (or (symbol? v)
50
+                           (functionp v)))
51
+(define (eq? a b) (eql a b))
52
+(define (set-cdr! pair value) (setf (cdr pair) value))
53
+
54
+(defmacro set! (thing val)
55
+  `(setq ,thing ,val))
56
+
57
+
58
+
59
+;; Environments
60
+(define (lookup id env)
61
+  (if (pair? env)
62
+      (if (eq? (caar env) id)
63
+          (cdar env)
64
+          (lookup id (cdr env)))
65
+      (error "No such binding ~s" id)))
66
+(define (update! id env value)
67
+  (if (pair? env)
68
+      (if (eq? (caar env) id)
69
+          (progn (set-cdr! (car env) value)
70
+                 value)
71
+          (update! id (cdr env) value))
72
+      (error "No such binding ~s" id)))
73
+(define (extend env variables values)
74
+  (cond ((pair? variables)
75
+         (if (pair? values)
76
+             (cons (cons (car variables)
77
+                         (car values))
78
+                   (extend env
79
+                           (cdr variables)
80
+                           (cdr values)))
81
+             (error "Too few values")))
82
+        ((null? variables)
83
+         (if (null? values)
84
+             env
85
+             (error "Too many values")))
86
+        ((symbol? variables) (cons (cons variables values) env))))
87
+
88
+(define env.init '())
89
+(defmacro definitial (name &optional (value nil value-p))
90
+  (if value-p
91
+      `(progn (set! env.global (acons ',name ,value
92
+                                      env.global))
93
+              ',name)
94
+      `(progn (set! env.global (acons ',name 'void
95
+                                      env.global))
96
+              ',name)))
97
+
98
+(defmacro defprimitive (name value arity)
99
+  (alexandria:with-gensyms (values)
100
+    `(definitial ,name
101
+         (lambda (,values)
102
+           (if (= ,arity (length ,values))
103
+               (apply ,value ,values)
104
+               (error "Incorrect arity: ~s ~s" ',name ,values))))))
105
+
106
+(defun embedded< (a b)
107
+  (or (< a b)
108
+      false))
109
+
110
+(progn (define env.global env.init)
111
+
112
+       (definitial t true)
113
+       (definitial f false)
114
+       (definitial nil ())
115
+
116
+       (definitial apply
117
+           (lambda (values)
118
+             (invoke (car values)
119
+                     (cadr values))))
120
+
121
+       (definitial foo)
122
+       (definitial bar)
123
+       (definitial fib)
124
+       (definitial fact)
125
+
126
+       (defprimitive cons #'cons 2)
127
+       (defprimitive car #'car 1)
128
+       (defprimitive cdr #'cdr 1)
129
+       (defprimitive set-cdr! 'set-cdr! 2)
130
+       (defprimitive + #'+ 2)
131
+       (defprimitive eq? 'eq? 2)
132
+       (defprimitive < 'embedded< 2))
133
+
134
+
135
+
136
+;; Functions
137
+(define (invoke fn args)
138
+  (if (procedure? fn)
139
+      (funcall fn args)
140
+      (error "Not a function ~s" fn)))
141
+(define (make-function variables body env)
142
+  (lambda (values)
143
+    (eprogn body
144
+            (extend env variables values))))
145
+
146
+
147
+
148
+;; Interpreter
149
+(define empty-begin 813)
150
+(define (eprogn exps env)
151
+  (if (pair? exps)
152
+      (if (pair? (cdr exps))
153
+          (progn (evaluate (car exps) env)
154
+                 (eprogn (cdr exps) env))
155
+          (evaluate (car exps) env))
156
+      empty-begin))
157
+
158
+(define (evlis exps env)
159
+  (if (pair? exps)
160
+      (cons (evaluate (car exps) env)
161
+            (evlis (cdr exps) env))
162
+      '()))
163
+
164
+(let ((*eval-depth* 0))
165
+  (declare (special *eval-depth*))
166
+  (define (evaluate e env)
167
+    (let ((*eval-depth* (if (boundp '*eval-depth*)
168
+                            (1+ *eval-depth*)
169
+                            0)))
170
+      (declare (special *eval-depth*))
171
+      (if (atom? e)
172
+          (cond
173
+            ((symbol? e) (lookup e env))
174
+            ((or (number? e)
175
+                 (string? e)
176
+                 (char? e)
177
+                 (boolean? e)
178
+                 (vector? e))
179
+             e)
180
+            (t (error "cannot evaluate ~s" e)))
181
+          (case (car e)
182
+            (quote (cadr e))
183
+            (if (if (not (false-p (evaluate (cadr e) env)))
184
+                    (evaluate (caddr e) env)
185
+                    (evaluate (cadddr e) env)))
186
+            (begin (eprogn (cdr e) env))
187
+            (set! (update! (cadr e) env
188
+                           (evaluate (caddr e) env)))
189
+            (lambda (make-function (cadr e) (cddr e) env))
190
+            (t
191
+             (let ((function (evaluate (car e) env))
192
+                   (args (evlis (cdr e) env)))
193
+               (format t "~&~a=> (~s ~{~s~^ ~})~%"
194
+                       (fill (make-string (* 2 *eval-depth*))
195
+                             #\space)
196
+                       (car e) args)
197
+               (let ((result (invoke function args)))
198
+                 (format t "~&~a<= ~s~%"
199
+                         (fill (make-string (* 2 *eval-depth*))
200
+                               #\space)
201
+                         result)
202
+                 result))))))))
203
+
204
+(define (chapter1-scheme)
205
+  (labels ((toplevel ()
206
+             (let* ((*package* (find-package :fwoar.interp))
207
+                    (exp (read)))
208
+               (unless (equal exp '(end))
209
+                 (format t "~&~s~%"
210
+                         (evaluate exp env.global))
211
+                 (toplevel)))))
212
+    (toplevel)))
0 213
new file mode 100644
... ...
@@ -0,0 +1,222 @@
1
+(defpackage :fwoar.interp2
2
+  (:use :cl )
3
+  (:export ))
4
+(in-package :fwoar.interp2)
5
+
6
+;; pseudo-scheme
7
+
8
+(define-condition not-implemented (error)
9
+  ())
10
+(defun not-implemented (&optional (note ""))
11
+  (error 'not-implemented :note note))
12
+
13
+(defstruct true)
14
+(defmethod make-load-form ((o true) &optional environment)
15
+  (declare (ignore environment))
16
+  '(if (boundp true) true (setf true (make-true))))
17
+(defstruct false)
18
+(defmethod make-load-form ((o false) &optional environment)
19
+  (declare (ignore environment))
20
+  '(if (boundp false) false (setf false (make-false))))
21
+
22
+(defparameter true
23
+  (if (boundp 'true)
24
+      true
25
+      (make-true)))
26
+(defparameter false
27
+  (if (boundp 'false)
28
+      false
29
+      (make-false)))
30
+
31
+(defmacro define (what &body body)
32
+  (etypecase what
33
+    (cons (destructuring-bind (name . args) what
34
+            `(progn (defun ,name ,args
35
+                      ,@body)
36
+                    (defparameter ,name ',name))))
37
+    (symbol `(defparameter ,what
38
+               (progn ,@body)))))
39
+
40
+(define (symbol? v) (symbolp v))
41
+(define (string? v) (stringp v))
42
+(define (number? v) (numberp v))
43
+(define (char? v) (characterp v))
44
+(define (boolean? v) (member v (list true false)))
45
+(define (vector? v) (vectorp v))
46
+(define (atom? v) (not (consp v)))
47
+(define (pair? v) (consp v))
48
+(define (null? v) (null v))
49
+(define (procedure? v) (or (symbol? v)
50
+                           (functionp v)))
51
+(define (eq? a b) (eql a b))
52
+(define (set-cdr! pair value) (setf (cdr pair) value))
53
+
54
+(defmacro set! (thing val)
55
+  `(setq ,thing ,val))
56
+
57
+
58
+
59
+;; Environments
60
+(define (lookup id env)
61
+  (if (pair? env)
62
+      (if (eq? (caar env) id)
63
+          (cdar env)
64
+          (lookup id (cdr env)))
65
+      (error "No such binding ~s" id)))
66
+(define (update! id env value)
67
+  (if (pair? env)
68
+      (if (eq? (caar env) id)
69
+          (progn (set-cdr! (car env) value)
70
+                 value)
71
+          (update! id (cdr env) value))
72
+      (error "No such binding ~s" id)))
73
+(define (extend env variables values)
74
+  (cond ((pair? variables)
75
+         (if (pair? values)
76
+             (cons (cons (car variables)
77
+                         (car values))
78
+                   (extend env
79
+                           (cdr variables)
80
+                           (cdr values)))
81
+             (error "Too few values")))
82
+        ((null? variables)
83
+         (if (null? values)
84
+             env
85
+             (error "Too many values")))
86
+        ((symbol? variables) (cons (cons variables values) env))))
87
+
88
+(define env.init '())
89
+(defmacro definitial (name &optional (value nil value-p))
90
+  (if value-p
91
+      `(progn (set! env.global (acons ',name ,value
92
+                                      env.global))
93
+              ',name)
94
+      `(progn (set! env.global (acons ',name 'void
95
+                                      env.global))
96
+              ',name)))
97
+
98
+(defmacro definitial-function (name &optional (value nil value-p))
99
+  (if value-p
100
+      `(progn (set! fenv.global (acons ',name ,value
101
+                                       fenv.global))
102
+              ',name)
103
+      `(progn (set! fenv.global (acons ',name 'void
104
+                                       fenv.global))
105
+              ',name)))
106
+
107
+(defmacro defprimitive (name value arity)
108
+  (alexandria:with-gensyms (values)
109
+    `(definitial-function ,name
110
+         (lambda (,values)
111
+           (if (= ,arity (length ,values))
112
+               (apply ,value ,values)
113
+               (error "Incorrect arity: ~s ~s" ',name ,values))))))
114
+
115
+(defun embedded< (a b)
116
+  (or (< a b)
117
+      false))
118
+(defun embedded-eq? (a b)
119
+  (or (eq? a b)
120
+      false))
121
+
122
+(progn (define env.global (copy-seq env.init))
123
+       (define fenv.global (copy-seq env.init))
124
+
125
+       (definitial t true)
126
+       (definitial f false)
127
+       (definitial nil ())
128
+
129
+       (definitial-function apply
130
+           (lambda (values)
131
+             (invoke (car values)
132
+                     (cadr values))))
133
+
134
+       (definitial foo)
135
+       (definitial bar)
136
+       (definitial fib)
137
+       (definitial fact)
138
+
139
+       (defprimitive cons #'cons 2)
140
+       (defprimitive car #'car 1)
141
+       (defprimitive cdr #'cdr 1)
142
+       (defprimitive set-cdr! 'set-cdr! 2)
143
+       (defprimitive + #'+ 2)
144
+       (defprimitive eq? 'embedded-eq? 2)
145
+       (defprimitive < 'embedded< 2))
146
+
147
+
148
+
149
+;; Functions
150
+(define (invoke fn args)
151
+  (if (procedure? fn)
152
+      (funcall fn args)
153
+      (error "Not a function ~s" fn)))
154
+
155
+(define (f.make-function variables body env fenv)
156
+  (lambda (values)
157
+    (f.eprogn body
158
+              (extend env variables values)
159
+              fenv)))
160
+
161
+
162
+
163
+;; Interpreter
164
+(define empty-begin 813)
165
+(define (f.eprogn exps env fenv)
166
+  (if (pair? exps)
167
+      (if (pair? (cdr exps))
168
+          (progn (f.evaluate (car exps) env fenv)
169
+                 (f.eprogn (cdr exps) env fenv))
170
+          (f.evaluate (car exps) env fenv))
171
+      empty-begin))
172
+
173
+(define (f.evlis exps env fenv)
174
+  (if (pair? exps)
175
+      (cons (f.evaluate (car exps) env fenv)
176
+            (f.evlis (cdr exps) env fenv))
177
+      '()))
178
+
179
+(define (evaluate-application fn args env fenv)
180
+  (cond ((symbol? fn)
181
+         (invoke (lookup fn fenv) args))
182
+        ((and (pair? fn) (eq? (car fn) 'lambda))
183
+         (f.eprogn (cddr fn)
184
+                   (extend env (cadr fn) args)
185
+                   fenv))
186
+        (t (error "Incorrect functional term: ~s" fn))))
187
+
188
+(define (f.evaluate e env fenv)
189
+  (if (atom? e)
190
+      (cond
191
+        ((symbol? e) (lookup e env))
192
+        ((or (number? e)
193
+             (string? e)
194
+             (char? e)
195
+             (boolean? e)
196
+             (vector? e))
197
+         e)
198
+        (t (error "cannot evaluate ~s" e)))
199
+      (case (car e)
200
+        (quote (cadr e))
201
+        (if (if (not (false-p (f.evaluate (cadr e) env fenv)))
202
+                (f.evaluate (caddr e) env fenv)
203
+                (f.evaluate (cadddr e) env fenv)))
204
+        (begin (f.eprogn (cdr e) env fenv))
205
+        (set! (update! (cadr e) env
206
+                       (f.evaluate (caddr e) env fenv)))
207
+        (lambda (f.make-function (cadr e) (cddr e) env fenv))
208
+        (t
209
+         (evaluate-application (car e)
210
+                               (f.evlis (cdr e) env fenv)
211
+                               env
212
+                               fenv)))))
213
+
214
+(define (chapter2-scheme)
215
+  (labels ((toplevel ()
216
+             (let* ((*package* (find-package :fwoar.interp2))
217
+                    (exp (read)))
218
+               (unless (equal exp '(end))
219
+                 (format t "~&~s~%"
220
+                         (f.evaluate exp env.global fenv.global))
221
+                 (toplevel)))))
222
+    (toplevel)))