porffor 0.2.0-c6c8c81 → 0.2.0-c87ffeb

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 (54) hide show
  1. package/.vscode/launch.json +18 -0
  2. package/LICENSE +20 -20
  3. package/README.md +131 -71
  4. package/asur/README.md +2 -0
  5. package/asur/index.js +1262 -0
  6. package/byg/index.js +237 -0
  7. package/compiler/2c.js +325 -72
  8. package/compiler/{sections.js → assemble.js} +63 -15
  9. package/compiler/builtins/annexb_string.js +72 -0
  10. package/compiler/builtins/annexb_string.ts +19 -0
  11. package/compiler/builtins/array.ts +145 -0
  12. package/compiler/builtins/base64.ts +151 -0
  13. package/compiler/builtins/crypto.ts +120 -0
  14. package/compiler/builtins/date.ts +7 -0
  15. package/compiler/builtins/escape.ts +141 -0
  16. package/compiler/builtins/int.ts +147 -0
  17. package/compiler/builtins/number.ts +527 -0
  18. package/compiler/builtins/porffor.d.ts +42 -0
  19. package/compiler/builtins/string.ts +1055 -0
  20. package/compiler/builtins/tostring.ts +45 -0
  21. package/compiler/builtins.js +601 -269
  22. package/compiler/{codeGen.js → codegen.js} +1231 -472
  23. package/compiler/decompile.js +11 -12
  24. package/compiler/embedding.js +22 -22
  25. package/compiler/encoding.js +98 -114
  26. package/compiler/generated_builtins.js +695 -0
  27. package/compiler/index.js +40 -37
  28. package/compiler/log.js +6 -3
  29. package/compiler/opt.js +65 -29
  30. package/compiler/parse.js +42 -11
  31. package/compiler/precompile.js +123 -0
  32. package/compiler/prefs.js +26 -0
  33. package/compiler/prototype.js +177 -37
  34. package/compiler/types.js +37 -0
  35. package/compiler/wasmSpec.js +30 -7
  36. package/compiler/wrap.js +141 -45
  37. package/package.json +9 -5
  38. package/porf +4 -0
  39. package/rhemyn/compile.js +5 -3
  40. package/rhemyn/parse.js +323 -320
  41. package/rhemyn/test/parse.js +58 -58
  42. package/runner/compare.js +34 -34
  43. package/runner/debug.js +122 -0
  44. package/runner/index.js +49 -10
  45. package/runner/profiler.js +102 -0
  46. package/runner/repl.js +42 -9
  47. package/runner/sizes.js +37 -37
  48. package/test262_changes_from_1afe9b87d2_to_04-09.md +270 -0
  49. package/compiler/builtins/base64.js +0 -92
  50. package/runner/info.js +0 -89
  51. package/runner/profile.js +0 -46
  52. package/runner/results.json +0 -1
  53. package/runner/transform.js +0 -15
  54. package/util/enum.js +0 -20
@@ -1,5 +1,8 @@
1
- import { Blocktype, Opcodes, Valtype } from "./wasmSpec.js";
1
+ import { Blocktype, Opcodes, Valtype, ValtypeSize } from "./wasmSpec.js";
2
2
  import { number, i32x4 } from "./embedding.js";
3
+ import Prefs from './prefs.js';
4
+ import * as GeneratedBuiltins from './generated_builtins.js';
5
+ import { TYPES } from './types.js';
3
6
 
4
7
  export const importedFuncs = [
5
8
  {
@@ -19,6 +22,24 @@ export const importedFuncs = [
19
22
  import: 't',
20
23
  params: 0,
21
24
  returns: 1
25
+ },
26
+ {
27
+ name: 'timeOrigin',
28
+ import: 'u',
29
+ params: 0,
30
+ returns: 1
31
+ },
32
+ {
33
+ name: 'profile1',
34
+ import: 'y',
35
+ params: 1,
36
+ returns: 0
37
+ },
38
+ {
39
+ name: 'profile2',
40
+ import: 'z',
41
+ params: 1,
42
+ returns: 0
22
43
  }
23
44
  ];
24
45
 
@@ -29,16 +50,31 @@ for (let i = 0; i < importedFuncs.length; i++) {
29
50
 
30
51
  const char = c => number(c.charCodeAt(0));
31
52
 
53
+ const printStaticStr = str => {
54
+ const out = [];
55
+
56
+ for (let i = 0; i < str.length; i++) {
57
+ out.push(
58
+ // ...number(str.charCodeAt(i)),
59
+ ...number(str.charCodeAt(i), Valtype.i32),
60
+ Opcodes.i32_from_u,
61
+ [ Opcodes.call, importedFuncs.printChar ]
62
+ );
63
+ }
64
+
65
+ return out;
66
+ };
67
+
32
68
  // todo: somehow diff between these (undefined != null) while remaining falsey in wasm as a number value
33
69
  export const UNDEFINED = 0;
34
70
  export const NULL = 0;
35
71
 
36
72
  export const BuiltinVars = function() {
37
73
  this.undefined = number(UNDEFINED);
38
- this.undefined.type = 'undefined';
74
+ this.undefined.type = TYPES.undefined;
39
75
 
40
76
  this.null = number(NULL);
41
- this.null.type = 'object';
77
+ this.null.type = TYPES.object;
42
78
 
43
79
  this.NaN = number(NaN);
44
80
  this.NaN.floatOnly = true;
@@ -102,6 +138,18 @@ export const BuiltinVars = function() {
102
138
 
103
139
  // stubs just so that parent objects exist
104
140
  this.Math = number(1);
141
+
142
+ // wintercg(tm)
143
+ this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.2.0`, false, '__navigator_userAgent');
144
+ this.__navigator_userAgent.type = Prefs.bytestring ? TYPES._bytestring : TYPES.string;
145
+
146
+ for (const x in TYPES) {
147
+ this['__Porffor_TYPES_' + x] = number(TYPES[x]);
148
+ }
149
+
150
+ this.__performance_timeOrigin = [
151
+ [ Opcodes.call, importedFuncs.timeOrigin ]
152
+ ];
105
153
  };
106
154
 
107
155
  export const BuiltinFuncs = function() {
@@ -155,44 +203,173 @@ export const BuiltinFuncs = function() {
155
203
  ]
156
204
  };
157
205
 
158
- // todo: return false for NaN
159
- this.Boolean = {
160
- params: [ valtypeBinary ],
161
- locals: [],
162
- returns: [ valtypeBinary ],
163
- returnType: 'boolean',
164
- wasm: [
165
- [ Opcodes.local_get, 0 ],
166
- ...(valtype === 'f64' ? [
167
- ...number(0),
168
- [ Opcodes.f64_ne ]
169
- ] : [
170
- ...Opcodes.eqz,
171
- [ Opcodes.i32_eqz ]
172
- ]),
173
- Opcodes.i32_from
174
- ]
175
- };
176
-
177
206
  // just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
178
207
  this.Object = {
179
208
  params: [ valtypeBinary ],
180
209
  locals: [],
181
210
  returns: [ valtypeBinary ],
182
- returnType: 'object',
211
+ returnType: TYPES.object,
183
212
  wasm: [
184
- [ Opcodes.local_get, 0 ]
213
+ // [ Opcodes.local_get, 0 ]
214
+ ...number(1)
185
215
  ]
186
216
  };
187
217
 
188
218
 
189
219
  this.__console_log = {
190
- params: [ valtypeBinary ],
191
- locals: [],
220
+ params: [ valtypeBinary, Valtype.i32 ],
221
+ typedParams: true,
222
+ locals: [ Valtype.i32, Valtype.i32 ],
192
223
  returns: [],
193
- wasm: [
194
- [ Opcodes.local_get, 0 ],
195
- [ Opcodes.call, importedFuncs.print ],
224
+ wasm: (scope, { typeSwitch }) => [
225
+ ...typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], {
226
+ [TYPES.number]: [
227
+ [ Opcodes.local_get, 0 ],
228
+ [ Opcodes.call, importedFuncs.print ],
229
+ ],
230
+ [TYPES.boolean]: [
231
+ [ Opcodes.local_get, 0 ],
232
+ Opcodes.i32_to_u,
233
+ [ Opcodes.if, Blocktype.void ],
234
+ ...printStaticStr('true'),
235
+ [ Opcodes.else ],
236
+ ...printStaticStr('false'),
237
+ [ Opcodes.end ]
238
+ ],
239
+ [TYPES.string]: [
240
+ // simply print a string :))
241
+ // cache input pointer as i32
242
+ [ Opcodes.local_get, 0 ],
243
+ Opcodes.i32_to_u,
244
+ [ Opcodes.local_tee, 2 ],
245
+
246
+ // make end pointer
247
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
248
+ ...number(ValtypeSize.i16, Valtype.i32),
249
+ [ Opcodes.i32_mul ],
250
+
251
+ [ Opcodes.local_get, 2 ],
252
+ [ Opcodes.i32_add ],
253
+ [ Opcodes.local_set, 3 ],
254
+
255
+ [ Opcodes.loop, Blocktype.void ],
256
+
257
+ // print current char
258
+ [ Opcodes.local_get, 2 ],
259
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
260
+ Opcodes.i32_from_u,
261
+ [ Opcodes.call, importedFuncs.printChar ],
262
+
263
+ // increment pointer by sizeof i16
264
+ [ Opcodes.local_get, 2 ],
265
+ ...number(ValtypeSize.i16, Valtype.i32),
266
+ [ Opcodes.i32_add ],
267
+ [ Opcodes.local_tee, 2 ],
268
+
269
+ // if pointer != end pointer, loop
270
+ [ Opcodes.local_get, 3 ],
271
+ [ Opcodes.i32_ne ],
272
+ [ Opcodes.br_if, 0 ],
273
+
274
+ [ Opcodes.end ]
275
+ ],
276
+ [TYPES._bytestring]: [
277
+ // simply print a (byte)string :))
278
+ // cache input pointer as i32
279
+ [ Opcodes.local_get, 0 ],
280
+ Opcodes.i32_to_u,
281
+ [ Opcodes.local_tee, 2 ],
282
+
283
+ // make end pointer
284
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
285
+ [ Opcodes.local_get, 2 ],
286
+ [ Opcodes.i32_add ],
287
+ [ Opcodes.local_set, 3 ],
288
+
289
+ [ Opcodes.loop, Blocktype.void ],
290
+
291
+ // print current char
292
+ [ Opcodes.local_get, 2 ],
293
+ [ Opcodes.i32_load8_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
294
+ Opcodes.i32_from_u,
295
+ [ Opcodes.call, importedFuncs.printChar ],
296
+
297
+ // increment pointer
298
+ [ Opcodes.local_get, 2 ],
299
+ [ Opcodes.i32_const, 1 ],
300
+ [ Opcodes.i32_add ],
301
+ [ Opcodes.local_tee, 2 ],
302
+
303
+ // if pointer != end pointer, loop
304
+ [ Opcodes.local_get, 3 ],
305
+ [ Opcodes.i32_ne ],
306
+ [ Opcodes.br_if, 0 ],
307
+
308
+ [ Opcodes.end ]
309
+ ],
310
+ [TYPES._array]: [
311
+ ...printStaticStr('[ '),
312
+
313
+ // cache input pointer as i32
314
+ [ Opcodes.local_get, 0 ],
315
+ Opcodes.i32_to_u,
316
+ [ Opcodes.local_tee, 2 ],
317
+
318
+ // make end pointer
319
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
320
+ ...number(ValtypeSize[valtype], Valtype.i32),
321
+ [ Opcodes.i32_mul ],
322
+
323
+ [ Opcodes.local_get, 2 ],
324
+ [ Opcodes.i32_add ],
325
+ [ Opcodes.local_set, 3 ],
326
+
327
+ [ Opcodes.loop, Blocktype.void ],
328
+
329
+ // print current char
330
+ [ Opcodes.local_get, 2 ],
331
+ [ Opcodes.load, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
332
+ [ Opcodes.call, importedFuncs.print ],
333
+
334
+ // increment pointer by sizeof valtype
335
+ [ Opcodes.local_get, 2 ],
336
+ ...number(ValtypeSize[valtype], Valtype.i32),
337
+ [ Opcodes.i32_add ],
338
+ [ Opcodes.local_tee, 2 ],
339
+
340
+ // if pointer != end pointer, print separator and loop
341
+ [ Opcodes.local_get, 3 ],
342
+ [ Opcodes.i32_ne ],
343
+ [ Opcodes.if, Blocktype.void ],
344
+ ...printStaticStr(', '),
345
+ [ Opcodes.br, 1 ],
346
+ [ Opcodes.end ],
347
+
348
+ [ Opcodes.end ],
349
+
350
+ ...printStaticStr(' ]'),
351
+ ],
352
+ [TYPES.undefined]: [
353
+ ...printStaticStr('undefined')
354
+ ],
355
+ [TYPES.function]: [
356
+ ...printStaticStr('function () {}')
357
+ ],
358
+ [TYPES.object]: [
359
+ [ Opcodes.local_get, 0 ],
360
+ Opcodes.i32_to_u,
361
+ [ Opcodes.if, Blocktype.void ],
362
+ ...printStaticStr('{}'),
363
+ [ Opcodes.else ],
364
+ ...printStaticStr('null'),
365
+ [ Opcodes.end ]
366
+ ],
367
+ default: [
368
+ [ Opcodes.local_get, 0 ],
369
+ [ Opcodes.call, importedFuncs.print ],
370
+ ]
371
+ }, Blocktype.void),
372
+
196
373
  ...char('\n'),
197
374
  [ Opcodes.call, importedFuncs.printChar ]
198
375
  ]
@@ -206,7 +383,7 @@ export const BuiltinFuncs = function() {
206
383
  params: [ valtypeBinary ],
207
384
  locals: [],
208
385
  returns: [ valtypeBinary ],
209
- returnType: 'boolean',
386
+ returnType: TYPES.boolean,
210
387
  wasm: [
211
388
  [ Opcodes.local_get, 0 ],
212
389
  [ Opcodes.local_get, 0 ],
@@ -221,7 +398,7 @@ export const BuiltinFuncs = function() {
221
398
  params: [ valtypeBinary ],
222
399
  locals: [ valtypeBinary ],
223
400
  returns: [ valtypeBinary ],
224
- returnType: 'boolean',
401
+ returnType: TYPES.boolean,
225
402
  wasm: [
226
403
  [ Opcodes.local_get, 0 ],
227
404
  [ Opcodes.local_get, 0 ],
@@ -240,7 +417,7 @@ export const BuiltinFuncs = function() {
240
417
  params: [ valtypeBinary ],
241
418
  locals: [],
242
419
  returns: [ valtypeBinary ],
243
- returnType: 'boolean',
420
+ returnType: TYPES.boolean,
244
421
  wasm: [
245
422
  [ Opcodes.local_get, 0 ],
246
423
  [ Opcodes.local_get, 0 ],
@@ -255,7 +432,7 @@ export const BuiltinFuncs = function() {
255
432
  params: [ valtypeBinary ],
256
433
  locals: [],
257
434
  returns: [ valtypeBinary ],
258
- returnType: 'boolean',
435
+ returnType: TYPES.boolean,
259
436
  wasm: [
260
437
  [ Opcodes.local_get, 0 ],
261
438
  [ Opcodes.local_get, 0 ],
@@ -395,61 +572,314 @@ export const BuiltinFuncs = function() {
395
572
 
396
573
  // this is an implementation of xorshift128+ (in wasm bytecode)
397
574
  // fun fact: v8, SM, JSC also use this (you will need this fun fact to maintain your sanity reading this code)
398
- const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
575
+ // const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
576
+ const prngSeed0 = (Math.random() * (2 ** 30)) | 0, prngSeed1 = (Math.random() * (2 ** 30)) | 0;
577
+
578
+ const prng = ({
579
+ 'lcg32_glibc': {
580
+ globals: [ Valtype.i32 ],
581
+ locals: [],
582
+ returns: Valtype.i32,
583
+ wasm: [
584
+ // seed = (MULTIPLIER * seed + INCREMENT) % MODULUS
585
+ // MULTIPLIER * state0
586
+ [ Opcodes.global_get, 0 ],
587
+ ...number(1103515245, Valtype.i32),
588
+ [ Opcodes.i32_mul ],
589
+
590
+ // + INCREMENT
591
+ ...number(12345, Valtype.i32),
592
+ [ Opcodes.i32_add ],
593
+
594
+ // % MODULUS
595
+ ...number(2 ** 31, Valtype.i32),
596
+ [ Opcodes.i32_rem_s ],
597
+
598
+ // state0 =
599
+ [ Opcodes.global_set, 0 ],
600
+
601
+ // state0
602
+ [ Opcodes.global_get, 0 ],
603
+ ],
604
+ },
605
+ 'lcg32_minstd': {
606
+ globals: [ Valtype.i32 ],
607
+ locals: [],
608
+ returns: Valtype.i32,
609
+ wasm: [
610
+ // seed = (MULTIPLIER * seed + INCREMENT) % MODULUS
611
+ // MULTIPLIER * state0
612
+ [ Opcodes.global_get, 0 ],
613
+ ...number(48271, Valtype.i32),
614
+ [ Opcodes.i32_mul ],
615
+
616
+ // % MODULUS
617
+ ...number((2 ** 31) - 1, Valtype.i32),
618
+ [ Opcodes.i32_rem_s ],
619
+
620
+ // state0 =
621
+ [ Opcodes.global_set, 0 ],
622
+
623
+ // state0
624
+ [ Opcodes.global_get, 0 ],
625
+ ],
626
+ },
627
+ 'lcg64_musl': 0, // todo
628
+
629
+ 'xorshift32+': {
630
+ globals: [ Valtype.i32 ],
631
+ locals: [ Valtype.i32 ],
632
+ returns: Valtype.i32,
633
+ wasm: [
634
+ // setup: s1 = state0
635
+ [ Opcodes.global_get, 0 ], // state0
636
+ [ Opcodes.local_tee, 0 ], // s1
637
+
638
+ // s1 ^= s1 << 13
639
+ [ Opcodes.local_get, 0 ], // s1
640
+ [ Opcodes.i32_const, 13 ],
641
+ [ Opcodes.i32_shl ], // <<
642
+ [ Opcodes.i32_xor ], // ^
643
+ [ Opcodes.local_tee, 0 ], // s1
644
+
645
+ // s1 ^= s1 >> 17
646
+ [ Opcodes.local_get, 0 ], // s1
647
+ [ Opcodes.i32_const, 17 ],
648
+ [ Opcodes.i32_shr_s ], // >>
649
+ [ Opcodes.i32_xor ], // ^
650
+ [ Opcodes.local_tee, 0 ], // s1
651
+
652
+ // s1 ^= s1 << 5
653
+ [ Opcodes.local_get, 0 ], // s1
654
+ [ Opcodes.i32_const, 5 ],
655
+ [ Opcodes.i32_shl ], // <<
656
+ [ Opcodes.i32_xor ], // ^
657
+ [ Opcodes.local_tee, 0 ], // s1
658
+
659
+ // state0 = s1
660
+ [ Opcodes.global_set, 0 ],
661
+
662
+ // s1
663
+ [ Opcodes.local_get, 0 ],
664
+ ],
665
+ },
666
+
667
+ 'xorshift64+': {
668
+ globals: [ Valtype.i64 ],
669
+ locals: [ Valtype.i64 ],
670
+ returns: Valtype.i64,
671
+ wasm: [
672
+ // setup: s1 = state0
673
+ [ Opcodes.global_get, 0 ], // state0
674
+ [ Opcodes.local_tee, 0 ], // s1
675
+
676
+ // s1 ^= s1 >> 12
677
+ [ Opcodes.local_get, 0 ], // s1
678
+ [ Opcodes.i64_const, 12 ],
679
+ [ Opcodes.i64_shr_s ], // >>
680
+ [ Opcodes.i64_xor ], // ^
681
+ [ Opcodes.local_tee, 0 ], // s1
682
+
683
+ // s1 ^= s1 << 25
684
+ [ Opcodes.local_get, 0 ], // s1
685
+ [ Opcodes.i64_const, 25 ],
686
+ [ Opcodes.i64_shl ], // <<
687
+ [ Opcodes.i64_xor ], // ^
688
+ [ Opcodes.local_tee, 0 ], // s1
689
+
690
+ // s1 ^= s1 >> 27
691
+ [ Opcodes.local_get, 0 ], // s1
692
+ [ Opcodes.i64_const, 27 ],
693
+ [ Opcodes.i64_shr_s ], // >>
694
+ [ Opcodes.i64_xor ], // ^
695
+ [ Opcodes.local_tee, 0 ], // s1
696
+
697
+ // state0 = s1
698
+ [ Opcodes.global_set, 0 ],
699
+
700
+ // // s1 * 0x2545F4914F6CDD1D
701
+ // [ Opcodes.local_get, 0 ],
702
+ // [ Opcodes.i64_const, 0x9d, 0xba, 0xb3, 0xfb, 0x94, 0x92, 0xfd, 0xa2, 0x25 ],
703
+ // [ Opcodes.i64_mul ]
704
+
705
+ // s1
706
+ [ Opcodes.local_get, 0 ],
707
+ ],
708
+ },
709
+
710
+ 'xorshift128+': {
711
+ globals: [ Valtype.i64, Valtype.i64 ],
712
+ locals: [ Valtype.i64, Valtype.i64 ],
713
+ returns: Valtype.i64,
714
+ wasm: [
715
+ // setup: s1 = state0, s0 = state1, state0 = s0
716
+ [ Opcodes.global_get, 0 ], // state0
717
+ [ Opcodes.local_tee, 0 ], // s1
718
+ [ Opcodes.global_get, 1 ], // state1
719
+ [ Opcodes.local_tee, 1, ], // s0
720
+ [ Opcodes.global_set, 0 ], // state0
721
+
722
+ // s1 ^= s1 << 23
723
+ // [ Opcodes.local_get, 0 ], // s1
724
+ [ Opcodes.local_get, 0 ], // s1
725
+ [ Opcodes.i64_const, 23 ],
726
+ [ Opcodes.i64_shl ], // <<
727
+ [ Opcodes.i64_xor ], // ^
728
+ [ Opcodes.local_set, 0 ], // s1
729
+
730
+ // state1 = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26)
731
+ // s1 ^ s0
732
+ [ Opcodes.local_get, 0 ], // s1
733
+ [ Opcodes.local_get, 1 ], // s0
734
+ [ Opcodes.i64_xor ], // ^
735
+
736
+ // ^ (s1 >> 17)
737
+ [ Opcodes.local_get, 0 ], // s1
738
+ [ Opcodes.i64_const, 17 ],
739
+ [ Opcodes.i64_shr_u ], // >>
740
+ [ Opcodes.i64_xor ], // ^
741
+
742
+ // ^ (s0 >> 26)
743
+ [ Opcodes.local_get, 1 ], // s0
744
+ [ Opcodes.i64_const, 26 ],
745
+ [ Opcodes.i64_shr_u ], // >>
746
+ [ Opcodes.i64_xor ], // ^
747
+
748
+ // state1 =
749
+ [ Opcodes.global_set, 1 ],
750
+
751
+ // state1 + s0
752
+ [ Opcodes.global_get, 1 ], // state1
753
+ [ Opcodes.local_get, 1 ], // s0
754
+ [ Opcodes.i64_add ]
755
+ ]
756
+ },
757
+
758
+ 'xoroshiro128+': {
759
+ globals: [ Valtype.i64, Valtype.i64 ],
760
+ locals: [ Valtype.i64, Valtype.i64, Valtype.i64 ],
761
+ returns: Valtype.i64,
762
+ wasm: [
763
+ // setup: s1 = state1, s0 = state0
764
+ [ Opcodes.global_get, 1 ], // state0
765
+ [ Opcodes.local_tee, 0 ], // s1
766
+ [ Opcodes.global_get, 0 ], // state1
767
+ [ Opcodes.local_tee, 1, ], // s0
768
+
769
+ // result = s0 + s1
770
+ [ Opcodes.i64_add ],
771
+ [ Opcodes.local_set, 2 ], // result
772
+
773
+ // s1 ^= s0
774
+ [ Opcodes.local_get, 0 ], // s1
775
+ [ Opcodes.local_get, 1 ], // s0
776
+ [ Opcodes.i64_xor ],
777
+ [ Opcodes.local_set, 0 ], // s1
778
+
779
+ // state0 = rotl(s0, 24) ^ s1 ^ (s1 << 16)
780
+
781
+ // rotl(s0, 24) ^ s1
782
+ [ Opcodes.local_get, 1 ], // s0
783
+ ...number(24, Valtype.i64),
784
+ [ Opcodes.i64_rotl ],
785
+ [ Opcodes.local_get, 0 ], // s1
786
+ [ Opcodes.i64_xor ],
787
+
788
+ // ^ (s1 << 16)
789
+ [ Opcodes.local_get, 0 ], // s1
790
+ ...number(16, Valtype.i64),
791
+ [ Opcodes.i64_shl ],
792
+ [ Opcodes.i64_xor ],
793
+
794
+ // state0 =
795
+ [ Opcodes.global_set, 0 ], // state0
796
+
797
+ // state1 = rotl(s1, 37)
798
+ [ Opcodes.local_get, 0 ], // s1
799
+ ...number(37, Valtype.i64),
800
+ [ Opcodes.i64_rotl ],
801
+ [ Opcodes.global_set, 1 ], // state1
802
+
803
+ // result
804
+ [ Opcodes.local_get, 2 ],
805
+ ]
806
+ },
807
+
808
+ 'xoshiro128+': {
809
+ globals: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32 ],
810
+ locals: [ Valtype.i32, Valtype.i32 ],
811
+ returns: Valtype.i32,
812
+ wasm: [
813
+ // result = state0 + state3
814
+ [ Opcodes.global_get, 0 ], // state0
815
+ [ Opcodes.global_get, 3 ], // state0
816
+ [ Opcodes.i32_add ],
817
+ [ Opcodes.local_set, 0 ], // result
818
+
819
+ // t = state1 << 9
820
+ [ Opcodes.global_get, 1 ], // state1
821
+ ...number(9, Valtype.i32),
822
+ [ Opcodes.i32_shl ],
823
+ [ Opcodes.local_set, 1 ], // t
824
+
825
+ // state2 ^= state0
826
+ [ Opcodes.global_get, 2 ], // state2
827
+ [ Opcodes.global_get, 0 ], // state0
828
+ [ Opcodes.i32_xor ],
829
+ [ Opcodes.global_set, 2 ], // state2
830
+
831
+ // state3 ^= state1
832
+ [ Opcodes.global_get, 3 ], // state3
833
+ [ Opcodes.global_get, 1 ], // state1
834
+ [ Opcodes.i32_xor ],
835
+ [ Opcodes.global_set, 3 ], // state3
836
+
837
+ // state1 ^= state2
838
+ [ Opcodes.global_get, 1 ], // state1
839
+ [ Opcodes.global_get, 2 ], // state2
840
+ [ Opcodes.i32_xor ],
841
+ [ Opcodes.global_set, 1 ], // state1
842
+
843
+ // state0 ^= state3
844
+ [ Opcodes.global_get, 0 ], // state2
845
+ [ Opcodes.global_get, 3 ], // state0
846
+ [ Opcodes.i32_xor ],
847
+ [ Opcodes.global_set, 0 ], // state2
848
+
849
+ // state2 ^= t
850
+ [ Opcodes.global_get, 2 ], // state2
851
+ [ Opcodes.local_get, 1 ], // t
852
+ [ Opcodes.i32_xor ],
853
+ [ Opcodes.global_set, 2 ], // state2
854
+
855
+ // state3 = rotl(state3, 11)
856
+ [ Opcodes.global_get, 3 ], // state3
857
+ ...number(11, Valtype.i32),
858
+ [ Opcodes.i32_rotl ],
859
+ [ Opcodes.global_set, 3 ], // state3
860
+
861
+ // result
862
+ [ Opcodes.local_get, 0 ],
863
+ ]
864
+ }
865
+ })[Prefs.prng ?? 'xorshift128+'];
866
+
867
+ if (!prng) throw new Error(`unknown prng algo: ${Prefs.prng}`);
399
868
 
400
869
  this.__Math_random = {
401
870
  floatOnly: true,
402
871
  params: [],
403
- locals: [ Valtype.i64, Valtype.i64 ],
872
+ locals: prng.locals,
404
873
  localNames: [ 's1', 's0' ],
405
- globals: [ Valtype.i64, Valtype.i64 ],
874
+ globals: prng.globals,
406
875
  globalNames: [ 'state0', 'state1' ],
407
876
  globalInits: [ prngSeed0, prngSeed1 ],
408
877
  returns: [ Valtype.f64 ],
409
878
  wasm: [
410
- // setup: s1 = state0, s0 = state1, state0 = s0
411
- [ Opcodes.global_get, 0 ], // state0
412
- [ Opcodes.local_tee, 0 ], // s1
413
- [ Opcodes.global_get, 1 ], // state1
414
- [ Opcodes.local_tee, 1, ], // s0
415
- [ Opcodes.global_set, 0 ], // state0
416
-
417
- // s1 ^= s1 << 23
418
- // [ Opcodes.local_get, 0 ], // s1
419
- [ Opcodes.local_get, 0 ], // s1
420
- [ Opcodes.i64_const, 23 ],
421
- [ Opcodes.i64_shl ], // <<
422
- [ Opcodes.i64_xor ], // ^
423
- [ Opcodes.local_set, 0 ], // s1
424
-
425
- // state1 = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26)
426
- // s1 ^ s0
427
- [ Opcodes.local_get, 0 ], // s1
428
- [ Opcodes.local_get, 1 ], // s0
429
- [ Opcodes.i64_xor ], // ^
430
-
431
- // ^ (s1 >> 17)
432
- [ Opcodes.local_get, 0 ], // s1
433
- [ Opcodes.i64_const, 17 ],
434
- [ Opcodes.i64_shr_u ], // >>
435
- [ Opcodes.i64_xor ], // ^
436
-
437
- // ^ (s0 >> 26)
438
- [ Opcodes.local_get, 1 ], // s0
439
- [ Opcodes.i64_const, 26 ],
440
- [ Opcodes.i64_shr_u ], // >>
441
- [ Opcodes.i64_xor ], // ^
442
-
443
- // state1 =
444
- [ Opcodes.global_set, 1 ],
879
+ ...prng.wasm,
445
880
 
446
881
  // you thought it was over? now we need the result as a f64 between 0-1 :)
447
882
 
448
- // state1 + s0
449
- [ Opcodes.global_get, 1 ], // state1
450
- [ Opcodes.local_get, 1 ], // s0
451
- [ Opcodes.i64_add ],
452
-
453
883
  // should we >> 12 here?
454
884
  // it feels like it but it breaks values
455
885
 
@@ -464,15 +894,72 @@ export const BuiltinFuncs = function() {
464
894
  // ...number(1),
465
895
  // [ Opcodes.f64_sub ],
466
896
 
467
- ...number((1 << 53) - 1, Valtype.i64),
468
- [ Opcodes.i64_and ],
897
+ ...(prng.returns === Valtype.i64 ? [
898
+ ...number((1 << 53) - 1, Valtype.i64),
899
+ [ Opcodes.i64_and ],
469
900
 
470
- // double(mantissa)
471
- [ Opcodes.f64_convert_i64_u ],
901
+ // double(mantissa)
902
+ [ Opcodes.f64_convert_i64_u ],
472
903
 
473
- // / (1 << 53)
474
- ...number(1 << 53),
475
- [ Opcodes.f64_div ]
904
+ // / (1 << 53)
905
+ ...number(1 << 53),
906
+ [ Opcodes.f64_div ]
907
+ ] : [
908
+ ...number((1 << 21) - 1, Valtype.i32),
909
+ [ Opcodes.i32_and ],
910
+
911
+ // double(mantissa)
912
+ [ Opcodes.f64_convert_i32_u ],
913
+
914
+ // / (1 << 21)
915
+ ...number(1 << 21),
916
+ [ Opcodes.f64_div ]
917
+ ])
918
+ ]
919
+ };
920
+
921
+ // this.__Porffor_randomInt = {
922
+ // params: [],
923
+ // locals: prng.locals,
924
+ // localNames: [ 's1', 's0' ],
925
+ // globals: prng.globals,
926
+ // globalNames: [ 'state0', 'state1' ],
927
+ // globalInits: [ prngSeed0, prngSeed1 ],
928
+ // returns: [ Valtype.i32 ],
929
+ // wasm: [
930
+ // ...prng.wasm,
931
+
932
+ // ...(prng.returns === Valtype.i64 ? [
933
+ // // the lowest bits of the output generated by xorshift128+ have low quality
934
+ // ...number(56, Valtype.i64),
935
+ // [ Opcodes.i64_shr_u ],
936
+
937
+ // [ Opcodes.i32_wrap_i64 ],
938
+ // ] : []),
939
+ // ]
940
+ // };
941
+
942
+ this.__Porffor_randomByte = {
943
+ params: [],
944
+ locals: prng.locals,
945
+ localNames: [ 's1', 's0' ],
946
+ globals: prng.globals,
947
+ globalNames: [ 'state0', 'state1' ],
948
+ globalInits: [ prngSeed0, prngSeed1 ],
949
+ returns: [ Valtype.i32 ],
950
+ wasm: [
951
+ ...prng.wasm,
952
+
953
+ ...(prng.returns === Valtype.i64 ? [
954
+ // the lowest bits of the output generated by xorshift128+ have low quality
955
+ ...number(56, Valtype.i64),
956
+ [ Opcodes.i64_shr_u ],
957
+
958
+ [ Opcodes.i32_wrap_i64 ],
959
+ ] : []),
960
+
961
+ ...number(0xff, Valtype.i32),
962
+ [ Opcodes.i32_and ],
476
963
  ]
477
964
  };
478
965
 
@@ -551,7 +1038,7 @@ export const BuiltinFuncs = function() {
551
1038
  params: [ valtypeBinary ],
552
1039
  locals: [],
553
1040
  returns: [ valtypeBinary ],
554
- returnType: 'boolean',
1041
+ returnType: TYPES.boolean,
555
1042
  wasm: [
556
1043
  [ Opcodes.local_get, 0 ],
557
1044
  ...number(0),
@@ -571,206 +1058,51 @@ export const BuiltinFuncs = function() {
571
1058
  };
572
1059
 
573
1060
 
574
- this.__SIMD_i32x4_load = {
575
- params: [ Valtype.i32 ],
576
- locals: [],
577
- returns: [ Valtype.v128 ],
578
- wasm: [
579
- [ Opcodes.local_get, 0 ],
580
- [ ...Opcodes.v128_load, 0, 0 ]
581
- ]
582
- };
583
-
584
- this.__SIMD_i32x4_splat = {
585
- params: [ Valtype.i32 ],
586
- locals: [],
587
- returns: [ Valtype.v128 ],
588
- wasm: [
589
- [ Opcodes.local_get, 0 ],
590
- [ ...Opcodes.i32x4_splat ],
591
- ]
592
- };
593
-
594
- this.__SIMD_i16x8_create = {
595
- params: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32 ],
596
- locals: [],
597
- returns: [ Valtype.v128 ],
598
- wasm: [
599
- ...i32x4(0, 0, 0, 0),
600
- [ Opcodes.local_get, 0 ],
601
- [ ...Opcodes.i16x8_replace_lane, 0 ],
602
- [ Opcodes.local_get, 1 ],
603
- [ ...Opcodes.i16x8_replace_lane, 1 ],
604
- [ Opcodes.local_get, 2 ],
605
- [ ...Opcodes.i16x8_replace_lane, 2 ],
606
- [ Opcodes.local_get, 3 ],
607
- [ ...Opcodes.i16x8_replace_lane, 3 ],
608
- [ Opcodes.local_get, 4 ],
609
- [ ...Opcodes.i16x8_replace_lane, 4 ],
610
- [ Opcodes.local_get, 5 ],
611
- [ ...Opcodes.i16x8_replace_lane, 5 ],
612
- [ Opcodes.local_get, 6 ],
613
- [ ...Opcodes.i16x8_replace_lane, 6 ],
614
- [ Opcodes.local_get, 7 ],
615
- [ ...Opcodes.i16x8_replace_lane, 7 ],
616
- ]
617
- };
618
-
619
- this.__SIMD_i32x4_dot_i16x8 = {
620
- params: [ Valtype.v128, Valtype.v128 ],
621
- locals: [],
622
- returns: [ Valtype.v128 ],
623
- wasm: [
624
- [ Opcodes.local_get, 0 ],
625
- [ Opcodes.local_get, 1 ],
626
- [ ...Opcodes.i32x4_dot_i16x8_s ]
627
- ]
628
- };
629
-
630
- this.__SIMD_i32x4_create = {
631
- params: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32 ],
632
- locals: [],
633
- returns: [ Valtype.v128 ],
634
- wasm: [
635
- ...i32x4(0, 0, 0, 0),
636
- [ Opcodes.local_get, 0 ],
637
- [ ...Opcodes.i32x4_replace_lane, 0 ],
638
- [ Opcodes.local_get, 1 ],
639
- [ ...Opcodes.i32x4_replace_lane, 1 ],
640
- [ Opcodes.local_get, 2 ],
641
- [ ...Opcodes.i32x4_replace_lane, 2 ],
642
- [ Opcodes.local_get, 3 ],
643
- [ ...Opcodes.i32x4_replace_lane, 3 ],
644
- ]
645
- };
646
-
647
- this.__SIMD_i32x4_add = {
648
- params: [ Valtype.v128, Valtype.v128 ],
649
- locals: [],
650
- returns: [ Valtype.v128 ],
651
- wasm: [
652
- [ Opcodes.local_get, 0 ],
653
- [ Opcodes.local_get, 1 ],
654
- [ ...Opcodes.i32x4_add ]
655
- ]
1061
+ this.__Porffor_type = {
1062
+ params: [ valtypeBinary, Valtype.i32 ],
1063
+ typedParams: true,
1064
+ locals: [ Valtype.i32, Valtype.i32 ],
1065
+ returns: [ valtypeBinary ],
1066
+ returnType: Prefs.bytestring ? TYPES._bytestring : TYPES.string,
1067
+ wasm: (scope, { TYPE_NAMES, typeSwitch, makeString }) => {
1068
+ const bc = {};
1069
+ for (const x in TYPE_NAMES) {
1070
+ bc[x] = makeString(scope, TYPE_NAMES[x], false, '#Porffor_type_result');
1071
+ }
1072
+
1073
+ return typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], bc);
1074
+ }
656
1075
  };
657
1076
 
658
- this.__SIMD_i32x4_sub = {
659
- params: [ Valtype.v128, Valtype.v128 ],
1077
+ this.__Porffor_rawType = {
1078
+ params: [ valtypeBinary, Valtype.i32 ],
1079
+ typedParams: true,
660
1080
  locals: [],
661
- returns: [ Valtype.v128 ],
1081
+ returns: [ valtypeBinary ],
662
1082
  wasm: [
663
- [ Opcodes.local_get, 0 ],
664
1083
  [ Opcodes.local_get, 1 ],
665
- [ ...Opcodes.i32x4_sub ]
1084
+ Opcodes.i32_from_u
666
1085
  ]
667
1086
  };
668
1087
 
669
- this.__SIMD_i32x4_mul = {
670
- params: [ Valtype.v128, Valtype.v128 ],
1088
+ this.__Porffor_clone = {
1089
+ params: [ valtypeBinary, valtypeBinary ],
671
1090
  locals: [],
672
- returns: [ Valtype.v128 ],
1091
+ returns: [],
673
1092
  wasm: [
674
- [ Opcodes.local_get, 0 ],
1093
+ // dst
675
1094
  [ Opcodes.local_get, 1 ],
676
- [ ...Opcodes.i32x4_mul ]
677
- ]
678
- };
1095
+ Opcodes.i32_to_u,
679
1096
 
680
- this.__SIMD_i32x4_get0 = {
681
- params: [ Valtype.v128 ],
682
- locals: [],
683
- returns: [ Valtype.i32 ],
684
- wasm: [
1097
+ // src
685
1098
  [ Opcodes.local_get, 0 ],
686
- [ ...Opcodes.i32x4_extract_lane, 0 ],
687
- ],
688
- },
689
-
690
- this.__SIMD_i32x4_get1 = {
691
- params: [ Valtype.v128 ],
692
- locals: [],
693
- returns: [ Valtype.i32 ],
694
- wasm: [
695
- [ Opcodes.local_get, 0 ],
696
- [ ...Opcodes.i32x4_extract_lane, 1 ],
697
- ],
698
- };
699
-
700
- this.__SIMD_i32x4_get2 = {
701
- params: [ Valtype.v128 ],
702
- locals: [],
703
- returns: [ Valtype.i32 ],
704
- wasm: [
705
- [ Opcodes.local_get, 0 ],
706
- [ ...Opcodes.i32x4_extract_lane, 2 ],
707
- ],
708
- };
1099
+ Opcodes.i32_to_u,
709
1100
 
710
- this.__SIMD_i32x4_get3 = {
711
- params: [ Valtype.v128 ],
712
- locals: [],
713
- returns: [ Valtype.i32 ],
714
- wasm: [
715
- [ Opcodes.local_get, 0 ],
716
- [ ...Opcodes.i32x4_extract_lane, 3 ],
717
- ],
718
- };
719
-
720
- this.__SIMD_i32x4_shuffle_000c = {
721
- params: [ Valtype.v128 ],
722
- locals: [],
723
- returns: [ Valtype.v128 ],
724
- wasm: [
725
- [ Opcodes.local_get, 0 ],
726
- ...i32x4(0, 0, 0, 0),
727
- [ ...Opcodes.i8x16_shuffle, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 9, 10, 11 ], // i32x4 (a, b, c, d) -> i32x4 (0, 0, 0, c)
728
- ]
729
- };
730
-
731
- this.__SIMD_i32x4_shuffle_00ab = {
732
- params: [ Valtype.v128 ],
733
- locals: [],
734
- returns: [ Valtype.v128 ],
735
- wasm: [
736
- [ Opcodes.local_get, 0 ],
737
- ...i32x4(0, 0, 0, 0),
738
- [ ...Opcodes.i8x16_shuffle, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 2, 3, 4, 5, 6, 7 ], // i32x4 (a, b, c, d) -> i32x4 (0, 0, a, b)
1101
+ // size = pageSize
1102
+ ...number(pageSize, Valtype.i32),
1103
+ [ ...Opcodes.memory_copy, 0x00, 0x00 ],
739
1104
  ]
740
1105
  };
741
- };
742
-
743
- export const BuiltinPreludes = {
744
- btoa: `var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
745
- var btoa = function (input) {
746
- // todo: throw invalid character for unicode
747
-
748
- let output = "";
749
- let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
750
- let i = 0;
751
-
752
- while (i < input.length) {
753
- chr1 = input.charCodeAt(i++);
754
- chr2 = input.charCodeAt(i++);
755
- chr3 = input.charCodeAt(i++);
756
-
757
- enc1 = chr1 >> 2;
758
- enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
759
- enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
760
- enc4 = chr3 & 63;
761
-
762
- if (isNaN(chr2)) {
763
- enc3 = enc4 = 64;
764
- } else if (isNaN(chr3)) {
765
- enc4 = 64;
766
- }
767
-
768
- output += keyStr.charAt(enc1);
769
- output += keyStr.charAt(enc2);
770
- output += keyStr.charAt(enc3);
771
- output += keyStr.charAt(enc4);
772
- }
773
1106
 
774
- return output;
775
- };`
1107
+ GeneratedBuiltins.BuiltinFuncs.call(this);
776
1108
  };