watr 5.0.0 → 5.1.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/dist/watr.js +822 -904
- package/dist/watr.min.js +5 -6
- package/dist/watr.wasm +0 -0
- package/package.json +3 -3
- package/readme.md +20 -5
- package/src/compile.js +227 -109
- package/src/const.js +125 -131
- package/src/encode.js +28 -3
- package/src/optimize.js +2909 -421
- package/src/util.js +33 -9
- package/types/src/compile.d.ts +1 -0
- package/types/src/compile.d.ts.map +1 -1
- package/types/src/const.d.ts +2 -1
- package/types/src/const.d.ts.map +1 -1
- package/types/src/encode.d.ts +5 -26
- package/types/src/encode.d.ts.map +1 -1
- package/types/src/optimize.d.ts +41 -33
- package/types/src/optimize.d.ts.map +1 -1
- package/types/src/util.d.ts +5 -10
- package/types/src/util.d.ts.map +1 -1
package/src/util.js
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
|
+
// Ambient source/position for err()'s "at line:col" suffix — set by assemble()
|
|
2
|
+
// as it walks a module (err.loc/err.src used to be expando properties on the
|
|
3
|
+
// `err` function itself; a self-hosted compile-clear-compile loop bump-allocates
|
|
4
|
+
// a HASH props table the first time a property lands on a function value, and
|
|
5
|
+
// that table dangles across an arena `_clear` between compiles — corrupting the
|
|
6
|
+
// SECOND self-host compile. Plain module-level `let`s are a global-set, not a
|
|
7
|
+
// dynamic-key write, so they carry no such table and are `_clear`-safe.
|
|
8
|
+
let errLoc, errSrc
|
|
9
|
+
|
|
1
10
|
/**
|
|
2
11
|
* Throws an error with optional source position.
|
|
3
|
-
* Uses
|
|
4
|
-
* If pos provided or
|
|
12
|
+
* Uses the ambient errSrc for source and errLoc for default position.
|
|
13
|
+
* If pos provided or errLoc set, appends "at line:col".
|
|
5
14
|
*
|
|
6
15
|
* @param {string} text - Error message
|
|
7
|
-
* @param {number} [pos] - Byte offset in source (defaults to
|
|
16
|
+
* @param {number} [pos] - Byte offset in source (defaults to errLoc)
|
|
8
17
|
* @throws {Error}
|
|
9
18
|
*/
|
|
10
|
-
export const err = (text, pos=
|
|
11
|
-
if (pos != null &&
|
|
19
|
+
export const err = (text, pos=errLoc) => {
|
|
20
|
+
if (pos != null && errSrc) {
|
|
12
21
|
let line = 1, col = 1
|
|
13
|
-
for (let i = 0; i < pos && i <
|
|
14
|
-
if (
|
|
22
|
+
for (let i = 0; i < pos && i < errSrc.length; i++) {
|
|
23
|
+
if (errSrc.charCodeAt(i) === 10) line++, col = 1
|
|
15
24
|
else col++
|
|
16
25
|
}
|
|
17
26
|
text += ` at ${line}:${col}`
|
|
18
27
|
}
|
|
19
28
|
throw Error(text)
|
|
20
29
|
}
|
|
30
|
+
// Accessors for the ambient position/source (compile.js is the only writer).
|
|
31
|
+
export const setErrLoc = (loc) => { errLoc = loc }
|
|
32
|
+
export const setErrSrc = (src) => { errSrc = src }
|
|
33
|
+
export const getErrLoc = () => errLoc
|
|
34
|
+
export const getErrSrc = () => errSrc
|
|
21
35
|
|
|
22
36
|
/** Regex to detect invalid underscore placement in numbers */
|
|
23
37
|
export const sepRE = /^_|_$|[^\da-f]_|_[^\da-f]/i
|
|
@@ -97,7 +111,13 @@ export const clone = (node) => Array.isArray(node) ? node.map(clone) : node
|
|
|
97
111
|
*/
|
|
98
112
|
export const walk = (node, fn, parent, idx) => {
|
|
99
113
|
fn(node, parent, idx)
|
|
100
|
-
if (Array.isArray(node)) for (let i = 0; i < node.length; i++)
|
|
114
|
+
if (Array.isArray(node)) for (let i = 0; i < node.length; i++) {
|
|
115
|
+
const c = node[i]
|
|
116
|
+
// leaves get their visit inline — half of all nodes are strings/numbers, and a
|
|
117
|
+
// full recursive frame per leaf dominates traversal cost on big modules
|
|
118
|
+
if (Array.isArray(c)) walk(c, fn, node, i)
|
|
119
|
+
else fn(c, node, i)
|
|
120
|
+
}
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
/**
|
|
@@ -115,7 +135,11 @@ export const walk = (node, fn, parent, idx) => {
|
|
|
115
135
|
* @returns {any} The (possibly replaced) node
|
|
116
136
|
*/
|
|
117
137
|
export const walkPost = (node, fn, parent, idx) => {
|
|
118
|
-
if (Array.isArray(node)) for (let i = 0; i < node.length; i++)
|
|
138
|
+
if (Array.isArray(node)) for (let i = 0; i < node.length; i++) {
|
|
139
|
+
const c = node[i]
|
|
140
|
+
if (Array.isArray(c)) walkPost(c, fn, node, i)
|
|
141
|
+
else { const r = fn(c, node, i); if (r !== undefined) node[i] = r }
|
|
142
|
+
}
|
|
119
143
|
const result = fn(node, parent, idx)
|
|
120
144
|
if (result !== undefined && parent) parent[idx] = result
|
|
121
145
|
return result !== undefined ? result : node
|
package/types/src/compile.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/compile.js"],"names":[],"mappings":"AAsVA;;;;GAIG;AACH,iDAAiE;AAEjE;;;;GAIG;AACH,sCAA4D;AAg8BrD,0CAcN"}
|
package/types/src/const.d.ts
CHANGED
package/types/src/const.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../src/const.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../../src/const.js"],"names":[],"mappings":"AAgKa,wBAAW;AAAE,qBAAQ;AAoB3B,+BAHI,MAAM,GACJ,MAAM,GAAC,IAAI,CAavB"}
|
package/types/src/encode.d.ts
CHANGED
|
@@ -6,14 +6,7 @@
|
|
|
6
6
|
* @returns {number[]} 5-byte array
|
|
7
7
|
*/
|
|
8
8
|
export function uleb5(value: number): number[];
|
|
9
|
-
|
|
10
|
-
* Encode signed LEB128 for i32 values.
|
|
11
|
-
*
|
|
12
|
-
* @param {number|string} n - Signed 32-bit value
|
|
13
|
-
* @param {number[]} [buffer=[]] - Output buffer
|
|
14
|
-
* @returns {number[]} Encoded bytes
|
|
15
|
-
*/
|
|
16
|
-
export function i32(n: number | string, buffer?: number[]): number[];
|
|
9
|
+
export function i32(n: any, buffer?: any[]): any[];
|
|
17
10
|
export namespace i32 {
|
|
18
11
|
function parse(n: any): any;
|
|
19
12
|
}
|
|
@@ -28,32 +21,18 @@ export function i64(n: bigint | string, buffer?: number[]): number[];
|
|
|
28
21
|
export namespace i64 {
|
|
29
22
|
function parse(n: any): any;
|
|
30
23
|
}
|
|
31
|
-
export function f32(input: any, value: any, idx: any): number[];
|
|
24
|
+
export function f32(input: any, out: any, value: any, idx: any): number[];
|
|
32
25
|
export namespace f32 {
|
|
33
26
|
function parse(input: any): number;
|
|
34
27
|
}
|
|
35
|
-
export function f64(input: any, value: any, idx: any):
|
|
28
|
+
export function f64(input: any, out: any, value: any, idx: any): any;
|
|
36
29
|
export namespace f64 {
|
|
37
30
|
function parse(input: any, max?: number): number;
|
|
38
31
|
}
|
|
39
32
|
export function uleb(n: number | bigint | string | null, buffer?: number[]): number[];
|
|
40
|
-
|
|
41
|
-
* Encode signed LEB128 for i32 values.
|
|
42
|
-
*
|
|
43
|
-
* @param {number|string} n - Signed 32-bit value
|
|
44
|
-
* @param {number[]} [buffer=[]] - Output buffer
|
|
45
|
-
* @returns {number[]} Encoded bytes
|
|
46
|
-
*/
|
|
47
|
-
export function i8(n: number | string, buffer?: number[]): number[];
|
|
33
|
+
export function i8(n: any, buffer?: any[]): any[];
|
|
48
34
|
export namespace i8 { }
|
|
49
|
-
|
|
50
|
-
* Encode signed LEB128 for i32 values.
|
|
51
|
-
*
|
|
52
|
-
* @param {number|string} n - Signed 32-bit value
|
|
53
|
-
* @param {number[]} [buffer=[]] - Output buffer
|
|
54
|
-
* @returns {number[]} Encoded bytes
|
|
55
|
-
*/
|
|
56
|
-
export function i16(n: number | string, buffer?: number[]): number[];
|
|
35
|
+
export function i16(n: any, buffer?: any[]): any[];
|
|
57
36
|
export namespace i16 { }
|
|
58
37
|
export function v128(input: any): any[];
|
|
59
38
|
//# sourceMappingURL=encode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../src/encode.js"],"names":[],"mappings":"AA6CA;;;;;;GAMG;AACH,6BAHW,MAAM,GACJ,MAAM,EAAE,CAapB;
|
|
1
|
+
{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../src/encode.js"],"names":[],"mappings":"AA6CA;;;;;;GAMG;AACH,6BAHW,MAAM,GACJ,MAAM,EAAE,CAapB;AAYD,mDAqBC;;IAQD,4BAIC;;AAED;;;;;;GAMG;AACH,uBAJW,MAAM,GAAC,MAAM,WACb,MAAM,EAAE,GACN,MAAM,EAAE,CAoBpB;;IAID,4BAmBC;;AAGD,0EAkBC;;IAiFD,mCAA6D;;AA7E7D,qEA6BC;;IAED,iDA4CC;;AAnPM,wBAJI,MAAM,GAAC,MAAM,GAAC,MAAM,GAAC,IAAI,WACzB,MAAM,EAAE,GACN,MAAM,EAAE,CA8BpB;AAgCD,kDAqBC;;AArBD,mDAqBC;;AAsKM,wCAKN"}
|
package/types/src/optimize.d.ts
CHANGED
|
@@ -18,12 +18,8 @@ export function binarySize(ast: any[]): number;
|
|
|
18
18
|
* @returns {Array}
|
|
19
19
|
*/
|
|
20
20
|
export function treeshake(ast: any[]): any[];
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
* @param {Array} ast
|
|
24
|
-
* @returns {Array}
|
|
25
|
-
*/
|
|
26
|
-
export function fold(ast: any[]): any[];
|
|
21
|
+
/** Constant folding as a standalone pass. */
|
|
22
|
+
export function fold(ast: any): any;
|
|
27
23
|
/**
|
|
28
24
|
* Remove dead code after control flow terminators.
|
|
29
25
|
* @param {Array} ast
|
|
@@ -37,25 +33,53 @@ export function deadcode(ast: any[]): any[];
|
|
|
37
33
|
* @returns {Array}
|
|
38
34
|
*/
|
|
39
35
|
export function localReuse(ast: any[]): any[];
|
|
36
|
+
/** Identity elimination as a standalone pass. */
|
|
37
|
+
export function identity(ast: any): any;
|
|
38
|
+
/** Strength reduction as a standalone pass. */
|
|
39
|
+
export function strength(ast: any): any;
|
|
40
|
+
/**
|
|
41
|
+
* Simplify branches with constant conditions.
|
|
42
|
+
* @param {Array} ast
|
|
43
|
+
* @returns {Array}
|
|
44
|
+
*/
|
|
45
|
+
export function branch(ast: any[]): any[];
|
|
46
|
+
export function propagate(ast: any): any;
|
|
40
47
|
/**
|
|
41
|
-
*
|
|
48
|
+
* Merge alias locals: `(local.set $A (local.tee $B V))` writes the same value into
|
|
49
|
+
* two slots. When that is the ONLY write either local ever gets, their write
|
|
50
|
+
* histories are identical — every read of $A (even one sequenced before the def,
|
|
51
|
+
* which sees the zero default on both) equals the same read of $B. So $A's reads
|
|
52
|
+
* rename to $B and the alias write drops. Params are excluded ($B would carry a
|
|
53
|
+
* call-argument value where $A held zero).
|
|
42
54
|
* @param {Array} ast
|
|
43
55
|
* @returns {Array}
|
|
44
56
|
*/
|
|
45
|
-
export function
|
|
57
|
+
export function mergeLocals(ast: any[]): any[];
|
|
46
58
|
/**
|
|
47
|
-
*
|
|
59
|
+
* Local common-subexpression elimination: identical pure subtrees repeated within a
|
|
60
|
+
* straight-line scope compute once into a fresh local (first site tees, later sites
|
|
61
|
+
* get). Grouping stops at every invalidation: a statement that writes a local the
|
|
62
|
+
* expression reads, writes memory (for memory-reading exprs), or calls out (memory/
|
|
63
|
+
* global-reading exprs). Candidates come only from the unconditional part of each
|
|
64
|
+
* statement — nested control bodies are separate scopes with their own table.
|
|
65
|
+
* Fires only when the byte win is provable: (n−1)·bytes(expr) > tee+gets+decl cost.
|
|
48
66
|
* @param {Array} ast
|
|
49
67
|
* @returns {Array}
|
|
50
68
|
*/
|
|
51
|
-
export function
|
|
69
|
+
export function cse(ast: any[]): any[];
|
|
52
70
|
/**
|
|
53
|
-
*
|
|
71
|
+
* Macro inlining: a function whose whole body is ONE small expression using each
|
|
72
|
+
* param exactly once, in declaration order, expands at every call site by
|
|
73
|
+
* substituting the arguments positionally — no wrapper, no locals, argument
|
|
74
|
+
* evaluation order preserved verbatim (so impure args stay sound). The husk loses
|
|
75
|
+
* its callers and treeshake collects it; the expansion feeds fold/offset/cse.
|
|
54
76
|
* @param {Array} ast
|
|
55
77
|
* @returns {Array}
|
|
56
78
|
*/
|
|
57
|
-
export function
|
|
58
|
-
|
|
79
|
+
export function inlineMacro(ast: any[], { pin }?: {
|
|
80
|
+
pin?: any;
|
|
81
|
+
}): any[];
|
|
82
|
+
export function tailmerge(ast: any): any;
|
|
59
83
|
export function inline(ast: any, { simdOnly, pin }?: {
|
|
60
84
|
simdOnly?: boolean;
|
|
61
85
|
pin?: any;
|
|
@@ -137,12 +161,8 @@ export const OPTS: any;
|
|
|
137
161
|
* @returns {Array}
|
|
138
162
|
*/
|
|
139
163
|
export function vacuum(ast: any[]): any[];
|
|
140
|
-
/**
|
|
141
|
-
|
|
142
|
-
* @param {Array} ast
|
|
143
|
-
* @returns {Array}
|
|
144
|
-
*/
|
|
145
|
-
export function peephole(ast: any[]): any[];
|
|
164
|
+
/** Peephole rules as a standalone pass. */
|
|
165
|
+
export function peephole(ast: any): any;
|
|
146
166
|
/**
|
|
147
167
|
* Replace `global.get` of an immutable, const-initialised global with the
|
|
148
168
|
* constant — but only when it doesn't grow the module. A `global.get` costs
|
|
@@ -158,12 +178,7 @@ export function peephole(ast: any[]): any[];
|
|
|
158
178
|
export function globals(ast: any[]): any[];
|
|
159
179
|
/** Match (type.load/store (i32.add ptr (type.const N))) and fold offset */
|
|
160
180
|
export function offset(ast: any): any;
|
|
161
|
-
|
|
162
|
-
* Remove br to a block's own label when it is the last instruction.
|
|
163
|
-
* @param {Array} ast
|
|
164
|
-
* @returns {Array}
|
|
165
|
-
*/
|
|
166
|
-
export function unbranch(ast: any[]): any[];
|
|
181
|
+
export function unbranch(ast: any): any;
|
|
167
182
|
/**
|
|
168
183
|
* Collapse the `while`-emit idiom into a single loop.
|
|
169
184
|
*
|
|
@@ -196,14 +211,7 @@ export function loopify(ast: any[]): any[];
|
|
|
196
211
|
* @returns {Array}
|
|
197
212
|
*/
|
|
198
213
|
export function stripmut(ast: any[]): any[];
|
|
199
|
-
|
|
200
|
-
* Simplify (if cond (then (br $label))) → (br_if $label cond)
|
|
201
|
-
* and (if cond (then) (else (br $label))) → (br_if $label (i32.eqz cond))
|
|
202
|
-
* Only when the br is the sole instruction in the arm.
|
|
203
|
-
* @param {Array} ast
|
|
204
|
-
* @returns {Array}
|
|
205
|
-
*/
|
|
206
|
-
export function brif(ast: any[]): any[];
|
|
214
|
+
export function brif(ast: any): any;
|
|
207
215
|
/**
|
|
208
216
|
* Fold identical trailing code out of if/else arms.
|
|
209
217
|
* (if cond (then A X) (else B X)) → (if cond (then A) (else B)) X
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/optimize.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/optimize.js"],"names":[],"mappings":"AA4lMA,gEA+MC;AArxMD;;;;GAIG;AACH,4BAHW,GAAG,GACD,MAAM,CAOlB;AAED;;;;GAIG;AACH,wCAFa,MAAM,CAOlB;AA8CD;;;;;GAKG;AACH,6CAmSC;AAgbD,6CAA6C;AAC7C,oCAA6C;AA2iB7C;;;;GAIG;AACH,4CAqBC;AAoCD;;;;;GAKG;AACH,8CAkFC;AAvlBD,iDAAiD;AACjD,wCAAqD;AAgErD,+CAA+C;AAC/C,wCAAqD;AAIrD;;;;GAIG;AACH,0CA0KC;AAotED,yCA8EC;AA7HD;;;;;;;;;GASG;AACH,+CAuBC;AA3tBD;;;;;;;;;;GAUG;AACH,uCAsJC;AAED;;;;;;;;GAQG;AACH;;UA8DC;AAkZD,yCA4DC;AAkWD;;;QAqEC;AAuQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;;UA2JC;AA3bD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,sCAwOC;AAgjED;;;;;;;;GAQG;AACH,gCAHW,OAAO,GAAC,MAAM,MAAO,OAc/B;AAvBD,qEAAqE;AACrE,uBAA8D;AA1iD9D;;;;;GAKG;AACH,0CAyEC;AA8FD,2CAA2C;AAC3C,wCAAqD;AAwDrD;;;;;;;;;;;GAWG;AACH,2CAiHC;AAID,2EAA2E;AAC3E,sCAgEC;AA0BD,wCA0DC;AAID;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,2CAiDC;AAID;;;;;GAKG;AACH,4CAqBC;AA6BD,oCAuCC;AAID;;;;;GAKG;AACH,4CAiDC;AAuCD;;;;;GAKG;AACH,0CAqFC;AA2cD,uCAyBC;AAheD;;;;;GAKG;AACH,8CAyEC;AAiLD;;;;GAIG;AACH,4CAsHC;AAqBD;;;;;GAKG;AACH,iDAgBC;AAtjDD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,+CAiFC;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,kDA8JC"}
|
package/types/src/util.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* @param {string} text - Error message
|
|
7
|
-
* @param {number} [pos] - Byte offset in source (defaults to err.loc)
|
|
8
|
-
* @throws {Error}
|
|
9
|
-
*/
|
|
10
|
-
export const err: (text: string, pos?: number) => never;
|
|
1
|
+
export function err(text: string, pos?: number): never;
|
|
2
|
+
export function setErrLoc(loc: any): void;
|
|
3
|
+
export function setErrSrc(src: any): void;
|
|
4
|
+
export function getErrLoc(): any;
|
|
5
|
+
export function getErrSrc(): any;
|
|
11
6
|
/** Regex to detect invalid underscore placement in numbers */
|
|
12
7
|
export const sepRE: RegExp;
|
|
13
8
|
/** Regex to match valid integer literals (decimal or hex) */
|
package/types/src/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.js"],"names":[],"mappings":"AAkBO,0BAJI,MAAM,QACN,MAAM,SAahB;AAEM,0CAA2C;AAC3C,0CAA2C;AAC3C,iCAA8B;AAC9B,iCAA8B;AAErC,8DAA8D;AAC9D,2BAAiD;AAEjD,6DAA6D;AAC7D,2BAAiD;AAe1C,uBAHI,MAAM,GACJ,MAAM,EAAE,CA8BpB;AAUM,4BAHI,MAAM,GACJ,MAAM,CAE6C;AAUzD,4BAHI,GAAG,GACD,GAAG,CAE2D;AASpE,2BALI,GAAG,yBAEH,GAAG,QACH,MAAM,QAWhB;AAgBM,+BANI,GAAG,yBAEH,GAAG,QACH,MAAM,GACJ,GAAG,CAWf"}
|