porffor 0.2.0-69d30a8 → 0.2.0-6bc63ef

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.
Files changed (50) hide show
  1. package/CONTRIBUTING.md +256 -0
  2. package/README.md +64 -44
  3. package/asur/index.js +2 -2
  4. package/byg/index.js +3 -24
  5. package/compiler/2c.js +2 -53
  6. package/compiler/assemble.js +6 -7
  7. package/compiler/builtins/annexb_string.js +12 -12
  8. package/compiler/builtins/annexb_string.ts +5 -6
  9. package/compiler/builtins/array.ts +15 -15
  10. package/compiler/builtins/base64.ts +4 -79
  11. package/compiler/builtins/boolean.ts +18 -0
  12. package/compiler/builtins/crypto.ts +1 -1
  13. package/compiler/builtins/date.ts +2067 -0
  14. package/compiler/builtins/escape.ts +2 -2
  15. package/compiler/builtins/function.ts +5 -0
  16. package/compiler/builtins/int.ts +2 -4
  17. package/compiler/builtins/number.ts +11 -9
  18. package/compiler/builtins/object.ts +4 -0
  19. package/compiler/builtins/porffor.d.ts +28 -10
  20. package/compiler/builtins/set.ts +187 -0
  21. package/compiler/builtins/string.ts +47 -22
  22. package/compiler/builtins.js +19 -36
  23. package/compiler/codegen.js +239 -199
  24. package/compiler/decompile.js +2 -3
  25. package/compiler/embedding.js +2 -2
  26. package/compiler/encoding.js +0 -14
  27. package/compiler/expression.js +1 -1
  28. package/compiler/generated_builtins.js +1138 -208
  29. package/compiler/index.js +0 -2
  30. package/compiler/opt.js +7 -7
  31. package/compiler/parse.js +5 -5
  32. package/compiler/precompile.js +21 -24
  33. package/compiler/prefs.js +6 -5
  34. package/compiler/prototype.js +19 -19
  35. package/compiler/types.js +3 -2
  36. package/compiler/wasmSpec.js +1 -0
  37. package/compiler/wrap.js +70 -54
  38. package/package.json +1 -1
  39. package/rhemyn/compile.js +42 -25
  40. package/rhemyn/parse.js +4 -5
  41. package/runner/compare.js +0 -1
  42. package/runner/debug.js +1 -6
  43. package/runner/index.js +45 -4
  44. package/runner/profiler.js +15 -42
  45. package/runner/repl.js +3 -9
  46. package/runner/sizes.js +2 -2
  47. package/runner/version.js +3 -3
  48. package/.vscode/launch.json +0 -18
  49. package/compiler/builtins/tostring.ts +0 -45
  50. package/test262_changes_from_1afe9b87d2_to_04-09.md +0 -270
package/compiler/2c.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
2
2
  import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
3
3
  import { operatorOpcode } from './expression.js';
4
- import { log } from "./log.js";
4
+ import { log } from './log.js';
5
5
 
6
6
  const CValtype = {
7
7
  i8: 'i8',
@@ -106,17 +106,6 @@ for (const x in CValtype) {
106
106
  if (Valtype[x]) CValtype[Valtype[x]] = CValtype[x];
107
107
  }
108
108
 
109
- const todo = msg => {
110
- class TodoError extends Error {
111
- constructor(message) {
112
- super(message);
113
- this.name = 'TodoError';
114
- }
115
- }
116
-
117
- throw new TodoError(msg);
118
- };
119
-
120
109
  const removeBrackets = str => {
121
110
  // return str;
122
111
  // if (str.startsWith(`(${CValtype.i32})(${CValtype.u32})`)) return `(${CValtype.i32})(${CValtype.u32})(` + removeBrackets(str.slice(22, -1)) + ')';
@@ -167,11 +156,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
167
156
  prependMain.set('_data', data.map(x => `memcpy(_memory + ${x.offset}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n'));
168
157
  }
169
158
 
170
- // for (const [ x, p ] of pages) {
171
- // out += `${CValtype[p.type]} ${x.replace(': ', '_').replace(/[^0-9a-zA-Z_]/g, '')}[100]`;
172
- // out += ';\n';
173
- // }
174
-
175
159
  if (out) out += '\n';
176
160
 
177
161
  let depth = 1;
@@ -213,9 +197,9 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
213
197
 
214
198
  for (const f of funcs) {
215
199
  depth = 1;
200
+ brDepth = 0;
216
201
 
217
202
  const invLocals = inv(f.locals, x => x.idx);
218
- // if (f.returns.length > 1) todo('funcs returning >1 value unsupported');
219
203
 
220
204
  for (const x in invLocals) {
221
205
  invLocals[x] = sanitize(invLocals[x]);
@@ -247,12 +231,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
247
231
  const brs = [];
248
232
  let lastCond = false;
249
233
 
250
- // let brDepth = 0;
251
-
252
234
  const blockStart = (i, loop) => {
253
- // reset "stack"
254
- // vals = [];
255
-
256
235
  rets.push(i[1]);
257
236
 
258
237
  const br = brId++;
@@ -269,25 +248,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
269
248
  brDepth++;
270
249
  };
271
250
 
272
- const highlight = i => {
273
- const surrounding = 6;
274
-
275
- const decomp = decompile(f.wasm.slice(i - surrounding, i + surrounding + 1), '', 0, f.locals, f.params, f.returns, funcs, globals, exceptions).slice(0, -1).split('\n');
276
-
277
- const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
278
- let longest = 0;
279
- for (let j = 0; j < decomp.length; j++) {
280
- longest = Math.max(longest, noAnsi(decomp[j]).length);
281
- }
282
-
283
- const middle = Math.floor(decomp.length / 2);
284
- decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
285
-
286
- console.log('\x1B[90m...\x1B[0m');
287
- console.log(decomp.join('\n'));
288
- console.log('\x1B[90m...\x1B[0m\n');
289
- };
290
-
291
251
  for (let _ = 0; _ < f.wasm.length; _++) {
292
252
  const i = f.wasm[_];
293
253
  if (!i || !i[0]) continue;
@@ -415,8 +375,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
415
375
  const br = brs.at(-1);
416
376
  const ret = rets.at(-1);
417
377
  if (ret && ret !== Blocktype.void) {
418
- // console.log(vals, ret);
419
- // console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
420
378
  if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
421
379
  // vals.push(`_r${br}`);
422
380
  }
@@ -425,8 +383,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
425
383
  line(`} else {`, false);
426
384
  depth++;
427
385
 
428
- // reset "stack"
429
- // vals = [];
430
386
  break;
431
387
  }
432
388
 
@@ -441,8 +397,6 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
441
397
  const br = brs.pop();
442
398
  const ret = rets.pop();
443
399
  if (ret && ret !== Blocktype.void) {
444
- // console.log(vals, ret);
445
- // console.log(decompile(f.wasm.slice(_ - 5, _ + 1)));
446
400
  if (vals.length > 0) line(`_r${br} = ${removeBrackets(vals.pop())}`);
447
401
  vals.push(`_r${br}`);
448
402
  }
@@ -541,18 +495,14 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
541
495
 
542
496
  case Opcodes.br: {
543
497
  const ret = rets[brDepth - i[1] - 1];
544
- // console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
545
498
  if (ret !== Blocktype.void) line(`_r${brs[brDepth - i[1] - 1]} = ${removeBrackets(vals.pop())}`);
546
499
  line(`goto j${brs[brDepth - i[1] - 1]}`);
547
500
 
548
- // // reset "stack"
549
- // vals = [];
550
501
  break;
551
502
  }
552
503
 
553
504
  case Opcodes.br_if: {
554
505
  const ret = rets[brDepth - i[1] - 1];
555
- // console.log(rets, brDepth, i[1], brDepth - i[1] - 1, ret, vals);
556
506
 
557
507
  let cond = removeBrackets(vals.pop());
558
508
  if (!lastCond) {
@@ -602,7 +552,6 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
602
552
  }
603
553
 
604
554
  log.warning('2c', `unimplemented op: ${invOpcodes[i[0]]}`);
605
- // todo(`unimplemented op: ${invOpcodes[i[0]]}`);
606
555
  }
607
556
 
608
557
  lastCond = false;
@@ -1,8 +1,7 @@
1
- import { Valtype, FuncType, Empty, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize } from './wasmSpec.js';
2
- import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, ieee754_binary64, unsignedLEB128_into, signedLEB128_into, ieee754_binary64_into } from './encoding.js';
3
- // import { number } from './embedding.js';
1
+ import { Valtype, FuncType, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize } from './wasmSpec.js';
2
+ import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, unsignedLEB128_into, signedLEB128_into, ieee754_binary64_into } from './encoding.js';
4
3
  import { importedFuncs } from './builtins.js';
5
- import { log } from "./log.js";
4
+ import { log } from './log.js';
6
5
  import Prefs from './prefs.js';
7
6
 
8
7
  const createSection = (type, data) => [
@@ -45,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
45
44
 
46
45
  let importFuncs = [];
47
46
 
48
- if (optLevel < 1) {
47
+ if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
49
48
  importFuncs = importedFuncs;
50
49
  } else {
51
50
  let imports = new Map();
@@ -102,7 +101,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
102
101
 
103
102
  // const t0 = performance.now();
104
103
 
105
- // specially optimized assembly for globals as this version is much (>5x) faster than traditional createSection(...)
104
+ // specially optimized assembly for globals as this version is much (>5x) faster than traditional createSection()
106
105
  const globalsValues = Object.values(globals);
107
106
 
108
107
  let globalSection = [];
@@ -154,7 +153,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
154
153
 
155
154
  const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
156
155
 
157
- if (Prefs.alwaysMemory && pages.size === 0) pages.set('-always-memory', 0);
156
+ if (Prefs.alwaysMemory && pages.size === 0) pages.set('--always-memory', 0);
158
157
  if (optLevel === 0) pages.set('O0 precaution', 0);
159
158
 
160
159
  const usesMemory = pages.size > 0;
@@ -1,8 +1,8 @@
1
1
  export default () => {
2
- let out = `// @porf -funsafe-no-unlikely-proto-checks -valtype=i32
2
+ let out = `// @porf --funsafe-no-unlikely-proto-checks --valtype=i32
3
3
  `;
4
4
 
5
- const annexB_noArgs = (a0, a1) => out += `
5
+ const noArgs = (a0, a1) => out += `
6
6
  export const __String_prototype_${a0} = (_this: string) => {
7
7
  let out: string = Porffor.s\`<${a1}>\`;
8
8
 
@@ -31,7 +31,7 @@ ${[...a1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)},
31
31
 
32
32
  return out;
33
33
  };
34
- export const ___bytestring_prototype_${a0} = (_this: bytestring) => {
34
+ export const __ByteString_prototype_${a0} = (_this: bytestring) => {
35
35
  let out: bytestring = Porffor.bs\`<${a1}>\`;
36
36
 
37
37
  let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${2 + a1.length};
@@ -58,15 +58,15 @@ ${[...a1].map((x, i) => ` Porffor.wasm.i32.store8(outPtr, ${x.charCodeAt(0)}, 0
58
58
  };
59
59
  `;
60
60
 
61
- annexB_noArgs('big', 'big');
62
- annexB_noArgs('blink', 'blink');
63
- annexB_noArgs('bold', 'b');
64
- annexB_noArgs('fixed', 'tt');
65
- annexB_noArgs('italics', 'i');
66
- annexB_noArgs('small', 'small');
67
- annexB_noArgs('strike', 'strike');
68
- annexB_noArgs('sub', 'sub');
69
- annexB_noArgs('sup', 'sup');
61
+ noArgs('big', 'big');
62
+ noArgs('blink', 'blink');
63
+ noArgs('bold', 'b');
64
+ noArgs('fixed', 'tt');
65
+ noArgs('italics', 'i');
66
+ noArgs('small', 'small');
67
+ noArgs('strike', 'strike');
68
+ noArgs('sub', 'sub');
69
+ noArgs('sup', 'sup');
70
70
 
71
71
  return out;
72
72
  };
@@ -1,12 +1,11 @@
1
- // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
1
+ // @porf --valtype=i32
2
2
 
3
- // todo: trimLeft, trimRight
4
3
  export const __String_prototype_trimLeft = (_this: string) => {
5
4
  return __String_prototype_trimStart(_this);
6
5
  };
7
6
 
8
- export const ___bytestring_prototype_trimLeft = (_this: string) => {
9
- return ___bytestring_prototype_trimStart(_this);
7
+ export const __ByteString_prototype_trimLeft = (_this: string) => {
8
+ return __ByteString_prototype_trimStart(_this);
10
9
  };
11
10
 
12
11
 
@@ -14,6 +13,6 @@ export const __String_prototype_trimRight = (_this: string) => {
14
13
  return __String_prototype_trimEnd(_this);
15
14
  };
16
15
 
17
- export const ___bytestring_prototype_trimEnd = (_this: string) => {
18
- return ___bytestring_prototype_trimRight(_this);
16
+ export const __ByteString_prototype_trimRight = (_this: string) => {
17
+ return __ByteString_prototype_trimEnd(_this);
19
18
  };
@@ -1,10 +1,8 @@
1
- // @porf -funsafe-no-unlikely-proto-checks
2
-
3
1
  export const __Array_isArray = (x: unknown): boolean =>
4
- // Porffor.wasm`local.get ${x+1}` == Porffor.TYPES._array;
5
- Porffor.rawType(x) == Porffor.TYPES._array;
2
+ // Porffor.wasm`local.get ${x+1}` == Porffor.TYPES.array;
3
+ Porffor.rawType(x) == Porffor.TYPES.array;
6
4
 
7
- export const ___array_prototype_slice = (_this: any[], start: number, end: number) => {
5
+ export const __Array_prototype_slice = (_this: any[], start: number, end: number) => {
8
6
  const len: i32 = _this.length;
9
7
  if (Porffor.rawType(end) == Porffor.TYPES.undefined) end = len;
10
8
 
@@ -44,7 +42,7 @@ export const ___array_prototype_slice = (_this: any[], start: number, end: numbe
44
42
  return out;
45
43
  };
46
44
 
47
- export const ___array_prototype_indexOf = (_this: any[], searchElement: any, position: number) => {
45
+ export const __Array_prototype_indexOf = (_this: any[], searchElement: any, position: number) => {
48
46
  const len: i32 = _this.length;
49
47
  if (position > 0) {
50
48
  if (position > len) position = len;
@@ -58,7 +56,7 @@ export const ___array_prototype_indexOf = (_this: any[], searchElement: any, pos
58
56
  return -1;
59
57
  };
60
58
 
61
- export const ___array_prototype_lastIndexOf = (_this: any[], searchElement: any, position: number) => {
59
+ export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any, position: number) => {
62
60
  const len: i32 = _this.length;
63
61
  if (position > 0) {
64
62
  if (position > len) position = len;
@@ -72,7 +70,7 @@ export const ___array_prototype_lastIndexOf = (_this: any[], searchElement: any,
72
70
  return -1;
73
71
  };
74
72
 
75
- export const ___array_prototype_includes = (_this: any[], searchElement: any, position: number) => {
73
+ export const __Array_prototype_includes = (_this: any[], searchElement: any, position: number) => {
76
74
  const len: i32 = _this.length;
77
75
  if (position > 0) {
78
76
  if (position > len) position = len;
@@ -86,19 +84,17 @@ export const ___array_prototype_includes = (_this: any[], searchElement: any, po
86
84
  return false;
87
85
  };
88
86
 
89
- export const ___array_prototype_with = (_this: any[], index: number, value: any) => {
87
+ export const __Array_prototype_with = (_this: any[], index: number, value: any) => {
90
88
  const len: i32 = _this.length;
91
89
  if (index < 0) {
92
90
  index = len + index;
93
91
  if (index < 0) {
94
- // todo: throw RangeError: Invalid index
95
- return null;
92
+ throw new RangeError('Invalid index');
96
93
  }
97
94
  }
98
95
 
99
96
  if (index > len) {
100
- // todo: throw RangeError: Invalid index
101
- return null;
97
+ throw new RangeError('Invalid index');
102
98
  }
103
99
 
104
100
  // todo: allocator is bad here?
@@ -111,7 +107,7 @@ export const ___array_prototype_with = (_this: any[], index: number, value: any)
111
107
  return out;
112
108
  };
113
109
 
114
- export const ___array_prototype_reverse = (_this: any[]) => {
110
+ export const __Array_prototype_reverse = (_this: any[]) => {
115
111
  const len: i32 = _this.length;
116
112
 
117
113
  let start: i32 = 0;
@@ -127,7 +123,7 @@ export const ___array_prototype_reverse = (_this: any[]) => {
127
123
  };
128
124
 
129
125
  // todo: this has memory/allocation bugs so sometimes crashes :(
130
- export const ___array_prototype_toReversed = (_this: any[]) => {
126
+ export const __Array_prototype_toReversed = (_this: any[]) => {
131
127
  const len: i32 = _this.length;
132
128
 
133
129
  let start: i32 = 0;
@@ -142,4 +138,8 @@ export const ___array_prototype_toReversed = (_this: any[]) => {
142
138
  }
143
139
 
144
140
  return out;
141
+ };
142
+
143
+ export const __Array_prototype_valueOf = (_this: any[]) => {
144
+ return _this;
145
145
  };
@@ -1,82 +1,4 @@
1
- // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
2
-
3
- // while (len >= 8) {
4
- // Porffor.wasm`
5
- // local tmp i64
6
- // local.get ${i}
7
- // i64.load 0 4
8
- // local.set tmp
9
-
10
- // local k i64
11
- // i64.const 0
12
- // local.set k
13
-
14
- // loop 64
15
- // local.get ${j}
16
-
17
- // local.get ${keyStrPtr}
18
-
19
- // local.get tmp
20
-
21
- // ;; k * 6
22
- // i64.const 58
23
-
24
- // local.get k
25
- // i64.const 6
26
- // i64.mul
27
-
28
- // i64.sub
29
-
30
- // ;; tmp >> (58 - (k * 6))
31
- // i64.shr_u
32
-
33
- // ;; (tmp >> (58 - (k * 6))) & 0x3f
34
- // i64.const 63
35
- // i64.and
36
-
37
- // i32.wrap_i64
38
-
39
- // ;; keyStrPtr + ...
40
- // i32.add
41
-
42
- // ;; load character from keyStr
43
- // i32.load8_u 0 4
44
-
45
- // ;; store in output at j
46
- // i32.store8 0 4
47
-
48
- // local.get ${j}
49
- // i32.const 1
50
- // i32.add
51
- // local.set ${j}
52
-
53
- // local.get k
54
- // i64.const 1
55
- // i64.add
56
- // local.tee k
57
-
58
- // i64.const 8
59
- // i64.lt_s
60
- // br_if 0
61
- // end
62
-
63
- // `;
64
-
65
- // // len -= 6;
66
- // i += 6;
67
- // }
68
-
69
- // // while (k < 8) {
70
- // // Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + Porffor.wasm.i32.wrap_i64(Porffor.wasm.i64.and(
71
- // // Porffor.wasm.i64.shr_u(tmp, Porffor.wasm.i64.extend_i32_u(58 - k * 6)),
72
- // // Porffor.wasm.i64.const(0x3f)
73
- // // )), 0, 4), 0, 4);
74
- // // k += 1;
75
- // // }
76
-
77
- // i += 6;
78
- // len -= 6;
79
- // }
1
+ // @porf --valtype=i32
80
2
 
81
3
  export const btoa = (input: bytestring): bytestring => {
82
4
  const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
@@ -89,6 +11,8 @@ export const btoa = (input: bytestring): bytestring => {
89
11
  let i: i32 = Porffor.wasm`local.get ${input}`,
90
12
  j: i32 = Porffor.wasm`local.get ${output}`;
91
13
 
14
+ // todo/perf: add some per 6 char variant using bitwise magic
15
+
92
16
  const endPtr = i + len;
93
17
  while (i < endPtr) {
94
18
  const chr1: i32 = Porffor.wasm.i32.load8_u(i++, 0, 4);
@@ -116,6 +40,7 @@ export const btoa = (input: bytestring): bytestring => {
116
40
  return output;
117
41
  };
118
42
 
43
+ // todo: impl atob by converting below to "porf ts"
119
44
  /* var atob = function (input) {
120
45
  const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
121
46
 
@@ -0,0 +1,18 @@
1
+ // 20.3.3.2 Boolean.prototype.toString ()
2
+ // https://tc39.es/ecma262/#sec-boolean.prototype.tostring
3
+ export const __Boolean_prototype_toString = (_this: boolean) => {
4
+ // 1. Let b be ? ThisBooleanValue(this value).
5
+ // 2. If b is true, return "true"; else return "false".
6
+ let out: bytestring = '';
7
+ if (_this) out = 'true';
8
+ else out = 'false';
9
+
10
+ return out;
11
+ };
12
+
13
+ // 20.3.3.3 Boolean.prototype.valueOf ()
14
+ // https://tc39.es/ecma262/#sec-boolean.prototype.valueof
15
+ export const __Boolean_prototype_valueOf = (_this: boolean) => {
16
+ // 1. Return ? ThisBooleanValue(this value).
17
+ return _this;
18
+ };
@@ -1,4 +1,4 @@
1
- // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
1
+ // @porf --valtype=i32
2
2
 
3
3
  export const __crypto_randomUUID = (): bytestring => {
4
4
  let bytes: bytestring = '................';