porffor 0.2.0-eaee2da → 0.2.0-f2bbe1f
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/README.md +1 -1
- package/compiler/codeGen.js +21 -99
- package/compiler/prototype.js +16 -171
- package/compiler/wasmSpec.js +0 -3
- package/compiler/wrap.js +1 -9
- package/package.json +1 -1
package/README.md
CHANGED
@@ -215,7 +215,7 @@ Basically none right now (other than giving people headaches). Potential ideas:
|
|
215
215
|
- More in future probably?
|
216
216
|
|
217
217
|
## Usage
|
218
|
-
Basically nothing will work :). See files in `test`
|
218
|
+
Basically nothing will work :). See files in `test` for examples.
|
219
219
|
|
220
220
|
1. Clone repo
|
221
221
|
2. `npm install`
|
package/compiler/codeGen.js
CHANGED
@@ -55,7 +55,7 @@ const todo = msg => {
|
|
55
55
|
};
|
56
56
|
|
57
57
|
const isFuncType = type => type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression';
|
58
|
-
const generate = (scope, decl, global = false, name = undefined
|
58
|
+
const generate = (scope, decl, global = false, name = undefined) => {
|
59
59
|
switch (decl.type) {
|
60
60
|
case 'BinaryExpression':
|
61
61
|
return generateBinaryExp(scope, decl, global, name);
|
@@ -86,7 +86,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
86
86
|
return generateExp(scope, decl);
|
87
87
|
|
88
88
|
case 'CallExpression':
|
89
|
-
return generateCall(scope, decl, global, name
|
89
|
+
return generateCall(scope, decl, global, name);
|
90
90
|
|
91
91
|
case 'NewExpression':
|
92
92
|
return generateNew(scope, decl, global, name);
|
@@ -685,15 +685,6 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
685
685
|
[ Opcodes.i32_eqz ], */
|
686
686
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
687
687
|
],
|
688
|
-
[TYPES._bytestring]: [ // duplicate of string
|
689
|
-
[ Opcodes.local_get, tmp ],
|
690
|
-
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
691
|
-
|
692
|
-
// get length
|
693
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
694
|
-
|
695
|
-
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
696
|
-
],
|
697
688
|
default: def
|
698
689
|
}, intOut ? Valtype.i32 : valtypeBinary)
|
699
690
|
];
|
@@ -721,17 +712,6 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
721
712
|
[ Opcodes.i32_eqz ],
|
722
713
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
723
714
|
],
|
724
|
-
[TYPES._bytestring]: [ // duplicate of string
|
725
|
-
[ Opcodes.local_get, tmp ],
|
726
|
-
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
727
|
-
|
728
|
-
// get length
|
729
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
730
|
-
|
731
|
-
// if length == 0
|
732
|
-
[ Opcodes.i32_eqz ],
|
733
|
-
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
734
|
-
],
|
735
715
|
default: [
|
736
716
|
// if value == 0
|
737
717
|
[ Opcodes.local_get, tmp ],
|
@@ -1064,8 +1044,7 @@ const TYPES = {
|
|
1064
1044
|
|
1065
1045
|
// these are not "typeof" types but tracked internally
|
1066
1046
|
_array: 0x10,
|
1067
|
-
_regexp: 0x11
|
1068
|
-
_bytestring: 0x12
|
1047
|
+
_regexp: 0x11
|
1069
1048
|
};
|
1070
1049
|
|
1071
1050
|
const TYPE_NAMES = {
|
@@ -1079,8 +1058,7 @@ const TYPE_NAMES = {
|
|
1079
1058
|
[TYPES.bigint]: 'BigInt',
|
1080
1059
|
|
1081
1060
|
[TYPES._array]: 'Array',
|
1082
|
-
[TYPES._regexp]: 'RegExp'
|
1083
|
-
[TYPES._bytestring]: 'ByteString'
|
1061
|
+
[TYPES._regexp]: 'RegExp'
|
1084
1062
|
};
|
1085
1063
|
|
1086
1064
|
const getType = (scope, _name) => {
|
@@ -1133,8 +1111,6 @@ const getNodeType = (scope, node) => {
|
|
1133
1111
|
if (node.type === 'Literal') {
|
1134
1112
|
if (node.regex) return TYPES._regexp;
|
1135
1113
|
|
1136
|
-
if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES._bytestring;
|
1137
|
-
|
1138
1114
|
return TYPES[typeof node.value];
|
1139
1115
|
}
|
1140
1116
|
|
@@ -1148,15 +1124,6 @@ const getNodeType = (scope, node) => {
|
|
1148
1124
|
|
1149
1125
|
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
1150
1126
|
const name = node.callee.name;
|
1151
|
-
if (!name) {
|
1152
|
-
// iife
|
1153
|
-
if (scope.locals['#last_type']) return [ getLastType(scope) ];
|
1154
|
-
|
1155
|
-
// presume
|
1156
|
-
// todo: warn here?
|
1157
|
-
return TYPES.number;
|
1158
|
-
}
|
1159
|
-
|
1160
1127
|
const func = funcs.find(x => x.name === name);
|
1161
1128
|
|
1162
1129
|
if (func) {
|
@@ -1251,7 +1218,7 @@ const getNodeType = (scope, node) => {
|
|
1251
1218
|
if (node.operator === '!') return TYPES.boolean;
|
1252
1219
|
if (node.operator === 'void') return TYPES.undefined;
|
1253
1220
|
if (node.operator === 'delete') return TYPES.boolean;
|
1254
|
-
if (node.operator === 'typeof') return
|
1221
|
+
if (node.operator === 'typeof') return TYPES.string;
|
1255
1222
|
|
1256
1223
|
return TYPES.number;
|
1257
1224
|
}
|
@@ -1332,9 +1299,9 @@ const countLeftover = wasm => {
|
|
1332
1299
|
|
1333
1300
|
if (depth === 0)
|
1334
1301
|
if ([Opcodes.throw,Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1335
|
-
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.
|
1302
|
+
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x0a)) {}
|
1336
1303
|
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const].includes(inst[0])) count++;
|
1337
|
-
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16
|
1304
|
+
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16].includes(inst[0])) count -= 2;
|
1338
1305
|
else if (Opcodes.memory_copy[0] === inst[0] && Opcodes.memory_copy[1] === inst[1]) count -= 3;
|
1339
1306
|
else if (inst[0] === Opcodes.return) count = 0;
|
1340
1307
|
else if (inst[0] === Opcodes.call) {
|
@@ -1360,7 +1327,7 @@ const disposeLeftover = wasm => {
|
|
1360
1327
|
const generateExp = (scope, decl) => {
|
1361
1328
|
const expression = decl.expression;
|
1362
1329
|
|
1363
|
-
const out = generate(scope, expression
|
1330
|
+
const out = generate(scope, expression);
|
1364
1331
|
disposeLeftover(out);
|
1365
1332
|
|
1366
1333
|
return out;
|
@@ -1418,7 +1385,7 @@ const RTArrayUtil = {
|
|
1418
1385
|
]
|
1419
1386
|
};
|
1420
1387
|
|
1421
|
-
const generateCall = (scope, decl, _global, _name
|
1388
|
+
const generateCall = (scope, decl, _global, _name) => {
|
1422
1389
|
/* const callee = decl.callee;
|
1423
1390
|
const args = decl.arguments;
|
1424
1391
|
|
@@ -1537,18 +1504,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1537
1504
|
// use local for cached i32 length as commonly used
|
1538
1505
|
const lengthLocal = localTmp(scope, '__proto_length_cache', Valtype.i32);
|
1539
1506
|
const pointerLocal = localTmp(scope, '__proto_pointer_cache', Valtype.i32);
|
1507
|
+
const getPointer = [ [ Opcodes.local_get, pointerLocal ] ];
|
1540
1508
|
|
1541
1509
|
// TODO: long-term, prototypes should be their individual separate funcs
|
1542
1510
|
|
1543
|
-
const rawPointer = [
|
1544
|
-
...generate(scope, target),
|
1545
|
-
Opcodes.i32_to_u
|
1546
|
-
];
|
1547
|
-
|
1548
|
-
const usePointerCache = !Object.values(protoCands).every(x => x.noPointerCache === true);
|
1549
|
-
const getPointer = usePointerCache ? [ [ Opcodes.local_get, pointerLocal ] ] : rawPointer;
|
1550
|
-
|
1551
|
-
let allOptUnused = true;
|
1552
1511
|
let lengthI32CacheUsed = false;
|
1553
1512
|
const protoBC = {};
|
1554
1513
|
for (const x in protoCands) {
|
@@ -1568,7 +1527,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1568
1527
|
const protoLocal = protoFunc.local ? localTmp(scope, `__${protoName}_tmp`, protoFunc.local) : -1;
|
1569
1528
|
const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
|
1570
1529
|
|
1571
|
-
let optUnused = false;
|
1572
1530
|
const protoOut = protoFunc(getPointer, {
|
1573
1531
|
getCachedI32: () => {
|
1574
1532
|
lengthI32CacheUsed = true;
|
@@ -1583,15 +1541,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1583
1541
|
return makeArray(scope, {
|
1584
1542
|
rawElements: new Array(length)
|
1585
1543
|
}, _global, _name, true, itemType);
|
1586
|
-
}, () => {
|
1587
|
-
optUnused = true;
|
1588
|
-
return unusedValue;
|
1589
1544
|
});
|
1590
1545
|
|
1591
|
-
if (!optUnused) allOptUnused = false;
|
1592
|
-
|
1593
1546
|
protoBC[x] = [
|
1594
|
-
[ Opcodes.block,
|
1547
|
+
[ Opcodes.block, valtypeBinary ],
|
1595
1548
|
...protoOut,
|
1596
1549
|
|
1597
1550
|
...number(protoFunc.returnType ?? TYPES.number, Valtype.i32),
|
@@ -1600,13 +1553,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1600
1553
|
];
|
1601
1554
|
}
|
1602
1555
|
|
1603
|
-
// todo: if some cands use optUnused and some don't, we will probably crash
|
1604
|
-
|
1605
1556
|
return [
|
1606
|
-
...(
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1557
|
+
...generate(scope, target),
|
1558
|
+
|
1559
|
+
Opcodes.i32_to_u,
|
1560
|
+
[ Opcodes.local_set, pointerLocal ],
|
1610
1561
|
|
1611
1562
|
...(!lengthI32CacheUsed ? [] : [
|
1612
1563
|
...RTArrayUtil.getLengthI32(getPointer),
|
@@ -1618,7 +1569,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1618
1569
|
|
1619
1570
|
// TODO: error better
|
1620
1571
|
default: internalThrow(scope, 'TypeError', `'${protoName}' proto func tried to be called on a type without an impl`)
|
1621
|
-
},
|
1572
|
+
}, valtypeBinary),
|
1622
1573
|
];
|
1623
1574
|
}
|
1624
1575
|
}
|
@@ -1826,8 +1777,6 @@ const brTable = (input, bc, returns) => {
|
|
1826
1777
|
};
|
1827
1778
|
|
1828
1779
|
const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
1829
|
-
if (!process.argv.includes('-bytestring')) delete bc[TYPES._bytestring];
|
1830
|
-
|
1831
1780
|
const known = knownType(scope, type);
|
1832
1781
|
if (known != null) {
|
1833
1782
|
return bc[known] ?? bc.default;
|
@@ -2218,8 +2167,6 @@ const generateUnary = (scope, decl) => {
|
|
2218
2167
|
[TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
|
2219
2168
|
[TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
|
2220
2169
|
|
2221
|
-
[TYPES._bytestring]: makeString(scope, 'string', false, '#typeof_result'),
|
2222
|
-
|
2223
2170
|
// object and internal types
|
2224
2171
|
default: makeString(scope, 'object', false, '#typeof_result'),
|
2225
2172
|
});
|
@@ -2408,7 +2355,6 @@ const generateForOf = (scope, decl) => {
|
|
2408
2355
|
}
|
2409
2356
|
|
2410
2357
|
// set type for local
|
2411
|
-
// todo: optimize away counter and use end pointer
|
2412
2358
|
out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
|
2413
2359
|
[TYPES._array]: [
|
2414
2360
|
...setType(scope, leftName, TYPES.number),
|
@@ -2627,8 +2573,7 @@ const StoreOps = {
|
|
2627
2573
|
f64: Opcodes.f64_store,
|
2628
2574
|
|
2629
2575
|
// expects i32 input!
|
2630
|
-
|
2631
|
-
i16: Opcodes.i32_store16,
|
2576
|
+
i16: Opcodes.i32_store16
|
2632
2577
|
};
|
2633
2578
|
|
2634
2579
|
let data = [];
|
@@ -2647,15 +2592,6 @@ const compileBytes = (val, itemType, signed = true) => {
|
|
2647
2592
|
}
|
2648
2593
|
};
|
2649
2594
|
|
2650
|
-
const getAllocType = itemType => {
|
2651
|
-
switch (itemType) {
|
2652
|
-
case 'i8': return 'bytestring';
|
2653
|
-
case 'i16': return 'string';
|
2654
|
-
|
2655
|
-
default: return 'array';
|
2656
|
-
}
|
2657
|
-
};
|
2658
|
-
|
2659
2595
|
const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false, itemType = valtype) => {
|
2660
2596
|
const out = [];
|
2661
2597
|
|
@@ -2665,7 +2601,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2665
2601
|
|
2666
2602
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
2667
2603
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
2668
|
-
arrays.set(name, allocPage(`${
|
2604
|
+
arrays.set(name, allocPage(`${itemType === 'i16' ? 'string' : 'array'}: ${uniqueName}`, itemType) * pageSize);
|
2669
2605
|
}
|
2670
2606
|
|
2671
2607
|
const pointer = arrays.get(name);
|
@@ -2711,7 +2647,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2711
2647
|
out.push(
|
2712
2648
|
...number(0, Valtype.i32),
|
2713
2649
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
2714
|
-
[ storeOp,
|
2650
|
+
[ storeOp, Math.log2(ValtypeSize[itemType]) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
|
2715
2651
|
);
|
2716
2652
|
}
|
2717
2653
|
|
@@ -2721,29 +2657,15 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2721
2657
|
return [ out, pointer ];
|
2722
2658
|
};
|
2723
2659
|
|
2724
|
-
const byteStringable = str => {
|
2725
|
-
if (!process.argv.includes('-bytestring')) return false;
|
2726
|
-
|
2727
|
-
for (let i = 0; i < str.length; i++) {
|
2728
|
-
if (str.charCodeAt(i) > 0xFF) return false;
|
2729
|
-
}
|
2730
|
-
|
2731
|
-
return true;
|
2732
|
-
};
|
2733
|
-
|
2734
2660
|
const makeString = (scope, str, global = false, name = '$undeclared') => {
|
2735
2661
|
const rawElements = new Array(str.length);
|
2736
|
-
let byteStringable = process.argv.includes('-bytestring');
|
2737
2662
|
for (let i = 0; i < str.length; i++) {
|
2738
|
-
|
2739
|
-
rawElements[i] = c;
|
2740
|
-
|
2741
|
-
if (byteStringable && c > 0xFF) byteStringable = false;
|
2663
|
+
rawElements[i] = str.charCodeAt(i);
|
2742
2664
|
}
|
2743
2665
|
|
2744
2666
|
return makeArray(scope, {
|
2745
2667
|
rawElements
|
2746
|
-
}, global, name, false,
|
2668
|
+
}, global, name, false, 'i16')[0];
|
2747
2669
|
};
|
2748
2670
|
|
2749
2671
|
let arrays = new Map();
|
package/compiler/prototype.js
CHANGED
@@ -16,8 +16,7 @@ const TYPES = {
|
|
16
16
|
|
17
17
|
// these are not "typeof" types but tracked internally
|
18
18
|
_array: 0x10,
|
19
|
-
_regexp: 0x11
|
20
|
-
_bytestring: 0x12
|
19
|
+
_regexp: 0x11
|
21
20
|
};
|
22
21
|
|
23
22
|
// todo: turn these into built-ins once arrays and these become less hacky
|
@@ -72,7 +71,7 @@ export const PrototypeFuncs = function() {
|
|
72
71
|
],
|
73
72
|
|
74
73
|
// todo: only for 1 argument
|
75
|
-
push: (pointer, length, wNewMember
|
74
|
+
push: (pointer, length, wNewMember) => [
|
76
75
|
// get memory offset of array at last index (length)
|
77
76
|
...length.getCachedI32(),
|
78
77
|
...number(ValtypeSize[valtype], Valtype.i32),
|
@@ -93,28 +92,22 @@ export const PrototypeFuncs = function() {
|
|
93
92
|
...number(1, Valtype.i32),
|
94
93
|
[ Opcodes.i32_add ],
|
95
94
|
|
96
|
-
...(
|
97
|
-
|
98
|
-
...length.getCachedI32(),
|
99
|
-
])
|
95
|
+
...length.setCachedI32(),
|
96
|
+
...length.getCachedI32(),
|
100
97
|
]),
|
101
98
|
|
102
|
-
...(
|
103
|
-
|
104
|
-
Opcodes.i32_from_u
|
105
|
-
])
|
99
|
+
...length.getCachedI32(),
|
100
|
+
Opcodes.i32_from_u
|
106
101
|
|
107
102
|
// ...length.get()
|
108
103
|
],
|
109
104
|
|
110
|
-
pop: (pointer, length
|
105
|
+
pop: (pointer, length) => [
|
111
106
|
// if length == 0, noop
|
112
107
|
...length.getCachedI32(),
|
113
108
|
[ Opcodes.i32_eqz ],
|
114
109
|
[ Opcodes.if, Blocktype.void ],
|
115
|
-
...(
|
116
|
-
...number(UNDEFINED),
|
117
|
-
]),
|
110
|
+
...number(UNDEFINED),
|
118
111
|
[ Opcodes.br, 1 ],
|
119
112
|
[ Opcodes.end ],
|
120
113
|
|
@@ -126,23 +119,19 @@ export const PrototypeFuncs = function() {
|
|
126
119
|
...number(1, Valtype.i32),
|
127
120
|
[ Opcodes.i32_sub ],
|
128
121
|
|
129
|
-
...(
|
130
|
-
|
131
|
-
...length.getCachedI32(),
|
132
|
-
])
|
122
|
+
...length.setCachedI32(),
|
123
|
+
...length.getCachedI32(),
|
133
124
|
]),
|
134
125
|
|
135
126
|
// load last element
|
136
|
-
...(
|
137
|
-
|
138
|
-
|
139
|
-
[ Opcodes.i32_mul ],
|
127
|
+
...length.getCachedI32(),
|
128
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
129
|
+
[ Opcodes.i32_mul ],
|
140
130
|
|
141
|
-
|
142
|
-
|
131
|
+
...pointer,
|
132
|
+
[ Opcodes.i32_add ],
|
143
133
|
|
144
|
-
|
145
|
-
])
|
134
|
+
[ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
|
146
135
|
],
|
147
136
|
|
148
137
|
shift: (pointer, length) => [
|
@@ -483,152 +472,8 @@ export const PrototypeFuncs = function() {
|
|
483
472
|
this[TYPES.string].at.returnType = TYPES.string;
|
484
473
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
485
474
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
486
|
-
this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
487
475
|
|
488
476
|
this[TYPES.string].isWellFormed.local = Valtype.i32;
|
489
477
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
490
478
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
491
|
-
|
492
|
-
if (process.argv.includes('-bytestring')) {
|
493
|
-
this[TYPES._bytestring] = {
|
494
|
-
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
495
|
-
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
496
|
-
|
497
|
-
return [
|
498
|
-
// setup new/out array
|
499
|
-
...newOut,
|
500
|
-
[ Opcodes.drop ],
|
501
|
-
|
502
|
-
...number(0, Valtype.i32), // base 0 for store later
|
503
|
-
|
504
|
-
...wIndex,
|
505
|
-
Opcodes.i32_to_u,
|
506
|
-
[ Opcodes.local_tee, iTmp ],
|
507
|
-
|
508
|
-
// if index < 0: access index + array length
|
509
|
-
...number(0, Valtype.i32),
|
510
|
-
[ Opcodes.i32_lt_s ],
|
511
|
-
[ Opcodes.if, Blocktype.void ],
|
512
|
-
[ Opcodes.local_get, iTmp ],
|
513
|
-
...length.getCachedI32(),
|
514
|
-
[ Opcodes.i32_add ],
|
515
|
-
[ Opcodes.local_set, iTmp ],
|
516
|
-
[ Opcodes.end ],
|
517
|
-
|
518
|
-
// if still < 0 or >= length: return undefined
|
519
|
-
[ Opcodes.local_get, iTmp ],
|
520
|
-
...number(0, Valtype.i32),
|
521
|
-
[ Opcodes.i32_lt_s ],
|
522
|
-
|
523
|
-
[ Opcodes.local_get, iTmp ],
|
524
|
-
...length.getCachedI32(),
|
525
|
-
[ Opcodes.i32_ge_s ],
|
526
|
-
[ Opcodes.i32_or ],
|
527
|
-
|
528
|
-
[ Opcodes.if, Blocktype.void ],
|
529
|
-
...number(UNDEFINED),
|
530
|
-
[ Opcodes.br, 1 ],
|
531
|
-
[ Opcodes.end ],
|
532
|
-
|
533
|
-
[ Opcodes.local_get, iTmp ],
|
534
|
-
|
535
|
-
...pointer,
|
536
|
-
[ Opcodes.i32_add ],
|
537
|
-
|
538
|
-
// load current string ind {arg}
|
539
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
540
|
-
|
541
|
-
// store to new string ind 0
|
542
|
-
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
543
|
-
|
544
|
-
// return new string (pointer)
|
545
|
-
...number(newPointer)
|
546
|
-
];
|
547
|
-
},
|
548
|
-
|
549
|
-
// todo: out of bounds properly
|
550
|
-
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
551
|
-
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
552
|
-
|
553
|
-
return [
|
554
|
-
// setup new/out array
|
555
|
-
...newOut,
|
556
|
-
[ Opcodes.drop ],
|
557
|
-
|
558
|
-
...number(0, Valtype.i32), // base 0 for store later
|
559
|
-
|
560
|
-
...wIndex,
|
561
|
-
|
562
|
-
Opcodes.i32_to,
|
563
|
-
|
564
|
-
...pointer,
|
565
|
-
[ Opcodes.i32_add ],
|
566
|
-
|
567
|
-
// load current string ind {arg}
|
568
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
569
|
-
|
570
|
-
// store to new string ind 0
|
571
|
-
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
572
|
-
|
573
|
-
// return new string (page)
|
574
|
-
...number(newPointer)
|
575
|
-
];
|
576
|
-
},
|
577
|
-
|
578
|
-
charCodeAt: (pointer, length, wIndex, iTmp) => {
|
579
|
-
return [
|
580
|
-
...wIndex,
|
581
|
-
Opcodes.i32_to,
|
582
|
-
|
583
|
-
...(zeroChecks.charcodeat ? [] : [
|
584
|
-
[ Opcodes.local_set, iTmp ],
|
585
|
-
|
586
|
-
// index < 0
|
587
|
-
...(noUnlikelyChecks ? [] : [
|
588
|
-
[ Opcodes.local_get, iTmp ],
|
589
|
-
...number(0, Valtype.i32),
|
590
|
-
[ Opcodes.i32_lt_s ],
|
591
|
-
]),
|
592
|
-
|
593
|
-
// index >= length
|
594
|
-
[ Opcodes.local_get, iTmp ],
|
595
|
-
...length.getCachedI32(),
|
596
|
-
[ Opcodes.i32_ge_s ],
|
597
|
-
|
598
|
-
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
599
|
-
[ Opcodes.if, Blocktype.void ],
|
600
|
-
...number(NaN),
|
601
|
-
[ Opcodes.br, 1 ],
|
602
|
-
[ Opcodes.end ],
|
603
|
-
|
604
|
-
[ Opcodes.local_get, iTmp ],
|
605
|
-
]),
|
606
|
-
|
607
|
-
...pointer,
|
608
|
-
[ Opcodes.i32_add ],
|
609
|
-
|
610
|
-
// load current string ind {arg}
|
611
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
612
|
-
Opcodes.i32_from_u
|
613
|
-
];
|
614
|
-
},
|
615
|
-
|
616
|
-
isWellFormed: () => {
|
617
|
-
return [
|
618
|
-
// we know it must be true as it is a bytestring lol
|
619
|
-
...number(1)
|
620
|
-
]
|
621
|
-
}
|
622
|
-
};
|
623
|
-
|
624
|
-
this[TYPES._bytestring].at.local = Valtype.i32;
|
625
|
-
this[TYPES._bytestring].at.returnType = TYPES._bytestring;
|
626
|
-
this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
|
627
|
-
this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
|
628
|
-
this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
629
|
-
|
630
|
-
this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
|
631
|
-
this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
|
632
|
-
this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
|
633
|
-
}
|
634
479
|
};
|
package/compiler/wasmSpec.js
CHANGED
package/compiler/wrap.js
CHANGED
@@ -19,8 +19,7 @@ const TYPES = {
|
|
19
19
|
|
20
20
|
// internal
|
21
21
|
[internalTypeBase]: '_array',
|
22
|
-
[internalTypeBase + 1]: '_regexp'
|
23
|
-
[internalTypeBase + 2]: '_bytestring'
|
22
|
+
[internalTypeBase + 1]: '_regexp'
|
24
23
|
};
|
25
24
|
|
26
25
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
@@ -178,13 +177,6 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
178
177
|
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
179
178
|
}
|
180
179
|
|
181
|
-
case '_bytestring': {
|
182
|
-
const pointer = ret;
|
183
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
184
|
-
|
185
|
-
return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
186
|
-
}
|
187
|
-
|
188
180
|
case 'function': {
|
189
181
|
// wasm func index, including all imports
|
190
182
|
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
package/package.json
CHANGED