porffor 0.17.0-a818353a5 → 0.17.0-b103c8894
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/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 +14 -0
- package/compiler/codegen.js +298 -16
- package/compiler/generated_builtins.js +304 -122
- package/compiler/types.js +31 -5
- package/compiler/wasmSpec.js +2 -0
- package/compiler/wrap.js +14 -1
- package/package.json +1 -1
- package/runner/repl.js +11 -6
@@ -225,6 +225,16 @@ export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
|
|
225
225
|
return true;
|
226
226
|
};
|
227
227
|
|
228
|
+
export const __Array_prototype_some = (_this: any[], callbackFn: any) => {
|
229
|
+
const len: i32 = _this.length;
|
230
|
+
let i: i32 = 0;
|
231
|
+
while (i < len) {
|
232
|
+
if (Boolean(callbackFn(_this[i], i++, _this))) return true;
|
233
|
+
}
|
234
|
+
|
235
|
+
return false;
|
236
|
+
};
|
237
|
+
|
228
238
|
export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialValue: any) => {
|
229
239
|
let acc: any = initialValue ?? _this[0];
|
230
240
|
|
@@ -237,6 +247,18 @@ export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialV
|
|
237
247
|
return acc;
|
238
248
|
};
|
239
249
|
|
250
|
+
export const __Array_prototype_reduceRight = (_this: any[], callbackFn: any, initialValue: any) => {
|
251
|
+
const len: i32 = _this.length;
|
252
|
+
let acc: any = initialValue ?? _this[len - 1];
|
253
|
+
|
254
|
+
let i: i32 = len;
|
255
|
+
while (i > 0) {
|
256
|
+
acc = callbackFn(acc, _this[i], --i, _this);
|
257
|
+
}
|
258
|
+
|
259
|
+
return acc;
|
260
|
+
};
|
261
|
+
|
240
262
|
export const __Array_prototype_toString = (_this: any[]) => {
|
241
263
|
// todo: this is bytestring only!
|
242
264
|
|
@@ -16,7 +16,7 @@ export const __Math_exp = (x: number): number => {
|
|
16
16
|
return 1 / Math.exp(-x);
|
17
17
|
}
|
18
18
|
|
19
|
-
|
19
|
+
let k: number = Math.floor(x / Math.LN2);
|
20
20
|
const r: number = x - k * Math.LN2;
|
21
21
|
|
22
22
|
// Taylor series via Horner's method
|
@@ -30,7 +30,11 @@ export const __Math_exp = (x: number): number => {
|
|
30
30
|
i++;
|
31
31
|
}
|
32
32
|
|
33
|
-
|
33
|
+
while (k-- > 0) {
|
34
|
+
sum *= 2;
|
35
|
+
}
|
36
|
+
|
37
|
+
return sum;
|
34
38
|
};
|
35
39
|
|
36
40
|
export const __Math_log2 = (y: number): number => {
|
package/compiler/builtins/set.ts
CHANGED
@@ -170,15 +170,8 @@ export const Set = () => {
|
|
170
170
|
export const Set$constructor = (iterable: any): Set => {
|
171
171
|
const out: Set = __Porffor_allocate();
|
172
172
|
|
173
|
-
|
174
|
-
|
175
|
-
type == Porffor.TYPES.array,
|
176
|
-
type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
|
177
|
-
type == Porffor.TYPES.set
|
178
|
-
)) {
|
179
|
-
for (const x of iterable) {
|
180
|
-
__Set_prototype_add(out, x);
|
181
|
-
}
|
173
|
+
if (Porffor.rawType(iterable) != Porffor.TYPES.undefined) for (const x of iterable) {
|
174
|
+
__Set_prototype_add(out, x);
|
182
175
|
}
|
183
176
|
|
184
177
|
return out;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
export default () => {
|
2
|
+
let out = '';
|
3
|
+
|
4
|
+
const constr = name => out += `export const ${name} = () => {
|
5
|
+
throw new TypeError("Constructor ${name} requires 'new'");
|
6
|
+
};
|
7
|
+
|
8
|
+
export const ${name}$constructor = (arg: any): ${name} => {
|
9
|
+
const out: ${name} = Porffor.allocate();
|
10
|
+
let len: i32 = 0;
|
11
|
+
|
12
|
+
const type: i32 = Porffor.rawType(arg);
|
13
|
+
if (Porffor.fastOr(
|
14
|
+
type == Porffor.TYPES.array,
|
15
|
+
type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
|
16
|
+
type == Porffor.TYPES.set
|
17
|
+
)) {
|
18
|
+
let i: i32 = 0;
|
19
|
+
for (const x of arg) {
|
20
|
+
out[i++] = x;
|
21
|
+
}
|
22
|
+
len = i;
|
23
|
+
} else if (type == Porffor.TYPES.number) {
|
24
|
+
len = arg;
|
25
|
+
}
|
26
|
+
|
27
|
+
out.length = len;
|
28
|
+
return out;
|
29
|
+
};`;
|
30
|
+
|
31
|
+
constr('Uint8Array');
|
32
|
+
constr('Int8Array');
|
33
|
+
constr('Uint8ClampedArray');
|
34
|
+
constr('Uint16Array');
|
35
|
+
constr('Int16Array');
|
36
|
+
constr('Uint32Array');
|
37
|
+
constr('Int32Array');
|
38
|
+
constr('Float32Array');
|
39
|
+
constr('Float64Array');
|
40
|
+
|
41
|
+
return out;
|
42
|
+
};
|
package/compiler/builtins.js
CHANGED
@@ -184,6 +184,20 @@ export const BuiltinFuncs = function() {
|
|
184
184
|
]
|
185
185
|
};
|
186
186
|
|
187
|
+
this['f64_**'] = this['i32_**'] = {
|
188
|
+
params: [ valtypeBinary, valtypeBinary ],
|
189
|
+
locals: [],
|
190
|
+
returns: [ valtypeBinary ],
|
191
|
+
returnType: TYPES.number,
|
192
|
+
wasm: (scope, { builtin }) => [
|
193
|
+
[ Opcodes.local_get, 0 ],
|
194
|
+
...number(TYPES.number, Valtype.i32),
|
195
|
+
[ Opcodes.local_get, 1 ],
|
196
|
+
...number(TYPES.number, Valtype.i32),
|
197
|
+
[ Opcodes.call, builtin('__Math_pow') ]
|
198
|
+
]
|
199
|
+
};
|
200
|
+
|
187
201
|
// add bitwise ops by converting operands to i32 first
|
188
202
|
for (const [ char, op ] of [ ['&', Opcodes.i32_and], ['|', Opcodes.i32_or], ['^', Opcodes.i32_xor], ['<<', Opcodes.i32_shl], ['>>', Opcodes.i32_shr_s], ['>>>', Opcodes.i32_shr_u] ]) {
|
189
203
|
this[`f64_${char}`] = {
|
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
|
|
@@ -976,6 +979,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
976
979
|
};
|
977
980
|
|
978
981
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
982
|
+
if (decl.operator === 'instanceof') {
|
983
|
+
// very hacky basic instanceof
|
984
|
+
// todo: support dynamic right-hand side
|
985
|
+
|
986
|
+
const out = generate(scope, decl.left);
|
987
|
+
disposeLeftover(out);
|
988
|
+
|
989
|
+
const rightName = decl.right.name;
|
990
|
+
if (!rightName) return todo(scope, 'instanceof dynamic right-hand side is not supported yet', true);
|
991
|
+
|
992
|
+
const checkType = TYPES[rightName.toLowerCase()];
|
993
|
+
if (checkType == null || rightName !== TYPE_NAMES[checkType] || checkType === TYPES.undefined) return todo(scope, 'instanceof right-hand side type unsupported', true);
|
994
|
+
|
995
|
+
if ([TYPES.number, TYPES.boolean, TYPES.string, TYPES.symbol, TYPES.object].includes(checkType)) {
|
996
|
+
out.push(...number(0));
|
997
|
+
} else {
|
998
|
+
out.push(
|
999
|
+
...getNodeType(scope, decl.left),
|
1000
|
+
...number(checkType, Valtype.i32),
|
1001
|
+
[ Opcodes.i32_eq ],
|
1002
|
+
Opcodes.i32_from_u
|
1003
|
+
);
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
return out;
|
1007
|
+
}
|
1008
|
+
|
979
1009
|
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
1010
|
|
981
1011
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1282,7 +1312,7 @@ const getNodeType = (scope, node) => {
|
|
1282
1312
|
}
|
1283
1313
|
|
1284
1314
|
if (node.type === 'BinaryExpression') {
|
1285
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1315
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1286
1316
|
if (node.operator !== '+') return TYPES.number;
|
1287
1317
|
|
1288
1318
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1315,7 +1345,7 @@ const getNodeType = (scope, node) => {
|
|
1315
1345
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1316
1346
|
if (objectKnownType != null) {
|
1317
1347
|
if (name === 'length') {
|
1318
|
-
if (
|
1348
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1319
1349
|
else return TYPES.undefined;
|
1320
1350
|
}
|
1321
1351
|
|
@@ -1427,6 +1457,18 @@ const generateExp = (scope, decl) => {
|
|
1427
1457
|
return out;
|
1428
1458
|
};
|
1429
1459
|
|
1460
|
+
const generateSequence = (scope, decl) => {
|
1461
|
+
let out = [];
|
1462
|
+
|
1463
|
+
const exprs = decl.expressions;
|
1464
|
+
for (let i = 0; i < exprs.length; i++) {
|
1465
|
+
if (i > 0) disposeLeftover(out);
|
1466
|
+
out.push(...generate(scope, exprs[i]));
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
return out;
|
1470
|
+
};
|
1471
|
+
|
1430
1472
|
const CTArrayUtil = {
|
1431
1473
|
getLengthI32: pointer => [
|
1432
1474
|
...number(0, Valtype.i32),
|
@@ -2015,7 +2057,7 @@ const unhackName = name => {
|
|
2015
2057
|
|
2016
2058
|
const knownType = (scope, type) => {
|
2017
2059
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2018
|
-
return type[0]
|
2060
|
+
return read_signedLEB128(type[0].slice(1));
|
2019
2061
|
}
|
2020
2062
|
|
2021
2063
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2302,11 +2344,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2302
2344
|
const { type, name } = decl.left;
|
2303
2345
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2304
2346
|
|
2305
|
-
if (type === 'ObjectPattern') {
|
2306
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2307
|
-
return generate(scope, decl.right);
|
2308
|
-
}
|
2309
|
-
|
2310
2347
|
if (isFuncType(decl.right.type)) {
|
2311
2348
|
// hack for a = function () { ... }
|
2312
2349
|
decl.right.id = { name };
|
@@ -2379,10 +2416,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2379
2416
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2380
2417
|
], getNodeType(scope, decl.right), false, name, true)),
|
2381
2418
|
[ Opcodes.local_tee, newValueTmp ],
|
2382
|
-
|
2383
2419
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2384
2420
|
],
|
2385
2421
|
|
2422
|
+
...wrapBC({
|
2423
|
+
[TYPES.uint8array]: [
|
2424
|
+
[ Opcodes.i32_add ],
|
2425
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2426
|
+
|
2427
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2428
|
+
[ Opcodes.local_get, pointerTmp ],
|
2429
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2430
|
+
Opcodes.i32_from_u
|
2431
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2432
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2433
|
+
|
2434
|
+
Opcodes.i32_to_u,
|
2435
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2436
|
+
],
|
2437
|
+
[TYPES.uint8clampedarray]: [
|
2438
|
+
[ Opcodes.i32_add ],
|
2439
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2440
|
+
|
2441
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2442
|
+
[ Opcodes.local_get, pointerTmp ],
|
2443
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2444
|
+
Opcodes.i32_from_u
|
2445
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2446
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2447
|
+
|
2448
|
+
...number(0),
|
2449
|
+
[ Opcodes.f64_max ],
|
2450
|
+
...number(255),
|
2451
|
+
[ Opcodes.f64_min ],
|
2452
|
+
Opcodes.i32_to_u,
|
2453
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2454
|
+
],
|
2455
|
+
[TYPES.int8array]: [
|
2456
|
+
[ Opcodes.i32_add ],
|
2457
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2458
|
+
|
2459
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2460
|
+
[ Opcodes.local_get, pointerTmp ],
|
2461
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2462
|
+
Opcodes.i32_from
|
2463
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2464
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2465
|
+
|
2466
|
+
Opcodes.i32_to,
|
2467
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2468
|
+
],
|
2469
|
+
[TYPES.uint16array]: [
|
2470
|
+
...number(2, Valtype.i32),
|
2471
|
+
[ Opcodes.i32_mul ],
|
2472
|
+
[ Opcodes.i32_add ],
|
2473
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2474
|
+
|
2475
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2476
|
+
[ Opcodes.local_get, pointerTmp ],
|
2477
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
2478
|
+
Opcodes.i32_from_u
|
2479
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2480
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2481
|
+
|
2482
|
+
Opcodes.i32_to_u,
|
2483
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2484
|
+
],
|
2485
|
+
[TYPES.int16array]: [
|
2486
|
+
...number(2, Valtype.i32),
|
2487
|
+
[ Opcodes.i32_mul ],
|
2488
|
+
[ Opcodes.i32_add ],
|
2489
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2490
|
+
|
2491
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2492
|
+
[ Opcodes.local_get, pointerTmp ],
|
2493
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2494
|
+
Opcodes.i32_from
|
2495
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2496
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2497
|
+
|
2498
|
+
Opcodes.i32_to,
|
2499
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2500
|
+
],
|
2501
|
+
[TYPES.uint32array]: [
|
2502
|
+
...number(4, Valtype.i32),
|
2503
|
+
[ Opcodes.i32_mul ],
|
2504
|
+
[ Opcodes.i32_add ],
|
2505
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2506
|
+
|
2507
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2508
|
+
[ Opcodes.local_get, pointerTmp ],
|
2509
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2510
|
+
Opcodes.i32_from_u
|
2511
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2512
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2513
|
+
|
2514
|
+
Opcodes.i32_to_u,
|
2515
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2516
|
+
],
|
2517
|
+
[TYPES.int32array]: [
|
2518
|
+
...number(4, Valtype.i32),
|
2519
|
+
[ Opcodes.i32_mul ],
|
2520
|
+
[ Opcodes.i32_add ],
|
2521
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2522
|
+
|
2523
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2524
|
+
[ Opcodes.local_get, pointerTmp ],
|
2525
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2526
|
+
Opcodes.i32_from
|
2527
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2528
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2529
|
+
|
2530
|
+
Opcodes.i32_to,
|
2531
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2532
|
+
],
|
2533
|
+
[TYPES.float32array]: [
|
2534
|
+
...number(4, Valtype.i32),
|
2535
|
+
[ Opcodes.i32_mul ],
|
2536
|
+
[ Opcodes.i32_add ],
|
2537
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2538
|
+
|
2539
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2540
|
+
[ Opcodes.local_get, pointerTmp ],
|
2541
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2542
|
+
[ Opcodes.f64_promote_f32 ]
|
2543
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2544
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2545
|
+
|
2546
|
+
[ Opcodes.f32_demote_f64 ],
|
2547
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2548
|
+
],
|
2549
|
+
[TYPES.float64array]: [
|
2550
|
+
...number(8, Valtype.i32),
|
2551
|
+
[ Opcodes.i32_mul ],
|
2552
|
+
[ Opcodes.i32_add ],
|
2553
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2554
|
+
|
2555
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2556
|
+
[ Opcodes.local_get, pointerTmp ],
|
2557
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2558
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2559
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2560
|
+
|
2561
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2562
|
+
],
|
2563
|
+
}, {
|
2564
|
+
prelude: [
|
2565
|
+
...generate(scope, decl.left.object),
|
2566
|
+
Opcodes.i32_to_u,
|
2567
|
+
...generate(scope, decl.left.property),
|
2568
|
+
Opcodes.i32_to_u,
|
2569
|
+
],
|
2570
|
+
postlude: setLastType(scope, TYPES.number)
|
2571
|
+
}),
|
2572
|
+
|
2386
2573
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2387
2574
|
}, Blocktype.void),
|
2388
2575
|
|
@@ -2960,6 +3147,7 @@ const generateForOf = (scope, decl) => {
|
|
2960
3147
|
[ Opcodes.end ],
|
2961
3148
|
[ Opcodes.end ]
|
2962
3149
|
],
|
3150
|
+
// todo: typed arrays
|
2963
3151
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2964
3152
|
}, Blocktype.void));
|
2965
3153
|
|
@@ -3048,13 +3236,14 @@ const generateThrow = (scope, decl) => {
|
|
3048
3236
|
idx: tags.length
|
3049
3237
|
});
|
3050
3238
|
|
3051
|
-
let exceptId = exceptions.
|
3239
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3240
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3052
3241
|
|
3053
3242
|
scope.exceptions ??= [];
|
3054
3243
|
scope.exceptions.push(exceptId);
|
3055
3244
|
|
3056
3245
|
return [
|
3057
|
-
|
3246
|
+
...number(exceptId, Valtype.i32),
|
3058
3247
|
[ Opcodes.throw, tags[0].idx ]
|
3059
3248
|
];
|
3060
3249
|
}
|
@@ -3121,7 +3310,7 @@ const generateThrow = (scope, decl) => {
|
|
3121
3310
|
scope.exceptions.push(exceptId);
|
3122
3311
|
|
3123
3312
|
return [
|
3124
|
-
|
3313
|
+
...number(exceptId, Valtype.i32),
|
3125
3314
|
...generate(scope, message),
|
3126
3315
|
...getNodeType(scope, message),
|
3127
3316
|
[ Opcodes.throw, tags[0].idx ]
|
@@ -3479,6 +3668,19 @@ const withType = (scope, wasm, type) => [
|
|
3479
3668
|
...setLastType(scope, type)
|
3480
3669
|
];
|
3481
3670
|
|
3671
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3672
|
+
const out = {};
|
3673
|
+
for (const x in bc) {
|
3674
|
+
out[x] = [
|
3675
|
+
...prelude,
|
3676
|
+
...bc[x],
|
3677
|
+
...postlude
|
3678
|
+
];
|
3679
|
+
}
|
3680
|
+
|
3681
|
+
return out;
|
3682
|
+
};
|
3683
|
+
|
3482
3684
|
const generateMember = (scope, decl, _global, _name) => {
|
3483
3685
|
const name = decl.object.name;
|
3484
3686
|
|
@@ -3532,7 +3734,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3532
3734
|
const type = getNodeType(scope, decl.object);
|
3533
3735
|
const known = knownType(scope, type);
|
3534
3736
|
if (known != null) {
|
3535
|
-
if (
|
3737
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3536
3738
|
...generate(scope, decl.object),
|
3537
3739
|
Opcodes.i32_to_u,
|
3538
3740
|
|
@@ -3544,7 +3746,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3544
3746
|
}
|
3545
3747
|
|
3546
3748
|
return [
|
3547
|
-
...
|
3749
|
+
...getNodeType(scope, decl.object),
|
3750
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3751
|
+
[ Opcodes.i32_and ],
|
3548
3752
|
[ Opcodes.if, valtypeBinary ],
|
3549
3753
|
...generate(scope, decl.object),
|
3550
3754
|
Opcodes.i32_to_u,
|
@@ -3593,7 +3797,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3593
3797
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3594
3798
|
// hack: this is naughty and will break things!
|
3595
3799
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3596
|
-
|
3800
|
+
|
3801
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3802
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3597
3803
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3598
3804
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3599
3805
|
rawElements: new Array(0)
|
@@ -3667,6 +3873,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3667
3873
|
...setLastType(scope, TYPES.bytestring)
|
3668
3874
|
],
|
3669
3875
|
|
3876
|
+
...wrapBC({
|
3877
|
+
[TYPES.uint8array]: [
|
3878
|
+
[ Opcodes.i32_add ],
|
3879
|
+
|
3880
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3881
|
+
Opcodes.i32_from_u
|
3882
|
+
],
|
3883
|
+
[TYPES.uint8clampedarray]: [
|
3884
|
+
[ Opcodes.i32_add ],
|
3885
|
+
|
3886
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3887
|
+
Opcodes.i32_from_u
|
3888
|
+
],
|
3889
|
+
[TYPES.int8array]: [
|
3890
|
+
[ Opcodes.i32_add ],
|
3891
|
+
|
3892
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3893
|
+
Opcodes.i32_from
|
3894
|
+
],
|
3895
|
+
[TYPES.uint16array]: [
|
3896
|
+
...number(2, Valtype.i32),
|
3897
|
+
[ Opcodes.i32_mul ],
|
3898
|
+
[ Opcodes.i32_add ],
|
3899
|
+
|
3900
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3901
|
+
Opcodes.i32_from_u
|
3902
|
+
],
|
3903
|
+
[TYPES.int16array]: [
|
3904
|
+
...number(2, Valtype.i32),
|
3905
|
+
[ Opcodes.i32_mul ],
|
3906
|
+
[ Opcodes.i32_add ],
|
3907
|
+
|
3908
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3909
|
+
Opcodes.i32_from
|
3910
|
+
],
|
3911
|
+
[TYPES.uint32array]: [
|
3912
|
+
...number(4, Valtype.i32),
|
3913
|
+
[ Opcodes.i32_mul ],
|
3914
|
+
[ Opcodes.i32_add ],
|
3915
|
+
|
3916
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3917
|
+
Opcodes.i32_from_u
|
3918
|
+
],
|
3919
|
+
[TYPES.int32array]: [
|
3920
|
+
...number(4, Valtype.i32),
|
3921
|
+
[ Opcodes.i32_mul ],
|
3922
|
+
[ Opcodes.i32_add ],
|
3923
|
+
|
3924
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3925
|
+
Opcodes.i32_from
|
3926
|
+
],
|
3927
|
+
[TYPES.float32array]: [
|
3928
|
+
...number(4, Valtype.i32),
|
3929
|
+
[ Opcodes.i32_mul ],
|
3930
|
+
[ Opcodes.i32_add ],
|
3931
|
+
|
3932
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3933
|
+
[ Opcodes.f64_promote_f32 ]
|
3934
|
+
],
|
3935
|
+
[TYPES.float64array]: [
|
3936
|
+
...number(8, Valtype.i32),
|
3937
|
+
[ Opcodes.i32_mul ],
|
3938
|
+
[ Opcodes.i32_add ],
|
3939
|
+
|
3940
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3941
|
+
],
|
3942
|
+
}, {
|
3943
|
+
prelude: [
|
3944
|
+
...object,
|
3945
|
+
Opcodes.i32_to_u,
|
3946
|
+
...property,
|
3947
|
+
Opcodes.i32_to_u
|
3948
|
+
],
|
3949
|
+
postlude: setLastType(scope, TYPES.number)
|
3950
|
+
}),
|
3951
|
+
|
3670
3952
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3671
3953
|
});
|
3672
3954
|
};
|