porffor 0.17.0-cab4904b8 → 0.17.0-f43ba190c
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/set.ts +2 -9
- package/compiler/builtins/typedarray.js +42 -0
- package/compiler/codegen.js +263 -15
- package/compiler/generated_builtins.js +303 -121
- 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/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/2c.js
CHANGED
@@ -182,7 +182,15 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
182
182
|
}, {});
|
183
183
|
const invGlobals = inv(globals, x => x.idx);
|
184
184
|
|
185
|
-
const
|
185
|
+
const codeToSanitizedStr = code => {
|
186
|
+
let out = '';
|
187
|
+
while (code > 0) {
|
188
|
+
out += String.fromCharCode(97 + code % 26);
|
189
|
+
code -= 26;
|
190
|
+
}
|
191
|
+
return out;
|
192
|
+
};
|
193
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
|
186
194
|
|
187
195
|
for (const x in invGlobals) {
|
188
196
|
invGlobals[x] = sanitize(invGlobals[x]);
|
@@ -273,10 +281,11 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
273
281
|
}
|
274
282
|
|
275
283
|
const returns = f.returns.length > 0;
|
284
|
+
const typedReturns = f.returnType == null;
|
276
285
|
|
277
286
|
const shouldInline = false; // f.internal;
|
278
287
|
if (f.name === 'main') out += `int main(${prependMain.has('argv') ? 'int argc, char* argv[]' : ''}) {\n`;
|
279
|
-
else out += `${
|
288
|
+
else out += `${!typedReturns ? (returns ? CValtype[f.returns[0]] : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
|
280
289
|
|
281
290
|
if (f.name === 'main') {
|
282
291
|
out += ' ' + [...prependMain.values()].join('\n ');
|
@@ -418,11 +427,14 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
418
427
|
continue;
|
419
428
|
|
420
429
|
case Opcodes.return:
|
421
|
-
|
422
|
-
|
423
|
-
|
430
|
+
if (!typedReturns) {
|
431
|
+
line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
|
432
|
+
break;
|
433
|
+
}
|
434
|
+
|
435
|
+
const b = returns ? vals.pop() : -1;
|
436
|
+
const a = returns ? vals.pop() : -1;
|
424
437
|
line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(a)}, ${removeBrackets(b)} }` : ''}`);
|
425
|
-
// line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
|
426
438
|
break;
|
427
439
|
|
428
440
|
case Opcodes.if: {
|
@@ -549,10 +561,15 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
549
561
|
|
550
562
|
prepend.set('__Porffor_readFile',
|
551
563
|
`i32 __Porffor_readFile(u32 pathPtr, u32 outPtr) {
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
564
|
+
FILE* fp;
|
565
|
+
if (pathPtr == 0) {
|
566
|
+
fp = stdin;
|
567
|
+
} else {
|
568
|
+
char* path = _memory + pathPtr + 4;
|
569
|
+
fp = fopen(path, "r");
|
570
|
+
if (fp == NULL) {
|
571
|
+
return -1;
|
572
|
+
}
|
556
573
|
}
|
557
574
|
|
558
575
|
u32 read = 0;
|
@@ -585,7 +602,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
585
602
|
for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
|
586
603
|
|
587
604
|
if (func.returns.length > 0) {
|
588
|
-
if (func.
|
605
|
+
if (func.returnType != null) {
|
589
606
|
vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
|
590
607
|
} else {
|
591
608
|
const id = retTmpId++;
|
@@ -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
|
|
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/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';
|
@@ -619,11 +619,14 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
619
619
|
};
|
620
620
|
|
621
621
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
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
|
+
];
|
627
630
|
|
628
631
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
629
632
|
|
@@ -1345,7 +1348,7 @@ const getNodeType = (scope, node) => {
|
|
1345
1348
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1346
1349
|
if (objectKnownType != null) {
|
1347
1350
|
if (name === 'length') {
|
1348
|
-
if (
|
1351
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1349
1352
|
else return TYPES.undefined;
|
1350
1353
|
}
|
1351
1354
|
|
@@ -2057,7 +2060,7 @@ const unhackName = name => {
|
|
2057
2060
|
|
2058
2061
|
const knownType = (scope, type) => {
|
2059
2062
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2060
|
-
return type[0]
|
2063
|
+
return read_signedLEB128(type[0].slice(1));
|
2061
2064
|
}
|
2062
2065
|
|
2063
2066
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2416,10 +2419,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2416
2419
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2417
2420
|
], getNodeType(scope, decl.right), false, name, true)),
|
2418
2421
|
[ Opcodes.local_tee, newValueTmp ],
|
2419
|
-
|
2420
2422
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2421
2423
|
],
|
2422
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
|
+
|
2423
2576
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2424
2577
|
}, Blocktype.void),
|
2425
2578
|
|
@@ -2997,6 +3150,7 @@ const generateForOf = (scope, decl) => {
|
|
2997
3150
|
[ Opcodes.end ],
|
2998
3151
|
[ Opcodes.end ]
|
2999
3152
|
],
|
3153
|
+
// todo: typed arrays
|
3000
3154
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
3001
3155
|
}, Blocktype.void));
|
3002
3156
|
|
@@ -3085,13 +3239,14 @@ const generateThrow = (scope, decl) => {
|
|
3085
3239
|
idx: tags.length
|
3086
3240
|
});
|
3087
3241
|
|
3088
|
-
let exceptId = exceptions.
|
3242
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3243
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3089
3244
|
|
3090
3245
|
scope.exceptions ??= [];
|
3091
3246
|
scope.exceptions.push(exceptId);
|
3092
3247
|
|
3093
3248
|
return [
|
3094
|
-
|
3249
|
+
...number(exceptId, Valtype.i32),
|
3095
3250
|
[ Opcodes.throw, tags[0].idx ]
|
3096
3251
|
];
|
3097
3252
|
}
|
@@ -3158,7 +3313,7 @@ const generateThrow = (scope, decl) => {
|
|
3158
3313
|
scope.exceptions.push(exceptId);
|
3159
3314
|
|
3160
3315
|
return [
|
3161
|
-
|
3316
|
+
...number(exceptId, Valtype.i32),
|
3162
3317
|
...generate(scope, message),
|
3163
3318
|
...getNodeType(scope, message),
|
3164
3319
|
[ Opcodes.throw, tags[0].idx ]
|
@@ -3516,6 +3671,19 @@ const withType = (scope, wasm, type) => [
|
|
3516
3671
|
...setLastType(scope, type)
|
3517
3672
|
];
|
3518
3673
|
|
3674
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3675
|
+
const out = {};
|
3676
|
+
for (const x in bc) {
|
3677
|
+
out[x] = [
|
3678
|
+
...prelude,
|
3679
|
+
...bc[x],
|
3680
|
+
...postlude
|
3681
|
+
];
|
3682
|
+
}
|
3683
|
+
|
3684
|
+
return out;
|
3685
|
+
};
|
3686
|
+
|
3519
3687
|
const generateMember = (scope, decl, _global, _name) => {
|
3520
3688
|
const name = decl.object.name;
|
3521
3689
|
|
@@ -3569,7 +3737,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3569
3737
|
const type = getNodeType(scope, decl.object);
|
3570
3738
|
const known = knownType(scope, type);
|
3571
3739
|
if (known != null) {
|
3572
|
-
if (
|
3740
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3573
3741
|
...generate(scope, decl.object),
|
3574
3742
|
Opcodes.i32_to_u,
|
3575
3743
|
|
@@ -3581,7 +3749,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3581
3749
|
}
|
3582
3750
|
|
3583
3751
|
return [
|
3584
|
-
...
|
3752
|
+
...getNodeType(scope, decl.object),
|
3753
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3754
|
+
[ Opcodes.i32_and ],
|
3585
3755
|
[ Opcodes.if, valtypeBinary ],
|
3586
3756
|
...generate(scope, decl.object),
|
3587
3757
|
Opcodes.i32_to_u,
|
@@ -3630,7 +3800,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3630
3800
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3631
3801
|
// hack: this is naughty and will break things!
|
3632
3802
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3633
|
-
|
3803
|
+
|
3804
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3805
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3634
3806
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3635
3807
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3636
3808
|
rawElements: new Array(0)
|
@@ -3704,6 +3876,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3704
3876
|
...setLastType(scope, TYPES.bytestring)
|
3705
3877
|
],
|
3706
3878
|
|
3879
|
+
...wrapBC({
|
3880
|
+
[TYPES.uint8array]: [
|
3881
|
+
[ Opcodes.i32_add ],
|
3882
|
+
|
3883
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3884
|
+
Opcodes.i32_from_u
|
3885
|
+
],
|
3886
|
+
[TYPES.uint8clampedarray]: [
|
3887
|
+
[ Opcodes.i32_add ],
|
3888
|
+
|
3889
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3890
|
+
Opcodes.i32_from_u
|
3891
|
+
],
|
3892
|
+
[TYPES.int8array]: [
|
3893
|
+
[ Opcodes.i32_add ],
|
3894
|
+
|
3895
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3896
|
+
Opcodes.i32_from
|
3897
|
+
],
|
3898
|
+
[TYPES.uint16array]: [
|
3899
|
+
...number(2, Valtype.i32),
|
3900
|
+
[ Opcodes.i32_mul ],
|
3901
|
+
[ Opcodes.i32_add ],
|
3902
|
+
|
3903
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3904
|
+
Opcodes.i32_from_u
|
3905
|
+
],
|
3906
|
+
[TYPES.int16array]: [
|
3907
|
+
...number(2, Valtype.i32),
|
3908
|
+
[ Opcodes.i32_mul ],
|
3909
|
+
[ Opcodes.i32_add ],
|
3910
|
+
|
3911
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3912
|
+
Opcodes.i32_from
|
3913
|
+
],
|
3914
|
+
[TYPES.uint32array]: [
|
3915
|
+
...number(4, Valtype.i32),
|
3916
|
+
[ Opcodes.i32_mul ],
|
3917
|
+
[ Opcodes.i32_add ],
|
3918
|
+
|
3919
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3920
|
+
Opcodes.i32_from_u
|
3921
|
+
],
|
3922
|
+
[TYPES.int32array]: [
|
3923
|
+
...number(4, Valtype.i32),
|
3924
|
+
[ Opcodes.i32_mul ],
|
3925
|
+
[ Opcodes.i32_add ],
|
3926
|
+
|
3927
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3928
|
+
Opcodes.i32_from
|
3929
|
+
],
|
3930
|
+
[TYPES.float32array]: [
|
3931
|
+
...number(4, Valtype.i32),
|
3932
|
+
[ Opcodes.i32_mul ],
|
3933
|
+
[ Opcodes.i32_add ],
|
3934
|
+
|
3935
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3936
|
+
[ Opcodes.f64_promote_f32 ]
|
3937
|
+
],
|
3938
|
+
[TYPES.float64array]: [
|
3939
|
+
...number(8, Valtype.i32),
|
3940
|
+
[ Opcodes.i32_mul ],
|
3941
|
+
[ Opcodes.i32_add ],
|
3942
|
+
|
3943
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3944
|
+
],
|
3945
|
+
}, {
|
3946
|
+
prelude: [
|
3947
|
+
...object,
|
3948
|
+
Opcodes.i32_to_u,
|
3949
|
+
...property,
|
3950
|
+
Opcodes.i32_to_u
|
3951
|
+
],
|
3952
|
+
postlude: setLastType(scope, TYPES.number)
|
3953
|
+
}),
|
3954
|
+
|
3707
3955
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3708
3956
|
});
|
3709
3957
|
};
|