watr 3.0.0 → 3.2.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.
- package/package.json +2 -5
- package/readme.md +27 -49
- package/src/compile.js +742 -465
- package/src/const.js +46 -34
- package/src/encode.js +55 -16
- package/src/parse.js +15 -7
- package/src/print.js +36 -48
- package/src/util.js +8 -0
package/src/const.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// https://webassembly.github.io/spec/core/appendix/index-instructions.html
|
|
2
2
|
export const INSTR = [
|
|
3
|
-
'unreachable', 'nop', 'block
|
|
4
|
-
'end', 'br
|
|
5
|
-
'drop', 'select', '
|
|
6
|
-
'local.get
|
|
7
|
-
'i32.load
|
|
8
|
-
'i32.load8_s
|
|
9
|
-
'i64.load8_s
|
|
10
|
-
'i32.store
|
|
11
|
-
'i32.store8
|
|
3
|
+
'unreachable', 'nop', 'block', 'loop', 'if', 'else', 'then', , , , ,
|
|
4
|
+
'end', 'br', 'br_if', 'br_table', 'return', 'call', 'call_indirect', 'return_call', 'return_call_indirect', 'call_ref', 'return_call_ref', , , , ,
|
|
5
|
+
'drop', 'select', '', , , ,
|
|
6
|
+
'local.get', 'local.set', 'local.tee', 'global.get', 'global.set', 'table.get', 'table.set', ,
|
|
7
|
+
'i32.load', 'i64.load', 'f32.load', 'f64.load',
|
|
8
|
+
'i32.load8_s', 'i32.load8_u', 'i32.load16_s', 'i32.load16_u',
|
|
9
|
+
'i64.load8_s', 'i64.load8_u', 'i64.load16_s', 'i64.load16_u', 'i64.load32_s', 'i64.load32_u',
|
|
10
|
+
'i32.store', 'i64.store', 'f32.store', 'f64.store',
|
|
11
|
+
'i32.store8', 'i32.store16', 'i64.store8', 'i64.store16', 'i64.store32',
|
|
12
12
|
'memory.size', 'memory.grow',
|
|
13
|
-
'i32.const
|
|
13
|
+
'i32.const', 'i64.const', 'f32.const', 'f64.const',
|
|
14
14
|
'i32.eqz', 'i32.eq', 'i32.ne', 'i32.lt_s', 'i32.lt_u', 'i32.gt_s', 'i32.gt_u', 'i32.le_s', 'i32.le_u', 'i32.ge_s', 'i32.ge_u',
|
|
15
15
|
'i64.eqz', 'i64.eq', 'i64.ne', 'i64.lt_s', 'i64.lt_u', 'i64.gt_s', 'i64.gt_u', 'i64.le_s', 'i64.le_u', 'i64.ge_s', 'i64.ge_u',
|
|
16
16
|
'f32.eq', 'f32.ne', 'f32.lt', 'f32.gt', 'f32.le', 'f32.ge',
|
|
@@ -26,36 +26,48 @@ export const INSTR = [
|
|
|
26
26
|
'f64.convert_i32_s', 'f64.convert_i32_u', 'f64.convert_i64_s', 'f64.convert_i64_u', 'f64.promote_f32',
|
|
27
27
|
'i32.reinterpret_f32', 'i64.reinterpret_f64', 'f32.reinterpret_i32', 'f64.reinterpret_i64',
|
|
28
28
|
'i32.extend8_s', 'i32.extend16_s', 'i64.extend8_s', 'i64.extend16_s', 'i64.extend32_s', , , , , , , , , , , ,
|
|
29
|
-
'ref.null
|
|
29
|
+
'ref.null', 'ref.is_null', 'ref.func', 'ref.eq', 'ref.as_non_null', 'br_on_null', 'br_on_non_null', , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
'
|
|
33
|
-
'memory.init:i', 'data.drop:i', 'memory.copy', 'memory.fill', 'table.init:i:i', 'elem.drop:i', 'table.copy:i:i', 'table.grow:i', 'table.size:i', 'table.fill:i', ,
|
|
31
|
+
// 0xFB 0xNN (0xFB shift)
|
|
32
|
+
'struct.new', 'struct.new_default', 'struct.get', 'struct.get_s', 'struct.get_u', 'struct.set', 'array.new', 'array.new_default', 'array.new_fixed', 'array.new_data', 'array.new_elem', 'array.get', 'array.get_s', 'array.get_u', 'array.set', 'array.len', 'array.fill', 'array.copy', 'array.init_data', 'array.init_elem', 'ref.test', '', 'ref.cast', '', 'br_on_cast', 'br_on_cast_fail', 'any.convert_extern', 'extern.convert_any', 'ref.i31', 'i31.get_s', 'i31.get_u', ,
|
|
34
33
|
|
|
35
|
-
//
|
|
36
|
-
'
|
|
34
|
+
// 0xFC 0xNN (0x11b shift)
|
|
35
|
+
'i32.trunc_sat_f32_s', 'i32.trunc_sat_f32_u', 'i32.trunc_sat_f64_s', 'i32.trunc_sat_f64_u', 'i64.trunc_sat_f32_s', 'i64.trunc_sat_f32_u', 'i64.trunc_sat_f64_s', 'i64.trunc_sat_f64_u',
|
|
36
|
+
'memory.init', 'data.drop', 'memory.copy', 'memory.fill', 'table.init', 'elem.drop', 'table.copy', 'table.grow', 'table.size', 'table.fill', ,
|
|
37
|
+
'i64.add128', 'i64.sub128', 'i64.mul_wide_s', 'i64.mul_wide_u', ,
|
|
38
|
+
|
|
39
|
+
// 0xFD 0xNN (0x133 shift)
|
|
40
|
+
'v128.load', 'v128.load8x8_s', 'v128.load8x8_u', 'v128.load16x4_s', 'v128.load16x4_u', 'v128.load32x2_s', 'v128.load32x2_u', 'v128.load8_splat', 'v128.load16_splat', 'v128.load32_splat', 'v128.load64_splat', 'v128.store', 'v128.const', 'i8x16.shuffle',
|
|
37
41
|
'i8x16.swizzle', 'i8x16.splat', 'i16x8.splat', 'i32x4.splat', 'i64x2.splat', 'f32x4.splat', 'f64x2.splat',
|
|
38
|
-
'i8x16.extract_lane_s
|
|
42
|
+
'i8x16.extract_lane_s', 'i8x16.extract_lane_u', 'i8x16.replace_lane', 'i16x8.extract_lane_s', 'i16x8.extract_lane_u', 'i16x8.replace_lane', 'i32x4.extract_lane', 'i32x4.replace_lane', 'i64x2.extract_lane', 'i64x2.replace_lane', 'f32x4.extract_lane', 'f32x4.replace_lane', 'f64x2.extract_lane', 'f64x2.replace_lane',
|
|
39
43
|
'i8x16.eq', 'i8x16.ne', 'i8x16.lt_s', 'i8x16.lt_u', 'i8x16.gt_s', 'i8x16.gt_u', 'i8x16.le_s', 'i8x16.le_u', 'i8x16.ge_s', 'i8x16.ge_u', 'i16x8.eq', 'i16x8.ne', 'i16x8.lt_s', 'i16x8.lt_u', 'i16x8.gt_s', 'i16x8.gt_u', 'i16x8.le_s', 'i16x8.le_u', 'i16x8.ge_s', 'i16x8.ge_u', 'i32x4.eq', 'i32x4.ne', 'i32x4.lt_s', 'i32x4.lt_u', 'i32x4.gt_s', 'i32x4.gt_u', 'i32x4.le_s', 'i32x4.le_u', 'i32x4.ge_s', 'i32x4.ge_u', 'f32x4.eq', 'f32x4.ne', 'f32x4.lt', 'f32x4.gt', 'f32x4.le', 'f32x4.ge', 'f64x2.eq', 'f64x2.ne', 'f64x2.lt', 'f64x2.gt', 'f64x2.le', 'f64x2.ge', 'v128.not', 'v128.and', 'v128.andnot', 'v128.or', 'v128.xor', 'v128.bitselect', 'v128.any_true',
|
|
40
|
-
'v128.load8_lane
|
|
44
|
+
'v128.load8_lane', 'v128.load16_lane', 'v128.load32_lane', 'v128.load64_lane', 'v128.store8_lane', 'v128.store16_lane', 'v128.store32_lane', 'v128.store64_lane', 'v128.load32_zero', 'v128.load64_zero', 'f32x4.demote_f64x2_zero', 'f64x2.promote_low_f32x4',
|
|
41
45
|
'i8x16.abs', 'i8x16.neg', 'i8x16.popcnt', 'i8x16.all_true', 'i8x16.bitmask', 'i8x16.narrow_i16x8_s', 'i8x16.narrow_i16x8_u', 'f32x4.ceil', 'f32x4.floor', 'f32x4.trunc', 'f32x4.nearest', 'i8x16.shl', 'i8x16.shr_s', 'i8x16.shr_u', 'i8x16.add', 'i8x16.add_sat_s', 'i8x16.add_sat_u', 'i8x16.sub', 'i8x16.sub_sat_s', 'i8x16.sub_sat_u', 'f64x2.ceil', 'f64x2.floor', 'i8x16.min_s', 'i8x16.min_u', 'i8x16.max_s', 'i8x16.max_u', 'f64x2.trunc', 'i8x16.avgr_u',
|
|
42
46
|
'i16x8.extadd_pairwise_i8x16_s', 'i16x8.extadd_pairwise_i8x16_u', 'i32x4.extadd_pairwise_i16x8_s', 'i32x4.extadd_pairwise_i16x8_u', 'i16x8.abs', 'i16x8.neg', 'i16x8.q15mulr_sat_s', 'i16x8.all_true', 'i16x8.bitmask', 'i16x8.narrow_i32x4_s', 'i16x8.narrow_i32x4_u', 'i16x8.extend_low_i8x16_s', 'i16x8.extend_high_i8x16_s', 'i16x8.extend_low_i8x16_u', 'i16x8.extend_high_i8x16_u',
|
|
43
47
|
'i16x8.shl', 'i16x8.shr_s', 'i16x8.shr_u', 'i16x8.add', 'i16x8.add_sat_s', 'i16x8.add_sat_u', 'i16x8.sub', 'i16x8.sub_sat_s', 'i16x8.sub_sat_u', 'f64x2.nearest', 'i16x8.mul', 'i16x8.min_s', 'i16x8.min_u', 'i16x8.max_s', 'i16x8.max_u', , 'i16x8.avgr_u',
|
|
44
|
-
'i16x8.extmul_low_i8x16_s', 'i16x8.extmul_high_i8x16_s', 'i16x8.extmul_low_i8x16_u', 'i16x8.extmul_high_i8x16_u', 'i32x4.abs', 'i32x4.neg', , 'i32x4.all_true', 'i32x4.bitmask', , , 'i32x4.extend_low_i16x8_s', 'i32x4.extend_high_i16x8_s', 'i32x4.extend_low_i16x8_u', 'i32x4.extend_high_i16x8_u', 'i32x4.shl', 'i32x4.shr_s', 'i32x4.shr_u', 'i32x4.add', , , 'i32x4.sub', , , , 'i32x4.mul', 'i32x4.min_s', 'i32x4.min_u', 'i32x4.max_s', 'i32x4.max_u', 'i32x4.dot_i16x8_s', , 'i32x4.extmul_low_i16x8_s', 'i32x4.extmul_high_i16x8_s', 'i32x4.extmul_low_i16x8_u', 'i32x4.extmul_high_i16x8_u', 'i64x2.abs', 'i64x2.neg', , 'i64x2.all_true', 'i64x2.bitmask', , , 'i64x2.extend_low_i32x4_s', 'i64x2.extend_high_i32x4_s', 'i64x2.extend_low_i32x4_u', 'i64x2.extend_high_i32x4_u', 'i64x2.shl', 'i64x2.shr_s', 'i64x2.shr_u', 'i64x2.add', , , 'i64x2.sub', , , , 'i64x2.mul', 'i64x2.eq', 'i64x2.ne', 'i64x2.lt_s', 'i64x2.gt_s', 'i64x2.le_s', 'i64x2.ge_s', 'i64x2.extmul_low_i32x4_s', 'i64x2.extmul_high_i32x4_s', 'i64x2.extmul_low_i32x4_u', 'i64x2.extmul_high_i32x4_u', 'f32x4.abs', 'f32x4.neg', , 'f32x4.sqrt', 'f32x4.add', 'f32x4.sub', 'f32x4.mul', 'f32x4.div', 'f32x4.min', 'f32x4.max', 'f32x4.pmin', 'f32x4.pmax', 'f64x2.abs', 'f64x2.neg', , 'f64x2.sqrt', 'f64x2.add', 'f64x2.sub', 'f64x2.mul', 'f64x2.div', 'f64x2.min', 'f64x2.max', 'f64x2.pmin', 'f64x2.pmax', 'i32x4.trunc_sat_f32x4_s', 'i32x4.trunc_sat_f32x4_u', 'f32x4.convert_i32x4_s', 'f32x4.convert_i32x4_u', 'i32x4.trunc_sat_f64x2_s_zero', 'i32x4.trunc_sat_f64x2_u_zero', 'f64x2.convert_low_i32x4_s', 'f64x2.convert_low_i32x4_u'
|
|
48
|
+
'i16x8.extmul_low_i8x16_s', 'i16x8.extmul_high_i8x16_s', 'i16x8.extmul_low_i8x16_u', 'i16x8.extmul_high_i8x16_u', 'i32x4.abs', 'i32x4.neg', , 'i32x4.all_true', 'i32x4.bitmask', , , 'i32x4.extend_low_i16x8_s', 'i32x4.extend_high_i16x8_s', 'i32x4.extend_low_i16x8_u', 'i32x4.extend_high_i16x8_u', 'i32x4.shl', 'i32x4.shr_s', 'i32x4.shr_u', 'i32x4.add', , , 'i32x4.sub', , , , 'i32x4.mul', 'i32x4.min_s', 'i32x4.min_u', 'i32x4.max_s', 'i32x4.max_u', 'i32x4.dot_i16x8_s', , 'i32x4.extmul_low_i16x8_s', 'i32x4.extmul_high_i16x8_s', 'i32x4.extmul_low_i16x8_u', 'i32x4.extmul_high_i16x8_u', 'i64x2.abs', 'i64x2.neg', , 'i64x2.all_true', 'i64x2.bitmask', , , 'i64x2.extend_low_i32x4_s', 'i64x2.extend_high_i32x4_s', 'i64x2.extend_low_i32x4_u', 'i64x2.extend_high_i32x4_u', 'i64x2.shl', 'i64x2.shr_s', 'i64x2.shr_u', 'i64x2.add', , , 'i64x2.sub', , , , 'i64x2.mul', 'i64x2.eq', 'i64x2.ne', 'i64x2.lt_s', 'i64x2.gt_s', 'i64x2.le_s', 'i64x2.ge_s', 'i64x2.extmul_low_i32x4_s', 'i64x2.extmul_high_i32x4_s', 'i64x2.extmul_low_i32x4_u', 'i64x2.extmul_high_i32x4_u', 'f32x4.abs', 'f32x4.neg', , 'f32x4.sqrt', 'f32x4.add', 'f32x4.sub', 'f32x4.mul', 'f32x4.div', 'f32x4.min', 'f32x4.max', 'f32x4.pmin', 'f32x4.pmax', 'f64x2.abs', 'f64x2.neg', , 'f64x2.sqrt', 'f64x2.add', 'f64x2.sub', 'f64x2.mul', 'f64x2.div', 'f64x2.min', 'f64x2.max', 'f64x2.pmin', 'f64x2.pmax', 'i32x4.trunc_sat_f32x4_s', 'i32x4.trunc_sat_f32x4_u', 'f32x4.convert_i32x4_s', 'f32x4.convert_i32x4_u', 'i32x4.trunc_sat_f64x2_s_zero', 'i32x4.trunc_sat_f64x2_u_zero', 'f64x2.convert_low_i32x4_s', 'f64x2.convert_low_i32x4_u',
|
|
49
|
+
// relaxed SIMD instructions
|
|
50
|
+
'i8x16.relaxed_swizzle', 'i32x4.relaxed_trunc_f32x4_s', 'i32x4.relaxed_trunc_f32x4_u', 'i32x4.relaxed_trunc_f64x2_s_zero', 'i32x4.relaxed_trunc_f64x2_u_zero', 'f32x4.relaxed_madd', 'f32x4.relaxed_nmadd', 'f64x2.relaxed_madd', 'f64x2.relaxed_nmadd', 'i8x16.relaxed_laneselect', 'i16x8.relaxed_laneselect', 'i32x4.relaxed_laneselect', 'i64x2.relaxed_laneselect', 'f32x4.relaxed_min', 'f32x4.relaxed_max', 'f64x2.relaxed_min', 'f64x2.relaxed_max', 'i16x8.relaxed_q15mulr_s', 'i16x8.relaxed_dot_i8x16_i7x16_s', 'i32x4.relaxed_dot_i8x16_i7x16_add_s'
|
|
45
51
|
],
|
|
46
|
-
SECTION = { custom: 0, type: 1, import: 2, func: 3, table: 4, memory: 5, global: 6, export: 7, start: 8, elem: 9, code: 10, data: 11
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
SECTION = { custom: 0, type: 1, import: 2, func: 3, table: 4, memory: 5, global: 6, export: 7, start: 8, elem: 9, datacount: 12, code: 10, data: 11 },
|
|
53
|
+
RECTYPE = { sub: 0x50, subfinal: 0x4F, rec: 0x4E },
|
|
54
|
+
DEFTYPE = { func: 0x60, struct: 0x5F, array: 0x5E, ...RECTYPE },
|
|
55
|
+
HEAPTYPE = { nofunc: 0x73, noextern: 0x72, none: 0x71, func: 0x70, extern: 0x6F, any: 0x6E, eq: 0x6D, i31: 0x6C, struct: 0x6B, array: 0x6A },
|
|
56
|
+
REFTYPE = {
|
|
57
|
+
// absheaptype abbrs
|
|
58
|
+
nullfuncref: HEAPTYPE.nofunc,
|
|
59
|
+
nullexternref: HEAPTYPE.noextern,
|
|
60
|
+
nullref: HEAPTYPE.none,
|
|
61
|
+
funcref: HEAPTYPE.func,
|
|
62
|
+
externref: HEAPTYPE.extern,
|
|
63
|
+
anyref: HEAPTYPE.any,
|
|
64
|
+
eqref: HEAPTYPE.eq,
|
|
65
|
+
i31ref: HEAPTYPE.i31,
|
|
66
|
+
structref: HEAPTYPE.struct,
|
|
67
|
+
arrayref: HEAPTYPE.array,
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
// ref, refnull
|
|
70
|
+
ref: 0x64 /* -0x1c */, refnull: 0x63 /* -0x1d */
|
|
71
|
+
},
|
|
72
|
+
TYPE = { i8: 0x78, i16: 0x77, i32: 0x7f, i64: 0x7e, f32: 0x7d, f64: 0x7c, void: 0x40, v128: 0x7B, ...HEAPTYPE, ...REFTYPE },
|
|
73
|
+
KIND = { func: 0, table: 1, memory: 2, global: 3 }
|
package/src/encode.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { err, intRE, sepRE } from './util.js'
|
|
2
|
+
|
|
1
3
|
// encoding ref: https://github.com/j-s-n/WebBS/blob/master/compiler/byteCode.js
|
|
2
4
|
|
|
3
5
|
// uleb
|
|
@@ -17,6 +19,21 @@ export const uleb = (n, buffer = []) => {
|
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
// fixed-width uleb
|
|
23
|
+
// export function full_uleb(value) {
|
|
24
|
+
// const result = [];
|
|
25
|
+
// for (let i = 0; i < 5; i++) {
|
|
26
|
+
// let byte = value & 0x7f;
|
|
27
|
+
// value >>>= 7;
|
|
28
|
+
// if (i < 4) {
|
|
29
|
+
// byte |= 0x80; // Set continuation bit for first 4 bytes
|
|
30
|
+
// }
|
|
31
|
+
// result.push(byte);
|
|
32
|
+
// }
|
|
33
|
+
// return result;
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
|
|
20
37
|
// leb
|
|
21
38
|
export function i32(n, buffer = []) {
|
|
22
39
|
if (typeof n === 'string') n = i32.parse(n)
|
|
@@ -32,10 +49,14 @@ export function i32(n, buffer = []) {
|
|
|
32
49
|
}
|
|
33
50
|
return buffer
|
|
34
51
|
}
|
|
52
|
+
|
|
53
|
+
// for tests complacency we check format
|
|
54
|
+
const cleanInt = (v) => (!sepRE.test(v) && intRE.test(v=v.replaceAll('_',''))) ? v : err(`Bad int ${v}`)
|
|
55
|
+
|
|
35
56
|
// alias
|
|
36
57
|
export const i8 = i32, i16 = i32
|
|
37
58
|
|
|
38
|
-
i32.parse = n => parseInt(n
|
|
59
|
+
i32.parse = n => parseInt(cleanInt(n))
|
|
39
60
|
|
|
40
61
|
// bigleb
|
|
41
62
|
export function i64(n, buffer = []) {
|
|
@@ -53,13 +74,13 @@ export function i64(n, buffer = []) {
|
|
|
53
74
|
return buffer
|
|
54
75
|
}
|
|
55
76
|
i64.parse = n => {
|
|
56
|
-
n = n
|
|
57
|
-
n = n[0] === '-' ? -BigInt(n.slice(1)) : BigInt(n)
|
|
77
|
+
n = cleanInt(n)
|
|
78
|
+
n = n[0] === '-' ? -BigInt(n.slice(1)) : BigInt(n) // can be -0x123
|
|
58
79
|
byteView.setBigInt64(0, n)
|
|
59
|
-
return
|
|
80
|
+
return byteView.getBigInt64(0)
|
|
60
81
|
}
|
|
61
82
|
|
|
62
|
-
const byteView = new DataView(new
|
|
83
|
+
const byteView = new DataView(new Float64Array(1).buffer)
|
|
63
84
|
|
|
64
85
|
const F32_SIGN = 0x80000000, F32_NAN = 0x7f800000
|
|
65
86
|
export function f32(input, value, idx) {
|
|
@@ -95,7 +116,7 @@ export function f64(input, value, idx) {
|
|
|
95
116
|
byteView.setFloat64(0, value);
|
|
96
117
|
}
|
|
97
118
|
|
|
98
|
-
return [
|
|
119
|
+
return ([
|
|
99
120
|
byteView.getUint8(7),
|
|
100
121
|
byteView.getUint8(6),
|
|
101
122
|
byteView.getUint8(5),
|
|
@@ -104,21 +125,39 @@ export function f64(input, value, idx) {
|
|
|
104
125
|
byteView.getUint8(2),
|
|
105
126
|
byteView.getUint8(1),
|
|
106
127
|
byteView.getUint8(0)
|
|
107
|
-
];
|
|
128
|
+
]);
|
|
108
129
|
}
|
|
109
130
|
|
|
110
|
-
|
|
111
|
-
if (input.includes('nan')) return input[0] === '-' ? -NaN : NaN;
|
|
112
|
-
if (input.includes('inf')) return input[0] === '-' ? -Infinity : Infinity;
|
|
113
|
-
|
|
131
|
+
f64.parse = (input, max=Number.MAX_VALUE) => {
|
|
114
132
|
input = input.replaceAll('_', '')
|
|
133
|
+
let sign = 1;
|
|
134
|
+
if (input[0] === '-') sign = -1, input = input.slice(1);
|
|
135
|
+
else if (input[0] === '+') input = input.slice(1);
|
|
115
136
|
|
|
137
|
+
// ref: https://github.com/WebAssembly/wabt/blob/ea193b40d6d4a1a697d68ae855b2b3b3e263b377/src/literal.cc#L253
|
|
116
138
|
// 0x1.5p3
|
|
117
|
-
if (input
|
|
118
|
-
let [sig, exp] = input.split(/p/i)
|
|
119
|
-
|
|
120
|
-
|
|
139
|
+
if (input[1] === 'x') {
|
|
140
|
+
let [sig, exp='0'] = input.split(/p/i); // significand and exponent
|
|
141
|
+
let [int, fract=''] = sig.split('.'); // integer and fractional parts
|
|
142
|
+
let flen = fract.length ?? 0;
|
|
143
|
+
|
|
144
|
+
// FIXME: this is not accurate, it must be byte-perfect
|
|
145
|
+
sig = parseInt(int + fract); // 0x is included in int
|
|
146
|
+
exp = parseInt(exp, 10);
|
|
147
|
+
|
|
148
|
+
// 0x10a.fbc = 0x10afbc * 16⁻³ = 266.9833984375
|
|
149
|
+
let value = sign * sig * (2 ** (exp - 4 * flen));
|
|
150
|
+
|
|
151
|
+
// make sure it is not Infinity
|
|
152
|
+
value = Math.max(-max, Math.min(max, value))
|
|
153
|
+
|
|
154
|
+
return value
|
|
121
155
|
}
|
|
122
156
|
|
|
123
|
-
|
|
157
|
+
if (input.includes('nan')) return sign < 0 ? -NaN : NaN;
|
|
158
|
+
if (input.includes('inf')) return sign * Infinity;
|
|
159
|
+
|
|
160
|
+
return sign * parseFloat(input)
|
|
124
161
|
}
|
|
162
|
+
|
|
163
|
+
f32.parse = input => f64.parse(input, 3.4028234663852886e+38)
|
package/src/parse.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const OPAREN = 40, CPAREN = 41, OBRACK = 91, CBRACK = 93, SPACE = 32, DQUOTE = 34, PERIOD = 46,
|
|
2
|
-
_0 = 48, _9 = 57, SEMIC = 59, NEWLINE = 32, PLUS = 43, MINUS = 45, COLON = 58
|
|
2
|
+
_0 = 48, _9 = 57, SEMIC = 59, NEWLINE = 32, PLUS = 43, MINUS = 45, COLON = 58, BSLASH = 39
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parses a wasm text string and constructs a nested array structure (AST).
|
|
6
6
|
*
|
|
7
7
|
* @param {string} str - The input string with WAT code to parse.
|
|
8
|
+
* @param {object} options - Parse options, like comments, etc.
|
|
8
9
|
* @returns {Array} An array representing the nested syntax tree (AST).
|
|
9
10
|
*/
|
|
10
|
-
export default (str) => {
|
|
11
|
-
let i = 0, level = [], buf = ''
|
|
11
|
+
export default (str, o={ comments: false }) => {
|
|
12
|
+
let i = 0, level = [], buf = '', comment = ''
|
|
12
13
|
|
|
13
14
|
const commit = () => buf && (
|
|
14
15
|
level.push(buf),
|
|
@@ -16,15 +17,22 @@ export default (str) => {
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
const parseLevel = () => {
|
|
19
|
-
for (let c, root; i < str.length;) {
|
|
20
|
+
for (let c, root, q; i < str.length;) {
|
|
20
21
|
|
|
21
22
|
c = str.charCodeAt(i)
|
|
22
|
-
if (
|
|
23
|
+
if (q) {
|
|
24
|
+
buf += str[i++]
|
|
25
|
+
if (str[i-1] === '\\') buf += str[i++]
|
|
26
|
+
else if (c === DQUOTE) commit(), q = 0
|
|
27
|
+
}
|
|
28
|
+
else if (c === DQUOTE) {
|
|
29
|
+
commit(), q = c, buf += str[i++]
|
|
30
|
+
}
|
|
23
31
|
else if (c === OPAREN) {
|
|
24
|
-
if (str.charCodeAt(i + 1) === SEMIC) i = str.indexOf(';)', i) + 2 // (; ... ;)
|
|
32
|
+
if (str.charCodeAt(i + 1) === SEMIC) comment = str.slice(i, i = str.indexOf(';)', i) + 2), o.comments && level.push(comment) // (; ... ;)
|
|
25
33
|
else commit(), i++, (root = level).push(level = []), parseLevel(), level = root
|
|
26
34
|
}
|
|
27
|
-
else if (c === SEMIC) i = str.indexOf('\n', i) + 1 || str.length // ; ...
|
|
35
|
+
else if (c === SEMIC) comment = str.slice(i, i = str.indexOf('\n', i) + 1 || str.length), o.comments && level.push(comment) // ; ...
|
|
28
36
|
else if (c <= SPACE) commit(), i++
|
|
29
37
|
else if (c === CPAREN) return commit(), i++
|
|
30
38
|
else buf += str[i++]
|
package/src/print.js
CHANGED
|
@@ -1,69 +1,57 @@
|
|
|
1
1
|
import parse from './parse.js';
|
|
2
2
|
|
|
3
|
-
let indent = '', newline = '\n'
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
* Formats a tree or a WAT string.
|
|
5
|
+
* Formats a tree or a WAT (WebAssembly Text) string into a readable format.
|
|
7
6
|
*
|
|
8
|
-
* @param {string | Array} tree - The code to print. If a string is provided, it will be parsed first.
|
|
9
|
-
* @param {Object} [options] -
|
|
10
|
-
* @param {string} [options.indent=' '] - The string used for one level of indentation.
|
|
11
|
-
* @param {string} [options.newline='\n'] - The string used for line breaks.
|
|
7
|
+
* @param {string | Array} tree - The code to print. If a string is provided, it will be parsed into a tree structure first.
|
|
8
|
+
* @param {Object} [options={}] - Optional settings for printing.
|
|
9
|
+
* @param {string} [options.indent=' '] - The string used for one level of indentation. Defaults to two spaces.
|
|
10
|
+
* @param {string} [options.newline='\n'] - The string used for line breaks. Defaults to a newline character.
|
|
12
11
|
* @returns {string} The formatted WAT string.
|
|
13
12
|
*/
|
|
14
13
|
export default function print(tree, options = {}) {
|
|
15
14
|
if (typeof tree === 'string') tree = parse(tree);
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
indent ||= '', newline ||= '';
|
|
16
|
+
let { indent=' ', newline='\n' } = options;
|
|
17
|
+
indent ||= '', newline ||= ''; // false -> str
|
|
19
18
|
|
|
20
19
|
return typeof tree[0] === 'string' ? printNode(tree) : tree.map(node => printNode(node)).join(newline)
|
|
21
|
-
}
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'local',
|
|
26
|
-
'drop',
|
|
27
|
-
'f32.const',
|
|
28
|
-
'f64.const',
|
|
29
|
-
'i32.const',
|
|
30
|
-
'i64.const',
|
|
31
|
-
'local.get',
|
|
32
|
-
'global.get',
|
|
33
|
-
'memory.size',
|
|
34
|
-
'result',
|
|
35
|
-
'export',
|
|
36
|
-
'unreachable',
|
|
37
|
-
'nop'
|
|
38
|
-
]
|
|
21
|
+
function printNode(node, level = 0) {
|
|
22
|
+
if (!Array.isArray(node)) return node
|
|
39
23
|
|
|
40
|
-
|
|
41
|
-
if (!Array.isArray(node)) return node + ''
|
|
24
|
+
let content = node[0]
|
|
42
25
|
|
|
43
|
-
|
|
26
|
+
// flat node (no deep subnodes), eg. (i32.const 1), (module (export "") 1)
|
|
27
|
+
let flat = !!newline && node.length < 4
|
|
28
|
+
let curIndent = indent.repeat(level + 1)
|
|
44
29
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
for (let i = 1; i < node.length; i++) {
|
|
31
|
+
// (<keyword> ...)
|
|
32
|
+
if (Array.isArray(node[i])) {
|
|
33
|
+
// check if it's still flat
|
|
34
|
+
if (flat) flat = node[i].every(subnode => !Array.isArray(subnode))
|
|
50
35
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
content += newline
|
|
58
|
-
|
|
36
|
+
// new line
|
|
37
|
+
content += newline + curIndent + printNode(node[i], level + 1)
|
|
38
|
+
}
|
|
39
|
+
// data chunks "\00..."
|
|
40
|
+
else if (node[0] === 'data') {
|
|
41
|
+
flat = false;
|
|
42
|
+
if (newline || content[content.length-1] !== ')') content += newline || ' '
|
|
43
|
+
content += curIndent + node[i]
|
|
44
|
+
}
|
|
45
|
+
// inline nodes
|
|
46
|
+
else {
|
|
47
|
+
if (newline || content[content.length-1] !== ')') content += ' '
|
|
48
|
+
content += node[i]
|
|
59
49
|
}
|
|
60
|
-
|
|
61
|
-
content += printNode(node[i], level + 1)
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
content += ` `
|
|
65
|
-
content += node[i]
|
|
66
50
|
}
|
|
51
|
+
|
|
52
|
+
// shrink unnecessary spaces
|
|
53
|
+
if (flat) return `(${content.replaceAll(newline + curIndent + '(', ' (')})`
|
|
54
|
+
|
|
55
|
+
return `(${content + newline + indent.repeat(level)})`
|
|
67
56
|
}
|
|
68
|
-
return `(${content})`
|
|
69
57
|
}
|
package/src/util.js
ADDED