watr 0.0.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ import fs from 'fs'
2
+ import t from 'tst'
3
+
4
+ t.only('table', () => {
5
+ var buffer = fs.readFileSync('./table.wasm');
6
+ const mod = new WebAssembly.Module(buffer)
7
+ const instance = new WebAssembly.Instance(mod)
8
+
9
+ // console.time('instantiate')
10
+ // for (let i = 0; i < 30000; i++) new WebAssembly.Instance(mod)
11
+ // console.timeEnd('instantiate')
12
+ // 290ms to instantiate 30k modules
13
+
14
+ const {callByIndex, getByIndex} = instance.exports
15
+
16
+ console.log(callByIndex(0)) // => 42
17
+ console.log(callByIndex(1)) // => 13
18
+ // console.log(callByIndex(2)) // => error
19
+
20
+ let fn = getByIndex(0)
21
+ console.log(fn, fn?.())
22
+ })
23
+
24
+ t('global', () => {
25
+ var buf = fs.readFileSync('./global.wasm')
26
+ const mod = new WebAssembly.Module(buf)
27
+ const importObj = {
28
+ "js": {
29
+ "log": arg=>console.log(arg),
30
+ "g1": new WebAssembly.Global({value: 'i32', mutable: true}, 123)
31
+ }
32
+ }
33
+
34
+ console.log(importObj.js.g1)
35
+ const instance = new WebAssembly.Instance(mod, importObj)
36
+ const {getG1, setG1, getG0} = instance.exports
37
+
38
+ // console.log(getG0())
39
+ console.log(getG1())
40
+ setG1(100)
41
+ console.log(getG1())
42
+ })
43
+
44
+
45
+ t('stack', () => {
46
+ var buf = fs.readFileSync('./stack.wasm')
47
+ const mod = new WebAssembly.Module(buf)
48
+ const importObj = {"js": {}}
49
+ const instance = new WebAssembly.Instance(mod, importObj)
50
+ const {get, swap, mul} = instance.exports
51
+ console.log(mul(12,13))
52
+ // console.log(swap(1,2,3,4))
53
+ // console.log(get())
54
+ })
55
+
56
+ t('memory', () => {
57
+ var buf = fs.readFileSync('./memory.wasm')
58
+ const mod = new WebAssembly.Module(buf)
59
+ const mem = new WebAssembly.Memory({ initial: 1 })
60
+
61
+ const importObj = {
62
+ js: { log: arg=>console.log(arg) }
63
+ }
64
+ const instance = new WebAssembly.Instance(mod, importObj)
65
+ const api = instance.exports
66
+
67
+ console.log(mem.buffer)
68
+ // console.log(api.mem, api.g)
69
+
70
+ // api.populate()
71
+ // let view = new DataView(mem.buffer)
72
+ // view.setInt16(1, 123)
73
+ let i32 = new Int32Array(mem.buffer)
74
+ i32[1] = 123
75
+ console.log(api.get(4))
76
+ api.set(4,2)
77
+ console.log(api.get(4))
78
+
79
+ // grow by one page
80
+ // console.log(mem.grow(4))
81
+ })
82
+
83
+
84
+
85
+ t('loop', () => {
86
+ var buf = fs.readFileSync('./loops.wasm')
87
+ const mod = new WebAssembly.Module(buf)
88
+ // const mem = new WebAssembly.Memory({ initial:1 })
89
+ // const f32mem = new Float32Array(mem.buffer)
90
+ const importObj = {console: {log:(arg)=>console.log(arg)}}
91
+ const instance = new WebAssembly.Instance(mod, importObj)
92
+
93
+ })
94
+
95
+
96
+ t('amp bench', () => {
97
+ const BLOCK = 1024
98
+ var buf = fs.readFileSync('./array.wasm')
99
+ const mod = new WebAssembly.Module(buf)
100
+ const mem = new WebAssembly.Memory({ initial:1 })
101
+ const blockSize = new WebAssembly.Global({value: 'i32', mutable: true}, BLOCK)
102
+ // blockSize.value
103
+ const f32mem = new Float32Array(mem.buffer)
104
+ const importObj = {js: {mem, blockSize}, console:{log(a,b){console.log(a,b)}}}
105
+ const instance = new WebAssembly.Instance(mod, importObj)
106
+ const {amp, ampMulti, ampShort} = instance.exports
107
+
108
+
109
+ let src = Array.from({length:BLOCK}, (a,i)=>i)
110
+
111
+
112
+ f32mem.set(src)
113
+ amp('2')
114
+ console.log(f32mem)
115
+
116
+ const MAX = 1e5
117
+ f32mem.set(src)
118
+ console.time('warmup')
119
+ for (let i = 0; i < MAX; i++) amp(.5)
120
+ console.timeEnd('warmup')
121
+
122
+ f32mem.set(src)
123
+ console.time('wasm amp')
124
+ for (let i = 0; i < MAX; i++) amp(.5)
125
+ console.timeEnd('wasm amp')
126
+
127
+ f32mem.set(src)
128
+ console.time('wasm amp multivariable')
129
+ for (let i = 0; i < MAX; i++) ampMulti(.5)
130
+ console.timeEnd('wasm amp multivariable')
131
+
132
+ f32mem.set(src)
133
+ console.time('wasm short')
134
+ for (let i = 0; i < MAX; i++) ampShort(.5)
135
+ console.timeEnd('wasm short')
136
+
137
+
138
+ console.time('js amp')
139
+ for (let i = 0; i < MAX; i++) for (let j = 0; j < src.length; j++) src[j]*=.5
140
+ console.timeEnd('js amp')
141
+ })
142
+
143
+
144
+
145
+ t('types', () => {
146
+ var buf = fs.readFileSync('./types.wasm')
147
+ const mod = new WebAssembly.Module(buf)
148
+ // const mem = new WebAssembly.Memory({ initial:1 })
149
+ // const f32mem = new Float32Array(mem.buffer)
150
+ const importObj = {console: {log:(...abc)=>console.log(...abc)}}
151
+ const instance = new WebAssembly.Instance(mod, importObj)
152
+ const {run} = instance.exports
153
+
154
+ console.log(run(123, 13.3, 'abc'))
155
+ })
@@ -0,0 +1,14 @@
1
+ <doctype html>
2
+
3
+ <script type="importmap">
4
+ {
5
+ "imports": {
6
+ "tst": "../node_modules/tst/tst.js",
7
+ "subscript": "../../subscript/subscript.js",
8
+ "subscript/parse.js": "../node_modules/subscript/parse.js"
9
+ }
10
+ }
11
+ </script>
12
+
13
+ <script src="./parse.js" type="module"></script>
14
+ <script src="./compile.js" type="module"></script>
package/test/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import './parse.js'
2
+ import './compile.js'
package/test/parse.js ADDED
@@ -0,0 +1,179 @@
1
+ import t, { is, ok, same } from 'tst'
2
+ import parse from '../src/parse.js'
3
+
4
+ t('parser: s-expr', () => {
5
+ const tree = parse('(module)')
6
+ is(tree, ['module'])
7
+ })
8
+
9
+ t.skip('parser: s-expr no instruction (throws)', () => {
10
+ try {
11
+ parse('()')
12
+ } catch (error) {
13
+ ok(/Empty/.test(error.message))
14
+ return
15
+ }
16
+ throw 'Failed'
17
+ })
18
+
19
+ t('parser: s-expr named', () => {
20
+ const tree = parse('(module $hello)')
21
+ is(tree, ['module', '$hello'])
22
+ })
23
+
24
+ t('parser: ref labels as children', () => {
25
+ const tree = parse('(elem (i32.const 0) $f1 $f2)')
26
+ is(tree, ['elem', ['i32.const', '0'], '$f1', '$f2'])
27
+ })
28
+
29
+ t('parser: s-expr number params', () => {
30
+ const tree = parse('(memory 1 2)')
31
+ is(tree, ['memory', '1', '2'])
32
+ })
33
+
34
+ t('parser: s-expr number params + named params', () => {
35
+ const tree = parse('(memory 1 2 shared)')
36
+ is(tree, ['memory', '1', '2', 'shared'])
37
+ })
38
+
39
+ t('parser: s-expr named params with = value', () => {
40
+ const tree = parse('(i32.load offset=0 align=4)')
41
+ is(tree, ['i32.load', ['offset','0'], ['align','4']])
42
+ })
43
+
44
+ t('parser: stack instruction', () => {
45
+ const code = '(func i32.const 42)'
46
+ const tree = parse(code)
47
+ is(tree, ['func', 'i32.const', '42'])
48
+ })
49
+
50
+ t('parser: many stack instructions', () => {
51
+ const code = '(func i32.const 22 i32.const 20 i32.add)'
52
+ const tree = parse(code)
53
+ is(tree, ['func', 'i32.const', '22', 'i32.const', '20', 'i32.add'])
54
+ })
55
+
56
+ t('parser: children', () => {
57
+ const code = '(func $answer (result i32) (i32.add (i32.const 20) (i32.const 22)))'
58
+ const tree = parse(code)
59
+ is(tree, ['func', '$answer', ['result', 'i32'], ['i32.add', ['i32.const', '20'], ['i32.const', '22']]])
60
+ })
61
+
62
+ t('parser: minimal export function', () => {
63
+ const code = '(func (export "answer") (result i32) (i32.const 42))'
64
+ const tree = parse(code)
65
+ is(tree, ['func', ['export', '"answer"'], ['result', 'i32'], ['i32.const', '42']])
66
+ })
67
+
68
+ t.skip('parser: children', () => {
69
+ const code = String.raw`(data (i32.const 0) "\2a")`
70
+ const tree = parse(code)
71
+ console.log(code)
72
+ is(tree, ['data', ['i32.const', '0'], '"\\2a"'])
73
+ })
74
+
75
+ t('parse: instr', () => {
76
+ const tokens = parse('hello')
77
+ is(tokens, 'hello')
78
+ })
79
+
80
+ t('parse: param', () => {
81
+ const tokens = parse('align=4')
82
+ is(tokens, ['align', '4'])
83
+ })
84
+
85
+ t('parse: label', () => {
86
+ const tokens = parse('$$hi')
87
+ is(tokens, '$$hi')
88
+ })
89
+
90
+ t.skip('parse: string', () => {
91
+ const r = String.raw
92
+ const tokens = parse(r`"hello""ano\"t\n\ther""more"`)
93
+ expect(tokens).to.deep.equal([
94
+ { value: 'hello', kind: 'string', index: 0 },
95
+ { value: r`ano\"t\n\ther`, kind: 'string', index: 7 },
96
+ { value: 'more', kind: 'string', index: 22 }
97
+ ])
98
+ })
99
+
100
+ t('parse: number', () => {
101
+ const tokens = parse('123')
102
+ is(tokens, '123')
103
+ })
104
+
105
+ t('parse: hex', () => {
106
+ const tokens = parse('0xf2')
107
+ is(tokens, '0xf2')
108
+ })
109
+
110
+ t('parse: comments', () => {
111
+ const tokens = parse('(an (; inline ;) comment\n;; line comment\n1)')
112
+ is(tokens, ['an', 'comment', '1'])
113
+ })
114
+
115
+ t('parse: nul', () => {
116
+ const tokens = parse(' \n\t')
117
+ is(tokens, undefined)
118
+ })
119
+
120
+ t.skip('parse: error', () => {
121
+ try {
122
+ let tree = parse('§what')
123
+ } catch (e) {
124
+ ok(/syntax/.test(e.message))
125
+ }
126
+ })
127
+
128
+ t('parse: number', t => {
129
+ ;[
130
+ '12',
131
+ '12.3',
132
+ '-12.3',
133
+ '+12.3',
134
+ '1e5',
135
+ '1.23e5',
136
+ '1.23e-5',
137
+ '1.23e+5',
138
+ 'nan',
139
+ 'inf',
140
+ '+inf',
141
+ '-inf',
142
+ ].forEach(n => {
143
+ const tokens = parse(n)
144
+ is(tokens, n)
145
+ })
146
+
147
+ ;[
148
+ '-0xf2',
149
+ '+0xf2',
150
+ '0xf2.ef',
151
+ '0xf2.ePf',
152
+ '0xf2.P-f',
153
+ 'nan:0xff',
154
+ ].forEach(n => {
155
+ const tokens = parse(n)
156
+ is(tokens, n)
157
+ })
158
+ })
159
+
160
+
161
+ t('parse: complex case 1', () => {
162
+ const tokens = parse(`(
163
+ (hello $hi
164
+ "world")
165
+ ;; (should) be a comment
166
+ and (; another ;) line 0x312 43.23
167
+ )`)
168
+ is(tokens, [['hello', '$hi', '"world"'], 'and', 'line', '0x312', '43.23'])
169
+ })
170
+
171
+ t('parse: minimal function', () => {
172
+ let tokens = parse('(func (export "answer") (result i32) (i32.const 42))')
173
+ is(tokens, ['func', ['export', '"answer"'], ['result', 'i32'], ['i32.const', '42']])
174
+ })
175
+
176
+ t('parse: multiple functions', () => {
177
+ let tokens = parse('(func $a) (func $b)')
178
+ is(tokens, [['func','$a'],['func','$b']])
179
+ })