porffor 0.55.17 → 0.55.19
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/__internal_object.ts +7 -11
- package/compiler/builtins/__internal_string.ts +0 -6
- package/compiler/builtins/_internal_object.ts +8 -15
- package/compiler/builtins/_internal_string.ts +1 -1
- package/compiler/builtins/array.ts +2 -4
- package/compiler/builtins/bigint.ts +131 -35
- package/compiler/builtins/boolean.ts +1 -2
- package/compiler/builtins/generator.ts +10 -14
- package/compiler/builtins/json.ts +8 -5
- package/compiler/builtins/number.ts +8 -4
- package/compiler/builtins/object.ts +15 -14
- package/compiler/builtins/promise.ts +19 -30
- package/compiler/builtins/string_f64.ts +1 -2
- package/compiler/builtins/symbol.ts +1 -3
- package/compiler/builtins/z_ecma262.ts +10 -7
- package/compiler/builtins.js +2 -2
- package/compiler/builtins_objects.js +1 -3
- package/compiler/builtins_precompiled.js +1944 -1918
- package/compiler/codegen.js +151 -96
- package/compiler/precompile.js +7 -7
- package/compiler/wrap.js +8 -3
- package/package.json +1 -1
- package/r.cjs +2 -0
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -136,7 +136,12 @@ const funcRef = func => {
|
|
136
136
|
}
|
137
137
|
}
|
138
138
|
|
139
|
-
if (func.returns.length ===
|
139
|
+
if (func.returns.length === 0) {
|
140
|
+
// add to stack if returns nothing
|
141
|
+
wasm.push(number(UNDEFINED));
|
142
|
+
}
|
143
|
+
|
144
|
+
if (func.returns.length < 2) {
|
140
145
|
// add built-in returnType if only returns a value
|
141
146
|
wasm.push(number(func.returnType ?? TYPES.number, Valtype.i32));
|
142
147
|
}
|
@@ -353,6 +358,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
353
358
|
|
354
359
|
return cacheAst(decl, [ number(UNDEFINED) ]);
|
355
360
|
|
361
|
+
case 'TSAsExpression':
|
362
|
+
return cacheAst(decl, generate(scope, decl.expression));
|
363
|
+
|
356
364
|
default:
|
357
365
|
// ignore typescript nodes
|
358
366
|
if (decl.type.startsWith('TS') ||
|
@@ -497,7 +505,7 @@ const lookup = (scope, name, failEarly = false) => {
|
|
497
505
|
|
498
506
|
if (failEarly) return null;
|
499
507
|
|
500
|
-
return [ [ null, () => hoistLookup(scope, name)
|
508
|
+
return [ [ null, () => hoistLookup(scope, name) ] ];
|
501
509
|
}
|
502
510
|
|
503
511
|
return [
|
@@ -539,12 +547,10 @@ const generateYield = (scope, decl) => {
|
|
539
547
|
...getNodeType(scope, arg),
|
540
548
|
|
541
549
|
[ Opcodes.call, includeBuiltin(scope, scope.async ? '__Porffor_AsyncGenerator_yield' : '__Porffor_Generator_yield').index ],
|
542
|
-
[ Opcodes.drop ],
|
543
|
-
[ Opcodes.drop ],
|
544
550
|
|
545
551
|
// return generator
|
546
552
|
[ Opcodes.local_get, scope.locals['#generator_out'].idx ],
|
547
|
-
number(scope.async ? TYPES.__porffor_asyncgenerator : TYPES.__porffor_generator, Valtype.i32),
|
553
|
+
...(scope.returnType != null ? [] : [ number(scope.async ? TYPES.__porffor_asyncgenerator : TYPES.__porffor_generator, Valtype.i32) ]),
|
548
554
|
[ Opcodes.return ],
|
549
555
|
|
550
556
|
// use undefined as yield expression value
|
@@ -565,8 +571,9 @@ const generateReturn = (scope, decl) => {
|
|
565
571
|
...generate(scope, arg),
|
566
572
|
...getNodeType(scope, arg),
|
567
573
|
|
574
|
+
// return generator
|
568
575
|
[ Opcodes.call, includeBuiltin(scope, scope.async ? '__Porffor_AsyncGenerator_return' : '__Porffor_Generator_return').index ],
|
569
|
-
|
576
|
+
...(scope.returnType != null ? [] : [ number(scope.async ? TYPES.__porffor_asyncgenerator : TYPES.__porffor_generator, Valtype.i32) ]),
|
570
577
|
[ Opcodes.return ]
|
571
578
|
];
|
572
579
|
}
|
@@ -581,16 +588,18 @@ const generateReturn = (scope, decl) => {
|
|
581
588
|
number(TYPES.promise, Valtype.i32),
|
582
589
|
|
583
590
|
[ Opcodes.call, includeBuiltin(scope, '__Porffor_promise_resolve').index ],
|
584
|
-
[ Opcodes.drop ],
|
585
|
-
[ Opcodes.drop ],
|
586
591
|
|
587
592
|
// return promise
|
588
593
|
[ Opcodes.local_get, scope.locals['#async_out_promise'].idx ],
|
589
|
-
number(TYPES.promise, Valtype.i32),
|
594
|
+
...(scope.returnType != null ? [] : [ number(TYPES.promise, Valtype.i32) ]),
|
590
595
|
[ Opcodes.return ]
|
591
596
|
];
|
592
597
|
}
|
593
598
|
|
599
|
+
if (scope.returns.length === 0) return [
|
600
|
+
[ Opcodes.return ]
|
601
|
+
];
|
602
|
+
|
594
603
|
if (
|
595
604
|
scope.constr && // only do this in constructors
|
596
605
|
!globalThis.precompile // skip in precompiled built-ins, we should not require this and handle it ourselves
|
@@ -650,7 +659,7 @@ const generateReturn = (scope, decl) => {
|
|
650
659
|
]),
|
651
660
|
|
652
661
|
[ Opcodes.local_get, localTmp(scope, '#return') ],
|
653
|
-
[ Opcodes.local_get, localTmp(scope, '#return#type', Valtype.i32) ],
|
662
|
+
...(scope.returnType != null ? [] : [ [ Opcodes.local_get, localTmp(scope, '#return#type', Valtype.i32) ] ]),
|
654
663
|
[ Opcodes.return ]
|
655
664
|
];
|
656
665
|
}
|
@@ -757,8 +766,7 @@ const compareStrings = (scope, left, right, leftType, rightType, noConv = false)
|
|
757
766
|
Opcodes.i32_to_u,
|
758
767
|
...rightType,
|
759
768
|
|
760
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_strcmp').index ]
|
761
|
-
[ Opcodes.drop ]
|
769
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_strcmp').index ]
|
762
770
|
];
|
763
771
|
|
764
772
|
return [
|
@@ -771,7 +779,6 @@ const compareStrings = (scope, left, right, leftType, rightType, noConv = false)
|
|
771
779
|
...rightType,
|
772
780
|
|
773
781
|
[ Opcodes.call, includeBuiltin(scope, '__Porffor_compareStrings').index ],
|
774
|
-
[ Opcodes.drop ],
|
775
782
|
|
776
783
|
// convert valtype result to i32 as i32 output expected
|
777
784
|
Opcodes.i32_trunc_sat_f64_u
|
@@ -997,6 +1004,18 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
|
|
997
1004
|
);
|
998
1005
|
}
|
999
1006
|
|
1007
|
+
if (!eqOp && (knownLeft === TYPES.bigint || knownRight === TYPES.bigint) && !(knownLeft === TYPES.bigint && knownRight === TYPES.bigint)) {
|
1008
|
+
const unknownType = knownLeft === TYPES.bigint ? rightType : leftType;
|
1009
|
+
startOut.push(
|
1010
|
+
...unknownType,
|
1011
|
+
number(TYPES.bigint, Valtype.i32),
|
1012
|
+
[ Opcodes.i32_ne ],
|
1013
|
+
[ Opcodes.if, Blocktype.void ],
|
1014
|
+
...internalThrow(scope, 'TypeError', 'Cannot mix BigInts and non-BigInts in numeric expressions'),
|
1015
|
+
[ Opcodes.end ]
|
1016
|
+
);
|
1017
|
+
}
|
1018
|
+
|
1000
1019
|
// todo: if equality op and an operand is undefined, return false
|
1001
1020
|
// todo: niche null hell with 0
|
1002
1021
|
|
@@ -1211,7 +1230,7 @@ const generateBinaryExp = (scope, decl) => {
|
|
1211
1230
|
|
1212
1231
|
const asmFuncToAsm = (scope, func) => {
|
1213
1232
|
return func(scope, {
|
1214
|
-
Valtype, Opcodes, TYPES, TYPE_NAMES, typeSwitch, makeString, internalThrow,
|
1233
|
+
Valtype, Opcodes, TYPES, TYPE_NAMES, usedTypes, typeSwitch, makeString, internalThrow,
|
1215
1234
|
getNodeType, generate, generateIdent,
|
1216
1235
|
builtin: (n, offset = false) => {
|
1217
1236
|
let idx = funcIndex[n] ?? importedFuncs[n];
|
@@ -1282,7 +1301,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1282
1301
|
return [ [ null, () => {
|
1283
1302
|
if (types.some(x => usedTypes.has(x))) return wasm();
|
1284
1303
|
return [];
|
1285
|
-
}
|
1304
|
+
} ] ];
|
1286
1305
|
}
|
1287
1306
|
},
|
1288
1307
|
i32ify: wasm => {
|
@@ -1432,7 +1451,11 @@ const setInferred = (scope, name, type, global = false) => {
|
|
1432
1451
|
};
|
1433
1452
|
|
1434
1453
|
const getType = (scope, name, failEarly = false) => {
|
1435
|
-
const fallback = failEarly ? [
|
1454
|
+
const fallback = failEarly ? [
|
1455
|
+
number(TYPES.undefined, Valtype.i32)
|
1456
|
+
] : [
|
1457
|
+
[ null, () => hoistLookupType(scope, name) ]
|
1458
|
+
];
|
1436
1459
|
|
1437
1460
|
if (Object.hasOwn(builtinVars, name)) return [ number(builtinVars[name].type ?? TYPES.number, Valtype.i32) ];
|
1438
1461
|
|
@@ -1527,6 +1550,11 @@ const getNodeType = (scope, node) => {
|
|
1527
1550
|
let guess = null;
|
1528
1551
|
const ret = (() => {
|
1529
1552
|
if (node._type) return node._type;
|
1553
|
+
|
1554
|
+
if (node.type === 'TSAsExpression') {
|
1555
|
+
return extractTypeAnnotation(node).type;
|
1556
|
+
}
|
1557
|
+
|
1530
1558
|
if (node.type === 'Literal') {
|
1531
1559
|
if (node.regex) return TYPES.regexp;
|
1532
1560
|
|
@@ -1549,7 +1577,7 @@ const getNodeType = (scope, node) => {
|
|
1549
1577
|
}
|
1550
1578
|
|
1551
1579
|
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
1552
|
-
|
1580
|
+
let name = node.callee.name;
|
1553
1581
|
|
1554
1582
|
// hack: special primitive object types
|
1555
1583
|
if (node.type === 'NewExpression') {
|
@@ -1558,8 +1586,13 @@ const getNodeType = (scope, node) => {
|
|
1558
1586
|
if (name === 'String') return TYPES.stringobject;
|
1559
1587
|
}
|
1560
1588
|
|
1589
|
+
// hack: try reading from member if call
|
1590
|
+
if (name == null && node.callee.type === 'MemberExpression' && node.callee.property.name === 'call') {
|
1591
|
+
name = node.callee.object.name;
|
1592
|
+
}
|
1593
|
+
|
1561
1594
|
if (name == null) {
|
1562
|
-
//
|
1595
|
+
// unknown name
|
1563
1596
|
return getLastType(scope);
|
1564
1597
|
}
|
1565
1598
|
|
@@ -1568,7 +1601,7 @@ const getNodeType = (scope, node) => {
|
|
1568
1601
|
if (func.returnType != null) return func.returnType;
|
1569
1602
|
}
|
1570
1603
|
|
1571
|
-
if (Object.hasOwn(builtinFuncs, name) &&
|
1604
|
+
if (Object.hasOwn(builtinFuncs, name) && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
|
1572
1605
|
if (Object.hasOwn(internalConstrs, name) && internalConstrs[name].type != null) return internalConstrs[name].type;
|
1573
1606
|
|
1574
1607
|
// check if this is a prototype function
|
@@ -1619,13 +1652,15 @@ const getNodeType = (scope, node) => {
|
|
1619
1652
|
|
1620
1653
|
if (node.type === 'BinaryExpression') {
|
1621
1654
|
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof', 'in'].includes(node.operator)) return TYPES.boolean;
|
1622
|
-
if (node.operator !== '+') return TYPES.number;
|
1623
1655
|
|
1624
1656
|
const leftType = getNodeType(scope, node.left);
|
1625
1657
|
const rightType = getNodeType(scope, node.right);
|
1626
1658
|
const knownLeft = knownTypeWithGuess(scope, leftType);
|
1627
1659
|
const knownRight = knownTypeWithGuess(scope, rightType);
|
1628
1660
|
|
1661
|
+
if (knownLeft === TYPES.bigint || knownRight === TYPES.bigint) return TYPES.bigint;
|
1662
|
+
if (node.operator !== '+') return TYPES.number;
|
1663
|
+
|
1629
1664
|
if ((knownLeft != null || knownRight != null) && !(
|
1630
1665
|
(knownLeft === TYPES.string || knownRight === TYPES.string) ||
|
1631
1666
|
(knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) ||
|
@@ -1650,6 +1685,11 @@ const getNodeType = (scope, node) => {
|
|
1650
1685
|
if (node.operator === 'delete') return TYPES.boolean;
|
1651
1686
|
if (node.operator === 'typeof') return TYPES.bytestring;
|
1652
1687
|
|
1688
|
+
// todo: proper bigint support
|
1689
|
+
const type = getNodeType(scope, node.argument);
|
1690
|
+
const known = knownType(scope, type);
|
1691
|
+
if (known === TYPES.bigint) return TYPES.bigint;
|
1692
|
+
|
1653
1693
|
return TYPES.number;
|
1654
1694
|
}
|
1655
1695
|
|
@@ -1756,6 +1796,29 @@ const generateLiteral = (scope, decl, global, name) => {
|
|
1756
1796
|
case 'string':
|
1757
1797
|
return makeString(scope, decl.value);
|
1758
1798
|
|
1799
|
+
case 'bigint':
|
1800
|
+
let n = decl.value;
|
1801
|
+
|
1802
|
+
// inline if small enough
|
1803
|
+
if ((n < 0 ? -n : n) < 0x8000000000000n) {
|
1804
|
+
return [ number(Number(n)) ];
|
1805
|
+
}
|
1806
|
+
|
1807
|
+
// todo/opt: calculate and statically store digits
|
1808
|
+
return generate(scope, {
|
1809
|
+
type: 'CallExpression',
|
1810
|
+
callee: {
|
1811
|
+
type: 'Identifier',
|
1812
|
+
name: '__Porffor_bigint_fromString'
|
1813
|
+
},
|
1814
|
+
arguments: [
|
1815
|
+
{
|
1816
|
+
type: 'Literal',
|
1817
|
+
value: decl.value.toString()
|
1818
|
+
}
|
1819
|
+
]
|
1820
|
+
});
|
1821
|
+
|
1759
1822
|
default:
|
1760
1823
|
return todo(scope, `cannot generate literal of type ${typeof decl.value}`, true);
|
1761
1824
|
}
|
@@ -1816,14 +1879,6 @@ const ArrayUtil = {
|
|
1816
1879
|
]
|
1817
1880
|
};
|
1818
1881
|
|
1819
|
-
const getLastInst = wasm => {
|
1820
|
-
for (let i = wasm.length - 1; i >= 0; i--) {
|
1821
|
-
if (wasm[i]?.[0] != null) return wasm[i];
|
1822
|
-
}
|
1823
|
-
|
1824
|
-
return null;
|
1825
|
-
};
|
1826
|
-
|
1827
1882
|
const createNewTarget = (scope, decl, idx = 0, force = false) => {
|
1828
1883
|
if (decl._new || force) {
|
1829
1884
|
return [
|
@@ -1971,8 +2026,6 @@ const createThisArg = (scope, decl) => {
|
|
1971
2026
|
number(TYPES.number, Valtype.i32),
|
1972
2027
|
|
1973
2028
|
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
|
1974
|
-
[ Opcodes.drop ],
|
1975
|
-
[ Opcodes.drop ],
|
1976
2029
|
|
1977
2030
|
[ Opcodes.local_get, tmp ],
|
1978
2031
|
number(TYPES.object, Valtype.i32)
|
@@ -2083,14 +2136,15 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2083
2136
|
}
|
2084
2137
|
|
2085
2138
|
if (name === 'Function') {
|
2086
|
-
const
|
2087
|
-
if (
|
2088
|
-
// new Function('with known/literal
|
2089
|
-
const code = String(
|
2139
|
+
const knowns = decl.arguments.map(x => knownValue(scope, x));
|
2140
|
+
if (knowns.every(x => x !== unknownValue)) {
|
2141
|
+
// new Function('with known/literal strings')
|
2142
|
+
const code = String(knowns[knowns.length - 1]);
|
2143
|
+
const args = knowns.slice(0, -1).map(x => String(x));
|
2090
2144
|
|
2091
2145
|
let parsed;
|
2092
2146
|
try {
|
2093
|
-
parsed = objectHack(parse(`(function(){${code}})`));
|
2147
|
+
parsed = objectHack(parse(`(function(${args.join(',')}){${code}})`));
|
2094
2148
|
} catch (e) {
|
2095
2149
|
if (e.name === 'SyntaxError') {
|
2096
2150
|
// throw syntax errors of evals at runtime instead
|
@@ -2609,7 +2663,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2609
2663
|
|
2610
2664
|
const userFunc = func && !func.internal;
|
2611
2665
|
const typedParams = userFunc || func?.typedParams;
|
2612
|
-
const typedReturns =
|
2666
|
+
const typedReturns = func && func.returnType == null;
|
2613
2667
|
let paramCount = countParams(func, name);
|
2614
2668
|
|
2615
2669
|
let paramOffset = 0;
|
@@ -2709,17 +2763,19 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2709
2763
|
// );
|
2710
2764
|
} else out.push(...setLastType(scope));
|
2711
2765
|
|
2712
|
-
if (
|
2713
|
-
|
2766
|
+
if (
|
2767
|
+
func?.returns?.length === 0 ||
|
2768
|
+
(idx === importedFuncs[name] && importedFuncs[importedFuncs[name]]?.returns === 0)
|
2769
|
+
) {
|
2770
|
+
out.push(number(UNDEFINED));
|
2714
2771
|
}
|
2715
2772
|
|
2716
|
-
if (
|
2717
|
-
out.push(Opcodes.
|
2773
|
+
if (func?.returns?.[0] === Valtype.i32 && valtypeBinary !== Valtype.i32) {
|
2774
|
+
out.push(Opcodes.i32_from);
|
2718
2775
|
}
|
2719
2776
|
|
2720
|
-
if (
|
2721
|
-
|
2722
|
-
out.push(number(UNDEFINED));
|
2777
|
+
if (func?.returns?.[0] === Valtype.f64 && valtypeBinary === Valtype.i32 && !globalThis.noi32F64CallConv) {
|
2778
|
+
out.push(Opcodes.i32_trunc_sat_f64_s);
|
2723
2779
|
}
|
2724
2780
|
|
2725
2781
|
return out;
|
@@ -2756,7 +2812,7 @@ const generateThis = (scope, decl) => {
|
|
2756
2812
|
[ Opcodes.local_set, scope.locals['#this#type'].idx ],
|
2757
2813
|
[ Opcodes.end ]
|
2758
2814
|
];
|
2759
|
-
}
|
2815
|
+
} ],
|
2760
2816
|
|
2761
2817
|
[ Opcodes.local_get, scope.locals['#this'].idx ]
|
2762
2818
|
];
|
@@ -3038,7 +3094,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
|
|
3038
3094
|
depth = oldDepth;
|
3039
3095
|
}
|
3040
3096
|
return out;
|
3041
|
-
}
|
3097
|
+
} ]);
|
3042
3098
|
}
|
3043
3099
|
}
|
3044
3100
|
}
|
@@ -3143,6 +3199,7 @@ const extractTypeAnnotation = decl => {
|
|
3143
3199
|
type = a.typeName.name;
|
3144
3200
|
} else if (a.type.endsWith('Keyword')) {
|
3145
3201
|
type = a.type.slice(2, -7).toLowerCase();
|
3202
|
+
if (type === 'void') type = 'undefined';
|
3146
3203
|
} else if (a.type === 'TSArrayType') {
|
3147
3204
|
type = 'array';
|
3148
3205
|
elementType = extractTypeAnnotation(a.elementType).type;
|
@@ -4060,6 +4117,24 @@ const ifIdentifierErrors = (scope, decl) => {
|
|
4060
4117
|
};
|
4061
4118
|
|
4062
4119
|
const generateUnary = (scope, decl) => {
|
4120
|
+
const toNumeric = () => {
|
4121
|
+
// opt: skip if already known as number type
|
4122
|
+
generate(scope, decl.argument); // hack: fix last type not being defined for getNodeType before generation
|
4123
|
+
const known = knownType(scope, getNodeType(scope, decl.argument));
|
4124
|
+
if (known === TYPES.number) return generate(scope, decl.argument);
|
4125
|
+
|
4126
|
+
return generate(scope, {
|
4127
|
+
type: 'CallExpression',
|
4128
|
+
callee: {
|
4129
|
+
type: 'Identifier',
|
4130
|
+
name: '__ecma262_ToNumeric'
|
4131
|
+
},
|
4132
|
+
arguments: [
|
4133
|
+
decl.argument
|
4134
|
+
]
|
4135
|
+
});
|
4136
|
+
};
|
4137
|
+
|
4063
4138
|
switch (decl.operator) {
|
4064
4139
|
case '+':
|
4065
4140
|
// opt: skip ToNumber if already known as number type
|
@@ -4085,21 +4160,31 @@ const generateUnary = (scope, decl) => {
|
|
4085
4160
|
case '-':
|
4086
4161
|
// +x * -1
|
4087
4162
|
|
4088
|
-
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
4089
|
-
// if -n, just return that as a
|
4090
|
-
return
|
4163
|
+
if (decl.prefix && decl.argument.type === 'Literal' && (typeof decl.argument.value === 'number' || typeof decl.argument.value === 'bigint')) {
|
4164
|
+
// if -n, just return that as a literal
|
4165
|
+
return generate(scope, {
|
4166
|
+
type: 'Literal',
|
4167
|
+
value: -decl.argument.value
|
4168
|
+
});
|
4091
4169
|
}
|
4092
4170
|
|
4171
|
+
// todo: proper bigint support
|
4093
4172
|
return [
|
4094
|
-
...
|
4095
|
-
type: 'UnaryExpression',
|
4096
|
-
operator: '+',
|
4097
|
-
prefix: true,
|
4098
|
-
argument: decl.argument
|
4099
|
-
}),
|
4173
|
+
...toNumeric(),
|
4100
4174
|
...(valtype === 'f64' ? [ [ Opcodes.f64_neg ] ] : [ number(-1), [ Opcodes.mul ] ])
|
4101
4175
|
];
|
4102
4176
|
|
4177
|
+
case '~':
|
4178
|
+
// todo: proper bigint support
|
4179
|
+
return [
|
4180
|
+
...toNumeric(),
|
4181
|
+
Opcodes.i32_to,
|
4182
|
+
[ Opcodes.i32_const, ...signedLEB128(-1) ],
|
4183
|
+
[ Opcodes.i32_xor ],
|
4184
|
+
Opcodes.i32_from
|
4185
|
+
];
|
4186
|
+
|
4187
|
+
|
4103
4188
|
case '!':
|
4104
4189
|
const arg = decl.argument;
|
4105
4190
|
if (arg.type === 'UnaryExpression' && arg.operator === '!') {
|
@@ -4110,20 +4195,6 @@ const generateUnary = (scope, decl) => {
|
|
4110
4195
|
// !=
|
4111
4196
|
return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
|
4112
4197
|
|
4113
|
-
case '~':
|
4114
|
-
return [
|
4115
|
-
...generate(scope, {
|
4116
|
-
type: 'UnaryExpression',
|
4117
|
-
operator: '+',
|
4118
|
-
prefix: true,
|
4119
|
-
argument: decl.argument
|
4120
|
-
}),
|
4121
|
-
Opcodes.i32_to,
|
4122
|
-
[ Opcodes.i32_const, ...signedLEB128(-1) ],
|
4123
|
-
[ Opcodes.i32_xor ],
|
4124
|
-
Opcodes.i32_from
|
4125
|
-
];
|
4126
|
-
|
4127
4198
|
case 'void': {
|
4128
4199
|
// drop current expression value after running, give undefined
|
4129
4200
|
const out = generate(scope, decl.argument);
|
@@ -4155,7 +4226,6 @@ const generateUnary = (scope, decl) => {
|
|
4155
4226
|
...toPropertyKey(scope, generate(scope, property), getNodeType(scope, property), decl.argument.computed, true),
|
4156
4227
|
|
4157
4228
|
[ Opcodes.call, includeBuiltin(scope, scope.strict ? '__Porffor_object_deleteStrict' : '__Porffor_object_delete').index ],
|
4158
|
-
[ Opcodes.drop ],
|
4159
4229
|
Opcodes.i32_from_u
|
4160
4230
|
];
|
4161
4231
|
|
@@ -5616,10 +5686,7 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
5616
5686
|
...(kind !== 'init' ? [ Opcodes.i32_to_u ] : []),
|
5617
5687
|
...getNodeType(scope, value),
|
5618
5688
|
|
5619
|
-
[ Opcodes.call, includeBuiltin(scope, `__Porffor_object_expr_${kind}`).index ]
|
5620
|
-
|
5621
|
-
[ Opcodes.drop ],
|
5622
|
-
[ Opcodes.drop ]
|
5689
|
+
[ Opcodes.call, includeBuiltin(scope, `__Porffor_object_expr_${kind}`).index ]
|
5623
5690
|
);
|
5624
5691
|
}
|
5625
5692
|
}
|
@@ -6264,10 +6331,7 @@ const generateClass = (scope, decl) => {
|
|
6264
6331
|
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
6265
6332
|
...getNodeType(outScope, value),
|
6266
6333
|
|
6267
|
-
[ Opcodes.call, includeBuiltin(outScope, `__Porffor_object_class_${initKind}`).index ]
|
6268
|
-
|
6269
|
-
[ Opcodes.drop ],
|
6270
|
-
[ Opcodes.drop ]
|
6334
|
+
[ Opcodes.call, includeBuiltin(outScope, `__Porffor_object_class_${initKind}`).index ]
|
6271
6335
|
);
|
6272
6336
|
}
|
6273
6337
|
|
@@ -6287,7 +6351,7 @@ const generateClass = (scope, decl) => {
|
|
6287
6351
|
return out;
|
6288
6352
|
};
|
6289
6353
|
|
6290
|
-
|
6354
|
+
const generateTemplate = (scope, decl) => {
|
6291
6355
|
let current = null;
|
6292
6356
|
const append = val => {
|
6293
6357
|
if (!current) {
|
@@ -6575,9 +6639,10 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6575
6639
|
number(0),
|
6576
6640
|
number(TYPES.undefined, Valtype.i32),
|
6577
6641
|
[ Opcodes.call, includeBuiltin(scope, '__Array_from').index ],
|
6642
|
+
[ Opcodes.local_set, func.locals[name].idx ],
|
6578
6643
|
|
6644
|
+
number(TYPES.array, Valtype.i32),
|
6579
6645
|
[ Opcodes.local_set, func.locals[name].idx + 1 ],
|
6580
|
-
[ Opcodes.local_set, func.locals[name].idx ],
|
6581
6646
|
[ Opcodes.end ]
|
6582
6647
|
);
|
6583
6648
|
}
|
@@ -6664,9 +6729,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6664
6729
|
// inject promise job runner func at the end of main if promises are made
|
6665
6730
|
if (Object.hasOwn(funcIndex, 'Promise') || Object.hasOwn(funcIndex, '__Promise_resolve') || Object.hasOwn(funcIndex, '__Promise_reject')) {
|
6666
6731
|
wasm.push(
|
6667
|
-
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ]
|
6668
|
-
[ Opcodes.drop ],
|
6669
|
-
[ Opcodes.drop ]
|
6732
|
+
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ]
|
6670
6733
|
);
|
6671
6734
|
}
|
6672
6735
|
} else {
|
@@ -6687,14 +6750,12 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6687
6750
|
number(TYPES.array, Valtype.i32),
|
6688
6751
|
|
6689
6752
|
[ Opcodes.call, includeBuiltin(func, func.async ? '__Porffor_AsyncGenerator' : '__Porffor_Generator').index ],
|
6690
|
-
[ Opcodes.drop ],
|
6691
6753
|
[ Opcodes.local_set, func.locals['#generator_out'].idx ]
|
6692
6754
|
);
|
6693
6755
|
} else if (func.async) {
|
6694
6756
|
// make promise at the start
|
6695
6757
|
wasm.unshift(
|
6696
6758
|
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_create').index ],
|
6697
|
-
[ Opcodes.drop ],
|
6698
6759
|
[ Opcodes.local_set, func.locals['#async_out_promise'].idx ],
|
6699
6760
|
|
6700
6761
|
// wrap in try for later catch
|
@@ -6704,18 +6765,15 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6704
6765
|
// reject with thrown value if caught error
|
6705
6766
|
wasm.push(
|
6706
6767
|
[ Opcodes.catch, 0 ],
|
6768
|
+
[ Opcodes.local_get, func.locals['#async_out_promise'].idx ],
|
6769
|
+
number(TYPES.promise, Valtype.i32),
|
6707
6770
|
|
6708
|
-
|
6709
|
-
number(TYPES.promise, Valtype.i32),
|
6710
|
-
|
6711
|
-
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_reject').index ],
|
6712
|
-
[ Opcodes.drop ],
|
6713
|
-
[ Opcodes.drop ],
|
6771
|
+
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_reject').index ],
|
6714
6772
|
[ Opcodes.end ],
|
6715
6773
|
|
6716
6774
|
// return promise at the end of func
|
6717
6775
|
[ Opcodes.local_get, func.locals['#async_out_promise'].idx ],
|
6718
|
-
number(TYPES.promise, Valtype.i32),
|
6776
|
+
...(scope.returnType != null ? [] : [ number(TYPES.promise, Valtype.i32) ]),
|
6719
6777
|
[ Opcodes.return ]
|
6720
6778
|
);
|
6721
6779
|
|
@@ -6732,10 +6790,9 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6732
6790
|
|
6733
6791
|
if (typedInput && decl.returnType) {
|
6734
6792
|
const { type } = extractTypeAnnotation(decl.returnType);
|
6735
|
-
if (type != null
|
6736
|
-
// if (type != null) {
|
6793
|
+
if (type != null) {
|
6737
6794
|
func.returnType = type;
|
6738
|
-
func.returns = [ valtypeBinary ];
|
6795
|
+
func.returns = func.returnType === TYPES.undefined && !func.async && !func.generator ? [] : [ valtypeBinary ];
|
6739
6796
|
}
|
6740
6797
|
}
|
6741
6798
|
|
@@ -7008,8 +7065,6 @@ export default program => {
|
|
7008
7065
|
Opcodes.load = [ Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load ][valtypeInd];
|
7009
7066
|
Opcodes.store = [ Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store ][valtypeInd];
|
7010
7067
|
|
7011
|
-
Opcodes.lt = [ Opcodes.i32_lt_s, Opcodes.i64_lt_s, Opcodes.f64_lt ][valtypeInd];
|
7012
|
-
|
7013
7068
|
builtinFuncs = new BuiltinFuncs();
|
7014
7069
|
builtinVars = new BuiltinVars({ builtinFuncs });
|
7015
7070
|
prototypeFuncs = new PrototypeFuncs();
|
package/compiler/precompile.js
CHANGED
@@ -17,11 +17,10 @@ globalThis.precompile = true;
|
|
17
17
|
globalThis.valtypeOverrides = {
|
18
18
|
returns: {
|
19
19
|
__Porffor_object_get: [ Valtype.f64, Valtype.i32 ],
|
20
|
-
__Porffor_object_getExplicit: [ Valtype.f64, Valtype.i32 ],
|
21
20
|
__Porffor_object_readValue: [ Valtype.f64, Valtype.i32 ],
|
22
21
|
__Porffor_object_set: [ Valtype.f64, Valtype.i32 ],
|
23
22
|
__Porffor_object_setStrict: [ Valtype.f64, Valtype.i32 ],
|
24
|
-
__Porffor_object_packAccessor: [ Valtype.f64
|
23
|
+
__Porffor_object_packAccessor: [ Valtype.f64 ]
|
25
24
|
},
|
26
25
|
params: {
|
27
26
|
__Porffor_object_set: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
@@ -209,10 +208,11 @@ const precompile = async () => {
|
|
209
208
|
}
|
210
209
|
|
211
210
|
const total = performance.now() - t;
|
212
|
-
console.log(`\r${' '.repeat(80)}\r\u001b[2m${`[${total.toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92mcompiled ${
|
211
|
+
console.log(`\r${' '.repeat(80)}\r\u001b[2m${`[${total.toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92mcompiled ${funcs.length} funcs from ${fileCount} files\u001b[0m \u001b[90m(${['parse', 'codegen', 'opt'].map(x => `${x}: ${((timing[x] / total) * 100).toFixed(0)}%`).join(', ')})\u001b[0m`);
|
213
212
|
|
214
213
|
const comptimeFlagChecks = {
|
215
|
-
hasFunc: x => `hasFunc('${x}')
|
214
|
+
hasFunc: x => `hasFunc('${x}')`,
|
215
|
+
hasType: x => `usedTypes.has(${TYPES[x]})`
|
216
216
|
};
|
217
217
|
|
218
218
|
return `// autogenerated by compiler/precompile.js
|
@@ -243,10 +243,10 @@ ${funcs.map(x => {
|
|
243
243
|
});
|
244
244
|
|
245
245
|
const [ id, extra ] = flag.split('.');
|
246
|
-
return `[null,()=>{if(${comptimeFlagChecks[id](extra)}){const r=()=>{valtype=Prefs.valtype??'f64';valtypeBinary=Valtype[valtype];const valtypeInd=['i32','i64','f64'].indexOf(valtype);Opcodes.i32_to=[[],[Opcodes.i32_wrap_i64],Opcodes.i32_trunc_sat_f64_s][valtypeInd];Opcodes.i32_to_u=[[],[Opcodes.i32_wrap_i64],Opcodes.i32_trunc_sat_f64_u][valtypeInd];Opcodes.i32_from=[[],[Opcodes.i64_extend_i32_s],[Opcodes.f64_convert_i32_s]][valtypeInd];Opcodes.i32_from_u=[[],[Opcodes.i64_extend_i32_u],[ Opcodes.f64_convert_i32_u]][valtypeInd]};const a=Prefs;Prefs=${prefs};r();const b=generate(_,${ast});Prefs=a;r();return b;}return []}]`;
|
246
|
+
return `[null,()=>{if(${comptimeFlagChecks[id](extra)}){const r=()=>{valtype=Prefs.valtype??'f64';valtypeBinary=Valtype[valtype];const valtypeInd=['i32','i64','f64'].indexOf(valtype);Opcodes.i32_to=[[],[Opcodes.i32_wrap_i64],Opcodes.i32_trunc_sat_f64_s][valtypeInd];Opcodes.i32_to_u=[[],[Opcodes.i32_wrap_i64],Opcodes.i32_trunc_sat_f64_u][valtypeInd];Opcodes.i32_from=[[],[Opcodes.i64_extend_i32_s],[Opcodes.f64_convert_i32_s]][valtypeInd];Opcodes.i32_from_u=[[],[Opcodes.i64_extend_i32_u],[ Opcodes.f64_convert_i32_u]][valtypeInd]};const a=Prefs;Prefs=${prefs};r();const b=generate(_,${ast}).slice(0,-1);Prefs=a;r();return b;}return []}]`;
|
247
247
|
});
|
248
248
|
|
249
|
-
return `(_,{${str.includes('hasFunc(') ? 'hasFunc,' : ''}${str.includes('Valtype[') ? 'Valtype,' : ''}${str.includes('i32ify') ? 'i32ify,' : ''}${str.includes('Opcodes.') ? 'Opcodes,' : ''}${str.includes('...t(') ? 't,' : ''}${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('makeString(') ? 'makeString,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('funcRef(') ? 'funcRef,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}${str.includes('generateIdent(') ? 'generateIdent,' : ''}${str.includes('generate(') ? 'generate,' : ''}`.slice(0, -1)}})=>`.replace('_,{}', '') + str;
|
249
|
+
return `(_,{${str.includes('usedTypes.') ? 'usedTypes,' : ''}${str.includes('hasFunc(') ? 'hasFunc,' : ''}${str.includes('Valtype[') ? 'Valtype,' : ''}${str.includes('i32ify') ? 'i32ify,' : ''}${str.includes('Opcodes.') ? 'Opcodes,' : ''}${str.includes('...t(') ? 't,' : ''}${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('makeString(') ? 'makeString,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('funcRef(') ? 'funcRef,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}${str.includes('generateIdent(') ? 'generateIdent,' : ''}${str.includes('generate(') ? 'generate,' : ''}`.slice(0, -1)}})=>`.replace('_,{}', '') + str;
|
250
250
|
};
|
251
251
|
|
252
252
|
const locals = Object.entries(x.locals).sort((a,b) => a[1].idx - b[1].idx)
|
@@ -258,7 +258,7 @@ ${funcs.map(x => {
|
|
258
258
|
|
259
259
|
return `this${name} = {
|
260
260
|
wasm:${rewriteWasm(x.wasm)},
|
261
|
-
params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)}
|
261
|
+
params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)},` : ''}
|
262
262
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
263
263
|
${usedTypes.length > 0 ? `usedTypes:${JSON.stringify(usedTypes)},` : ''}
|
264
264
|
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && Object.keys(x.data).length > 0 ? `data:${JSON.stringify(x.data)},` : ''}
|
package/compiler/wrap.js
CHANGED
@@ -336,11 +336,16 @@ ${flags & 0b0001 ? ` get func idx: ${get}
|
|
336
336
|
}
|
337
337
|
|
338
338
|
case TYPES.bigint: {
|
339
|
+
if (Math.abs(value) < 0x8000000000000) {
|
340
|
+
return BigInt(value);
|
341
|
+
}
|
342
|
+
value -= 0x8000000000000;
|
343
|
+
|
339
344
|
const negative = read(Uint8Array, memory, value, 1)[0] !== 0;
|
340
345
|
const len = read(Uint16Array, memory, value + 2, 1)[0];
|
341
346
|
const digits = read(Uint32Array, memory, value + 4, len);
|
342
347
|
|
343
|
-
console.log(digits);
|
348
|
+
if (Prefs.d) console.log(digits);
|
344
349
|
|
345
350
|
let result = 0n;
|
346
351
|
for (let i = 0; i < digits.length; i++) {
|
@@ -382,8 +387,8 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
382
387
|
|
383
388
|
const noAnsi = s => s && s.replace(/\u001b\[[0-9]+m/g, '');
|
384
389
|
let longest = 0;
|
385
|
-
for (let j = 0; j <
|
386
|
-
longest = Math.max(longest, noAnsi(
|
390
|
+
for (let j = 0; j < disasm.length; j++) {
|
391
|
+
longest = Math.max(longest, noAnsi(disasm[j])?.length ?? 0);
|
387
392
|
}
|
388
393
|
|
389
394
|
if (middleIndex != -1) {
|
package/package.json
CHANGED
package/r.cjs
CHANGED