porffor 0.2.0-e562242 → 0.2.0-e69a2a2

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 (55) hide show
  1. package/CONTRIBUTING.md +256 -0
  2. package/LICENSE +20 -20
  3. package/README.md +150 -89
  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 +317 -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 +18 -0
  11. package/compiler/builtins/array.ts +145 -0
  12. package/compiler/builtins/base64.ts +76 -0
  13. package/compiler/builtins/boolean.ts +6 -0
  14. package/compiler/builtins/crypto.ts +120 -0
  15. package/compiler/builtins/date.ts +2070 -0
  16. package/compiler/builtins/escape.ts +139 -0
  17. package/compiler/builtins/int.ts +147 -0
  18. package/compiler/builtins/number.ts +534 -0
  19. package/compiler/builtins/porffor.d.ts +59 -0
  20. package/compiler/builtins/string.ts +1070 -0
  21. package/compiler/builtins/tostring.ts +45 -0
  22. package/compiler/builtins.js +580 -272
  23. package/compiler/{codeGen.js → codegen.js} +1210 -446
  24. package/compiler/decompile.js +3 -4
  25. package/compiler/embedding.js +22 -22
  26. package/compiler/encoding.js +108 -10
  27. package/compiler/generated_builtins.js +1517 -0
  28. package/compiler/index.js +36 -34
  29. package/compiler/log.js +6 -3
  30. package/compiler/opt.js +51 -36
  31. package/compiler/parse.js +33 -23
  32. package/compiler/precompile.js +128 -0
  33. package/compiler/prefs.js +27 -0
  34. package/compiler/prototype.js +182 -42
  35. package/compiler/types.js +37 -0
  36. package/compiler/wasmSpec.js +30 -7
  37. package/compiler/wrap.js +141 -43
  38. package/package.json +9 -5
  39. package/porf +4 -0
  40. package/rhemyn/compile.js +46 -27
  41. package/rhemyn/parse.js +322 -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 +91 -11
  46. package/runner/profiler.js +102 -0
  47. package/runner/repl.js +42 -9
  48. package/runner/sizes.js +37 -37
  49. package/compiler/builtins/base64.js +0 -92
  50. package/node_trace.1.log +0 -1
  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/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,46 +203,172 @@ 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
- this.__console_log = {
190
- params: [ valtypeBinary ],
191
- locals: [],
219
+ this.__Porffor_print = {
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 ],
196
- ...char('\n'),
197
- [ Opcodes.call, importedFuncs.printChar ]
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)
198
372
  ]
199
373
  };
200
374
 
@@ -206,7 +380,7 @@ export const BuiltinFuncs = function() {
206
380
  params: [ valtypeBinary ],
207
381
  locals: [],
208
382
  returns: [ valtypeBinary ],
209
- returnType: 'boolean',
383
+ returnType: TYPES.boolean,
210
384
  wasm: [
211
385
  [ Opcodes.local_get, 0 ],
212
386
  [ Opcodes.local_get, 0 ],
@@ -221,7 +395,7 @@ export const BuiltinFuncs = function() {
221
395
  params: [ valtypeBinary ],
222
396
  locals: [ valtypeBinary ],
223
397
  returns: [ valtypeBinary ],
224
- returnType: 'boolean',
398
+ returnType: TYPES.boolean,
225
399
  wasm: [
226
400
  [ Opcodes.local_get, 0 ],
227
401
  [ Opcodes.local_get, 0 ],
@@ -240,7 +414,7 @@ export const BuiltinFuncs = function() {
240
414
  params: [ valtypeBinary ],
241
415
  locals: [],
242
416
  returns: [ valtypeBinary ],
243
- returnType: 'boolean',
417
+ returnType: TYPES.boolean,
244
418
  wasm: [
245
419
  [ Opcodes.local_get, 0 ],
246
420
  [ Opcodes.local_get, 0 ],
@@ -255,7 +429,7 @@ export const BuiltinFuncs = function() {
255
429
  params: [ valtypeBinary ],
256
430
  locals: [],
257
431
  returns: [ valtypeBinary ],
258
- returnType: 'boolean',
432
+ returnType: TYPES.boolean,
259
433
  wasm: [
260
434
  [ Opcodes.local_get, 0 ],
261
435
  [ Opcodes.local_get, 0 ],
@@ -395,61 +569,314 @@ export const BuiltinFuncs = function() {
395
569
 
396
570
  // this is an implementation of xorshift128+ (in wasm bytecode)
397
571
  // 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);
572
+ // const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
573
+ const prngSeed0 = (Math.random() * (2 ** 30)) | 0, prngSeed1 = (Math.random() * (2 ** 30)) | 0;
574
+
575
+ const prng = ({
576
+ 'lcg32_glibc': {
577
+ globals: [ Valtype.i32 ],
578
+ locals: [],
579
+ returns: Valtype.i32,
580
+ wasm: [
581
+ // seed = (MULTIPLIER * seed + INCREMENT) % MODULUS
582
+ // MULTIPLIER * state0
583
+ [ Opcodes.global_get, 0 ],
584
+ ...number(1103515245, Valtype.i32),
585
+ [ Opcodes.i32_mul ],
586
+
587
+ // + INCREMENT
588
+ ...number(12345, Valtype.i32),
589
+ [ Opcodes.i32_add ],
590
+
591
+ // % MODULUS
592
+ ...number(2 ** 31, Valtype.i32),
593
+ [ Opcodes.i32_rem_s ],
594
+
595
+ // state0 =
596
+ [ Opcodes.global_set, 0 ],
597
+
598
+ // state0
599
+ [ Opcodes.global_get, 0 ],
600
+ ],
601
+ },
602
+ 'lcg32_minstd': {
603
+ globals: [ Valtype.i32 ],
604
+ locals: [],
605
+ returns: Valtype.i32,
606
+ wasm: [
607
+ // seed = (MULTIPLIER * seed + INCREMENT) % MODULUS
608
+ // MULTIPLIER * state0
609
+ [ Opcodes.global_get, 0 ],
610
+ ...number(48271, Valtype.i32),
611
+ [ Opcodes.i32_mul ],
612
+
613
+ // % MODULUS
614
+ ...number((2 ** 31) - 1, Valtype.i32),
615
+ [ Opcodes.i32_rem_s ],
616
+
617
+ // state0 =
618
+ [ Opcodes.global_set, 0 ],
619
+
620
+ // state0
621
+ [ Opcodes.global_get, 0 ],
622
+ ],
623
+ },
624
+ 'lcg64_musl': 0, // todo
625
+
626
+ 'xorshift32+': {
627
+ globals: [ Valtype.i32 ],
628
+ locals: [ Valtype.i32 ],
629
+ returns: Valtype.i32,
630
+ wasm: [
631
+ // setup: s1 = state0
632
+ [ Opcodes.global_get, 0 ], // state0
633
+ [ Opcodes.local_tee, 0 ], // s1
634
+
635
+ // s1 ^= s1 << 13
636
+ [ Opcodes.local_get, 0 ], // s1
637
+ [ Opcodes.i32_const, 13 ],
638
+ [ Opcodes.i32_shl ], // <<
639
+ [ Opcodes.i32_xor ], // ^
640
+ [ Opcodes.local_tee, 0 ], // s1
641
+
642
+ // s1 ^= s1 >> 17
643
+ [ Opcodes.local_get, 0 ], // s1
644
+ [ Opcodes.i32_const, 17 ],
645
+ [ Opcodes.i32_shr_s ], // >>
646
+ [ Opcodes.i32_xor ], // ^
647
+ [ Opcodes.local_tee, 0 ], // s1
648
+
649
+ // s1 ^= s1 << 5
650
+ [ Opcodes.local_get, 0 ], // s1
651
+ [ Opcodes.i32_const, 5 ],
652
+ [ Opcodes.i32_shl ], // <<
653
+ [ Opcodes.i32_xor ], // ^
654
+ [ Opcodes.local_tee, 0 ], // s1
655
+
656
+ // state0 = s1
657
+ [ Opcodes.global_set, 0 ],
658
+
659
+ // s1
660
+ [ Opcodes.local_get, 0 ],
661
+ ],
662
+ },
663
+
664
+ 'xorshift64+': {
665
+ globals: [ Valtype.i64 ],
666
+ locals: [ Valtype.i64 ],
667
+ returns: Valtype.i64,
668
+ wasm: [
669
+ // setup: s1 = state0
670
+ [ Opcodes.global_get, 0 ], // state0
671
+ [ Opcodes.local_tee, 0 ], // s1
672
+
673
+ // s1 ^= s1 >> 12
674
+ [ Opcodes.local_get, 0 ], // s1
675
+ [ Opcodes.i64_const, 12 ],
676
+ [ Opcodes.i64_shr_s ], // >>
677
+ [ Opcodes.i64_xor ], // ^
678
+ [ Opcodes.local_tee, 0 ], // s1
679
+
680
+ // s1 ^= s1 << 25
681
+ [ Opcodes.local_get, 0 ], // s1
682
+ [ Opcodes.i64_const, 25 ],
683
+ [ Opcodes.i64_shl ], // <<
684
+ [ Opcodes.i64_xor ], // ^
685
+ [ Opcodes.local_tee, 0 ], // s1
686
+
687
+ // s1 ^= s1 >> 27
688
+ [ Opcodes.local_get, 0 ], // s1
689
+ [ Opcodes.i64_const, 27 ],
690
+ [ Opcodes.i64_shr_s ], // >>
691
+ [ Opcodes.i64_xor ], // ^
692
+ [ Opcodes.local_tee, 0 ], // s1
693
+
694
+ // state0 = s1
695
+ [ Opcodes.global_set, 0 ],
696
+
697
+ // // s1 * 0x2545F4914F6CDD1D
698
+ // [ Opcodes.local_get, 0 ],
699
+ // [ Opcodes.i64_const, 0x9d, 0xba, 0xb3, 0xfb, 0x94, 0x92, 0xfd, 0xa2, 0x25 ],
700
+ // [ Opcodes.i64_mul ]
701
+
702
+ // s1
703
+ [ Opcodes.local_get, 0 ],
704
+ ],
705
+ },
706
+
707
+ 'xorshift128+': {
708
+ globals: [ Valtype.i64, Valtype.i64 ],
709
+ locals: [ Valtype.i64, Valtype.i64 ],
710
+ returns: Valtype.i64,
711
+ wasm: [
712
+ // setup: s1 = state0, s0 = state1, state0 = s0
713
+ [ Opcodes.global_get, 0 ], // state0
714
+ [ Opcodes.local_tee, 0 ], // s1
715
+ [ Opcodes.global_get, 1 ], // state1
716
+ [ Opcodes.local_tee, 1, ], // s0
717
+ [ Opcodes.global_set, 0 ], // state0
718
+
719
+ // s1 ^= s1 << 23
720
+ // [ Opcodes.local_get, 0 ], // s1
721
+ [ Opcodes.local_get, 0 ], // s1
722
+ [ Opcodes.i64_const, 23 ],
723
+ [ Opcodes.i64_shl ], // <<
724
+ [ Opcodes.i64_xor ], // ^
725
+ [ Opcodes.local_set, 0 ], // s1
726
+
727
+ // state1 = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26)
728
+ // s1 ^ s0
729
+ [ Opcodes.local_get, 0 ], // s1
730
+ [ Opcodes.local_get, 1 ], // s0
731
+ [ Opcodes.i64_xor ], // ^
732
+
733
+ // ^ (s1 >> 17)
734
+ [ Opcodes.local_get, 0 ], // s1
735
+ [ Opcodes.i64_const, 17 ],
736
+ [ Opcodes.i64_shr_u ], // >>
737
+ [ Opcodes.i64_xor ], // ^
738
+
739
+ // ^ (s0 >> 26)
740
+ [ Opcodes.local_get, 1 ], // s0
741
+ [ Opcodes.i64_const, 26 ],
742
+ [ Opcodes.i64_shr_u ], // >>
743
+ [ Opcodes.i64_xor ], // ^
744
+
745
+ // state1 =
746
+ [ Opcodes.global_set, 1 ],
747
+
748
+ // state1 + s0
749
+ [ Opcodes.global_get, 1 ], // state1
750
+ [ Opcodes.local_get, 1 ], // s0
751
+ [ Opcodes.i64_add ]
752
+ ]
753
+ },
754
+
755
+ 'xoroshiro128+': {
756
+ globals: [ Valtype.i64, Valtype.i64 ],
757
+ locals: [ Valtype.i64, Valtype.i64, Valtype.i64 ],
758
+ returns: Valtype.i64,
759
+ wasm: [
760
+ // setup: s1 = state1, s0 = state0
761
+ [ Opcodes.global_get, 1 ], // state0
762
+ [ Opcodes.local_tee, 0 ], // s1
763
+ [ Opcodes.global_get, 0 ], // state1
764
+ [ Opcodes.local_tee, 1, ], // s0
765
+
766
+ // result = s0 + s1
767
+ [ Opcodes.i64_add ],
768
+ [ Opcodes.local_set, 2 ], // result
769
+
770
+ // s1 ^= s0
771
+ [ Opcodes.local_get, 0 ], // s1
772
+ [ Opcodes.local_get, 1 ], // s0
773
+ [ Opcodes.i64_xor ],
774
+ [ Opcodes.local_set, 0 ], // s1
775
+
776
+ // state0 = rotl(s0, 24) ^ s1 ^ (s1 << 16)
777
+
778
+ // rotl(s0, 24) ^ s1
779
+ [ Opcodes.local_get, 1 ], // s0
780
+ ...number(24, Valtype.i64),
781
+ [ Opcodes.i64_rotl ],
782
+ [ Opcodes.local_get, 0 ], // s1
783
+ [ Opcodes.i64_xor ],
784
+
785
+ // ^ (s1 << 16)
786
+ [ Opcodes.local_get, 0 ], // s1
787
+ ...number(16, Valtype.i64),
788
+ [ Opcodes.i64_shl ],
789
+ [ Opcodes.i64_xor ],
790
+
791
+ // state0 =
792
+ [ Opcodes.global_set, 0 ], // state0
793
+
794
+ // state1 = rotl(s1, 37)
795
+ [ Opcodes.local_get, 0 ], // s1
796
+ ...number(37, Valtype.i64),
797
+ [ Opcodes.i64_rotl ],
798
+ [ Opcodes.global_set, 1 ], // state1
799
+
800
+ // result
801
+ [ Opcodes.local_get, 2 ],
802
+ ]
803
+ },
804
+
805
+ 'xoshiro128+': {
806
+ globals: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32 ],
807
+ locals: [ Valtype.i32, Valtype.i32 ],
808
+ returns: Valtype.i32,
809
+ wasm: [
810
+ // result = state0 + state3
811
+ [ Opcodes.global_get, 0 ], // state0
812
+ [ Opcodes.global_get, 3 ], // state0
813
+ [ Opcodes.i32_add ],
814
+ [ Opcodes.local_set, 0 ], // result
815
+
816
+ // t = state1 << 9
817
+ [ Opcodes.global_get, 1 ], // state1
818
+ ...number(9, Valtype.i32),
819
+ [ Opcodes.i32_shl ],
820
+ [ Opcodes.local_set, 1 ], // t
821
+
822
+ // state2 ^= state0
823
+ [ Opcodes.global_get, 2 ], // state2
824
+ [ Opcodes.global_get, 0 ], // state0
825
+ [ Opcodes.i32_xor ],
826
+ [ Opcodes.global_set, 2 ], // state2
827
+
828
+ // state3 ^= state1
829
+ [ Opcodes.global_get, 3 ], // state3
830
+ [ Opcodes.global_get, 1 ], // state1
831
+ [ Opcodes.i32_xor ],
832
+ [ Opcodes.global_set, 3 ], // state3
833
+
834
+ // state1 ^= state2
835
+ [ Opcodes.global_get, 1 ], // state1
836
+ [ Opcodes.global_get, 2 ], // state2
837
+ [ Opcodes.i32_xor ],
838
+ [ Opcodes.global_set, 1 ], // state1
839
+
840
+ // state0 ^= state3
841
+ [ Opcodes.global_get, 0 ], // state2
842
+ [ Opcodes.global_get, 3 ], // state0
843
+ [ Opcodes.i32_xor ],
844
+ [ Opcodes.global_set, 0 ], // state2
845
+
846
+ // state2 ^= t
847
+ [ Opcodes.global_get, 2 ], // state2
848
+ [ Opcodes.local_get, 1 ], // t
849
+ [ Opcodes.i32_xor ],
850
+ [ Opcodes.global_set, 2 ], // state2
851
+
852
+ // state3 = rotl(state3, 11)
853
+ [ Opcodes.global_get, 3 ], // state3
854
+ ...number(11, Valtype.i32),
855
+ [ Opcodes.i32_rotl ],
856
+ [ Opcodes.global_set, 3 ], // state3
857
+
858
+ // result
859
+ [ Opcodes.local_get, 0 ],
860
+ ]
861
+ }
862
+ })[Prefs.prng ?? 'xorshift128+'];
863
+
864
+ if (!prng) throw new Error(`unknown prng algo: ${Prefs.prng}`);
399
865
 
400
866
  this.__Math_random = {
401
867
  floatOnly: true,
402
868
  params: [],
403
- locals: [ Valtype.i64, Valtype.i64 ],
869
+ locals: prng.locals,
404
870
  localNames: [ 's1', 's0' ],
405
- globals: [ Valtype.i64, Valtype.i64 ],
871
+ globals: prng.globals,
406
872
  globalNames: [ 'state0', 'state1' ],
407
873
  globalInits: [ prngSeed0, prngSeed1 ],
408
874
  returns: [ Valtype.f64 ],
409
875
  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 ],
876
+ ...prng.wasm,
445
877
 
446
878
  // you thought it was over? now we need the result as a f64 between 0-1 :)
447
879
 
448
- // state1 + s0
449
- [ Opcodes.global_get, 1 ], // state1
450
- [ Opcodes.local_get, 1 ], // s0
451
- [ Opcodes.i64_add ],
452
-
453
880
  // should we >> 12 here?
454
881
  // it feels like it but it breaks values
455
882
 
@@ -464,15 +891,51 @@ export const BuiltinFuncs = function() {
464
891
  // ...number(1),
465
892
  // [ Opcodes.f64_sub ],
466
893
 
467
- ...number((1 << 53) - 1, Valtype.i64),
468
- [ Opcodes.i64_and ],
894
+ ...(prng.returns === Valtype.i64 ? [
895
+ ...number((1 << 53) - 1, Valtype.i64),
896
+ [ Opcodes.i64_and ],
469
897
 
470
- // double(mantissa)
471
- [ Opcodes.f64_convert_i64_u ],
898
+ // double(mantissa)
899
+ [ Opcodes.f64_convert_i64_u ],
472
900
 
473
- // / (1 << 53)
474
- ...number(1 << 53),
475
- [ Opcodes.f64_div ]
901
+ // / (1 << 53)
902
+ ...number(1 << 53),
903
+ [ Opcodes.f64_div ]
904
+ ] : [
905
+ ...number((1 << 21) - 1, Valtype.i32),
906
+ [ Opcodes.i32_and ],
907
+
908
+ // double(mantissa)
909
+ [ Opcodes.f64_convert_i32_u ],
910
+
911
+ // / (1 << 21)
912
+ ...number(1 << 21),
913
+ [ Opcodes.f64_div ]
914
+ ])
915
+ ]
916
+ };
917
+
918
+ this.__Porffor_randomByte = {
919
+ params: [],
920
+ locals: prng.locals,
921
+ localNames: [ 's1', 's0' ],
922
+ globals: prng.globals,
923
+ globalNames: [ 'state0', 'state1' ],
924
+ globalInits: [ prngSeed0, prngSeed1 ],
925
+ returns: [ Valtype.i32 ],
926
+ wasm: [
927
+ ...prng.wasm,
928
+
929
+ ...(prng.returns === Valtype.i64 ? [
930
+ // the lowest bits of the output generated by xorshift128+ have low quality
931
+ ...number(56, Valtype.i64),
932
+ [ Opcodes.i64_shr_u ],
933
+
934
+ [ Opcodes.i32_wrap_i64 ],
935
+ ] : []),
936
+
937
+ ...number(0xff, Valtype.i32),
938
+ [ Opcodes.i32_and ],
476
939
  ]
477
940
  };
478
941
 
@@ -551,7 +1014,7 @@ export const BuiltinFuncs = function() {
551
1014
  params: [ valtypeBinary ],
552
1015
  locals: [],
553
1016
  returns: [ valtypeBinary ],
554
- returnType: 'boolean',
1017
+ returnType: TYPES.boolean,
555
1018
  wasm: [
556
1019
  [ Opcodes.local_get, 0 ],
557
1020
  ...number(0),
@@ -571,206 +1034,51 @@ export const BuiltinFuncs = function() {
571
1034
  };
572
1035
 
573
1036
 
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
- ]
1037
+ this.__Porffor_type = {
1038
+ params: [ valtypeBinary, Valtype.i32 ],
1039
+ typedParams: true,
1040
+ locals: [ Valtype.i32, Valtype.i32 ],
1041
+ returns: [ valtypeBinary ],
1042
+ returnType: Prefs.bytestring ? TYPES.bytestring : TYPES.string,
1043
+ wasm: (scope, { TYPE_NAMES, typeSwitch, makeString }) => {
1044
+ const bc = {};
1045
+ for (const x in TYPE_NAMES) {
1046
+ bc[x] = makeString(scope, TYPE_NAMES[x], false, '#Porffor_type_result');
1047
+ }
1048
+
1049
+ return typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], bc);
1050
+ }
656
1051
  };
657
1052
 
658
- this.__SIMD_i32x4_sub = {
659
- params: [ Valtype.v128, Valtype.v128 ],
1053
+ this.__Porffor_rawType = {
1054
+ params: [ valtypeBinary, Valtype.i32 ],
1055
+ typedParams: true,
660
1056
  locals: [],
661
- returns: [ Valtype.v128 ],
1057
+ returns: [ valtypeBinary ],
662
1058
  wasm: [
663
- [ Opcodes.local_get, 0 ],
664
1059
  [ Opcodes.local_get, 1 ],
665
- [ ...Opcodes.i32x4_sub ]
1060
+ Opcodes.i32_from_u
666
1061
  ]
667
1062
  };
668
1063
 
669
- this.__SIMD_i32x4_mul = {
670
- params: [ Valtype.v128, Valtype.v128 ],
1064
+ this.__Porffor_clone = {
1065
+ params: [ valtypeBinary, valtypeBinary ],
671
1066
  locals: [],
672
- returns: [ Valtype.v128 ],
1067
+ returns: [],
673
1068
  wasm: [
674
- [ Opcodes.local_get, 0 ],
1069
+ // dst
675
1070
  [ Opcodes.local_get, 1 ],
676
- [ ...Opcodes.i32x4_mul ]
677
- ]
678
- };
1071
+ Opcodes.i32_to_u,
679
1072
 
680
- this.__SIMD_i32x4_get0 = {
681
- params: [ Valtype.v128 ],
682
- locals: [],
683
- returns: [ Valtype.i32 ],
684
- wasm: [
1073
+ // src
685
1074
  [ 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
- };
1075
+ Opcodes.i32_to_u,
709
1076
 
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)
1077
+ // size = pageSize
1078
+ ...number(pageSize, Valtype.i32),
1079
+ [ ...Opcodes.memory_copy, 0x00, 0x00 ],
739
1080
  ]
740
1081
  };
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
1082
 
774
- return output;
775
- };`
1083
+ GeneratedBuiltins.BuiltinFuncs.call(this);
776
1084
  };