porffor 0.0.0-828ee15 → 0.0.0-a2afb57
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/README.md +49 -15
- package/c +0 -0
- package/c.exe +0 -0
- package/compiler/2c.js +354 -0
- package/compiler/builtins.js +0 -1
- package/compiler/codeGen.js +699 -148
- package/compiler/decompile.js +3 -3
- package/compiler/embedding.js +9 -5
- package/compiler/encoding.js +4 -2
- package/compiler/index.js +55 -4
- package/compiler/opt.js +49 -23
- package/compiler/parse.js +1 -0
- package/compiler/prototype.js +172 -34
- package/compiler/sections.js +47 -6
- package/compiler/wrap.js +12 -1
- package/cool.exe +0 -0
- package/g +0 -0
- package/g.exe +0 -0
- package/hi.c +37 -0
- package/out +0 -0
- package/out.exe +0 -0
- package/package.json +1 -1
- package/r.js +39 -0
- package/rhemyn/README.md +37 -0
- package/rhemyn/compile.js +214 -0
- package/rhemyn/parse.js +321 -0
- package/rhemyn/test/parse.js +59 -0
- package/runner/index.js +54 -33
- package/runner/info.js +37 -2
- package/runner/repl.js +6 -11
- package/runner/transform.js +5 -26
- package/runner/version.js +10 -0
- package/t.js +31 -0
- package/tmp.c +61 -0
package/compiler/sections.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Valtype, FuncType, Empty, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize } from './wasmSpec.js';
|
2
|
-
import { encodeVector, encodeString, encodeLocal } from './encoding.js';
|
2
|
+
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128 } from './encoding.js';
|
3
3
|
import { number } from './embedding.js';
|
4
4
|
import { importedFuncs } from './builtins.js';
|
5
5
|
|
@@ -8,11 +8,26 @@ const createSection = (type, data) => [
|
|
8
8
|
...encodeVector(data)
|
9
9
|
];
|
10
10
|
|
11
|
-
|
11
|
+
const customSection = (name, data) => [
|
12
|
+
Section.custom,
|
13
|
+
...encodeVector([...encodeString(name), ...data])
|
14
|
+
];
|
15
|
+
|
16
|
+
const chHint = (topTier, baselineTier, strategy) => {
|
17
|
+
// 1 byte of 4 2 bit components: spare, top tier, baseline tier, compilation strategy
|
18
|
+
// tiers: 0x00 = default, 0x01 = baseline (liftoff), 0x02 = optimized (turbofan)
|
19
|
+
// strategy: 0x00 = default, 0x01 = lazy, 0x02 = eager, 0x03 = lazy baseline, eager top tier
|
20
|
+
return (strategy | (baselineTier << 2) | (topTier << 4));
|
21
|
+
};
|
22
|
+
|
23
|
+
export default (funcs, globals, tags, pages, data, flags) => {
|
12
24
|
const types = [], typeCache = {};
|
13
25
|
|
14
26
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
15
27
|
|
28
|
+
const compileHints = process.argv.includes('-compile-hints');
|
29
|
+
if (compileHints) log('sections', 'warning: compile hints is V8 only w/ experimental arg! (you used -compile-hints)');
|
30
|
+
|
16
31
|
const getType = (params, returns) => {
|
17
32
|
const hash = `${params.join(',')}_${returns.join(',')}`;
|
18
33
|
if (optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
|
@@ -36,7 +51,7 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
36
51
|
// tree shake imports
|
37
52
|
for (const f of funcs) {
|
38
53
|
for (const inst of f.wasm) {
|
39
|
-
if (inst[0] === Opcodes.call && inst[1] < importedFuncs.length) {
|
54
|
+
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] < importedFuncs.length) {
|
40
55
|
const idx = inst[1];
|
41
56
|
const func = importedFuncs[idx];
|
42
57
|
|
@@ -51,15 +66,17 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
51
66
|
// fix call indexes for non-imports
|
52
67
|
const delta = importedFuncs.length - importFuncs.length;
|
53
68
|
for (const f of funcs) {
|
69
|
+
f.originalIndex = f.index;
|
54
70
|
f.index -= delta;
|
55
71
|
|
56
72
|
for (const inst of f.wasm) {
|
57
|
-
if (inst[0] === Opcodes.call && inst[1] >= importedFuncs.length) {
|
73
|
+
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
|
58
74
|
inst[1] -= delta;
|
59
75
|
}
|
60
76
|
}
|
61
77
|
}
|
62
78
|
}
|
79
|
+
globalThis.importFuncs = importFuncs;
|
63
80
|
|
64
81
|
if (optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
65
82
|
|
@@ -73,6 +90,14 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
73
90
|
encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
|
74
91
|
);
|
75
92
|
|
93
|
+
// compilation hints section - unspec v8 only
|
94
|
+
// https://github.com/WebAssembly/design/issues/1473#issuecomment-1431274746
|
95
|
+
const chSection = !compileHints ? [] : customSection(
|
96
|
+
'compilationHints',
|
97
|
+
// for now just do everything as optimise eager
|
98
|
+
encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
|
99
|
+
);
|
100
|
+
|
76
101
|
const globalSection = Object.keys(globals).length === 0 ? [] : createSection(
|
77
102
|
Section.global,
|
78
103
|
encodeVector(Object.keys(globals).map(x => [ globals[x].type, 0x01, ...number(globals[x].init ?? 0, globals[x].type).flat(), Opcodes.end ]))
|
@@ -80,6 +105,8 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
80
105
|
|
81
106
|
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
|
82
107
|
|
108
|
+
if (process.argv.includes('-always-memory') && pages.size === 0) pages.set('-always-memory', 0);
|
109
|
+
|
83
110
|
const usesMemory = pages.size > 0;
|
84
111
|
const memorySection = !usesMemory ? [] : createSection(
|
85
112
|
Section.memory,
|
@@ -130,13 +157,24 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
130
157
|
encodeVector(types)
|
131
158
|
);
|
132
159
|
|
160
|
+
const dataSection = data.length === 0 ? [] : createSection(
|
161
|
+
Section.data,
|
162
|
+
encodeVector(data.map(x => [ 0x00, Opcodes.i32_const, ...signedLEB128(x.offset), Opcodes.end, ...encodeVector(x.bytes) ]))
|
163
|
+
);
|
164
|
+
|
165
|
+
const dataCountSection = data.length === 0 ? [] : createSection(
|
166
|
+
Section.data_count,
|
167
|
+
unsignedLEB128(data.length)
|
168
|
+
);
|
169
|
+
|
133
170
|
if (process.argv.includes('-sections')) console.log({
|
134
171
|
typeSection: typeSection.map(x => x.toString(16)),
|
135
172
|
importSection: importSection.map(x => x.toString(16)),
|
136
173
|
funcSection: funcSection.map(x => x.toString(16)),
|
137
174
|
globalSection: globalSection.map(x => x.toString(16)),
|
138
175
|
exportSection: exportSection.map(x => x.toString(16)),
|
139
|
-
codeSection: codeSection.map(x => x.toString(16))
|
176
|
+
codeSection: codeSection.map(x => x.toString(16)),
|
177
|
+
dataSection: dataSection.map(x => x.toString(16)),
|
140
178
|
});
|
141
179
|
|
142
180
|
return Uint8Array.from([
|
@@ -145,10 +183,13 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
145
183
|
...typeSection,
|
146
184
|
...importSection,
|
147
185
|
...funcSection,
|
186
|
+
...chSection,
|
148
187
|
...memorySection,
|
149
188
|
...tagSection,
|
150
189
|
...globalSection,
|
151
190
|
...exportSection,
|
152
|
-
...
|
191
|
+
...dataCountSection,
|
192
|
+
...codeSection,
|
193
|
+
...dataSection
|
153
194
|
]);
|
154
195
|
};
|
package/compiler/wrap.js
CHANGED
@@ -5,6 +5,7 @@ import decompile from './decompile.js';
|
|
5
5
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
6
6
|
|
7
7
|
const typeBase = 0xffffffffffff0;
|
8
|
+
const internalTypeBase = 0xfffffffffff0f;
|
8
9
|
const TYPES = {
|
9
10
|
[typeBase]: 'number',
|
10
11
|
[typeBase + 1]: 'boolean',
|
@@ -16,7 +17,8 @@ const TYPES = {
|
|
16
17
|
[typeBase + 7]: 'bigint',
|
17
18
|
|
18
19
|
// internal
|
19
|
-
[
|
20
|
+
[internalTypeBase]: '_array',
|
21
|
+
[internalTypeBase + 1]: '_regexp'
|
20
22
|
};
|
21
23
|
|
22
24
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
@@ -90,6 +92,15 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
90
92
|
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
91
93
|
}
|
92
94
|
|
95
|
+
case 'function': {
|
96
|
+
// wasm func index, including all imports
|
97
|
+
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
98
|
+
if (!func) return ret;
|
99
|
+
|
100
|
+
// make fake empty func for repl/etc
|
101
|
+
return {[func.name]() {}}[func.name];
|
102
|
+
}
|
103
|
+
|
93
104
|
default: return ret;
|
94
105
|
}
|
95
106
|
} catch (e) {
|
package/cool.exe
ADDED
Binary file
|
package/g
ADDED
Binary file
|
package/g.exe
ADDED
Binary file
|
package/hi.c
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
|
3
|
+
double inline f64_f(double x, double y) {
|
4
|
+
return x - (int)(x / y) * y;
|
5
|
+
}
|
6
|
+
|
7
|
+
double isPrime(double number) {
|
8
|
+
double i;
|
9
|
+
|
10
|
+
if (number < 2e+0) {
|
11
|
+
return 0e+0;
|
12
|
+
}
|
13
|
+
i = 2e+0;
|
14
|
+
while (i < number) {
|
15
|
+
if (f64_f(number, i) == 0e+0) {
|
16
|
+
return 0e+0;
|
17
|
+
}
|
18
|
+
i = i + 1e+0;
|
19
|
+
}
|
20
|
+
return 1e+0;
|
21
|
+
}
|
22
|
+
|
23
|
+
int main() {
|
24
|
+
double sum;
|
25
|
+
double counter;
|
26
|
+
|
27
|
+
sum = 0e+0;
|
28
|
+
counter = 0e+0;
|
29
|
+
while (counter <= 1e+5) {
|
30
|
+
if (isPrime(counter) == 1e+0) {
|
31
|
+
sum = sum + counter;
|
32
|
+
}
|
33
|
+
counter = counter + 1e+0;
|
34
|
+
}
|
35
|
+
printf("%f\n", sum);
|
36
|
+
}
|
37
|
+
|
package/out
ADDED
Binary file
|
package/out.exe
ADDED
Binary file
|
package/package.json
CHANGED
package/r.js
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
compareArray.isSameValue = function(a, b) {
|
2
|
+
if (a === 0 && b === 0) return 1 / a === 1 / b;
|
3
|
+
if (a !== a && b !== b) return true;
|
4
|
+
|
5
|
+
return a === b;
|
6
|
+
};
|
7
|
+
|
8
|
+
function compareArray(a, b) {
|
9
|
+
// if either are nullish
|
10
|
+
if (a == null || b == null) return false;
|
11
|
+
|
12
|
+
// megahack: all arrays from now on will be >0 pointer
|
13
|
+
const _hack = '';
|
14
|
+
|
15
|
+
// hack: enforce type inference of being arrays
|
16
|
+
a ??= [];
|
17
|
+
b ??= [];
|
18
|
+
|
19
|
+
if (b.length !== a.length) {
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
|
23
|
+
for (var i = 0; i < a.length; i++) {
|
24
|
+
if (!compareArray.isSameValue(b[i], a[i])) {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
|
32
|
+
console.log(compareArray(null, []));
|
33
|
+
console.log(compareArray(undefined, []));
|
34
|
+
|
35
|
+
console.log(compareArray([], []));
|
36
|
+
console.log(compareArray([ 1 ], []));
|
37
|
+
console.log(compareArray([ 1 ], [ 1 ]));
|
38
|
+
console.log(compareArray([ 1, 2 ], [ 1 ]));
|
39
|
+
console.log(compareArray([ 1, 2 ], [ 1, 2 ]));
|
package/rhemyn/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# rhemyn
|
2
|
+
a basic experimental wip regex engine/aot wasm compiler in js. regex engine for porffor. uses own regex parser, no dependencies (excluding porffor internals). <br>
|
3
|
+
age: ~1 day
|
4
|
+
|
5
|
+
made for use with porffor but could possibly be adapted, implementation/library notes:
|
6
|
+
- exposes functions for each regex "operation" (eg test, match)
|
7
|
+
- given a regex pattern string (eg `a+`), it returns a "function" object
|
8
|
+
- wasm function returned expects an i32 pointer to a utf-16 string (can add utf-8 option later if someone else actually wants to use this)
|
9
|
+
|
10
|
+
## syntax
|
11
|
+
🟢 supported 🟡 partial 🟠 parsed only 🔴 unsupported
|
12
|
+
|
13
|
+
- 🟢 literal characters (eg `a`)
|
14
|
+
- 🟢 escaping (eg `\.\n\cJ\x0a\u000a`)
|
15
|
+
- 🟢 character itself (eg `\.`)
|
16
|
+
- 🟢 escape sequences (eg `\n`)
|
17
|
+
- 🟢 control character (eg `\cJ`)
|
18
|
+
- 🟢 unicode code points (eg `\x00`, `\u0000`)
|
19
|
+
- 🟢 sets (eg `[ab]`)
|
20
|
+
- 🟢 ranges (eg `[a-z]`)
|
21
|
+
- 🟢 negated sets (eg `[^ab]`)
|
22
|
+
- 🟢 metacharacters
|
23
|
+
- 🟢 dot (eg `a.b`)
|
24
|
+
- 🟢 digit, not digit (eg `\d\D`)
|
25
|
+
- 🟢 word, not word (eg `\w\W`)
|
26
|
+
- 🟢 whitespace, not whitespace (eg `\s\S`)
|
27
|
+
- 🟠 quantifiers
|
28
|
+
- 🟠 star (eg `a*`)
|
29
|
+
- 🟠 plus (eg `a+`)
|
30
|
+
- 🟠 optional (eg `a?`)
|
31
|
+
- 🟠 lazy modifier (eg `a*?`)
|
32
|
+
- 🔴 n repetitions (eg `a{4}`)
|
33
|
+
- 🔴 n-m repetitions (eg `a{2,4}`)
|
34
|
+
- 🔴 assertions
|
35
|
+
- 🔴 beginning (eg `^a`)
|
36
|
+
- 🔴 end (eg `a$`)
|
37
|
+
- 🔴 word boundary assertion (eg `\b\B`)
|
@@ -0,0 +1,214 @@
|
|
1
|
+
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../compiler/wasmSpec.js';
|
2
|
+
import { number } from '../compiler/embedding.js';
|
3
|
+
import { signedLEB128, unsignedLEB128 } from '../compiler/encoding.js';
|
4
|
+
import parse from './parse.js';
|
5
|
+
|
6
|
+
// local indexes
|
7
|
+
const BasePointer = 0; // base string pointer
|
8
|
+
const IterPointer = 1; // this iteration base pointer
|
9
|
+
const EndPointer = 2; // pointer for the end
|
10
|
+
const Counter = 3; // what char we are running on
|
11
|
+
const Pointer = 4; // next char BYTE pointer
|
12
|
+
const Length = 5;
|
13
|
+
const Tmp = 6;
|
14
|
+
|
15
|
+
let exprLastGet = false;
|
16
|
+
const generate = (node, negated = false, get = true, func = 'test') => {
|
17
|
+
let out = [];
|
18
|
+
switch (node.type) {
|
19
|
+
case 'Expression':
|
20
|
+
exprLastGet = false;
|
21
|
+
out = [
|
22
|
+
// set length local
|
23
|
+
[ Opcodes.local_get, BasePointer ],
|
24
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
25
|
+
[ Opcodes.local_set, Length ],
|
26
|
+
|
27
|
+
// set iter pointer local as base + sizeof i32 initially
|
28
|
+
[ Opcodes.local_get, BasePointer ],
|
29
|
+
...number(ValtypeSize.i32, Valtype.i32),
|
30
|
+
[ Opcodes.i32_add ],
|
31
|
+
[ Opcodes.local_set, IterPointer ],
|
32
|
+
|
33
|
+
[ Opcodes.loop, Blocktype.void ],
|
34
|
+
|
35
|
+
// reset pointer as iter pointer
|
36
|
+
[ Opcodes.local_get, IterPointer ],
|
37
|
+
[ Opcodes.local_set, Pointer ],
|
38
|
+
|
39
|
+
[ Opcodes.block, Blocktype.void ],
|
40
|
+
|
41
|
+
// generate checks
|
42
|
+
...node.body.flatMap((x, i) => {
|
43
|
+
exprLastGet = x.type !== 'Group' && i === (node.body.length - 1);
|
44
|
+
return generate(x, negated);
|
45
|
+
}),
|
46
|
+
|
47
|
+
// reached end without branching out, successful match
|
48
|
+
...({
|
49
|
+
test: number(1, Valtype.i32),
|
50
|
+
search: [
|
51
|
+
[ Opcodes.local_get, Counter ]
|
52
|
+
]
|
53
|
+
})[func],
|
54
|
+
[ Opcodes.return ],
|
55
|
+
|
56
|
+
[ Opcodes.end ],
|
57
|
+
|
58
|
+
// increment iter pointer by sizeof i16
|
59
|
+
[ Opcodes.local_get, IterPointer ],
|
60
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
61
|
+
[ Opcodes.i32_add ],
|
62
|
+
[ Opcodes.local_set, IterPointer ],
|
63
|
+
|
64
|
+
// increment counter by 1, check if eq length, if not loop
|
65
|
+
[ Opcodes.local_get, Counter ],
|
66
|
+
...number(1, Valtype.i32),
|
67
|
+
[ Opcodes.i32_add ],
|
68
|
+
[ Opcodes.local_tee, Counter ],
|
69
|
+
|
70
|
+
[ Opcodes.local_get, Length ],
|
71
|
+
[ Opcodes.i32_ne ],
|
72
|
+
|
73
|
+
[ Opcodes.br_if, 0 ],
|
74
|
+
[ Opcodes.end ],
|
75
|
+
|
76
|
+
// no match, return 0
|
77
|
+
...number(({
|
78
|
+
test: 0,
|
79
|
+
search: -1
|
80
|
+
})[func], Valtype.i32)
|
81
|
+
];
|
82
|
+
|
83
|
+
if (globalThis.regexLog) {
|
84
|
+
const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
|
85
|
+
console.log(`\n${underline('ast')}`);
|
86
|
+
console.log(node);
|
87
|
+
console.log(`\n${underline('wasm bytecode')}\n` + decompile(out) + '\n');
|
88
|
+
}
|
89
|
+
|
90
|
+
break;
|
91
|
+
|
92
|
+
case 'Character':
|
93
|
+
out = generateChar(node, node.negated ^ negated, get);
|
94
|
+
break;
|
95
|
+
|
96
|
+
case 'Set':
|
97
|
+
out = generateSet(node, node.negated, get);
|
98
|
+
break;
|
99
|
+
|
100
|
+
case 'Group':
|
101
|
+
out = generateGroup(node, negated, get);
|
102
|
+
break;
|
103
|
+
|
104
|
+
case 'Range':
|
105
|
+
out = generateRange(node, negated, get);
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
|
109
|
+
return out;
|
110
|
+
};
|
111
|
+
|
112
|
+
const getNextChar = () => [
|
113
|
+
// get char from pointer
|
114
|
+
[ Opcodes.local_get, Pointer ],
|
115
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(0) ],
|
116
|
+
|
117
|
+
...(exprLastGet ? [] : [
|
118
|
+
// pointer += sizeof i16
|
119
|
+
[ Opcodes.local_get, Pointer ],
|
120
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
121
|
+
[ Opcodes.i32_add ],
|
122
|
+
[ Opcodes.local_set, Pointer ]
|
123
|
+
])
|
124
|
+
];
|
125
|
+
|
126
|
+
const checkFailure = () => [
|
127
|
+
// surely we do not need to do this for every single mismatch, right?
|
128
|
+
/* [ Opcodes.if, Blocktype.void ],
|
129
|
+
...number(0, Valtype.i32),
|
130
|
+
[ Opcodes.return ],
|
131
|
+
[ Opcodes.end ], */
|
132
|
+
|
133
|
+
[ Opcodes.br_if, 0 ]
|
134
|
+
];
|
135
|
+
|
136
|
+
const generateChar = (node, negated, get) => {
|
137
|
+
return [
|
138
|
+
...(get ? getNextChar() : []),
|
139
|
+
...number(node.char.charCodeAt(0), Valtype.i32),
|
140
|
+
negated ? [ Opcodes.i32_eq ] : [ Opcodes.i32_ne ],
|
141
|
+
...(get ? checkFailure(): [])
|
142
|
+
];
|
143
|
+
};
|
144
|
+
|
145
|
+
const generateSet = (node, negated, get) => {
|
146
|
+
// for a single char we do not need a tmp, it is like just
|
147
|
+
const singleChar = node.body.length === 1 && node.body[0].type === 'Character';
|
148
|
+
|
149
|
+
let out = [
|
150
|
+
...(get ? getNextChar() : []),
|
151
|
+
...(singleChar ? [] : [ [ Opcodes.local_set, Tmp ] ]),
|
152
|
+
];
|
153
|
+
|
154
|
+
for (const x of node.body) {
|
155
|
+
out = [
|
156
|
+
...out,
|
157
|
+
...(singleChar ? [] : [ [ Opcodes.local_get, Tmp ] ]),
|
158
|
+
...generate(x, negated, false)
|
159
|
+
];
|
160
|
+
}
|
161
|
+
|
162
|
+
out = out.concat(new Array(node.body.length - 1).fill(negated ? [ Opcodes.i32_or ] : [ Opcodes.i32_and ]));
|
163
|
+
|
164
|
+
return [
|
165
|
+
...out,
|
166
|
+
...checkFailure()
|
167
|
+
];
|
168
|
+
};
|
169
|
+
|
170
|
+
const generateRange = (node, negated, get) => {
|
171
|
+
return [
|
172
|
+
...(get ? getNextChar() : []),
|
173
|
+
...(get ? [ [ Opcodes.local_tee, Tmp ] ] : []),
|
174
|
+
|
175
|
+
...number(node.from.charCodeAt(0), Valtype.i32),
|
176
|
+
// negated ? [ Opcodes.i32_lt_s ] : [ Opcodes.i32_ge_s ],
|
177
|
+
negated ? [ Opcodes.i32_ge_s ] : [ Opcodes.i32_lt_s ],
|
178
|
+
|
179
|
+
[ Opcodes.local_get, Tmp ],
|
180
|
+
...number(node.to.charCodeAt(0), Valtype.i32),
|
181
|
+
// negated ? [ Opcodes.i32_gt_s ] : [ Opcodes.i32_le_s ],
|
182
|
+
negated ? [ Opcodes.i32_le_s ] : [ Opcodes.i32_gt_s ],
|
183
|
+
|
184
|
+
negated ? [ Opcodes.i32_and ] : [ Opcodes.i32_or ],
|
185
|
+
...(get ? checkFailure(): [])
|
186
|
+
];
|
187
|
+
};
|
188
|
+
|
189
|
+
const generateGroup = (node, negated, get) => {
|
190
|
+
|
191
|
+
};
|
192
|
+
|
193
|
+
export const test = (regex, index = 0, name = 'regex_test_' + regex) => outputFunc(generate(parse(regex), false, true, 'test'), name, index);
|
194
|
+
export const search = (regex, index = 0, name = 'regex_search_' + regex) => outputFunc(generate(parse(regex), false, true, 'search'), name, index);
|
195
|
+
|
196
|
+
const outputFunc = (wasm, name, index) => ({
|
197
|
+
name,
|
198
|
+
index,
|
199
|
+
wasm,
|
200
|
+
|
201
|
+
export: true,
|
202
|
+
params: [ Valtype.i32 ],
|
203
|
+
returns: [ Valtype.i32 ],
|
204
|
+
returnType: 0xffffffffffff1, // boolean - todo: do not hardcode this
|
205
|
+
locals: {
|
206
|
+
basePointer: { idx: 0, type: Valtype.i32 },
|
207
|
+
iterPointer: { idx: 1, type: Valtype.i32 },
|
208
|
+
endPointer: { idx: 2, type: Valtype.i32 },
|
209
|
+
counter: { idx: 3, type: Valtype.i32 },
|
210
|
+
pointer: { idx: 4, type: Valtype.i32 },
|
211
|
+
length: { idx: 5, type: Valtype.i32 },
|
212
|
+
tmp: { idx: 6, type: Valtype.i32 },
|
213
|
+
}
|
214
|
+
});
|