-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwasm-syntax.scm
135 lines (115 loc) · 4.23 KB
/
wasm-syntax.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
(define-library (wasm-syntax)
(export wasm-definition-type wasm-definition-type?
wasm-elem-definition-func-index
wasm-const-value?
wasm-define-locals wasm-locals-definition? wasm-local-definitions-to-top
wasm-import-definition?
i32-as-wasm-data string-as-wasm-data
emit-wat)
(import (scheme base)
(scheme cxr)
(scheme write)
(srfi srfi-60)
(lists)
(pattern-match))
(begin
(define (wasm-definition-type wasm-definition)
(car wasm-definition))
(define (wasm-definition-type? type wasm-definition)
(eq? (wasm-definition-type wasm-definition) type))
(define (wasm-elem-definition-func-index elem-definition)
(cadr elem-definition))
(define wasm-const-instructions
'(i32.const f32.const))
(define (wasm-const-instruction? instr)
(memq instr wasm-const-instructions))
(define (wasm-const-value? instr)
(pattern-match? `(,wasm-const-instruction? ,??) instr))
(define (wasm-define-locals type n)
(cons 'local (make-list n type)))
(define (wasm-locals-definition? exp)
(pattern-match? `(local ,?? ,??*) exp))
(define (wasm-local-definitions-to-top seq)
(let ((split-code (partition-list wasm-locals-definition? seq)))
(append (car split-code) (cdr split-code))))
(define (wasm-import-definition? exp)
(cond ((null? exp) #f)
((pattern-match? `(import ,string? ,??*) exp))
((pattern-match? `((import ,string? ,??*) ,??*) exp))
(else (wasm-import-definition? (cdr exp)))))
(define (i32-as-wasm-data n)
(do ((bytes (make-bytevector 4))
(i 0 (+ i 1)))
((= i 4) (cons bytes 4))
(bytevector-u8-set!
bytes
i
(bitwise-and
(arithmetic-shift n (* -8 i))
#xff))))
(define (string-as-wasm-data s)
(cons s (bytevector-length (string->utf8 s))))
(define (emit-wat-string-char c port)
;; W3C / WebAssembly Core Specification / 6.3.3. Strings
(cond
((char=? c #\x09) (write-string "\\t" port))
((char=? c #\x0A) (write-string "\\n" port))
((char=? c #\x0D) (write-string "\\r" port))
((char=? c #\x22) (write-string "\\\"" port))
((char=? c #\x27) (write-string "\\'" port))
((char=? c #\x5C) (write-string "\\\\" port))
((and (char>=? c #\x20) (not (char=? c #\x7F)))
(write-char c port))
((or (char<=? c #\xD7FF) (char<=? #\xE000 c #\x10FFFF))
(write-string "\\u{" port)
(write-string (number->string (char->integer c) 16) port)
(write-char #\} port))
(else (error "Invalid UNICODE character" c))))
(define (emit-wat-string s port)
(write-char #\" port)
(string-for-each
(lambda (c) (emit-wat-string-char c port))
s)
(write-char #\" port))
(define (emit-wat-bytes bytes port)
(write-char #\" port)
(do ((hexchars "0123456789abcdef")
(i 0 (+ i 1))
(l (bytevector-length bytes)))
((= i l))
(let* ((b (bytevector-u8-ref bytes i))
(hn (bitwise-and (arithmetic-shift b -4) #x0f))
(ln (bitwise-and b #x0f)))
(write-char #\\ port)
(write-char (string-ref hexchars hn) port)
(write-char (string-ref hexchars ln) port)))
(write-char #\" port))
(define (emit-wat-cont ast port k)
(cond
((null? ast)
(k))
((number? ast)
(write-string (number->string ast) port) (k))
((symbol? ast)
(write-string (symbol->string ast) port) (k))
((string? ast)
(emit-wat-string ast port) (k))
((bytevector? ast)
(emit-wat-bytes ast port) (k))
((pair? ast)
(write-char #\( port)
(let loop ((lst ast))
(emit-wat-cont
(car lst)
port
(if (null? (cdr lst))
(lambda ()
(write-char #\) port)
(k))
(lambda ()
(write-char #\ port)
(loop (cdr lst)))))))
(else (error "Usupported WAT AST element" ast))))
(define (emit-wat ast port)
(emit-wat-cont ast port (lambda () (newline port))))
))