porffor 0.17.0-a818353a5 → 0.17.0-b4e7f7ee0
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/compiler/2c.js +28 -11
- package/compiler/builtins/array.ts +22 -0
- package/compiler/builtins/math.ts +6 -2
- package/compiler/builtins/set.ts +2 -9
- package/compiler/builtins/typedarray.js +42 -0
- package/compiler/builtins.js +25 -0
- package/compiler/codegen.js +412 -24
- package/compiler/generated_builtins.js +316 -134
- package/compiler/pgo.js +9 -1
- package/compiler/types.js +31 -5
- package/compiler/wasmSpec.js +2 -0
- package/compiler/wrap.js +20 -5
- package/package.json +1 -1
- package/rhemyn/README.md +7 -4
- package/rhemyn/compile.js +129 -55
- package/runner/debug.js +1 -1
- package/runner/index.js +3 -3
- package/runner/profile.js +1 -1
- package/runner/repl.js +16 -11
package/compiler/codegen.js
CHANGED
@@ -4,7 +4,7 @@ import { operatorOpcode } from './expression.js';
|
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
5
|
import { PrototypeFuncs } from './prototype.js';
|
6
6
|
import { number } from './embedding.js';
|
7
|
-
import { TYPES, TYPE_NAMES } from './types.js';
|
7
|
+
import { TYPES, TYPE_FLAGS, TYPE_NAMES, typeHasFlag } from './types.js';
|
8
8
|
import * as Rhemyn from '../rhemyn/compile.js';
|
9
9
|
import parse from './parse.js';
|
10
10
|
import { log } from './log.js';
|
@@ -72,6 +72,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
72
72
|
case 'ExpressionStatement':
|
73
73
|
return generateExp(scope, decl);
|
74
74
|
|
75
|
+
case 'SequenceExpression':
|
76
|
+
return generateSequence(scope, decl);
|
77
|
+
|
75
78
|
case 'CallExpression':
|
76
79
|
return generateCall(scope, decl, global, name, valueUnused);
|
77
80
|
|
@@ -616,11 +619,14 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
616
619
|
};
|
617
620
|
|
618
621
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
622
|
+
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
623
|
+
...wasm,
|
624
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
625
|
+
];
|
626
|
+
if (isIntOp(wasm[wasm.length - 1])) return [
|
627
|
+
...wasm,
|
628
|
+
...(intOut ? [] : [ Opcodes.i32_from ]),
|
629
|
+
];
|
624
630
|
|
625
631
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
626
632
|
|
@@ -976,6 +982,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
976
982
|
};
|
977
983
|
|
978
984
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
985
|
+
if (decl.operator === 'instanceof') {
|
986
|
+
// very hacky basic instanceof
|
987
|
+
// todo: support dynamic right-hand side
|
988
|
+
|
989
|
+
const out = generate(scope, decl.left);
|
990
|
+
disposeLeftover(out);
|
991
|
+
|
992
|
+
const rightName = decl.right.name;
|
993
|
+
if (!rightName) return todo(scope, 'instanceof dynamic right-hand side is not supported yet', true);
|
994
|
+
|
995
|
+
const checkType = TYPES[rightName.toLowerCase()];
|
996
|
+
if (checkType == null || rightName !== TYPE_NAMES[checkType] || checkType === TYPES.undefined) return todo(scope, 'instanceof right-hand side type unsupported', true);
|
997
|
+
|
998
|
+
if ([TYPES.number, TYPES.boolean, TYPES.string, TYPES.symbol, TYPES.object].includes(checkType)) {
|
999
|
+
out.push(...number(0));
|
1000
|
+
} else {
|
1001
|
+
out.push(
|
1002
|
+
...getNodeType(scope, decl.left),
|
1003
|
+
...number(checkType, Valtype.i32),
|
1004
|
+
[ Opcodes.i32_eq ],
|
1005
|
+
Opcodes.i32_from_u
|
1006
|
+
);
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
return out;
|
1010
|
+
}
|
1011
|
+
|
979
1012
|
const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
|
980
1013
|
|
981
1014
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1282,7 +1315,7 @@ const getNodeType = (scope, node) => {
|
|
1282
1315
|
}
|
1283
1316
|
|
1284
1317
|
if (node.type === 'BinaryExpression') {
|
1285
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1318
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1286
1319
|
if (node.operator !== '+') return TYPES.number;
|
1287
1320
|
|
1288
1321
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1315,7 +1348,7 @@ const getNodeType = (scope, node) => {
|
|
1315
1348
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1316
1349
|
if (objectKnownType != null) {
|
1317
1350
|
if (name === 'length') {
|
1318
|
-
if (
|
1351
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1319
1352
|
else return TYPES.undefined;
|
1320
1353
|
}
|
1321
1354
|
|
@@ -1387,9 +1420,9 @@ const countLeftover = wasm => {
|
|
1387
1420
|
|
1388
1421
|
if (depth === 0)
|
1389
1422
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1390
|
-
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.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1423
|
+
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.f32_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1391
1424
|
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const, Opcodes.memory_size].includes(inst[0])) count++;
|
1392
|
-
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1425
|
+
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.f32_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1393
1426
|
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1394
1427
|
else if (inst[0] === Opcodes.return) count = 0;
|
1395
1428
|
else if (inst[0] === Opcodes.call) {
|
@@ -1427,6 +1460,18 @@ const generateExp = (scope, decl) => {
|
|
1427
1460
|
return out;
|
1428
1461
|
};
|
1429
1462
|
|
1463
|
+
const generateSequence = (scope, decl) => {
|
1464
|
+
let out = [];
|
1465
|
+
|
1466
|
+
const exprs = decl.expressions;
|
1467
|
+
for (let i = 0; i < exprs.length; i++) {
|
1468
|
+
if (i > 0) disposeLeftover(out);
|
1469
|
+
out.push(...generate(scope, exprs[i]));
|
1470
|
+
}
|
1471
|
+
|
1472
|
+
return out;
|
1473
|
+
};
|
1474
|
+
|
1430
1475
|
const CTArrayUtil = {
|
1431
1476
|
getLengthI32: pointer => [
|
1432
1477
|
...number(0, Valtype.i32),
|
@@ -2015,7 +2060,7 @@ const unhackName = name => {
|
|
2015
2060
|
|
2016
2061
|
const knownType = (scope, type) => {
|
2017
2062
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2018
|
-
return type[0]
|
2063
|
+
return read_signedLEB128(type[0].slice(1));
|
2019
2064
|
}
|
2020
2065
|
|
2021
2066
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2302,11 +2347,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2302
2347
|
const { type, name } = decl.left;
|
2303
2348
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2304
2349
|
|
2305
|
-
if (type === 'ObjectPattern') {
|
2306
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2307
|
-
return generate(scope, decl.right);
|
2308
|
-
}
|
2309
|
-
|
2310
2350
|
if (isFuncType(decl.right.type)) {
|
2311
2351
|
// hack for a = function () { ... }
|
2312
2352
|
decl.right.id = { name };
|
@@ -2379,10 +2419,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2379
2419
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2380
2420
|
], getNodeType(scope, decl.right), false, name, true)),
|
2381
2421
|
[ Opcodes.local_tee, newValueTmp ],
|
2382
|
-
|
2383
2422
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2384
2423
|
],
|
2385
2424
|
|
2425
|
+
...wrapBC({
|
2426
|
+
[TYPES.uint8array]: [
|
2427
|
+
[ Opcodes.i32_add ],
|
2428
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2429
|
+
|
2430
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2431
|
+
[ Opcodes.local_get, pointerTmp ],
|
2432
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2433
|
+
Opcodes.i32_from_u
|
2434
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2435
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2436
|
+
|
2437
|
+
Opcodes.i32_to_u,
|
2438
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2439
|
+
],
|
2440
|
+
[TYPES.uint8clampedarray]: [
|
2441
|
+
[ Opcodes.i32_add ],
|
2442
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2443
|
+
|
2444
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2445
|
+
[ Opcodes.local_get, pointerTmp ],
|
2446
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2447
|
+
Opcodes.i32_from_u
|
2448
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2449
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2450
|
+
|
2451
|
+
...number(0),
|
2452
|
+
[ Opcodes.f64_max ],
|
2453
|
+
...number(255),
|
2454
|
+
[ Opcodes.f64_min ],
|
2455
|
+
Opcodes.i32_to_u,
|
2456
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2457
|
+
],
|
2458
|
+
[TYPES.int8array]: [
|
2459
|
+
[ Opcodes.i32_add ],
|
2460
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2461
|
+
|
2462
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2463
|
+
[ Opcodes.local_get, pointerTmp ],
|
2464
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2465
|
+
Opcodes.i32_from
|
2466
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2467
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2468
|
+
|
2469
|
+
Opcodes.i32_to,
|
2470
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2471
|
+
],
|
2472
|
+
[TYPES.uint16array]: [
|
2473
|
+
...number(2, Valtype.i32),
|
2474
|
+
[ Opcodes.i32_mul ],
|
2475
|
+
[ Opcodes.i32_add ],
|
2476
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2477
|
+
|
2478
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2479
|
+
[ Opcodes.local_get, pointerTmp ],
|
2480
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
2481
|
+
Opcodes.i32_from_u
|
2482
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2483
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2484
|
+
|
2485
|
+
Opcodes.i32_to_u,
|
2486
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2487
|
+
],
|
2488
|
+
[TYPES.int16array]: [
|
2489
|
+
...number(2, Valtype.i32),
|
2490
|
+
[ Opcodes.i32_mul ],
|
2491
|
+
[ Opcodes.i32_add ],
|
2492
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2493
|
+
|
2494
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2495
|
+
[ Opcodes.local_get, pointerTmp ],
|
2496
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2497
|
+
Opcodes.i32_from
|
2498
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2499
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2500
|
+
|
2501
|
+
Opcodes.i32_to,
|
2502
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2503
|
+
],
|
2504
|
+
[TYPES.uint32array]: [
|
2505
|
+
...number(4, Valtype.i32),
|
2506
|
+
[ Opcodes.i32_mul ],
|
2507
|
+
[ Opcodes.i32_add ],
|
2508
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2509
|
+
|
2510
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2511
|
+
[ Opcodes.local_get, pointerTmp ],
|
2512
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2513
|
+
Opcodes.i32_from_u
|
2514
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2515
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2516
|
+
|
2517
|
+
Opcodes.i32_to_u,
|
2518
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2519
|
+
],
|
2520
|
+
[TYPES.int32array]: [
|
2521
|
+
...number(4, Valtype.i32),
|
2522
|
+
[ Opcodes.i32_mul ],
|
2523
|
+
[ Opcodes.i32_add ],
|
2524
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2525
|
+
|
2526
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2527
|
+
[ Opcodes.local_get, pointerTmp ],
|
2528
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2529
|
+
Opcodes.i32_from
|
2530
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2531
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2532
|
+
|
2533
|
+
Opcodes.i32_to,
|
2534
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2535
|
+
],
|
2536
|
+
[TYPES.float32array]: [
|
2537
|
+
...number(4, Valtype.i32),
|
2538
|
+
[ Opcodes.i32_mul ],
|
2539
|
+
[ Opcodes.i32_add ],
|
2540
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2541
|
+
|
2542
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2543
|
+
[ Opcodes.local_get, pointerTmp ],
|
2544
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2545
|
+
[ Opcodes.f64_promote_f32 ]
|
2546
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2547
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2548
|
+
|
2549
|
+
[ Opcodes.f32_demote_f64 ],
|
2550
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2551
|
+
],
|
2552
|
+
[TYPES.float64array]: [
|
2553
|
+
...number(8, Valtype.i32),
|
2554
|
+
[ Opcodes.i32_mul ],
|
2555
|
+
[ Opcodes.i32_add ],
|
2556
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2557
|
+
|
2558
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2559
|
+
[ Opcodes.local_get, pointerTmp ],
|
2560
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2561
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2562
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2563
|
+
|
2564
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2565
|
+
],
|
2566
|
+
}, {
|
2567
|
+
prelude: [
|
2568
|
+
...generate(scope, decl.left.object),
|
2569
|
+
Opcodes.i32_to_u,
|
2570
|
+
...generate(scope, decl.left.property),
|
2571
|
+
Opcodes.i32_to_u,
|
2572
|
+
],
|
2573
|
+
postlude: setLastType(scope, TYPES.number)
|
2574
|
+
}),
|
2575
|
+
|
2386
2576
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2387
2577
|
}, Blocktype.void),
|
2388
2578
|
|
@@ -2766,7 +2956,9 @@ const generateForOf = (scope, decl) => {
|
|
2766
2956
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2767
2957
|
// hack: this is naughty and will break things!
|
2768
2958
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2769
|
-
|
2959
|
+
|
2960
|
+
const known = knownType(scope, getNodeType(scope, decl.right));
|
2961
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
2770
2962
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2771
2963
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2772
2964
|
rawElements: new Array(0)
|
@@ -2814,6 +3006,7 @@ const generateForOf = (scope, decl) => {
|
|
2814
3006
|
[ Opcodes.end ],
|
2815
3007
|
[ Opcodes.end ]
|
2816
3008
|
],
|
3009
|
+
|
2817
3010
|
[TYPES.string]: [
|
2818
3011
|
...setType(scope, leftName, TYPES.string),
|
2819
3012
|
|
@@ -2922,6 +3115,7 @@ const generateForOf = (scope, decl) => {
|
|
2922
3115
|
[ Opcodes.end ],
|
2923
3116
|
[ Opcodes.end ]
|
2924
3117
|
],
|
3118
|
+
|
2925
3119
|
[TYPES.set]: [
|
2926
3120
|
[ Opcodes.loop, Blocktype.void ],
|
2927
3121
|
|
@@ -2960,6 +3154,106 @@ const generateForOf = (scope, decl) => {
|
|
2960
3154
|
[ Opcodes.end ],
|
2961
3155
|
[ Opcodes.end ]
|
2962
3156
|
],
|
3157
|
+
|
3158
|
+
...wrapBC({
|
3159
|
+
[TYPES.uint8array]: [
|
3160
|
+
[ Opcodes.i32_add ],
|
3161
|
+
|
3162
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3163
|
+
Opcodes.i32_from_u
|
3164
|
+
],
|
3165
|
+
[TYPES.uint8clampedarray]: [
|
3166
|
+
[ Opcodes.i32_add ],
|
3167
|
+
|
3168
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3169
|
+
Opcodes.i32_from_u
|
3170
|
+
],
|
3171
|
+
[TYPES.int8array]: [
|
3172
|
+
[ Opcodes.i32_add ],
|
3173
|
+
|
3174
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3175
|
+
Opcodes.i32_from
|
3176
|
+
],
|
3177
|
+
[TYPES.uint16array]: [
|
3178
|
+
...number(2, Valtype.i32),
|
3179
|
+
[ Opcodes.i32_mul ],
|
3180
|
+
[ Opcodes.i32_add ],
|
3181
|
+
|
3182
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3183
|
+
Opcodes.i32_from_u
|
3184
|
+
],
|
3185
|
+
[TYPES.int16array]: [
|
3186
|
+
...number(2, Valtype.i32),
|
3187
|
+
[ Opcodes.i32_mul ],
|
3188
|
+
[ Opcodes.i32_add ],
|
3189
|
+
|
3190
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3191
|
+
Opcodes.i32_from
|
3192
|
+
],
|
3193
|
+
[TYPES.uint32array]: [
|
3194
|
+
...number(4, Valtype.i32),
|
3195
|
+
[ Opcodes.i32_mul ],
|
3196
|
+
[ Opcodes.i32_add ],
|
3197
|
+
|
3198
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3199
|
+
Opcodes.i32_from_u
|
3200
|
+
],
|
3201
|
+
[TYPES.int32array]: [
|
3202
|
+
...number(4, Valtype.i32),
|
3203
|
+
[ Opcodes.i32_mul ],
|
3204
|
+
[ Opcodes.i32_add ],
|
3205
|
+
|
3206
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3207
|
+
Opcodes.i32_from
|
3208
|
+
],
|
3209
|
+
[TYPES.float32array]: [
|
3210
|
+
...number(4, Valtype.i32),
|
3211
|
+
[ Opcodes.i32_mul ],
|
3212
|
+
[ Opcodes.i32_add ],
|
3213
|
+
|
3214
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3215
|
+
[ Opcodes.f64_promote_f32 ]
|
3216
|
+
],
|
3217
|
+
[TYPES.float64array]: [
|
3218
|
+
...number(8, Valtype.i32),
|
3219
|
+
[ Opcodes.i32_mul ],
|
3220
|
+
[ Opcodes.i32_add ],
|
3221
|
+
|
3222
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3223
|
+
],
|
3224
|
+
}, {
|
3225
|
+
prelude: [
|
3226
|
+
...setType(scope, leftName, TYPES.number),
|
3227
|
+
|
3228
|
+
[ Opcodes.loop, Blocktype.void ],
|
3229
|
+
|
3230
|
+
[ Opcodes.local_get, pointer ],
|
3231
|
+
[ Opcodes.local_get, counter ]
|
3232
|
+
],
|
3233
|
+
postlude: [
|
3234
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3235
|
+
|
3236
|
+
[ Opcodes.block, Blocktype.void ],
|
3237
|
+
[ Opcodes.block, Blocktype.void ],
|
3238
|
+
...generate(scope, decl.body),
|
3239
|
+
[ Opcodes.end ],
|
3240
|
+
|
3241
|
+
// increment counter by 1
|
3242
|
+
[ Opcodes.local_get, counter ],
|
3243
|
+
...number(1, Valtype.i32),
|
3244
|
+
[ Opcodes.i32_add ],
|
3245
|
+
[ Opcodes.local_tee, counter ],
|
3246
|
+
|
3247
|
+
// loop if counter != length
|
3248
|
+
[ Opcodes.local_get, length ],
|
3249
|
+
[ Opcodes.i32_ne ],
|
3250
|
+
[ Opcodes.br_if, 1 ],
|
3251
|
+
|
3252
|
+
[ Opcodes.end ],
|
3253
|
+
[ Opcodes.end ]
|
3254
|
+
]
|
3255
|
+
}),
|
3256
|
+
|
2963
3257
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2964
3258
|
}, Blocktype.void));
|
2965
3259
|
|
@@ -3048,13 +3342,14 @@ const generateThrow = (scope, decl) => {
|
|
3048
3342
|
idx: tags.length
|
3049
3343
|
});
|
3050
3344
|
|
3051
|
-
let exceptId = exceptions.
|
3345
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3346
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3052
3347
|
|
3053
3348
|
scope.exceptions ??= [];
|
3054
3349
|
scope.exceptions.push(exceptId);
|
3055
3350
|
|
3056
3351
|
return [
|
3057
|
-
|
3352
|
+
...number(exceptId, Valtype.i32),
|
3058
3353
|
[ Opcodes.throw, tags[0].idx ]
|
3059
3354
|
];
|
3060
3355
|
}
|
@@ -3121,7 +3416,7 @@ const generateThrow = (scope, decl) => {
|
|
3121
3416
|
scope.exceptions.push(exceptId);
|
3122
3417
|
|
3123
3418
|
return [
|
3124
|
-
|
3419
|
+
...number(exceptId, Valtype.i32),
|
3125
3420
|
...generate(scope, message),
|
3126
3421
|
...getNodeType(scope, message),
|
3127
3422
|
[ Opcodes.throw, tags[0].idx ]
|
@@ -3479,6 +3774,19 @@ const withType = (scope, wasm, type) => [
|
|
3479
3774
|
...setLastType(scope, type)
|
3480
3775
|
];
|
3481
3776
|
|
3777
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3778
|
+
const out = {};
|
3779
|
+
for (const x in bc) {
|
3780
|
+
out[x] = [
|
3781
|
+
...prelude,
|
3782
|
+
...bc[x],
|
3783
|
+
...postlude
|
3784
|
+
];
|
3785
|
+
}
|
3786
|
+
|
3787
|
+
return out;
|
3788
|
+
};
|
3789
|
+
|
3482
3790
|
const generateMember = (scope, decl, _global, _name) => {
|
3483
3791
|
const name = decl.object.name;
|
3484
3792
|
|
@@ -3532,7 +3840,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3532
3840
|
const type = getNodeType(scope, decl.object);
|
3533
3841
|
const known = knownType(scope, type);
|
3534
3842
|
if (known != null) {
|
3535
|
-
if (
|
3843
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3536
3844
|
...generate(scope, decl.object),
|
3537
3845
|
Opcodes.i32_to_u,
|
3538
3846
|
|
@@ -3544,7 +3852,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3544
3852
|
}
|
3545
3853
|
|
3546
3854
|
return [
|
3547
|
-
...
|
3855
|
+
...getNodeType(scope, decl.object),
|
3856
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3857
|
+
[ Opcodes.i32_and ],
|
3548
3858
|
[ Opcodes.if, valtypeBinary ],
|
3549
3859
|
...generate(scope, decl.object),
|
3550
3860
|
Opcodes.i32_to_u,
|
@@ -3593,7 +3903,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3593
3903
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3594
3904
|
// hack: this is naughty and will break things!
|
3595
3905
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3596
|
-
|
3906
|
+
|
3907
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3908
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3597
3909
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3598
3910
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3599
3911
|
rawElements: new Array(0)
|
@@ -3667,6 +3979,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3667
3979
|
...setLastType(scope, TYPES.bytestring)
|
3668
3980
|
],
|
3669
3981
|
|
3982
|
+
...wrapBC({
|
3983
|
+
[TYPES.uint8array]: [
|
3984
|
+
[ Opcodes.i32_add ],
|
3985
|
+
|
3986
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3987
|
+
Opcodes.i32_from_u
|
3988
|
+
],
|
3989
|
+
[TYPES.uint8clampedarray]: [
|
3990
|
+
[ Opcodes.i32_add ],
|
3991
|
+
|
3992
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3993
|
+
Opcodes.i32_from_u
|
3994
|
+
],
|
3995
|
+
[TYPES.int8array]: [
|
3996
|
+
[ Opcodes.i32_add ],
|
3997
|
+
|
3998
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3999
|
+
Opcodes.i32_from
|
4000
|
+
],
|
4001
|
+
[TYPES.uint16array]: [
|
4002
|
+
...number(2, Valtype.i32),
|
4003
|
+
[ Opcodes.i32_mul ],
|
4004
|
+
[ Opcodes.i32_add ],
|
4005
|
+
|
4006
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
4007
|
+
Opcodes.i32_from_u
|
4008
|
+
],
|
4009
|
+
[TYPES.int16array]: [
|
4010
|
+
...number(2, Valtype.i32),
|
4011
|
+
[ Opcodes.i32_mul ],
|
4012
|
+
[ Opcodes.i32_add ],
|
4013
|
+
|
4014
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
4015
|
+
Opcodes.i32_from
|
4016
|
+
],
|
4017
|
+
[TYPES.uint32array]: [
|
4018
|
+
...number(4, Valtype.i32),
|
4019
|
+
[ Opcodes.i32_mul ],
|
4020
|
+
[ Opcodes.i32_add ],
|
4021
|
+
|
4022
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4023
|
+
Opcodes.i32_from_u
|
4024
|
+
],
|
4025
|
+
[TYPES.int32array]: [
|
4026
|
+
...number(4, Valtype.i32),
|
4027
|
+
[ Opcodes.i32_mul ],
|
4028
|
+
[ Opcodes.i32_add ],
|
4029
|
+
|
4030
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4031
|
+
Opcodes.i32_from
|
4032
|
+
],
|
4033
|
+
[TYPES.float32array]: [
|
4034
|
+
...number(4, Valtype.i32),
|
4035
|
+
[ Opcodes.i32_mul ],
|
4036
|
+
[ Opcodes.i32_add ],
|
4037
|
+
|
4038
|
+
[ Opcodes.f32_load, 0, 4 ],
|
4039
|
+
[ Opcodes.f64_promote_f32 ]
|
4040
|
+
],
|
4041
|
+
[TYPES.float64array]: [
|
4042
|
+
...number(8, Valtype.i32),
|
4043
|
+
[ Opcodes.i32_mul ],
|
4044
|
+
[ Opcodes.i32_add ],
|
4045
|
+
|
4046
|
+
[ Opcodes.f64_load, 0, 4 ]
|
4047
|
+
],
|
4048
|
+
}, {
|
4049
|
+
prelude: [
|
4050
|
+
...object,
|
4051
|
+
Opcodes.i32_to_u,
|
4052
|
+
...property,
|
4053
|
+
Opcodes.i32_to_u
|
4054
|
+
],
|
4055
|
+
postlude: setLastType(scope, TYPES.number)
|
4056
|
+
}),
|
4057
|
+
|
3670
4058
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3671
4059
|
});
|
3672
4060
|
};
|