porffor 0.55.36 → 0.56.1
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/assemble.js +1 -0
- package/compiler/builtins.js +0 -55
- package/compiler/builtins_precompiled.js +112 -112
- package/compiler/codegen.js +37 -26
- package/compiler/expression.js +55 -3
- package/package.json +1 -1
- package/r.cjs +4 -4
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -93,7 +93,7 @@ const funcRef = func => {
|
|
93
93
|
}
|
94
94
|
|
95
95
|
const wasm = [];
|
96
|
-
const offset = func.constr ? 0 : 4;
|
96
|
+
const offset = func.constr ? 0 : (func.method ? 2 : 4);
|
97
97
|
for (let i = 0; i < func.params.length; i++) {
|
98
98
|
if (func.internal && func.name.includes('_prototype_') && i < 2) {
|
99
99
|
// special case: use real this for prototype internals
|
@@ -456,7 +456,7 @@ const lookup = (scope, name, failEarly = false) => {
|
|
456
456
|
// todo: not compliant
|
457
457
|
let len = countLength(scope);
|
458
458
|
const names = new Array(len);
|
459
|
-
const off = scope.constr ? 4 : 0;
|
459
|
+
const off = scope.constr ? 4 : (scope.method ? 2 : 0);
|
460
460
|
for (const x in scope.locals) {
|
461
461
|
const i = scope.locals[x].idx - off;
|
462
462
|
if (i >= 0 && i % 2 === 0 && i < len * 2) {
|
@@ -809,12 +809,23 @@ const compareStrings = (scope, left, right, leftType, rightType, noConv = false)
|
|
809
809
|
};
|
810
810
|
|
811
811
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
812
|
+
const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
|
812
813
|
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
813
814
|
...wasm,
|
814
|
-
...(
|
815
|
+
...(truthyMode === 'full' ? [
|
816
|
+
[ Opcodes.f64_const, 0 ],
|
817
|
+
[ Opcodes.f64_ne ],
|
818
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
819
|
+
] : [
|
820
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
821
|
+
])
|
815
822
|
];
|
816
823
|
if (isIntOp(wasm[wasm.length - 1])) return [
|
817
824
|
...wasm,
|
825
|
+
...(truthyMode === 'full' ? [
|
826
|
+
[ Opcodes.i32_eqz ],
|
827
|
+
[ Opcodes.i32_eqz ]
|
828
|
+
] : []),
|
818
829
|
...(intOut ? [] : [ Opcodes.i32_from ]),
|
819
830
|
];
|
820
831
|
|
@@ -822,8 +833,6 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
|
|
822
833
|
|
823
834
|
const useTmp = knownType(scope, type) == null;
|
824
835
|
const tmp = useTmp && localTmp(scope, `#logicinner_tmp${intIn ? '_int' : ''}`, intIn ? Valtype.i32 : valtypeBinary);
|
825
|
-
|
826
|
-
const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
|
827
836
|
const def = (() => {
|
828
837
|
if (truthyMode === 'full') return [
|
829
838
|
// if value != 0 or NaN
|
@@ -1059,21 +1068,9 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
|
|
1059
1068
|
|
1060
1069
|
let ops = operatorOpcode[valtype][op];
|
1061
1070
|
|
1062
|
-
// some complex ops are implemented
|
1063
|
-
|
1064
|
-
if (!ops && builtinFuncs[builtinName]) {
|
1065
|
-
includeBuiltin(scope, builtinName);
|
1066
|
-
const idx = funcIndex[builtinName];
|
1067
|
-
|
1068
|
-
return finalize([
|
1069
|
-
...left,
|
1070
|
-
...right,
|
1071
|
-
[ Opcodes.call, idx ]
|
1072
|
-
]);
|
1073
|
-
}
|
1074
|
-
|
1071
|
+
// some complex ops are implemented in funcs
|
1072
|
+
if (typeof ops === 'function') return finalize(asmFuncToAsm(scope, ops, { left, right }));
|
1075
1073
|
if (!ops) return todo(scope, `operator ${op} not implemented yet`, true);
|
1076
|
-
|
1077
1074
|
if (!Array.isArray(ops)) ops = [ ops ];
|
1078
1075
|
ops = [ ops ];
|
1079
1076
|
|
@@ -1244,7 +1241,7 @@ const generateBinaryExp = (scope, decl) => {
|
|
1244
1241
|
return out;
|
1245
1242
|
};
|
1246
1243
|
|
1247
|
-
const asmFuncToAsm = (scope, func) => {
|
1244
|
+
const asmFuncToAsm = (scope, func, extra) => {
|
1248
1245
|
return func(scope, {
|
1249
1246
|
Valtype, Opcodes, TYPES, TYPE_NAMES, usedTypes, typeSwitch, makeString, internalThrow,
|
1250
1247
|
getNodeType, generate, generateIdent,
|
@@ -1325,7 +1322,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1325
1322
|
return wasm;
|
1326
1323
|
},
|
1327
1324
|
allocPage: (scope, name) => allocPage({ scope, pages }, name)
|
1328
|
-
});
|
1325
|
+
}, extra);
|
1329
1326
|
};
|
1330
1327
|
|
1331
1328
|
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usesImports = false, usedTypes = [] } = {}) => {
|
@@ -1719,7 +1716,7 @@ const getNodeType = (scope, node) => {
|
|
1719
1716
|
|
1720
1717
|
if (node.type === 'ThisExpression') {
|
1721
1718
|
if (scope.overrideThisType) return scope.overrideThisType;
|
1722
|
-
if (!scope.constr) return getType(scope, 'globalThis');
|
1719
|
+
if (!scope.constr && !scope.method) return getType(scope, 'globalThis');
|
1723
1720
|
return [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ];
|
1724
1721
|
}
|
1725
1722
|
|
@@ -2639,6 +2636,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2639
2636
|
paramOffset += 4;
|
2640
2637
|
}
|
2641
2638
|
|
2639
|
+
if (func && func.method) {
|
2640
|
+
out.push(...(decl._thisWasm ?? createThisArg(scope, decl)));
|
2641
|
+
paramOffset += 2;
|
2642
|
+
}
|
2643
|
+
|
2642
2644
|
if (func && args.length < paramCount) {
|
2643
2645
|
// too little args, push undefineds
|
2644
2646
|
const underflow = paramCount - (func.hasRestArgument ? 1 : 0) - args.length;
|
@@ -2723,7 +2725,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2723
2725
|
const generateThis = (scope, decl) => {
|
2724
2726
|
if (scope.overrideThis) return scope.overrideThis;
|
2725
2727
|
|
2726
|
-
if (!scope.constr) {
|
2728
|
+
if (!scope.constr && !scope.method) {
|
2727
2729
|
// this in a non-constructor context is a reference to globalThis
|
2728
2730
|
return [
|
2729
2731
|
...generate(scope, { type: 'Identifier', name: 'globalThis' })
|
@@ -5530,7 +5532,10 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
5530
5532
|
|
5531
5533
|
for (const x of decl.properties) {
|
5532
5534
|
// method, shorthand are made into useful values by parser for us :)
|
5533
|
-
let { type, argument, computed, kind, value } = x;
|
5535
|
+
let { type, argument, computed, kind, value, method } = x;
|
5536
|
+
|
5537
|
+
// tag function as not a constructor
|
5538
|
+
if (method) value._method = true;
|
5534
5539
|
|
5535
5540
|
if (type === 'SpreadElement') {
|
5536
5541
|
out.push(
|
@@ -5623,6 +5628,7 @@ const countParams = (func, name = undefined) => {
|
|
5623
5628
|
name ??= func.name;
|
5624
5629
|
let params = func.params.length;
|
5625
5630
|
if (func.constr) params -= 4;
|
5631
|
+
if (func.method) params -= 2;
|
5626
5632
|
if (!func.internal || builtinFuncs[name]?.typedParams) params = Math.floor(params / 2);
|
5627
5633
|
|
5628
5634
|
return func.argc = params;
|
@@ -6126,6 +6132,9 @@ const generateClass = (scope, decl) => {
|
|
6126
6132
|
let { type, value, kind, static: _static, computed } = x;
|
6127
6133
|
if (kind === 'constructor') continue;
|
6128
6134
|
|
6135
|
+
// tag function as not a constructor
|
6136
|
+
if (type === 'MethodDefinition') value._method = true;
|
6137
|
+
|
6129
6138
|
if (type === 'StaticBlock') {
|
6130
6139
|
// todo: make this more compliant
|
6131
6140
|
out.push(
|
@@ -6451,7 +6460,8 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6451
6460
|
name,
|
6452
6461
|
index: currentFuncIndex++,
|
6453
6462
|
arrow,
|
6454
|
-
constr: !arrow && !decl.generator && !decl.async,
|
6463
|
+
constr: !arrow && !decl.generator && !decl.async && !decl._method, // constructable
|
6464
|
+
method: decl._method || decl.generator || decl.async, // has this but not constructable
|
6455
6465
|
async: decl.async,
|
6456
6466
|
subclass: decl._subclass, _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
6457
6467
|
strict: scope.strict || decl.strict,
|
@@ -6682,6 +6692,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6682
6692
|
|
6683
6693
|
const args = [];
|
6684
6694
|
if (func.constr) args.push({ name: '#newtarget' }, { name: '#this' });
|
6695
|
+
if (func.method) args.push({ name: '#this' });
|
6685
6696
|
|
6686
6697
|
let jsLength = 0;
|
6687
6698
|
for (let i = 0; i < params.length; i++) {
|
@@ -6722,7 +6733,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6722
6733
|
args.push({ name, def, destr, type: typedInput && params[i].typeAnnotation });
|
6723
6734
|
}
|
6724
6735
|
|
6725
|
-
func.params = new Array((params.length + (func.constr ? 2 : 0)) * 2).fill(0).map((_, i) => i % 2 ? Valtype.i32 : valtypeBinary);
|
6736
|
+
func.params = new Array((params.length + (func.constr ? 2 : (func.method ? 1 : 0))) * 2).fill(0).map((_, i) => i % 2 ? Valtype.i32 : valtypeBinary);
|
6726
6737
|
func.jsLength = jsLength;
|
6727
6738
|
|
6728
6739
|
// force generate for main
|
package/compiler/expression.js
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
import { Opcodes } from './wasmSpec.js';
|
1
|
+
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
|
+
import { TYPES } from './types.js';
|
3
|
+
|
4
|
+
const f64ifyBitwise = op => (_1, _2, { left, right }) => [
|
5
|
+
...left,
|
6
|
+
Opcodes.i32_trunc_sat_f64_s,
|
7
|
+
...right,
|
8
|
+
Opcodes.i32_trunc_sat_f64_s,
|
9
|
+
[ op ],
|
10
|
+
[ Opcodes.f64_convert_i32_s ]
|
11
|
+
];
|
2
12
|
|
3
13
|
export const operatorOpcode = {
|
4
14
|
i32: {
|
@@ -23,7 +33,17 @@ export const operatorOpcode = {
|
|
23
33
|
'>': Opcodes.i32_gt_s,
|
24
34
|
'>=': Opcodes.i32_ge_s,
|
25
35
|
'<': Opcodes.i32_lt_s,
|
26
|
-
'<=': Opcodes.i32_le_s
|
36
|
+
'<=': Opcodes.i32_le_s,
|
37
|
+
|
38
|
+
'**': (_, { builtin }, { left, right }) => [
|
39
|
+
...left,
|
40
|
+
[ Opcodes.f64_convert_i32_s ],
|
41
|
+
[ Opcodes.i32_const, TYPES.number ],
|
42
|
+
...right,
|
43
|
+
[ Opcodes.f64_convert_i32_s ],
|
44
|
+
[ Opcodes.i32_const, TYPES.number ],
|
45
|
+
[ Opcodes.call, builtin('__Math_pow') ]
|
46
|
+
]
|
27
47
|
},
|
28
48
|
|
29
49
|
i64: {
|
@@ -65,6 +85,38 @@ export const operatorOpcode = {
|
|
65
85
|
'>': Opcodes.f64_gt,
|
66
86
|
'>=': Opcodes.f64_ge,
|
67
87
|
'<': Opcodes.f64_lt,
|
68
|
-
'<=': Opcodes.f64_le
|
88
|
+
'<=': Opcodes.f64_le,
|
89
|
+
|
90
|
+
'**': (_, { builtin }, { left, right }) => [
|
91
|
+
...left,
|
92
|
+
[ Opcodes.i32_const, TYPES.number ],
|
93
|
+
...right,
|
94
|
+
[ Opcodes.i32_const, TYPES.number ],
|
95
|
+
[ Opcodes.call, builtin('__Math_pow') ]
|
96
|
+
],
|
97
|
+
|
98
|
+
'%': (_, { builtin, loc }, { left, right }) => [
|
99
|
+
// a - truncf(a / b) * b
|
100
|
+
...left,
|
101
|
+
[ Opcodes.local_tee, loc('#math_a', Valtype.f64) ],
|
102
|
+
...right,
|
103
|
+
[ Opcodes.local_tee, loc('#math_b', Valtype.f64) ],
|
104
|
+
|
105
|
+
[ Opcodes.local_get, loc('#math_a', Valtype.f64) ],
|
106
|
+
[ Opcodes.local_get, loc('#math_b', Valtype.f64) ],
|
107
|
+
[ Opcodes.f64_div ],
|
108
|
+
[ Opcodes.f64_trunc ],
|
109
|
+
|
110
|
+
[ Opcodes.f64_mul ],
|
111
|
+
[ Opcodes.f64_sub ]
|
112
|
+
],
|
113
|
+
|
114
|
+
// add bitwise ops by converting operands to i32 first
|
115
|
+
'&': f64ifyBitwise(Opcodes.i32_and),
|
116
|
+
'|': f64ifyBitwise(Opcodes.i32_or),
|
117
|
+
'^': f64ifyBitwise(Opcodes.i32_xor),
|
118
|
+
'<<': f64ifyBitwise(Opcodes.i32_shl),
|
119
|
+
'>>': f64ifyBitwise(Opcodes.i32_shr_s),
|
120
|
+
'>>>': f64ifyBitwise(Opcodes.i32_shr_u)
|
69
121
|
}
|
70
122
|
};
|
package/package.json
CHANGED
package/r.cjs
CHANGED