git.fiddlerwoaroof.com
Browse code

(init)

Ed Langley authored on 11/11/2019 09:21:07
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+*~
0 2
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; Package: ASDF-USER -*-
2
+(in-package :asdf-user)
3
+
4
+(defsystem :cl-wasm 
5
+  :description ""
6
+  :author "Ed L <edward@elangley.org>"
7
+  :license "MIT"
8
+  :depends-on (#:alexandria
9
+               #:uiop
10
+               #:serapeum
11
+               #:fwoar-lisputils)
12
+  :serial t
13
+  :components ((:file "package")
14
+               (:file "cl-wasm")))
0 15
new file mode 100644
... ...
@@ -0,0 +1,343 @@
1
+(in-package :cl-wasm)
2
+
3
+(defun signed (n i)
4
+  (if (and (<= 0 i)
5
+           (< i (expt 2 (1- n))))
6
+      i
7
+      (- i (expt 2 n))))
8
+(defun invsigned (n i)
9
+  (if (< i 0)
10
+      (+ i (expt 2 n))
11
+      i))
12
+
13
+(defgeneric run-inst (client stack locals instruction argument)
14
+  (:method (client (stack list) (locals vector) (instruction (eql :get-local)) (argument number))
15
+    (cons (aref locals argument)
16
+          stack)))
17
+
18
+(defmacro define-numeric-instruction (suffix (&optional (arg '(argument null))) &body body)
19
+  (let ((i32-name (alexandria:make-keyword (format nil "~a.~a" :i32 suffix)))
20
+        (i64-name (alexandria:make-keyword (format nil "~a.~a" :i64 suffix)))
21
+        (f32-name (alexandria:make-keyword (format nil "~a.~a" :f32 suffix)))
22
+        (f64-name (alexandria:make-keyword (format nil "~a.~a" :f64 suffix))))
23
+    (flet ((get-argument (type)
24
+             (case type
25
+               (:i32 (list (car arg)
26
+                           (case (cadr arg)
27
+                             (:type 'integer)
28
+                             (t (cadr arg)))))
29
+               (:i64 (list (car arg)
30
+                           (case (cadr arg)
31
+                             (:type 'integer)
32
+                             (t (cadr arg)))))
33
+               (:f32 (list (car arg)
34
+                           (case (cadr arg)
35
+                             (:type 'single-float)
36
+                             (t (cadr arg)))))
37
+               (:f64 (list (car arg)
38
+                           (case (cadr arg)
39
+                             (:type 'double-float)
40
+                             (t (cadr arg))))))))
41
+      `(macrolet ((numeric-dispatch (&body forms)
42
+                    (cons 'or forms)))
43
+         (defmethod run-inst (client (stack list) (locals vector) (inst (eql ,i32-name)) ,(get-argument :i32))
44
+           (declare (optimize (speed 3) (safety 1)))
45
+           (macrolet ((numeric-case (type &body body)
46
+                        (when (eql type :i32)
47
+                          (cons 'progn body))))
48
+             (let ((numeric-type '(integer 0 #.(1- (expt 2 32))))
49
+                   (size 32))
50
+               (declare (ignorable numeric-type size))
51
+               ,@body)))
52
+         (defmethod run-inst (client (stack list) (locals vector) (inst (eql ,i64-name)) ,(get-argument :i64))
53
+           (declare (optimize (speed 3) (safety 1)))
54
+           (macrolet ((numeric-case (type &body body)
55
+                        (when (eql type :i64)
56
+                          (cons 'progn body))))
57
+             (let ((numeric-type '(integer #.(1- (expt 2 64))))
58
+                   (size 64))
59
+               (declare (ignorable numeric-type size))
60
+               ,@body)))
61
+         (defmethod run-inst (client (stack list) (locals vector) (inst (eql ,f32-name)) ,(get-argument :f32))
62
+           (declare (optimize (speed 3) (safety 1)))
63
+           (macrolet ((numeric-case (type &body body)
64
+                        (when (eql type :f32)
65
+                          (cons 'progn body))))
66
+             (let ((numeric-type 'single-float)
67
+                   (size 32))
68
+               (declare (ignorable numeric-type size))
69
+               ,@body)))
70
+         (defmethod run-inst (client (stack list) (locals vector) (inst (eql ,f64-name)) ,(get-argument :f64))
71
+           (declare (optimize (speed 3) (safety 1)))
72
+           (macrolet ((numeric-case (type &body body)
73
+                        (when (eql type :f64)
74
+                          (cons 'progn body))))
75
+             (let ((numeric-type 'double-float)
76
+                   (size 64))
77
+               (declare (ignorable numeric-type size))
78
+               ,@body)))))))
79
+
80
+(define-numeric-instruction add ()
81
+  (let ((result (+ (coerce (pop stack) numeric-type)
82
+                    (coerce (pop stack) numeric-type))))
83
+    (cons (numeric-dispatch
84
+           (numeric-case :i32 (mod result #.(expt 2 32)))
85
+           (numeric-case :i64 (mod result #.(expt 2 64)))
86
+           (numeric-case :f32 result)
87
+           (numeric-case :f64 result))
88
+          stack)))
89
+
90
+(define-numeric-instruction mul ()
91
+  (let ((result (* (coerce (pop stack) numeric-type)
92
+                   (coerce (pop stack) numeric-type))))
93
+    (cons (numeric-dispatch
94
+           (numeric-case :i32 (mod result #.(expt 2 32)))
95
+           (numeric-case :i64 (mod result #.(expt 2 64)))
96
+           (numeric-case :f32 result)
97
+           (numeric-case :f64 result))
98
+          stack)))
99
+
100
+(define-numeric-instruction const ((arg :type))
101
+  (cons (coerce arg numeric-type) 
102
+        stack))
103
+
104
+(define-numeric-instruction sub ()
105
+  (let ((i2 (pop stack))
106
+        (i1 (pop stack)))
107
+    (declare (ignorable i1 i2))
108
+    (cons (numeric-dispatch
109
+           (numeric-case :i32 (mod (+ (- (coerce i1 numeric-type)
110
+                                          (coerce i2 numeric-type))
111
+                                       #.(expt 2 32))
112
+                                   #.(expt 2 32)))
113
+           (numeric-case :i64 (mod (+ (- (coerce i1 numeric-type)
114
+                                          (coerce i2 numeric-type))
115
+                                       #.(expt 2 64))
116
+                                   #.(expt 2 64)))
117
+           (numeric-case :f32 (- (coerce i1 numeric-type)
118
+                                  (coerce i2 numeric-type)))
119
+           (numeric-case :f64 (- (coerce i1 numeric-type)
120
+                                  (coerce i2 numeric-type))))
121
+          stack)))
122
+
123
+(define-numeric-instruction div_u ()
124
+  (let ((i2 (pop stack))
125
+        (i1 (pop stack)))
126
+    (declare (ignorable i1 i2))
127
+    (cons (numeric-dispatch
128
+           (numeric-case :i32 (mod (truncate (coerce i1 numeric-type)
129
+                                             (coerce i2 numeric-type))
130
+                                   #.(expt 2 32)))
131
+           (numeric-case :i64 (mod (truncate (coerce i1 numeric-type)
132
+                                             (coerce i2 numeric-type))
133
+                                   #.(expt 2 64)))
134
+           (numeric-case :f32 (error "floating div not implemented"))
135
+           (numeric-case :f64 (error "floating div not implemented")))
136
+          stack)))
137
+
138
+(define-numeric-instruction div_s ()
139
+  (let* ((i2 (coerce (pop stack) numeric-type))
140
+         (j2 (coerce (signed size i2) numeric-type))
141
+         (i1 (coerce (pop stack) numeric-type))
142
+         (j1 (coerce (signed size i1) numeric-type)))
143
+    (declare (ignorable i1 i2 j1 j2))
144
+    (cons (numeric-dispatch
145
+           (numeric-case :i32 (if (/= (truncate (coerce i1 numeric-type)
146
+                                                (coerce i2 numeric-type))
147
+                                      #.(expt 2 31))
148
+                                  (invsigned 32
149
+                                             (truncate (coerce j1 numeric-type)
150
+                                                       (coerce j2 numeric-type)))
151
+                                  (error "undefined result")))
152
+           (numeric-case :i64 (if (/= (truncate (coerce i1 numeric-type)
153
+                                                (coerce i2 numeric-type))
154
+                                      #.(expt 2 63))
155
+                                  (invsigned 64
156
+                                             (truncate (coerce j1 numeric-type)
157
+                                                       (coerce j2 numeric-type)))
158
+                                  (error "undefined result")))
159
+           (numeric-case :f32 (error "floating div not implemented"))
160
+           (numeric-case :f64 (error "floating div not implemented")))
161
+          stack)))
162
+
163
+(define-numeric-instruction rem_u ()
164
+  (let ((i2 (pop stack))
165
+        (i1 (pop stack)))
166
+    (declare (ignorable i1 i2))
167
+    (cons (numeric-dispatch
168
+           (numeric-case :i32 (mod (- (coerce i1 numeric-type)
169
+                                       (* (coerce i2 numeric-type)
170
+                                          (truncate i1 i2)))
171
+                                   #.(expt 2 32)))
172
+           (numeric-case :i64 (mod (- (coerce i1 numeric-type)
173
+                                       (* (coerce i2 numeric-type)
174
+                                          (truncate i1 i2)))
175
+                                   #.(expt 2 64)))
176
+           (numeric-case :f32 (error "floating rem not implemented"))
177
+           (numeric-case :f64 (error "floating rem not implemented")))
178
+          stack)))
179
+
180
+(define-numeric-instruction rem_s ()
181
+  (let* ((i2 (pop stack))
182
+         (j2 (signed size i2))
183
+         (i1 (pop stack))
184
+         (j1 (signed size i1)))
185
+    (declare (ignorable i1 i2 j1 j2))
186
+    (cons (numeric-dispatch
187
+           (numeric-case :i32 (mod (- (coerce j1 numeric-type)
188
+                                       (* (coerce j2 numeric-type)
189
+                                          (truncate j1 j2)))
190
+                                   #.(expt 2 32)))
191
+           (numeric-case :i64 (mod (- (coerce j1 numeric-type)
192
+                                       (* (coerce j2 numeric-type)
193
+                                          (truncate j1 j2)))
194
+                                   #.(expt 2 64)))
195
+           (numeric-case :f32 (error "floating rem not implemented"))
196
+           (numeric-case :f64 (error "floating rem not implemented")))
197
+          stack)))
198
+
199
+(define-numeric-instruction rem_s ()
200
+  (let* ((i2 (pop stack))
201
+         (j2 (signed size i2))
202
+         (i1 (pop stack))
203
+         (j1 (signed size i1)))
204
+    (declare (ignorable i1 i2 j1 j2))
205
+    (cons (numeric-dispatch
206
+           (numeric-case :i32 (mod (- (coerce j1 numeric-type)
207
+                                       (* (coerce j2 numeric-type)
208
+                                          (truncate j1 j2)))
209
+                                   #.(expt 2 32)))
210
+           (numeric-case :i64 (mod (- (coerce j1 numeric-type)
211
+                                       (* (coerce j2 numeric-type)
212
+                                          (truncate j1 j2)))
213
+                                   #.(expt 2 64)))
214
+           (numeric-case :f32 (error "floating rem not implemented"))
215
+           (numeric-case :f64 (error "floating rem not implemented")))
216
+          stack)))
217
+
218
+(define-numeric-instruction and ()
219
+  (let* ((i2 (coerce (pop stack)
220
+                     numeric-type))
221
+         (i1 (coerce (pop stack)
222
+                     numeric-type)))
223
+    (declare (ignorable i1 i2))
224
+    (cons (numeric-dispatch
225
+           (numeric-case :i32 (logand #.(1- (expt 2 32))
226
+                                      (logand i1 i2)))
227
+           (numeric-case :i64 (logand #.(1- (expt 2 64))
228
+                                      (logand i1 i2)))
229
+           (numeric-case :f32 (error "floating rem not implemented"))
230
+           (numeric-case :f64 (error "floating rem not implemented")))
231
+          stack)))
232
+
233
+(define-numeric-instruction or ()
234
+  (let* ((i2 (coerce (pop stack)
235
+                     numeric-type))
236
+         (i1 (coerce (pop stack)
237
+                     numeric-type)))
238
+    (declare (ignorable i1 i2))
239
+    (cons (numeric-dispatch
240
+           (numeric-case :i32 (logand #.(1- (expt 2 32))
241
+                                      (logior i1 i2)))
242
+           (numeric-case :i64 (logand #.(1- (expt 2 64))
243
+                                      (logior i1 i2)))
244
+           (numeric-case :f32 (error "floating rem not implemented"))
245
+           (numeric-case :f64 (error "floating rem not implemented")))
246
+          stack)))
247
+
248
+(define-numeric-instruction xor ()
249
+  (let* ((i2 (coerce (pop stack)
250
+                     numeric-type))
251
+         (i1 (coerce (pop stack)
252
+                     numeric-type)))
253
+    (declare (ignorable i1 i2))
254
+    (cons (numeric-dispatch
255
+           (numeric-case :i32 (logand #.(1- (expt 2 32))
256
+                                      (logxor i1 i2)))
257
+           (numeric-case :i64 (logand #.(1- (expt 2 64))
258
+                                      (logxor i1 i2)))
259
+           (numeric-case :f32 (error "floating rem not implemented"))
260
+           (numeric-case :f64 (error "floating rem not implemented")))
261
+          stack)))
262
+
263
+(fw.lu:defclass+ tracer ()
264
+  ((%level :initarg :level :accessor level)))
265
+(fw.lu:defclass+ wat-emitter ()
266
+  ((%level :initarg :level :accessor level)))
267
+
268
+(defvar *client*
269
+  (tracer 0))
270
+
271
+(defmethod run-inst :around ((client tracer) stack locals instruction argument)
272
+  (format t "~&~vt> ~s ~s ~s~%~vt~8t|~{~s~^ ~}|"
273
+          (level client) locals instruction argument
274
+          (level client) (reverse stack))
275
+  (incf (level client))
276
+  (unwind-protect
277
+       (let ((out (call-next-method)))
278
+         (prog1 out
279
+           (format t "~&~vt<~8t|~{~s~^ ~}|~%"
280
+                   (level client) (reverse out))))
281
+    (decf (level client))))
282
+
283
+(defmethod run-inst :around ((client wat-emitter) stack locals instruction argument)
284
+  (incf (level client))
285
+  (unwind-protect
286
+       (let ((out (call-next-method)))
287
+         (let ((*print-case* :downcase))
288
+           (format t "~&~4t~a~:[~; ~:*~a~]" instruction argument))
289
+         out)
290
+    (decf (level client))))
291
+
292
+(defgeneric pre-interpret (client)
293
+  (:method (client)))
294
+(defgeneric post-interpret (client)
295
+  (:method (client)))
296
+
297
+(defmethod pre-interpret ((client wat-emitter))
298
+  (format t "~&(module (func $it (result i32)"))
299
+(defmethod post-interpret ((client wat-emitter))
300
+  (format t ")
301
+  (export \"it\" (func $it)))~%"))
302
+
303
+(defun interpret (instructions locals)
304
+  (pre-interpret *client*)
305
+  (let ((stack ()))
306
+    (loop for (instruction argument) in instructions
307
+          do (setf stack
308
+                   (run-inst *client* stack locals instruction argument)))
309
+    (post-interpret *client*)
310
+    stack))
311
+
312
+(defun test-responder ()
313
+  (spinneret:with-html-string
314
+    (:html
315
+     (:body
316
+      (:script :src "https://localhost/~elangley/libwabt.js")
317
+      (:script 
318
+       (:raw
319
+        (format nil "v=`~a`;WabtModule().then(wabt => window.module = new WebAssembly.Instance(new WebAssembly.Module(wabt.parseWat('foo.wast', v).toBinary({log:true,write_debug_names:true}).buffer)));" 
320
+                (cl-ppcre:regex-replace-all "[\"]"
321
+                                            (with-output-to-string (*standard-output*)
322
+                                              (interpret '((:i32.const #.(invsigned 32 -4))
323
+                                                           (:i32.const #b10101010101010111)
324
+                                                           (:i32.and nil)
325
+                                                           )
326
+                                                         (vector 10)))
327
+                                            "\\\""))))))))
328
+
329
+(defvar *app*)
330
+(defvar *handler*)
331
+(defun demo ()
332
+  (let ((app (make-instance 'ningle:<app>)))
333
+    (setf (ningle:route app "/")
334
+          (lambda (params)
335
+            params
336
+            (list 200 () (list (test-responder)))))
337
+    (values (clack:clackup app
338
+                           :port 5001)
339
+            app)))
340
+
341
+(defun go* ()
342
+  (setf (values *handler* *app*)
343
+        (demo)))
0 344
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+(defpackage :cl-wasm.package
2
+  (:use :cl)
3
+  (:export ))
4
+(in-package :cl-wasm.package)
5
+
6
+(defpackage :cl-wasm
7
+  (:use :cl)
8
+  (:export ))
9
+
10
+(defpackage :cl-wasm-user
11
+  (:use :cl :cl-wasm))