porffor 0.17.0-9c7bd8098 → 0.17.0-a23029b3a

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/rhemyn/compile.js CHANGED
@@ -6,75 +6,78 @@ import { TYPES } from '../compiler/types.js';
6
6
 
7
7
  // local indexes
8
8
  const BasePointer = 0; // base string pointer
9
- const IterPointer = 1; // this iteration base pointer
10
- const EndPointer = 2; // pointer for the end
11
- const Counter = 3; // what char we are running on
12
- const Pointer = 4; // next char BYTE pointer
13
- const Length = 5;
14
- const Tmp = 6;
15
-
16
- let exprLastGet = false;
9
+ const Counter = 2; // what char we are running on
10
+ const Pointer = 3; // next char pointer
11
+ const Length = 4;
12
+ const Tmp = 5;
13
+ const QuantifierTmp = 6; // the temporary variable used for quanitifers
14
+
15
+ const doesSucceedZero = (node) => {
16
+ for (const n of node.body) {
17
+ if (n.type === "Group") {
18
+ if (!doesSucceedZero(node)) return false;
19
+ }
20
+ if (!n.quantifier || n.quantifier[0] > 0) {
21
+ return false;
22
+ }
23
+ }
24
+ return true;
25
+ }
26
+
17
27
  const generate = (node, negated = false, get = true, stringSize = 2, func = 'test') => {
18
28
  let out = [];
19
29
  switch (node.type) {
20
30
  case 'Expression':
21
- exprLastGet = false;
31
+ let succeedsZero = doesSucceedZero(node);
32
+
22
33
  out = [
23
34
  // set length local
24
35
  [ Opcodes.local_get, BasePointer ],
25
36
  [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
26
- [ Opcodes.local_set, Length ],
37
+ [ Opcodes.local_tee, Length ],
27
38
 
28
- // set iter pointer local as base + sizeof i32 initially
39
+ ...number(0, Valtype.i32),
40
+ [ Opcodes.i32_eq ],
41
+ [ Opcodes.if, Blocktype.void ],
42
+ ...number(succeedsZero ? 1 : 0, Valtype.i32),
43
+ [ Opcodes.return ],
44
+ [ Opcodes.end ],
45
+
46
+ // pointer = base + sizeof i32
29
47
  [ Opcodes.local_get, BasePointer ],
30
48
  ...number(ValtypeSize.i32, Valtype.i32),
31
49
  [ Opcodes.i32_add ],
32
- [ Opcodes.local_set, IterPointer ],
33
-
34
- [ Opcodes.loop, Blocktype.void ],
35
-
36
- // reset pointer as iter pointer
37
- [ Opcodes.local_get, IterPointer ],
38
50
  [ Opcodes.local_set, Pointer ],
39
51
 
40
- [ Opcodes.block, Blocktype.void ],
41
-
42
- // generate checks
43
- ...node.body.flatMap((x, i) => {
44
- exprLastGet = x.type !== 'Group' && i === (node.body.length - 1);
45
- return generate(x, negated, true, stringSize, func);
46
- }),
47
-
48
- // reached end without branching out, successful match
49
- ...({
50
- test: number(1, Valtype.i32),
51
- search: [
52
- [ Opcodes.local_get, Counter ]
53
- ]
54
- })[func],
55
- [ Opcodes.return ],
56
-
57
- [ Opcodes.end ],
58
-
59
- // increment iter pointer by string size
60
- [ Opcodes.local_get, IterPointer ],
61
- ...number(stringSize, Valtype.i32),
62
- [ Opcodes.i32_add ],
63
- [ Opcodes.local_set, IterPointer ],
64
-
65
- // increment counter by 1, check if eq length, if not loop
66
- [ Opcodes.local_get, Counter ],
67
- ...number(1, Valtype.i32),
68
- [ Opcodes.i32_add ],
69
- [ Opcodes.local_tee, Counter ],
70
-
71
- [ Opcodes.local_get, Length ],
72
- [ Opcodes.i32_ne ],
73
-
74
- [ Opcodes.br_if, 0 ],
52
+ [ Opcodes.loop, Blocktype.void ],
53
+ [ Opcodes.block, Blocktype.void ],
54
+ // generate checks
55
+ ...node.body.flatMap(x => generate(x, negated, true, stringSize, func)),
56
+
57
+ // reached end without branching out, successful match
58
+ ...({
59
+ test: number(1, Valtype.i32),
60
+ search: [
61
+ [ Opcodes.local_get, Counter ]
62
+ ]
63
+ })[func],
64
+ [ Opcodes.return ],
65
+ [ Opcodes.end ],
66
+
67
+ // counter++, if length > counter, loop
68
+ [ Opcodes.local_get, Length ],
69
+
70
+ [ Opcodes.local_get, Counter ],
71
+ ...number(1, Valtype.i32),
72
+ [ Opcodes.i32_add ],
73
+ [ Opcodes.local_tee, Counter ],
74
+
75
+ [ Opcodes.i32_gt_s ],
76
+
77
+ [ Opcodes.br_if, 0 ],
75
78
  [ Opcodes.end ],
76
79
 
77
- // no match, return 0
80
+ // no match
78
81
  ...number(({
79
82
  test: 0,
80
83
  search: -1
@@ -110,12 +113,12 @@ const generate = (node, negated = false, get = true, stringSize = 2, func = 'tes
110
113
  return out;
111
114
  };
112
115
 
113
- const getNextChar = (stringSize) => [
116
+ const getNextChar = (stringSize, peek = false) => [
114
117
  // get char from pointer
115
118
  [ Opcodes.local_get, Pointer ],
116
119
  [ stringSize == 2 ? Opcodes.i32_load16_u : Opcodes.i32_load8_u, 0, 0 ],
117
120
 
118
- ...(exprLastGet ? [] : [
121
+ ...(peek ? [] : [
119
122
  // pointer += string size
120
123
  [ Opcodes.local_get, Pointer ],
121
124
  ...number(stringSize, Valtype.i32),
@@ -134,37 +137,123 @@ const checkFailure = () => [
134
137
  [ Opcodes.br_if, 0 ]
135
138
  ];
136
139
 
137
- const generateChar = (node, negated, get, stringSize) => {
140
+ const wrapQuantifier = (node, method, get, stringSize) => {
141
+ const [ min, max ] = node.quantifier;
138
142
  return [
139
- ...(get ? getNextChar(stringSize) : []),
143
+ // initalize our temp value (number of matched characters)
144
+ ...number(0, Valtype.i32),
145
+ [Opcodes.local_set, QuantifierTmp],
146
+
147
+ // if len - counter == 0, if min == 0, succeed, else fail
148
+ [ Opcodes.local_get, Length ],
149
+ [ Opcodes.local_get, Counter ],
150
+ [ Opcodes.i32_sub ],
151
+ ...number(0, Valtype.i32),
152
+ [ Opcodes.i32_eq ],
153
+ ...(min == 0 ? [
154
+ [ Opcodes.if, Blocktype.void ],
155
+ ] : [
156
+ [ Opcodes.br_if, 0 ],
157
+ ]),
158
+
159
+ // start loop
160
+ [Opcodes.loop, Blocktype.void],
161
+ [ Opcodes.block, Blocktype.void ],
162
+ // if counter + tmp == length, break
163
+ [ Opcodes.local_get, Counter ],
164
+ [ Opcodes.local_get, QuantifierTmp ],
165
+ [ Opcodes.i32_add ],
166
+ [ Opcodes.local_get, Length ],
167
+ [ Opcodes.i32_eq ],
168
+ [ Opcodes.br_if, 0 ],
169
+
170
+ // if doesn't match, break
171
+ ...method,
172
+ [Opcodes.br_if, 0 ],
173
+ ...(get ? [
174
+ // pointer += stringSize
175
+ [ Opcodes.local_get, Pointer ],
176
+ ...number(stringSize, Valtype.i32),
177
+ [ Opcodes.i32_add ],
178
+ [ Opcodes.local_set, Pointer ]
179
+ ] : []),
180
+
181
+ // if maximum was reached, break
182
+ ...(max ? [
183
+ [ Opcodes.local_get, QuantifierTmp ],
184
+ ...number(max, Valtype.i32),
185
+ [ Opcodes.i32_eq ],
186
+ [ Opcodes.br_if, 0 ]
187
+ ] : []),
188
+
189
+ [ Opcodes.local_get, QuantifierTmp ],
190
+ ...number(1, Valtype.i32),
191
+ [ Opcodes.i32_add ],
192
+ [ Opcodes.local_set, QuantifierTmp ],
193
+ [ Opcodes.br, 1 ],
194
+ [ Opcodes.end ],
195
+ [ Opcodes.end ],
196
+
197
+ // if less than minimum, fail
198
+ [Opcodes.local_get, QuantifierTmp],
199
+ ...number(min, Valtype.i32),
200
+ [Opcodes.i32_lt_s],
201
+ ...(get ? checkFailure(): []),
202
+
203
+ ...(min == 0 ? [ [ Opcodes.end ] ] : []),
204
+ ];
205
+ }
206
+
207
+ const generateChar = (node, negated, get, stringSize) => {
208
+ const hasQuantifier = !!node.quantifier;
209
+ const out = [
210
+ ...(get ? getNextChar(stringSize, hasQuantifier) : []),
140
211
  ...number(node.char.charCodeAt(0), Valtype.i32),
141
212
  negated ? [ Opcodes.i32_eq ] : [ Opcodes.i32_ne ],
142
- ...(get ? checkFailure(): [])
213
+ ];
214
+
215
+ if (node.quantifier) {
216
+ return wrapQuantifier(node, out, get, stringSize);
217
+ }
218
+
219
+ return [
220
+ ...out,
221
+ ...(get ? checkFailure(): []),
143
222
  ];
144
223
  };
145
224
 
146
225
  const generateSet = (node, negated, get, stringSize) => {
147
226
  // for a single char we do not need a tmp, it is like just
148
227
  const singleChar = node.body.length === 1 && node.body[0].type === 'Character';
228
+ if (singleChar) return generateChar(node.body[0], negated, get, stringSize)
149
229
 
150
- let out = [
151
- ...(get ? getNextChar(stringSize) : []),
152
- ...(singleChar ? [] : [ [ Opcodes.local_set, Tmp ] ]),
230
+ const hasQuantifier = !!node.quantifier;
231
+
232
+ const out = [
233
+ ...(get ? getNextChar(stringSize, hasQuantifier) : []),
234
+ [ Opcodes.local_set, Tmp ],
153
235
  ];
154
236
 
155
237
  for (const x of node.body) {
156
- out = [
157
- ...out,
158
- ...(singleChar ? [] : [ [ Opcodes.local_get, Tmp ] ]),
238
+ out.push(
239
+ [ Opcodes.local_get, Tmp ],
159
240
  ...generate(x, negated, false, stringSize)
160
- ];
241
+ );
161
242
  }
162
243
 
163
- if (node.body.length > 0) out = out.concat(new Array(node.body.length - 1).fill(negated ? [ Opcodes.i32_or ] : [ Opcodes.i32_and ]));
244
+ if (node.body.length > 0) {
245
+ for (let i = 0; i < node.body.length - 1; i++) {
246
+ out.push(negated ? [ Opcodes.i32_or ] : [ Opcodes.i32_and ])
247
+ }
248
+ };
249
+
250
+ if (hasQuantifier) {
251
+ return wrapQuantifier(node, out, get, stringSize);
252
+ }
164
253
 
165
254
  return [
166
255
  ...out,
167
- ...checkFailure()
256
+ ...checkFailure(),
168
257
  ];
169
258
  };
170
259
 
@@ -206,28 +295,33 @@ const wrapFunc = (regex, func, name, index) => {
206
295
  // bytestring
207
296
  ...generate(parsed, false, true, 1, func),
208
297
  [ Opcodes.end ]
209
- ], name, index);
298
+ ], name, index, types[func]);
210
299
  };
211
300
 
212
301
  export const test = (regex, index = 0, name = 'regex_test_' + regex) => wrapFunc(regex, 'test', name, index);
213
302
  export const search = (regex, index = 0, name = 'regex_search_' + regex) => wrapFunc(regex, 'search', name, index);
214
303
 
215
- const outputFunc = (wasm, name, index) => ({
304
+ export const types = {
305
+ test: TYPES.boolean,
306
+ search: TYPES.number
307
+ };
308
+
309
+ const outputFunc = (wasm, name, index, returnType) => ({
216
310
  name,
217
311
  index,
218
312
  wasm,
313
+ returnType,
219
314
 
220
315
  export: true,
221
316
  params: [ Valtype.i32, Valtype.i32 ],
222
317
  returns: [ Valtype.i32 ],
223
- returnType: TYPES.boolean,
224
318
  locals: {
225
319
  basePointer: { idx: 0, type: Valtype.i32 },
226
- iterPointer: { idx: 1, type: Valtype.i32 },
227
- endPointer: { idx: 2, type: Valtype.i32 },
228
- counter: { idx: 3, type: Valtype.i32 },
229
- pointer: { idx: 4, type: Valtype.i32 },
230
- length: { idx: 5, type: Valtype.i32 },
231
- tmp: { idx: 6, type: Valtype.i32 },
320
+ inputType: { idx: 1, type: Valtype.i32 },
321
+ counter: { idx: 2, type: Valtype.i32 },
322
+ pointer: { idx: 3, type: Valtype.i32 },
323
+ length: { idx: 4, type: Valtype.i32 },
324
+ tmp: { idx: 5, type: Valtype.i32 },
325
+ quantifierTmp: { idx: 6, type: Valtype.i32 },
232
326
  }
233
327
  });
package/runner/debug.js CHANGED
@@ -43,7 +43,7 @@ let lastLine;
43
43
  let output = '';
44
44
 
45
45
  try {
46
- const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
46
+ const { exports } = compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
47
47
  y: n => {
48
48
  if (callStarts[callStarts.length - 1] === n - 1) {
49
49
  // end of call
package/runner/index.js CHANGED
@@ -130,14 +130,14 @@ const print = str => {
130
130
  let runStart;
131
131
  try {
132
132
  if (process.argv.includes('-b')) {
133
- const { wasm, exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
133
+ const { wasm, exports } = compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
134
134
 
135
135
  runStart = performance.now();
136
136
  if (!process.argv.includes('--no-run')) exports.main();
137
137
 
138
138
  console.log(`\n\nwasm size: ${wasm.byteLength} bytes`);
139
139
  } else {
140
- const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
140
+ const { exports } = compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
141
141
 
142
142
  runStart = performance.now();
143
143
  if (!process.argv.includes('--no-run')) exports.main();
@@ -145,7 +145,9 @@ try {
145
145
  // if (cache) process.stdout.write(cache);
146
146
  } catch (e) {
147
147
  // if (cache) process.stdout.write(cache);
148
- console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
148
+ let out = e;
149
+ if (!process.argv.includes('-i') && Object.getPrototypeOf(e).message != null) out = `${e.constructor.name}${e.message != null ? `: ${e.message}` : ''}`;
150
+ console.error(out);
149
151
  }
150
152
 
151
153
  if (process.argv.includes('-t')) console.log(`${process.argv.includes('-b') ? '' : '\n\n'}total time: ${(performance.now() - start).toFixed(2)}ms\nexecution time: ${(performance.now() - runStart).toFixed(2)}ms`);
package/runner/profile.js CHANGED
@@ -20,7 +20,7 @@ let spin = 0;
20
20
  let last = 0;
21
21
 
22
22
  try {
23
- const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
23
+ const { exports } = compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
24
24
  y: n => {
25
25
  tmp[n] = performance.now();
26
26
  },
package/runner/repl.js CHANGED
@@ -40,10 +40,9 @@ let lastMemory, lastPages;
40
40
  const PageSize = 65536;
41
41
  const memoryToString = mem => {
42
42
  let out = '';
43
- const pages = lastPages.length;
44
43
  const wasmPages = mem.buffer.byteLength / PageSize;
45
44
 
46
- out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KB\x1B[0m for ${pages} thing${pages === 1 ? '' : 's'} using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}\n\n`;
45
+ out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KiB\x1B[0m (using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'})\n\n`;
47
46
 
48
47
  const buf = new Uint8Array(mem.buffer);
49
48
 
@@ -55,10 +54,16 @@ const memoryToString = mem => {
55
54
  }
56
55
 
57
56
  out += `\x1B[0m\x1B[1m name${' '.repeat(longestName - 4)} \x1B[0m\x1B[90m│\x1B[0m\x1B[1m type${' '.repeat(longestType - 4)} \x1B[0m\x1B[90m│\x1B[0m\x1B[1m memory\x1B[0m\n`; // ─
58
- for (let i = 0; i < pages; i++) {
59
- const [ type, name ] = lastPages[i].split(': ');
60
- // out += `\x1B[36m${lastPages[i].replace(':', '\x1B[90m:\x1B[34m')}\x1B[90m${' '.repeat(longestName - lastPages[i].length)} | \x1B[0m`;
61
- out += ` \x1B[34m${name}${' '.repeat(longestName - name.length)} \x1B[90m│\x1B[0m \x1B[36m${type}${' '.repeat(longestType - type.length)} \x1B[90m│\x1B[0m `;
57
+ for (let i = 0; i < wasmPages; i++) {
58
+ if (lastPages[i]) {
59
+ const [ type, name ] = lastPages[i].split(': ');
60
+ // out += `\x1B[36m${lastPages[i].replace(':', '\x1B[90m:\x1B[34m')}\x1B[90m${' '.repeat(longestName - lastPages[i].length)} | \x1B[0m`;
61
+ out += ` \x1B[34m${name}${' '.repeat(longestName - name.length)} \x1B[90m│\x1B[0m \x1B[36m${type}${' '.repeat(longestType - type.length)} \x1B[90m│\x1B[0m `;
62
+ } else {
63
+ const type = '???';
64
+ const name = '???';
65
+ out += ` \x1B[34m${name}${' '.repeat(longestName - name.length)} \x1B[90m│\x1B[0m \x1B[36m${type}${' '.repeat(longestType - type.length)} \x1B[90m│\x1B[0m `;
66
+ }
62
67
 
63
68
  for (let j = 0; j < 40; j++) {
64
69
  const val = buf[i * pageSize + j];
@@ -75,13 +80,13 @@ const memoryToString = mem => {
75
80
  };
76
81
 
77
82
  let prev = '';
78
- const run = async (source, _context, _filename, callback, run = true) => {
83
+ const run = (source, _context, _filename, callback, run = true) => {
79
84
  // hack: print "secret" before latest code ran to only enable printing for new code
80
85
 
81
86
  let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source.trim();
82
87
 
83
88
  let shouldPrint = !prev;
84
- const { exports, pages } = await compile(toRun, [], {}, str => {
89
+ const { exports, pages } = compile(toRun, [], {}, str => {
85
90
  if (shouldPrint) process.stdout.write(str);
86
91
  if (str === '-4919') shouldPrint = true;
87
92
  });
@@ -122,12 +127,12 @@ replServer.defineCommand('memory', {
122
127
  });
123
128
  replServer.defineCommand('asm', {
124
129
  help: 'Log Wasm decompiled bytecode',
125
- async action() {
130
+ action() {
126
131
  this.clearBufferedCommand();
127
132
 
128
133
  try {
129
134
  process.argv.push('--opt-funcs');
130
- await run('', null, null, () => {}, false);
135
+ run('', null, null, () => {}, false);
131
136
  process.argv.pop();
132
137
  } catch { }
133
138
 
@@ -136,7 +141,7 @@ replServer.defineCommand('asm', {
136
141
  });
137
142
  replServer.defineCommand('js', {
138
143
  help: 'Log JS being actually ran',
139
- async action() {
144
+ action() {
140
145
  this.clearBufferedCommand();
141
146
  console.log(prev);
142
147
  this.displayPrompt();