porffor 0.2.0-6fd3f05 → 0.2.0-767de65

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