porffor 0.42.6 → 0.42.8
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/math.ts +1 -1
- package/compiler/builtins_precompiled.js +2 -2
- package/compiler/codegen.js +64 -58
- package/package.json +1 -1
- package/runner/index.js +1 -1
- package/runner/repl.js +8 -1
@@ -1780,9 +1780,9 @@ params:[124,127],typedParams:1,returns:[124,127],typedReturns:1,
|
|
1780
1780
|
locals:[124,124],localNames:["y","y#type","x","prev"],
|
1781
1781
|
}
|
1782
1782
|
this.__Math_cbrt = {
|
1783
|
-
wasm:(_,{builtin})=>[[32,0],[68,0],[97],[4,64],[68,0],[65,1],[15],[11],[32,0],[16,builtin('__Number_isFinite')],[68,0],[97],[4,64],[32,0],[65,1],[15],[11],[32,0],[16,builtin('__Math_abs')],[33,2],[
|
1783
|
+
wasm:(_,{builtin})=>[[32,0],[68,0],[97],[4,64],[68,0],[65,1],[15],[11],[32,0],[16,builtin('__Number_isFinite')],[68,0],[97],[4,64],[32,0],[65,1],[15],[11],[32,0],[16,builtin('__Math_abs')],[33,2],[3,64],[2,64],[32,2],[33,3],[68,2],[32,2],[162],[32,0],[32,2],[32,2],[162],[163],[160],[68,3],[163],[33,2],[32,3],[32,2],[161],[16,builtin('__Math_abs')],[68,1e-15],[100],[13,1],[11],[11],[32,0],[68,0],[99],[4,124],[32,2],[154],[65,1],[33,4],[5],[32,2],[65,1],[33,4],[11],[32,4],[15]],
|
1784
1784
|
params:[124,127],typedParams:1,returns:[124,127],typedReturns:1,
|
1785
|
-
locals:[124,
|
1785
|
+
locals:[124,124,127],localNames:["y","y#type","x","prev","#last_type"],
|
1786
1786
|
}
|
1787
1787
|
this.__Math_hypot = {
|
1788
1788
|
wasm:(_,{builtin})=>[[32,0],[32,0],[162],[32,2],[32,2],[162],[160],[65,1],[16,builtin('__Math_sqrt')],[34,4],[15]],
|
package/compiler/codegen.js
CHANGED
@@ -399,9 +399,19 @@ const generateIdent = (scope, decl) => {
|
|
399
399
|
|
400
400
|
if (local?.idx === undefined) {
|
401
401
|
if (name === 'arguments' && scope.name !== 'main' && !scope.arrow) {
|
402
|
-
// todo:
|
402
|
+
// todo: not compliant
|
403
|
+
let len = countLength(scope);
|
404
|
+
const names = new Array(len);
|
405
|
+
const off = scope.constr ? 4 : 0;
|
406
|
+
for (const x in scope.locals) {
|
407
|
+
const i = scope.locals[x].idx - off;
|
408
|
+
if (i >= 0 && i % 2 === 0 && i < len * 2) {
|
409
|
+
names[i / 2] = x;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
403
413
|
return generateArray(scope, {
|
404
|
-
elements:
|
414
|
+
elements: names.map(x => ({ type: 'Identifier', name: x }))
|
405
415
|
}, false, '#arguments');
|
406
416
|
}
|
407
417
|
|
@@ -1340,8 +1350,12 @@ const setType = (scope, name, type) => {
|
|
1340
1350
|
};
|
1341
1351
|
|
1342
1352
|
const getLastType = scope => {
|
1353
|
+
if (!scope.locals['#last_type']) return number(TYPES.number, Valtype.i32);
|
1354
|
+
|
1343
1355
|
scope.gotLastType = true;
|
1344
|
-
return [
|
1356
|
+
return [
|
1357
|
+
[ Opcodes.local_get, localTmp(scope, '#last_type', Valtype.i32) ]
|
1358
|
+
];
|
1345
1359
|
};
|
1346
1360
|
|
1347
1361
|
const setLastType = (scope, type = []) => {
|
@@ -1388,11 +1402,7 @@ const getNodeType = (scope, node) => {
|
|
1388
1402
|
|
1389
1403
|
if (name == null) {
|
1390
1404
|
// iife
|
1391
|
-
|
1392
|
-
|
1393
|
-
// presume
|
1394
|
-
if (Prefs.warnAssumedType) console.warn(`Indirect call assumed to be number`);
|
1395
|
-
return TYPES.number;
|
1405
|
+
return getLastType(scope);
|
1396
1406
|
}
|
1397
1407
|
|
1398
1408
|
const func = funcByName(name);
|
@@ -1426,38 +1436,7 @@ const getNodeType = (scope, node) => {
|
|
1426
1436
|
return TYPES.number;
|
1427
1437
|
}
|
1428
1438
|
|
1429
|
-
|
1430
|
-
|
1431
|
-
// presume
|
1432
|
-
if (Prefs.warnAssumedType) console.warn(`Call to ${name} assumed to be number`);
|
1433
|
-
return TYPES.number;
|
1434
|
-
|
1435
|
-
// let protoFunc;
|
1436
|
-
// // ident.func()
|
1437
|
-
// if (name && name.startsWith('__')) {
|
1438
|
-
// const spl = name.slice(2).split('_');
|
1439
|
-
|
1440
|
-
// const baseName = spl.slice(0, -1).join('_');
|
1441
|
-
// const baseType = getType(scope, baseName);
|
1442
|
-
|
1443
|
-
// const func = spl[spl.length - 1];
|
1444
|
-
// protoFunc = prototypeFuncs[baseType]?.[func];
|
1445
|
-
// }
|
1446
|
-
|
1447
|
-
// // literal.func()
|
1448
|
-
// if (!name && node.callee.type === 'MemberExpression') {
|
1449
|
-
// if (node.callee.object.regex) {
|
1450
|
-
// const funcName = node.callee.property.name;
|
1451
|
-
// return Rhemyn[funcName] ? TYPES.boolean : TYPES.undefined;
|
1452
|
-
// }
|
1453
|
-
|
1454
|
-
// const baseType = getNodeType(scope, node.callee.object);
|
1455
|
-
|
1456
|
-
// const func = node.callee.property.name;
|
1457
|
-
// protoFunc = prototypeFuncs[baseType]?.[func];
|
1458
|
-
// }
|
1459
|
-
|
1460
|
-
// if (protoFunc) return protoFunc.returnType;
|
1439
|
+
return getLastType(scope);
|
1461
1440
|
}
|
1462
1441
|
|
1463
1442
|
if (node.type === 'ExpressionStatement') {
|
@@ -1505,10 +1484,7 @@ const getNodeType = (scope, node) => {
|
|
1505
1484
|
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring)
|
1506
1485
|
guess = TYPES.bytestring;
|
1507
1486
|
|
1508
|
-
|
1509
|
-
|
1510
|
-
// presume
|
1511
|
-
return TYPES.number;
|
1487
|
+
return getLastType(scope);
|
1512
1488
|
}
|
1513
1489
|
|
1514
1490
|
if (node.type === 'UnaryExpression') {
|
@@ -1542,11 +1518,7 @@ const getNodeType = (scope, node) => {
|
|
1542
1518
|
}
|
1543
1519
|
}
|
1544
1520
|
|
1545
|
-
|
1546
|
-
|
1547
|
-
// presume
|
1548
|
-
if (Prefs.warnAssumedType) console.warn(`Member access to field .${name} assumed to be number`);
|
1549
|
-
return TYPES.number;
|
1521
|
+
return getLastType(scope);
|
1550
1522
|
}
|
1551
1523
|
|
1552
1524
|
if (node.type === 'TemplateLiteral') {
|
@@ -1579,11 +1551,7 @@ const getNodeType = (scope, node) => {
|
|
1579
1551
|
}
|
1580
1552
|
}
|
1581
1553
|
|
1582
|
-
|
1583
|
-
|
1584
|
-
// presume
|
1585
|
-
if (Prefs.warnAssumedType) console.warn(`AST node ${node.type} assumed to be number`);
|
1586
|
-
return TYPES.number;
|
1554
|
+
return getLastType(scope);
|
1587
1555
|
})();
|
1588
1556
|
|
1589
1557
|
const out = typeof ret === 'number' ? number(ret, Valtype.i32) : ret;
|
@@ -2447,6 +2415,31 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2447
2415
|
paramOffset += 4;
|
2448
2416
|
}
|
2449
2417
|
|
2418
|
+
if (args.at(-1)?.type === 'SpreadElement') {
|
2419
|
+
// hack: support spread element if last by doing essentially:
|
2420
|
+
// const foo = (a, b, c, d) => ...
|
2421
|
+
// foo(a, b, ...c) -> _ = c; foo(a, b, _[0], _[1])
|
2422
|
+
const arg = args.at(-1).argument;
|
2423
|
+
out.push(
|
2424
|
+
...generate(scope, arg),
|
2425
|
+
[ Opcodes.local_set, localTmp(scope, '#spread') ],
|
2426
|
+
...getNodeType(scope, arg),
|
2427
|
+
[ Opcodes.local_set, localTmp(scope, '#spread#type', Valtype.i32) ]
|
2428
|
+
);
|
2429
|
+
|
2430
|
+
args.pop();
|
2431
|
+
const leftover = paramCount - args.length;
|
2432
|
+
for (let i = 0; i < leftover; i++) {
|
2433
|
+
args.push({
|
2434
|
+
type: 'MemberExpression',
|
2435
|
+
object: { type: 'Identifier', name: '#spread' },
|
2436
|
+
property: { type: 'Literal', value: i },
|
2437
|
+
computed: true,
|
2438
|
+
optional: false
|
2439
|
+
});
|
2440
|
+
}
|
2441
|
+
}
|
2442
|
+
|
2450
2443
|
if (func && args.length < paramCount) {
|
2451
2444
|
// too little args, push undefineds
|
2452
2445
|
args = args.concat(new Array(paramCount - (func.hasRestArgument ? 1 : 0) - args.length).fill(DEFAULT_VALUE()));
|
@@ -3689,7 +3682,10 @@ const ifIdentifierErrors = (scope, decl) => {
|
|
3689
3682
|
const generateUnary = (scope, decl) => {
|
3690
3683
|
switch (decl.operator) {
|
3691
3684
|
case '+':
|
3692
|
-
//
|
3685
|
+
// opt: skip ToNumber if already known as number type
|
3686
|
+
generate(scope, decl.argument); // hack: fix last type not being defined for getNodeType before generation
|
3687
|
+
const known = knownType(scope, getNodeType(scope, decl.argument));
|
3688
|
+
if (known === TYPES.number) return generate(scope, decl.argument);
|
3693
3689
|
|
3694
3690
|
// 13.5.4 Unary + Operator, 13.5.4.1 Runtime Semantics: Evaluation
|
3695
3691
|
// https://tc39.es/ecma262/#sec-unary-plus-operator-runtime-semantics-evaluation
|
@@ -3707,7 +3703,7 @@ const generateUnary = (scope, decl) => {
|
|
3707
3703
|
});
|
3708
3704
|
|
3709
3705
|
case '-':
|
3710
|
-
// * -1
|
3706
|
+
// +x * -1
|
3711
3707
|
|
3712
3708
|
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
3713
3709
|
// if -n, just return that as a const
|
@@ -3715,7 +3711,12 @@ const generateUnary = (scope, decl) => {
|
|
3715
3711
|
}
|
3716
3712
|
|
3717
3713
|
return [
|
3718
|
-
...generate(scope,
|
3714
|
+
...generate(scope, {
|
3715
|
+
type: 'UnaryExpression',
|
3716
|
+
operator: '+',
|
3717
|
+
prefix: true,
|
3718
|
+
argument: decl.argument
|
3719
|
+
}),
|
3719
3720
|
...(valtype === 'f64' ? [ [ Opcodes.f64_neg ] ] : [ ...number(-1), [ Opcodes.mul ] ])
|
3720
3721
|
];
|
3721
3722
|
|
@@ -3731,7 +3732,12 @@ const generateUnary = (scope, decl) => {
|
|
3731
3732
|
|
3732
3733
|
case '~':
|
3733
3734
|
return [
|
3734
|
-
...generate(scope,
|
3735
|
+
...generate(scope, {
|
3736
|
+
type: 'UnaryExpression',
|
3737
|
+
operator: '+',
|
3738
|
+
prefix: true,
|
3739
|
+
argument: decl.argument
|
3740
|
+
}),
|
3735
3741
|
Opcodes.i32_to,
|
3736
3742
|
[ Opcodes.i32_const, ...signedLEB128(-1) ],
|
3737
3743
|
[ Opcodes.i32_xor ],
|
package/package.json
CHANGED
package/runner/index.js
CHANGED
package/runner/repl.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { TYPE_NAMES } from '../compiler/types.js';
|
2
2
|
import compile from '../compiler/wrap.js';
|
3
|
+
import parse from '../compiler/parse.js';
|
3
4
|
|
4
5
|
import util from 'node:util';
|
5
6
|
|
@@ -83,7 +84,13 @@ const run = (source, _context, _filename, callback, run = true) => {
|
|
83
84
|
// hack: print "secret" before latest code ran to only enable printing for new code
|
84
85
|
|
85
86
|
source = source.trim();
|
86
|
-
if (source.startsWith('{') && source.endsWith('}'))
|
87
|
+
if (source.startsWith('{') && source.endsWith('}')) {
|
88
|
+
const wrapped = '(' + source + ')';
|
89
|
+
try {
|
90
|
+
parse(wrapped);
|
91
|
+
source = wrapped;
|
92
|
+
} catch {}
|
93
|
+
}
|
87
94
|
|
88
95
|
let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source;
|
89
96
|
|