porffor 0.2.0-aea77ff → 0.2.0-b9abe0d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +18 -0
- package/LICENSE +20 -20
- package/README.md +124 -83
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +237 -0
- package/compiler/2c.js +317 -72
- package/compiler/{sections.js → assemble.js} +63 -15
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +19 -0
- package/compiler/builtins/array.ts +145 -0
- package/compiler/builtins/base64.ts +151 -0
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +9 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/int.ts +147 -0
- package/compiler/builtins/number.ts +527 -0
- package/compiler/builtins/porffor.d.ts +42 -0
- package/compiler/builtins/string.ts +1055 -0
- package/compiler/builtins/tostring.ts +45 -0
- package/compiler/builtins.js +479 -262
- package/compiler/{codeGen.js → codegen.js} +1049 -394
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +108 -10
- package/compiler/generated_builtins.js +722 -0
- package/compiler/index.js +36 -34
- package/compiler/log.js +6 -3
- package/compiler/opt.js +51 -36
- package/compiler/parse.js +35 -27
- package/compiler/precompile.js +123 -0
- package/compiler/prefs.js +26 -0
- package/compiler/prototype.js +177 -37
- package/compiler/types.js +37 -0
- package/compiler/wasmSpec.js +29 -7
- package/compiler/wrap.js +52 -39
- package/package.json +9 -5
- package/porf +4 -0
- package/rhemyn/compile.js +5 -3
- package/rhemyn/parse.js +323 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +34 -34
- package/runner/debug.js +122 -0
- package/runner/index.js +49 -10
- package/runner/profiler.js +102 -0
- package/runner/repl.js +40 -7
- package/runner/sizes.js +37 -37
- package/test262_changes_from_1afe9b87d2_to_04-09.md +270 -0
- package/compiler/builtins/base64.js +0 -92
- package/runner/info.js +0 -89
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
- package/runner/transform.js +0 -15
- package/util/enum.js +0 -20
package/compiler/prototype.js
CHANGED
@@ -2,29 +2,16 @@ import { Opcodes, Blocktype, Valtype, ValtypeSize, PageSize } from "./wasmSpec.j
|
|
2
2
|
import { number } from "./embedding.js";
|
3
3
|
import { unsignedLEB128 } from "./encoding.js";
|
4
4
|
import { UNDEFINED } from "./builtins.js";
|
5
|
-
|
6
|
-
|
7
|
-
const TYPES = {
|
8
|
-
number: 0x00,
|
9
|
-
boolean: 0x01,
|
10
|
-
string: 0x02,
|
11
|
-
undefined: 0x03,
|
12
|
-
object: 0x04,
|
13
|
-
function: 0x05,
|
14
|
-
symbol: 0x06,
|
15
|
-
bigint: 0x07,
|
16
|
-
|
17
|
-
// these are not "typeof" types but tracked internally
|
18
|
-
_array: 0x10,
|
19
|
-
_regexp: 0x11
|
20
|
-
};
|
5
|
+
import Prefs from './prefs.js';
|
6
|
+
import { TYPES } from './types.js';
|
21
7
|
|
22
8
|
// todo: turn these into built-ins once arrays and these become less hacky
|
23
9
|
|
24
10
|
export const PrototypeFuncs = function() {
|
25
|
-
const noUnlikelyChecks =
|
26
|
-
|
27
|
-
|
11
|
+
const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
|
12
|
+
|
13
|
+
let zeroChecks;
|
14
|
+
if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
|
28
15
|
else zeroChecks = {};
|
29
16
|
|
30
17
|
this[TYPES._array] = {
|
@@ -71,7 +58,7 @@ export const PrototypeFuncs = function() {
|
|
71
58
|
],
|
72
59
|
|
73
60
|
// todo: only for 1 argument
|
74
|
-
push: (pointer, length, wNewMember) => [
|
61
|
+
push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
|
75
62
|
// get memory offset of array at last index (length)
|
76
63
|
...length.getCachedI32(),
|
77
64
|
...number(ValtypeSize[valtype], Valtype.i32),
|
@@ -92,22 +79,28 @@ export const PrototypeFuncs = function() {
|
|
92
79
|
...number(1, Valtype.i32),
|
93
80
|
[ Opcodes.i32_add ],
|
94
81
|
|
95
|
-
...
|
96
|
-
|
82
|
+
...(unusedValue() ? [] : [
|
83
|
+
...length.setCachedI32(),
|
84
|
+
...length.getCachedI32(),
|
85
|
+
])
|
97
86
|
]),
|
98
87
|
|
99
|
-
...
|
100
|
-
|
88
|
+
...(unusedValue() ? [] : [
|
89
|
+
...length.getCachedI32(),
|
90
|
+
Opcodes.i32_from_u
|
91
|
+
])
|
101
92
|
|
102
93
|
// ...length.get()
|
103
94
|
],
|
104
95
|
|
105
|
-
pop: (pointer, length) => [
|
96
|
+
pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
|
106
97
|
// if length == 0, noop
|
107
98
|
...length.getCachedI32(),
|
108
99
|
[ Opcodes.i32_eqz ],
|
109
100
|
[ Opcodes.if, Blocktype.void ],
|
110
|
-
...
|
101
|
+
...(unusedValue() ? [] : [
|
102
|
+
...number(UNDEFINED),
|
103
|
+
]),
|
111
104
|
[ Opcodes.br, 1 ],
|
112
105
|
[ Opcodes.end ],
|
113
106
|
|
@@ -119,25 +112,29 @@ export const PrototypeFuncs = function() {
|
|
119
112
|
...number(1, Valtype.i32),
|
120
113
|
[ Opcodes.i32_sub ],
|
121
114
|
|
122
|
-
...
|
123
|
-
|
115
|
+
...(unusedValue() ? [] : [
|
116
|
+
...length.setCachedI32(),
|
117
|
+
...length.getCachedI32(),
|
118
|
+
])
|
124
119
|
]),
|
125
120
|
|
126
121
|
// load last element
|
127
|
-
...
|
128
|
-
|
129
|
-
|
122
|
+
...(unusedValue() ? [] : [
|
123
|
+
...length.getCachedI32(),
|
124
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
125
|
+
[ Opcodes.i32_mul ],
|
130
126
|
|
131
|
-
|
132
|
-
|
127
|
+
...pointer,
|
128
|
+
[ Opcodes.i32_add ],
|
133
129
|
|
134
|
-
|
130
|
+
[ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
|
131
|
+
])
|
135
132
|
],
|
136
133
|
|
137
134
|
shift: (pointer, length) => [
|
138
135
|
// if length == 0, noop
|
139
136
|
...length.getCachedI32(),
|
140
|
-
Opcodes.i32_eqz,
|
137
|
+
[ Opcodes.i32_eqz ],
|
141
138
|
[ Opcodes.if, Blocktype.void ],
|
142
139
|
...number(UNDEFINED),
|
143
140
|
[ Opcodes.br, 1 ],
|
@@ -331,8 +328,8 @@ export const PrototypeFuncs = function() {
|
|
331
328
|
...number(0, Valtype.i32), // base 0 for store later
|
332
329
|
|
333
330
|
...wIndex,
|
334
|
-
|
335
331
|
Opcodes.i32_to,
|
332
|
+
|
336
333
|
...number(ValtypeSize.i16, Valtype.i32),
|
337
334
|
[ Opcodes.i32_mul ],
|
338
335
|
|
@@ -372,7 +369,7 @@ export const PrototypeFuncs = function() {
|
|
372
369
|
|
373
370
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
374
371
|
[ Opcodes.if, Blocktype.void ],
|
375
|
-
...number(NaN),
|
372
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
376
373
|
[ Opcodes.br, 1 ],
|
377
374
|
[ Opcodes.end ],
|
378
375
|
|
@@ -472,8 +469,151 @@ export const PrototypeFuncs = function() {
|
|
472
469
|
this[TYPES.string].at.returnType = TYPES.string;
|
473
470
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
474
471
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
472
|
+
this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
475
473
|
|
476
474
|
this[TYPES.string].isWellFormed.local = Valtype.i32;
|
477
475
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
478
476
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
477
|
+
|
478
|
+
if (Prefs.bytestring) {
|
479
|
+
this[TYPES._bytestring] = {
|
480
|
+
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
481
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
482
|
+
|
483
|
+
return [
|
484
|
+
// setup new/out array
|
485
|
+
...newOut,
|
486
|
+
[ Opcodes.drop ],
|
487
|
+
|
488
|
+
...number(0, Valtype.i32), // base 0 for store later
|
489
|
+
|
490
|
+
...wIndex,
|
491
|
+
Opcodes.i32_to_u,
|
492
|
+
[ Opcodes.local_tee, iTmp ],
|
493
|
+
|
494
|
+
// if index < 0: access index + array length
|
495
|
+
...number(0, Valtype.i32),
|
496
|
+
[ Opcodes.i32_lt_s ],
|
497
|
+
[ Opcodes.if, Blocktype.void ],
|
498
|
+
[ Opcodes.local_get, iTmp ],
|
499
|
+
...length.getCachedI32(),
|
500
|
+
[ Opcodes.i32_add ],
|
501
|
+
[ Opcodes.local_set, iTmp ],
|
502
|
+
[ Opcodes.end ],
|
503
|
+
|
504
|
+
// if still < 0 or >= length: return undefined
|
505
|
+
[ Opcodes.local_get, iTmp ],
|
506
|
+
...number(0, Valtype.i32),
|
507
|
+
[ Opcodes.i32_lt_s ],
|
508
|
+
|
509
|
+
[ Opcodes.local_get, iTmp ],
|
510
|
+
...length.getCachedI32(),
|
511
|
+
[ Opcodes.i32_ge_s ],
|
512
|
+
[ Opcodes.i32_or ],
|
513
|
+
|
514
|
+
[ Opcodes.if, Blocktype.void ],
|
515
|
+
...number(UNDEFINED),
|
516
|
+
[ Opcodes.br, 1 ],
|
517
|
+
[ Opcodes.end ],
|
518
|
+
|
519
|
+
[ Opcodes.local_get, iTmp ],
|
520
|
+
|
521
|
+
...pointer,
|
522
|
+
[ Opcodes.i32_add ],
|
523
|
+
|
524
|
+
// load current string ind {arg}
|
525
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
526
|
+
|
527
|
+
// store to new string ind 0
|
528
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
529
|
+
|
530
|
+
// return new string (pointer)
|
531
|
+
...number(newPointer)
|
532
|
+
];
|
533
|
+
},
|
534
|
+
|
535
|
+
// todo: out of bounds properly
|
536
|
+
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
537
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
538
|
+
|
539
|
+
return [
|
540
|
+
// setup new/out array
|
541
|
+
...newOut,
|
542
|
+
[ Opcodes.drop ],
|
543
|
+
|
544
|
+
...number(0, Valtype.i32), // base 0 for store later
|
545
|
+
|
546
|
+
...wIndex,
|
547
|
+
Opcodes.i32_to,
|
548
|
+
|
549
|
+
...pointer,
|
550
|
+
[ Opcodes.i32_add ],
|
551
|
+
|
552
|
+
// load current string ind {arg}
|
553
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
554
|
+
|
555
|
+
// store to new string ind 0
|
556
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
557
|
+
|
558
|
+
// return new string (page)
|
559
|
+
...number(newPointer)
|
560
|
+
];
|
561
|
+
},
|
562
|
+
|
563
|
+
charCodeAt: (pointer, length, wIndex, iTmp) => {
|
564
|
+
return [
|
565
|
+
...wIndex,
|
566
|
+
Opcodes.i32_to,
|
567
|
+
|
568
|
+
...(zeroChecks.charcodeat ? [] : [
|
569
|
+
[ Opcodes.local_set, iTmp ],
|
570
|
+
|
571
|
+
// index < 0
|
572
|
+
...(noUnlikelyChecks ? [] : [
|
573
|
+
[ Opcodes.local_get, iTmp ],
|
574
|
+
...number(0, Valtype.i32),
|
575
|
+
[ Opcodes.i32_lt_s ],
|
576
|
+
]),
|
577
|
+
|
578
|
+
// index >= length
|
579
|
+
[ Opcodes.local_get, iTmp ],
|
580
|
+
...length.getCachedI32(),
|
581
|
+
[ Opcodes.i32_ge_s ],
|
582
|
+
|
583
|
+
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
584
|
+
[ Opcodes.if, Blocktype.void ],
|
585
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
586
|
+
[ Opcodes.br, 1 ],
|
587
|
+
[ Opcodes.end ],
|
588
|
+
|
589
|
+
[ Opcodes.local_get, iTmp ],
|
590
|
+
]),
|
591
|
+
|
592
|
+
...pointer,
|
593
|
+
[ Opcodes.i32_add ],
|
594
|
+
|
595
|
+
// load current string ind {arg}
|
596
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
597
|
+
Opcodes.i32_from_u
|
598
|
+
];
|
599
|
+
},
|
600
|
+
|
601
|
+
isWellFormed: () => {
|
602
|
+
return [
|
603
|
+
// we know it must be true as it is a bytestring lol
|
604
|
+
...number(1)
|
605
|
+
]
|
606
|
+
}
|
607
|
+
};
|
608
|
+
|
609
|
+
this[TYPES._bytestring].at.local = Valtype.i32;
|
610
|
+
this[TYPES._bytestring].at.returnType = TYPES._bytestring;
|
611
|
+
this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
|
612
|
+
this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
|
613
|
+
this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
614
|
+
|
615
|
+
this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
|
616
|
+
this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
|
617
|
+
this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
|
618
|
+
}
|
479
619
|
};
|
@@ -0,0 +1,37 @@
|
|
1
|
+
export const TYPES = {
|
2
|
+
number: 0x00,
|
3
|
+
boolean: 0x01,
|
4
|
+
string: 0x02,
|
5
|
+
undefined: 0x03,
|
6
|
+
object: 0x04,
|
7
|
+
function: 0x05,
|
8
|
+
symbol: 0x06,
|
9
|
+
bigint: 0x07
|
10
|
+
};
|
11
|
+
|
12
|
+
export const TYPE_NAMES = {
|
13
|
+
[TYPES.number]: 'Number',
|
14
|
+
[TYPES.boolean]: 'Boolean',
|
15
|
+
[TYPES.string]: 'String',
|
16
|
+
[TYPES.undefined]: 'undefined',
|
17
|
+
[TYPES.object]: 'Object',
|
18
|
+
[TYPES.function]: 'Function',
|
19
|
+
[TYPES.symbol]: 'Symbol',
|
20
|
+
[TYPES.bigint]: 'BigInt'
|
21
|
+
};
|
22
|
+
|
23
|
+
export const INTERNAL_TYPE_BASE = 0x10;
|
24
|
+
let internalTypeIndex = INTERNAL_TYPE_BASE;
|
25
|
+
const registerInternalType = name => {
|
26
|
+
const n = internalTypeIndex++;
|
27
|
+
TYPES['_' + name.toLowerCase()] = n;
|
28
|
+
TYPE_NAMES[n] = name;
|
29
|
+
};
|
30
|
+
|
31
|
+
// note: when adding a new internal type, please also add a deserializer to wrap.js
|
32
|
+
// (it is okay to add a throw todo deserializer for wips)
|
33
|
+
|
34
|
+
registerInternalType('Array');
|
35
|
+
registerInternalType('RegExp');
|
36
|
+
registerInternalType('ByteString');
|
37
|
+
registerInternalType('Date');
|
package/compiler/wasmSpec.js
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
const enumify = (...args) => {
|
2
|
+
const obj = {};
|
3
|
+
|
4
|
+
for (let i = 0; i < args.length; i++) {
|
5
|
+
obj[i] = args[i];
|
6
|
+
obj[args[i]] = i;
|
7
|
+
}
|
8
|
+
|
9
|
+
return obj;
|
10
|
+
};
|
2
11
|
|
3
12
|
export const Section = enumify('custom', 'type', 'import', 'func', 'table', 'memory', 'global', 'export', 'start', 'element', 'code', 'data', 'data_count', 'tag');
|
4
13
|
export const ExportDesc = enumify('func', 'table', 'mem', 'global', 'tag');
|
@@ -32,17 +41,16 @@ export const Opcodes = {
|
|
32
41
|
throw: 0x08,
|
33
42
|
rethrow: 0x09,
|
34
43
|
|
35
|
-
call: 0x10,
|
36
|
-
call_indirect: 0x11,
|
37
|
-
return_call: 0x12,
|
38
|
-
return_call_indirect: 0x13,
|
39
|
-
|
40
44
|
end: 0x0b,
|
41
45
|
br: 0x0c,
|
42
46
|
br_if: 0x0d,
|
43
47
|
br_table: 0x0e,
|
44
48
|
return: 0x0f,
|
49
|
+
|
45
50
|
call: 0x10,
|
51
|
+
call_indirect: 0x11,
|
52
|
+
return_call: 0x12,
|
53
|
+
return_call_indirect: 0x13,
|
46
54
|
|
47
55
|
drop: 0x1a,
|
48
56
|
|
@@ -57,15 +65,26 @@ export const Opcodes = {
|
|
57
65
|
i64_load: 0x29,
|
58
66
|
f64_load: 0x2b,
|
59
67
|
|
68
|
+
i32_load8_s: 0x2c,
|
69
|
+
i32_load8_u: 0x2d,
|
60
70
|
i32_load16_s: 0x2e,
|
61
71
|
i32_load16_u: 0x2f,
|
62
72
|
|
63
|
-
|
73
|
+
i64_load8_s: 0x30,
|
74
|
+
i64_load8_u: 0x31,
|
75
|
+
i64_load16_s: 0x32,
|
76
|
+
i64_load16_u: 0x33,
|
64
77
|
|
65
78
|
i32_store: 0x36,
|
66
79
|
i64_store: 0x37,
|
67
80
|
f64_store: 0x39,
|
68
81
|
|
82
|
+
i32_store8: 0x3a,
|
83
|
+
i32_store16: 0x3b,
|
84
|
+
|
85
|
+
i64_store8: 0x3c,
|
86
|
+
i64_store16: 0x3d,
|
87
|
+
|
69
88
|
memory_grow: 0x40,
|
70
89
|
|
71
90
|
i32_const: 0x41,
|
@@ -97,6 +116,8 @@ export const Opcodes = {
|
|
97
116
|
i32_shl: 0x74,
|
98
117
|
i32_shr_s: 0x75,
|
99
118
|
i32_shr_u: 0x76,
|
119
|
+
i32_rotl: 0x77,
|
120
|
+
i32_rotr: 0x78,
|
100
121
|
|
101
122
|
i64_eqz: 0x50,
|
102
123
|
i64_eq: 0x51,
|
@@ -120,6 +141,7 @@ export const Opcodes = {
|
|
120
141
|
i64_shr_s: 0x87,
|
121
142
|
i64_shr_u: 0x88,
|
122
143
|
i64_rotl: 0x89,
|
144
|
+
i64_rotr: 0x8a,
|
123
145
|
|
124
146
|
f64_eq: 0x61,
|
125
147
|
f64_ne: 0x62,
|
package/compiler/wrap.js
CHANGED
@@ -1,55 +1,56 @@
|
|
1
1
|
import compile from './index.js';
|
2
2
|
import decompile from './decompile.js';
|
3
3
|
import { encodeVector, encodeLocal } from './encoding.js';
|
4
|
-
|
4
|
+
import Prefs from './prefs.js';
|
5
|
+
import { log } from './log.js';
|
6
|
+
import { TYPES } from './types.js';
|
5
7
|
|
6
8
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
7
9
|
|
8
|
-
const typeBase = 0x00;
|
9
|
-
const internalTypeBase = 0x10;
|
10
|
-
const TYPES = {
|
11
|
-
[typeBase]: 'number',
|
12
|
-
[typeBase + 1]: 'boolean',
|
13
|
-
[typeBase + 2]: 'string',
|
14
|
-
[typeBase + 3]: 'undefined',
|
15
|
-
[typeBase + 4]: 'object',
|
16
|
-
[typeBase + 5]: 'function',
|
17
|
-
[typeBase + 6]: 'symbol',
|
18
|
-
[typeBase + 7]: 'bigint',
|
19
|
-
|
20
|
-
// internal
|
21
|
-
[internalTypeBase]: '_array',
|
22
|
-
[internalTypeBase + 1]: '_regexp'
|
23
|
-
};
|
24
|
-
|
25
10
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
26
11
|
const times = [];
|
27
12
|
|
28
13
|
const t1 = performance.now();
|
29
14
|
const { wasm, funcs, globals, tags, exceptions, pages, c } = compile(source, flags);
|
30
15
|
|
16
|
+
globalThis.porfDebugInfo = { funcs, globals };
|
17
|
+
|
31
18
|
if (source.includes('export function')) flags.push('module');
|
32
19
|
|
33
|
-
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
20
|
+
// (await import('node:fs')).writeFileSync('out.wasm', Buffer.from(wasm));
|
34
21
|
|
35
22
|
times.push(performance.now() - t1);
|
36
|
-
if (
|
23
|
+
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
37
24
|
|
38
25
|
const t2 = performance.now();
|
39
26
|
|
40
27
|
let instance;
|
41
28
|
try {
|
42
|
-
|
29
|
+
let wasmEngine = WebAssembly;
|
30
|
+
if (Prefs.asur) {
|
31
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
32
|
+
wasmEngine = await import('../asur/index.js');
|
33
|
+
}
|
34
|
+
|
35
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
43
36
|
'': {
|
44
37
|
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
45
38
|
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
46
|
-
t:
|
39
|
+
t: () => performance.now(),
|
40
|
+
u: () => performance.timeOrigin,
|
41
|
+
y: () => {},
|
42
|
+
z: () => {},
|
47
43
|
...customImports
|
48
44
|
}
|
49
45
|
});
|
50
46
|
} catch (e) {
|
51
|
-
|
52
|
-
|
47
|
+
// only backtrace for runner, not test262/etc
|
48
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
49
|
+
|
50
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
51
|
+
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
52
|
+
|
53
|
+
if (!funcInd) throw e;
|
53
54
|
|
54
55
|
// convert blob offset -> function wasm offset.
|
55
56
|
// this is not good code and is somewhat duplicated
|
@@ -127,7 +128,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
127
128
|
}
|
128
129
|
|
129
130
|
times.push(performance.now() - t2);
|
130
|
-
if (
|
131
|
+
if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
131
132
|
|
132
133
|
const exports = {};
|
133
134
|
|
@@ -155,12 +156,29 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
155
156
|
|
156
157
|
// if (ret >= typeBase && ret <= typeBase + 8) return ret > (typeBase + 7) ? 'object' : TYPES[ret];
|
157
158
|
|
158
|
-
switch (
|
159
|
-
case
|
160
|
-
case
|
161
|
-
case
|
159
|
+
switch (type) {
|
160
|
+
case TYPES.boolean: return Boolean(ret);
|
161
|
+
case TYPES.undefined: return undefined;
|
162
|
+
case TYPES.object: return ret === 0 ? null : {};
|
162
163
|
|
163
|
-
case
|
164
|
+
case TYPES.string: {
|
165
|
+
const pointer = ret;
|
166
|
+
const length = new Int32Array(memory.buffer, pointer, 1);
|
167
|
+
|
168
|
+
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
169
|
+
}
|
170
|
+
|
171
|
+
case TYPES.function: {
|
172
|
+
// wasm func index, including all imports
|
173
|
+
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
174
|
+
// if (!func) return ret;
|
175
|
+
if (!func) return function () {};
|
176
|
+
|
177
|
+
// make fake empty func for repl/etc
|
178
|
+
return {[func.name]() {}}[func.name];
|
179
|
+
}
|
180
|
+
|
181
|
+
case TYPES._array: {
|
164
182
|
const pointer = ret;
|
165
183
|
const length = new Int32Array(memory.buffer, pointer, 1);
|
166
184
|
|
@@ -170,20 +188,15 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
170
188
|
return Array.from(new Float64Array(buf));
|
171
189
|
}
|
172
190
|
|
173
|
-
case
|
191
|
+
case TYPES._bytestring: {
|
174
192
|
const pointer = ret;
|
175
193
|
const length = new Int32Array(memory.buffer, pointer, 1);
|
176
194
|
|
177
|
-
return Array.from(new
|
195
|
+
return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
178
196
|
}
|
179
197
|
|
180
|
-
case
|
181
|
-
|
182
|
-
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
183
|
-
if (!func) return ret;
|
184
|
-
|
185
|
-
// make fake empty func for repl/etc
|
186
|
-
return {[func.name]() {}}[func.name];
|
198
|
+
case TYPES._date: {
|
199
|
+
return new Date(ret);
|
187
200
|
}
|
188
201
|
|
189
202
|
default: return ret;
|
package/package.json
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
|
4
|
-
"version": "0.2.0-
|
4
|
+
"version": "0.2.0-b9abe0d",
|
5
5
|
"author": "CanadaHonk",
|
6
6
|
"license": "MIT",
|
7
|
+
"scripts": {
|
8
|
+
"precompile": "node ./compiler/precompile.js"
|
9
|
+
},
|
7
10
|
"dependencies": {
|
8
|
-
"acorn": "^8.
|
11
|
+
"acorn": "^8.11.3",
|
12
|
+
"node-repl-polyfill": "^0.1.1"
|
9
13
|
},
|
10
14
|
"optionalDependencies": {
|
11
|
-
"@babel/parser": "^7.
|
15
|
+
"@babel/parser": "^7.24.4",
|
12
16
|
"hermes-parser": "^0.18.2",
|
13
17
|
"meriyah": "^4.3.9"
|
14
18
|
},
|
15
19
|
"bin": {
|
16
20
|
"porf": "./runner/index.js"
|
17
21
|
},
|
18
|
-
"main": "./
|
22
|
+
"main": "./compiler/wrap.js",
|
19
23
|
"type": "module",
|
20
24
|
"repository": {
|
21
25
|
"type": "git",
|
@@ -25,4 +29,4 @@
|
|
25
29
|
"url": "https://github.com/CanadaHonk/porffor/issues"
|
26
30
|
},
|
27
31
|
"homepage": "https://porffor.goose.icu"
|
28
|
-
}
|
32
|
+
}
|
package/porf
ADDED
package/rhemyn/compile.js
CHANGED
@@ -2,6 +2,7 @@ import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../compiler/
|
|
2
2
|
import { number } from '../compiler/embedding.js';
|
3
3
|
import { signedLEB128, unsignedLEB128 } from '../compiler/encoding.js';
|
4
4
|
import parse from './parse.js';
|
5
|
+
import Prefs from '../compiler/prefs.js';
|
5
6
|
|
6
7
|
// local indexes
|
7
8
|
const BasePointer = 0; // base string pointer
|
@@ -80,7 +81,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
|
|
80
81
|
})[func], Valtype.i32)
|
81
82
|
];
|
82
83
|
|
83
|
-
if (
|
84
|
+
if (Prefs.regexLog) {
|
84
85
|
const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
|
85
86
|
console.log(`\n${underline('ast')}`);
|
86
87
|
console.log(node);
|
@@ -159,7 +160,7 @@ const generateSet = (node, negated, get) => {
|
|
159
160
|
];
|
160
161
|
}
|
161
162
|
|
162
|
-
out = out.concat(new Array(node.body.length - 1).fill(negated ? [ Opcodes.i32_or ] : [ Opcodes.i32_and ]));
|
163
|
+
if (node.body.length > 0) out = out.concat(new Array(node.body.length - 1).fill(negated ? [ Opcodes.i32_or ] : [ Opcodes.i32_and ]));
|
163
164
|
|
164
165
|
return [
|
165
166
|
...out,
|
@@ -187,7 +188,8 @@ const generateRange = (node, negated, get) => {
|
|
187
188
|
};
|
188
189
|
|
189
190
|
const generateGroup = (node, negated, get) => {
|
190
|
-
|
191
|
+
// todo
|
192
|
+
return [];
|
191
193
|
};
|
192
194
|
|
193
195
|
export const test = (regex, index = 0, name = 'regex_test_' + regex) => outputFunc(generate(parse(regex), false, true, 'test'), name, index);
|