porffor 0.36.6 → 0.37.0
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/combined.js +11575 -0
- package/compiler/builtins/__internal_string.ts +111 -5
- package/compiler/builtins/_internal_object.ts +133 -0
- package/compiler/builtins/console.ts +7 -3
- package/compiler/builtins_precompiled.js +23 -3
- package/compiler/codegen.js +90 -46
- package/compiler/precompile.js +2 -0
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -104,6 +104,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
104
104
|
case 'ThisExpression':
|
105
105
|
return cacheAst(decl, generateThis(scope, decl));
|
106
106
|
|
107
|
+
case 'Super':
|
108
|
+
return cacheAst(decl, generateSuper(scope, decl));
|
109
|
+
|
107
110
|
case 'Literal':
|
108
111
|
return cacheAst(decl, generateLiteral(scope, decl, global, name));
|
109
112
|
|
@@ -245,7 +248,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
245
248
|
|
246
249
|
const encodeFunc = ({
|
247
250
|
[Opcodes.f64_const]: x => x,
|
248
|
-
[Opcodes.if]: unsignedLEB128
|
251
|
+
[Opcodes.if]: unsignedLEB128,
|
252
|
+
[Opcodes.loop]: unsignedLEB128
|
249
253
|
})[inst[0]] ?? signedLEB128;
|
250
254
|
out.push([ ...inst, ...immediates.flatMap(x => encodeFunc(x)) ]);
|
251
255
|
}
|
@@ -311,7 +315,8 @@ const lookupName = (scope, _name) => {
|
|
311
315
|
};
|
312
316
|
|
313
317
|
const internalThrow = (scope, constructor, message, expectsValue = Prefs.alwaysValueInternalThrows) => [
|
314
|
-
...
|
318
|
+
...generate(scope, {
|
319
|
+
type: 'ThrowStatement',
|
315
320
|
argument: {
|
316
321
|
type: 'NewExpression',
|
317
322
|
callee: {
|
@@ -1601,8 +1606,8 @@ const RTArrayUtil = {
|
|
1601
1606
|
]
|
1602
1607
|
};
|
1603
1608
|
|
1604
|
-
const createNewTarget = (scope, decl, idx = 0) => {
|
1605
|
-
if (decl._new) {
|
1609
|
+
const createNewTarget = (scope, decl, idx = 0, force = false) => {
|
1610
|
+
if (decl._new || force) {
|
1606
1611
|
return [
|
1607
1612
|
...(typeof idx === 'number' ? number(idx) : idx),
|
1608
1613
|
...number(TYPES.function, Valtype.i32)
|
@@ -1632,7 +1637,7 @@ const makeObject = (scope, obj) => {
|
|
1632
1637
|
});
|
1633
1638
|
}
|
1634
1639
|
|
1635
|
-
return
|
1640
|
+
return generate(scope, {
|
1636
1641
|
type: 'ObjectExpression',
|
1637
1642
|
properties
|
1638
1643
|
});
|
@@ -1692,13 +1697,48 @@ const createThisArg = (scope, decl, knownThis = undefined) => {
|
|
1692
1697
|
return knownThis;
|
1693
1698
|
}
|
1694
1699
|
|
1700
|
+
const name = mapName(decl.callee?.name);
|
1695
1701
|
if (decl._new) {
|
1702
|
+
// if precompiling or builtin func, just make empty object
|
1703
|
+
if (globalThis.precompile || Object.hasOwn(builtinFuncs, name)) return [
|
1704
|
+
...makeObject(scope, {}),
|
1705
|
+
...number(TYPES.object, Valtype.i32)
|
1706
|
+
];
|
1707
|
+
|
1708
|
+
// create new object with __proto__ set to callee prototype
|
1709
|
+
const tmp = localTmp(scope, '#this_create_tmp');
|
1710
|
+
const proto = getObjProp(decl.callee, 'prototype');
|
1711
|
+
localTmp(scope, '#member_prop_assign');
|
1712
|
+
|
1696
1713
|
return [
|
1697
1714
|
...makeObject(scope, {}),
|
1715
|
+
[ Opcodes.local_tee, tmp ],
|
1716
|
+
Opcodes.i32_to_u,
|
1717
|
+
|
1718
|
+
...number(TYPES.object, Valtype.i32),
|
1719
|
+
|
1720
|
+
...generate(scope, {
|
1721
|
+
type: 'Literal',
|
1722
|
+
value: '__proto__'
|
1723
|
+
}, false, '#member_prop_assign'),
|
1724
|
+
Opcodes.i32_to_u,
|
1725
|
+
...number(TYPES.bytestring, Valtype.i32),
|
1726
|
+
|
1727
|
+
...generate(scope, proto),
|
1728
|
+
...getNodeType(scope, proto),
|
1729
|
+
|
1730
|
+
// flags: writable
|
1731
|
+
...number(0b1000, Valtype.i32),
|
1732
|
+
...number(TYPES.number, Valtype.i32),
|
1733
|
+
|
1734
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
|
1735
|
+
[ Opcodes.drop ],
|
1736
|
+
[ Opcodes.drop ],
|
1737
|
+
|
1738
|
+
[ Opcodes.local_get, tmp ],
|
1698
1739
|
...number(TYPES.object, Valtype.i32)
|
1699
1740
|
];
|
1700
1741
|
} else {
|
1701
|
-
const name = mapName(decl.callee?.name);
|
1702
1742
|
if (name && name.startsWith('__') && name.includes('_prototype_')) {
|
1703
1743
|
// todo: this should just be same as decl._new
|
1704
1744
|
// but we do not support prototype, constructor, etc yet
|
@@ -1714,7 +1754,7 @@ const createThisArg = (scope, decl, knownThis = undefined) => {
|
|
1714
1754
|
};
|
1715
1755
|
|
1716
1756
|
return [
|
1717
|
-
...
|
1757
|
+
...generate(scope, node),
|
1718
1758
|
...getNodeType(scope, node)
|
1719
1759
|
];
|
1720
1760
|
}
|
@@ -1733,7 +1773,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1733
1773
|
|
1734
1774
|
// opt: virtualize iifes
|
1735
1775
|
if (isFuncType(decl.callee.type)) {
|
1736
|
-
const [ func ] = generateFunc(scope, decl.callee
|
1776
|
+
const [ func ] = generateFunc(scope, decl.callee);
|
1737
1777
|
name = func.name;
|
1738
1778
|
}
|
1739
1779
|
|
@@ -1836,7 +1876,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1836
1876
|
const valTmp = localTmp(scope, '#call_val');
|
1837
1877
|
const typeTmp = localTmp(scope, '#call_type', Valtype.i32);
|
1838
1878
|
|
1839
|
-
return
|
1879
|
+
return generate(scope, {
|
1840
1880
|
type: 'CallExpression',
|
1841
1881
|
callee: target,
|
1842
1882
|
arguments: decl.arguments.slice(1),
|
@@ -1939,7 +1979,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1939
1979
|
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
1940
1980
|
if (type == null) continue;
|
1941
1981
|
|
1942
|
-
protoBC[type] =
|
1982
|
+
protoBC[type] = generate(scope, {
|
1983
|
+
type: 'CallExpression',
|
1943
1984
|
callee: {
|
1944
1985
|
type: 'Identifier',
|
1945
1986
|
name: x
|
@@ -2233,11 +2274,22 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2233
2274
|
];
|
2234
2275
|
}
|
2235
2276
|
|
2277
|
+
let callee = decl.callee, callAsNew = decl._new, overrideThisWasm = decl._thisWasm;
|
2278
|
+
if (callee.type === 'Super') {
|
2279
|
+
// call super constructor with direct super() call
|
2280
|
+
callee = getObjProp(callee, 'constructor');
|
2281
|
+
callAsNew = true;
|
2282
|
+
overrideThisWasm = [
|
2283
|
+
...generate(scope, { type: 'ThisExpression' }),
|
2284
|
+
...getNodeType(scope, { type: 'ThisExpression' })
|
2285
|
+
];
|
2286
|
+
}
|
2287
|
+
|
2236
2288
|
const newTargetWasm = decl._newTargetWasm ?? createNewTarget(scope, decl, [
|
2237
2289
|
[ Opcodes.local_get, funcLocal ],
|
2238
2290
|
Opcodes.i32_from_u
|
2239
|
-
]);
|
2240
|
-
const thisWasm =
|
2291
|
+
], callAsNew);
|
2292
|
+
const thisWasm = overrideThisWasm ?? createThisArg(scope, decl, knownThis);
|
2241
2293
|
|
2242
2294
|
const gen = argc => {
|
2243
2295
|
const argsOut = [];
|
@@ -2305,11 +2357,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2305
2357
|
return [
|
2306
2358
|
...(getCalleeObj ? [
|
2307
2359
|
...initCalleeObj,
|
2308
|
-
...
|
2309
|
-
]: generate(scope,
|
2360
|
+
...generate(scope, callee, false, undefined, getCalleeObj)
|
2361
|
+
]: generate(scope, callee)),
|
2310
2362
|
[ Opcodes.local_set, localTmp(scope, '#indirect_callee') ],
|
2311
2363
|
|
2312
|
-
...typeSwitch(scope, getNodeType(scope,
|
2364
|
+
...typeSwitch(scope, getNodeType(scope, callee), {
|
2313
2365
|
[TYPES.function]: [
|
2314
2366
|
...out,
|
2315
2367
|
|
@@ -2327,7 +2379,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2327
2379
|
[ Opcodes.local_set, flags ],
|
2328
2380
|
|
2329
2381
|
// check if non-constructor was called with new, if so throw
|
2330
|
-
...(
|
2382
|
+
...(callAsNew ? [
|
2331
2383
|
[ Opcodes.local_get, flags ],
|
2332
2384
|
...number(0b10, Valtype.i32),
|
2333
2385
|
[ Opcodes.i32_and ],
|
@@ -2535,6 +2587,9 @@ const generateThis = (scope, decl) => {
|
|
2535
2587
|
];
|
2536
2588
|
};
|
2537
2589
|
|
2590
|
+
const generateSuper = (scope, decl) => generate(scope,
|
2591
|
+
getObjProp(getObjProp({ type: 'ThisExpression', _noGlobalThis: true }, '__proto__'), '__proto__'));
|
2592
|
+
|
2538
2593
|
// bad hack for undefined and null working without additional logic
|
2539
2594
|
const DEFAULT_VALUE = () => ({
|
2540
2595
|
type: 'Identifier',
|
@@ -2892,7 +2947,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
2892
2947
|
// hack for let a = function () { ... }
|
2893
2948
|
if (!init.id) {
|
2894
2949
|
init.id = { name };
|
2895
|
-
generateFunc(scope, init
|
2950
|
+
generateFunc(scope, init);
|
2896
2951
|
return out;
|
2897
2952
|
}
|
2898
2953
|
}
|
@@ -3543,7 +3598,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3543
3598
|
|
3544
3599
|
const ifIdentifierErrors = (scope, decl) => {
|
3545
3600
|
if (decl.type === 'Identifier') {
|
3546
|
-
const out =
|
3601
|
+
const out = generate(scope, decl);
|
3547
3602
|
if (out[1]) return true;
|
3548
3603
|
}
|
3549
3604
|
|
@@ -3620,7 +3675,7 @@ const generateUnary = (scope, decl) => {
|
|
3620
3675
|
let toReturn = true, toGenerate = true;
|
3621
3676
|
|
3622
3677
|
if (decl.argument.type === 'Identifier') {
|
3623
|
-
const out =
|
3678
|
+
const out = generate(scope, decl.argument);
|
3624
3679
|
|
3625
3680
|
// if ReferenceError (undeclared var), ignore and return true. otherwise false
|
3626
3681
|
if (!out[1]) {
|
@@ -4397,7 +4452,7 @@ const generateSwitch = (scope, decl) => {
|
|
4397
4452
|
const ret = typeSwitch(scope, getNodeType(scope, decl.discriminant.arguments[0]), () => {
|
4398
4453
|
const ret = [];
|
4399
4454
|
for (const [type, consequent] of cases) {
|
4400
|
-
const o =
|
4455
|
+
const o = generate(scope, { type: 'BlockStatement', body: consequent });
|
4401
4456
|
ret.push([type, o]);
|
4402
4457
|
}
|
4403
4458
|
return ret;
|
@@ -4440,7 +4495,7 @@ const generateSwitch = (scope, decl) => {
|
|
4440
4495
|
depth.pop();
|
4441
4496
|
out.push(
|
4442
4497
|
[ Opcodes.end ],
|
4443
|
-
...
|
4498
|
+
...generate(scope, { type: 'BlockStatement', body: cases[i].consequent })
|
4444
4499
|
);
|
4445
4500
|
}
|
4446
4501
|
|
@@ -5042,7 +5097,7 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
5042
5097
|
|
5043
5098
|
if (type === 'SpreadElement') {
|
5044
5099
|
out.push(
|
5045
|
-
...
|
5100
|
+
...generate(scope, {
|
5046
5101
|
type: 'CallExpression',
|
5047
5102
|
callee: {
|
5048
5103
|
type: 'Identifier',
|
@@ -5237,7 +5292,8 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5237
5292
|
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
5238
5293
|
if (type == null) continue;
|
5239
5294
|
|
5240
|
-
if (type === known) return
|
5295
|
+
if (type === known) return generate(scope, {
|
5296
|
+
type: 'CallExpression',
|
5241
5297
|
callee: {
|
5242
5298
|
type: 'Identifier',
|
5243
5299
|
name: x
|
@@ -5246,7 +5302,8 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5246
5302
|
_protoInternalCall: true
|
5247
5303
|
});
|
5248
5304
|
|
5249
|
-
bc[type] =
|
5305
|
+
bc[type] = generate(scope, {
|
5306
|
+
type: 'CallExpression',
|
5250
5307
|
callee: {
|
5251
5308
|
type: 'Identifier',
|
5252
5309
|
name: x
|
@@ -5281,7 +5338,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5281
5338
|
};
|
5282
5339
|
|
5283
5340
|
bc[type] = [
|
5284
|
-
...
|
5341
|
+
...generate(scope, ident),
|
5285
5342
|
...setLastType(scope, getNodeType(scope, ident))
|
5286
5343
|
];
|
5287
5344
|
if (type === known) return bc[type];
|
@@ -5512,7 +5569,7 @@ const generateAwait = (scope, decl) => {
|
|
5512
5569
|
|
5513
5570
|
// todo: warn here if -d?
|
5514
5571
|
|
5515
|
-
return
|
5572
|
+
return generate(scope, {
|
5516
5573
|
type: 'CallExpression',
|
5517
5574
|
callee: {
|
5518
5575
|
type: 'Identifier',
|
@@ -5585,7 +5642,7 @@ const generateClass = (scope, decl) => {
|
|
5585
5642
|
|
5586
5643
|
const k = getProperty(x, true);
|
5587
5644
|
|
5588
|
-
let initKind = '
|
5645
|
+
let initKind = type === 'MethodDefinition' ? 'method' : 'value';
|
5589
5646
|
if (kind === 'get' || kind === 'set') initKind = kind;
|
5590
5647
|
|
5591
5648
|
// default value to undefined
|
@@ -5628,10 +5685,10 @@ const generateClass = (scope, decl) => {
|
|
5628
5685
|
...toPropertyKey(outScope, generate(outScope, k), getNodeType(outScope, k), computed, true),
|
5629
5686
|
|
5630
5687
|
...generate(outScope, value),
|
5631
|
-
...(initKind !== '
|
5688
|
+
...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
|
5632
5689
|
...getNodeType(outScope, value),
|
5633
5690
|
|
5634
|
-
[ Opcodes.call, includeBuiltin(outScope, `
|
5691
|
+
[ Opcodes.call, includeBuiltin(outScope, `__Porffor_object_class_${initKind}`).index ],
|
5635
5692
|
|
5636
5693
|
[ Opcodes.drop ],
|
5637
5694
|
[ Opcodes.drop ]
|
@@ -5748,7 +5805,7 @@ const funcByIndex = idx => {
|
|
5748
5805
|
};
|
5749
5806
|
const funcByName = name => funcByIndex(funcIndex[name]);
|
5750
5807
|
|
5751
|
-
const generateFunc = (scope, decl
|
5808
|
+
const generateFunc = (scope, decl) => {
|
5752
5809
|
const name = decl.id ? decl.id.name : `#anonymous${uniqId()}`;
|
5753
5810
|
if (decl.type.startsWith('Class')) {
|
5754
5811
|
const out = generateClass(scope, {
|
@@ -5757,6 +5814,7 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
5757
5814
|
});
|
5758
5815
|
|
5759
5816
|
const func = funcByName(name);
|
5817
|
+
astCache.set(decl, out);
|
5760
5818
|
return [ func, out ];
|
5761
5819
|
}
|
5762
5820
|
|
@@ -5834,21 +5892,6 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
5834
5892
|
// todo: wrap in try and reject thrown value once supported
|
5835
5893
|
}
|
5836
5894
|
|
5837
|
-
if (!globalThis.precompile && func.constr && !func._onlyThisMethod) {
|
5838
|
-
wasm.unshift(
|
5839
|
-
// opt: do not check for pure constructors
|
5840
|
-
...(func._onlyConstr ? [] : [
|
5841
|
-
// if being constructed
|
5842
|
-
[ Opcodes.local_get, func.locals['#newtarget'].idx ],
|
5843
|
-
Opcodes.i32_to_u,
|
5844
|
-
[ Opcodes.if, Blocktype.void ],
|
5845
|
-
]),
|
5846
|
-
// set prototype of this ;)
|
5847
|
-
...generate(func, setObjProp({ type: 'ThisExpression', _noGlobalThis: true }, '__proto__', getObjProp(func.name, 'prototype'))),
|
5848
|
-
...(func._onlyConstr ? [] : [ [ Opcodes.end ] ])
|
5849
|
-
);
|
5850
|
-
}
|
5851
|
-
|
5852
5895
|
if (name === 'main') {
|
5853
5896
|
func.gotLastType = true;
|
5854
5897
|
func.export = true;
|
@@ -6004,7 +6047,8 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
6004
6047
|
// force generate all for precompile
|
6005
6048
|
if (globalThis.precompile) func.generate();
|
6006
6049
|
|
6007
|
-
const out = decl.type.endsWith('Expression')
|
6050
|
+
const out = decl.type.endsWith('Expression') ? funcRef(func) : [];
|
6051
|
+
astCache.set(decl, out);
|
6008
6052
|
return [ func, out ];
|
6009
6053
|
};
|
6010
6054
|
|
package/compiler/precompile.js
CHANGED
@@ -62,6 +62,8 @@ const compile = async (file, _funcs) => {
|
|
62
62
|
__Porffor_object_setStrict: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
63
63
|
__Porffor_object_expr_init: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
64
64
|
__Porffor_object_expr_initWithFlags: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
|
65
|
+
__Porffor_object_class_value: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
66
|
+
__Porffor_object_class_method: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
65
67
|
__Porffor_object_define: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
|
66
68
|
};
|
67
69
|
|
package/package.json
CHANGED