porffor 0.60.27 → 0.60.28
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.js +159 -0
- package/compiler/codegen.js +4 -191
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/runtime/index.js +1 -1
package/compiler/builtins.js
CHANGED
|
@@ -1411,6 +1411,165 @@ export const BuiltinFuncs = () => {
|
|
|
1411
1411
|
]
|
|
1412
1412
|
};
|
|
1413
1413
|
|
|
1414
|
+
// allow non-comptime redefinition later in precompiled
|
|
1415
|
+
const comptime = (name, returnType, comptime) => {
|
|
1416
|
+
let v = {
|
|
1417
|
+
returnType,
|
|
1418
|
+
comptime,
|
|
1419
|
+
params: [],
|
|
1420
|
+
locals: [],
|
|
1421
|
+
returns: []
|
|
1422
|
+
};
|
|
1423
|
+
|
|
1424
|
+
Object.defineProperty(_, name, {
|
|
1425
|
+
get() {
|
|
1426
|
+
return v;
|
|
1427
|
+
},
|
|
1428
|
+
set(x) {
|
|
1429
|
+
// v = { ...x, comptime, returnType };
|
|
1430
|
+
x.comptime = comptime;
|
|
1431
|
+
x.returnType = returnType;
|
|
1432
|
+
v = x;
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
comptime('__Array_of', TYPES.array, (scope, decl, { generate }) => generate(scope, {
|
|
1438
|
+
type: 'ArrayExpression',
|
|
1439
|
+
elements: decl.arguments
|
|
1440
|
+
}));
|
|
1441
|
+
|
|
1442
|
+
comptime('__Porffor_fastOr', TYPES.boolean, (scope, decl, { generate }) => {
|
|
1443
|
+
const out = [];
|
|
1444
|
+
|
|
1445
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
|
1446
|
+
out.push(
|
|
1447
|
+
...generate(scope, decl.arguments[i]),
|
|
1448
|
+
Opcodes.i32_to_u,
|
|
1449
|
+
...(i > 0 ? [ [ Opcodes.i32_or ] ] : [])
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
out.push(Opcodes.i32_from_u);
|
|
1454
|
+
return out;
|
|
1455
|
+
});
|
|
1456
|
+
|
|
1457
|
+
comptime('__Porffor_fastAnd', TYPES.boolean, (scope, decl, { generate }) => {
|
|
1458
|
+
const out = [];
|
|
1459
|
+
|
|
1460
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
|
1461
|
+
out.push(
|
|
1462
|
+
...generate(scope, decl.arguments[i]),
|
|
1463
|
+
Opcodes.i32_to_u,
|
|
1464
|
+
...(i > 0 ? [ [ Opcodes.i32_and ] ] : [])
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
out.push(Opcodes.i32_from_u);
|
|
1469
|
+
return out;
|
|
1470
|
+
});
|
|
1471
|
+
|
|
1472
|
+
comptime('__Math_max', TYPES.number, (scope, decl, { generate }) => {
|
|
1473
|
+
const out = [
|
|
1474
|
+
number(-Infinity)
|
|
1475
|
+
];
|
|
1476
|
+
|
|
1477
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
|
1478
|
+
out.push(
|
|
1479
|
+
...generate(scope, decl.arguments[i]),
|
|
1480
|
+
[ Opcodes.f64_max ]
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
return out;
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
comptime('__Math_min', TYPES.number, (scope, decl, { generate }) => {
|
|
1488
|
+
const out = [
|
|
1489
|
+
number(Infinity)
|
|
1490
|
+
];
|
|
1491
|
+
|
|
1492
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
|
1493
|
+
out.push(
|
|
1494
|
+
...generate(scope, decl.arguments[i]),
|
|
1495
|
+
[ Opcodes.f64_min ]
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
return out;
|
|
1500
|
+
});
|
|
1501
|
+
|
|
1502
|
+
comptime('__Porffor_printStatic', TYPES.undefined, (scope, decl, { printStaticStr }) => {
|
|
1503
|
+
const str = decl.arguments[0].value;
|
|
1504
|
+
const out = printStaticStr(scope, str);
|
|
1505
|
+
out.push(number(UNDEFINED));
|
|
1506
|
+
return out;
|
|
1507
|
+
});
|
|
1508
|
+
|
|
1509
|
+
comptime('__Porffor_type', TYPES.number, (scope, decl, { getNodeType }) => [
|
|
1510
|
+
...getNodeType(scope, decl.arguments[0]),
|
|
1511
|
+
Opcodes.i32_from_u
|
|
1512
|
+
]);
|
|
1513
|
+
|
|
1514
|
+
comptime('__Porffor_compileType', TYPES.bytestring, (scope, decl, { makeString, knownType }) =>
|
|
1515
|
+
makeString(scope, TYPE_NAMES[knownType(scope, getNodeType(scope, decl.arguments[0]))] ?? 'unknown')
|
|
1516
|
+
);
|
|
1517
|
+
|
|
1518
|
+
// Porffor.call(func, argArray, this, newTarget)
|
|
1519
|
+
comptime('__Porffor_call', TYPES.number, (scope, decl, { generate, getNodeType }) => generate(scope, {
|
|
1520
|
+
type: 'CallExpression',
|
|
1521
|
+
callee: decl.arguments[0],
|
|
1522
|
+
arguments: [ {
|
|
1523
|
+
type: 'SpreadElement',
|
|
1524
|
+
argument: decl.arguments[1],
|
|
1525
|
+
} ],
|
|
1526
|
+
_thisWasm: decl.arguments[2].value === null ? null : [
|
|
1527
|
+
...generate(scope, decl.arguments[2]),
|
|
1528
|
+
...getNodeType(scope, decl.arguments[2])
|
|
1529
|
+
],
|
|
1530
|
+
_newTargetWasm: decl.arguments[3].value === null ? null : [
|
|
1531
|
+
...generate(scope, decl.arguments[3]),
|
|
1532
|
+
...getNodeType(scope, decl.arguments[3])
|
|
1533
|
+
],
|
|
1534
|
+
_new: decl.arguments[3].value !== null,
|
|
1535
|
+
_forceCreateThis: true
|
|
1536
|
+
}));
|
|
1537
|
+
|
|
1538
|
+
// compile-time aware console.log to optimize fast paths
|
|
1539
|
+
// todo: this breaks console.group, etc - disable this if those are used but edge case for now
|
|
1540
|
+
comptime('__console_log', TYPES.undefined, (scope, decl, { generate, getNodeType, knownTypeWithGuess, printStaticStr }) => {
|
|
1541
|
+
const slow = () => {
|
|
1542
|
+
decl._noInternalConstr = true;
|
|
1543
|
+
return generate(scope, decl);
|
|
1544
|
+
};
|
|
1545
|
+
const fast = name => {
|
|
1546
|
+
return [
|
|
1547
|
+
...generate(scope, {
|
|
1548
|
+
...decl,
|
|
1549
|
+
callee: {
|
|
1550
|
+
type: 'Identifier',
|
|
1551
|
+
name
|
|
1552
|
+
}
|
|
1553
|
+
}),
|
|
1554
|
+
...printStaticStr(scope, '\n')
|
|
1555
|
+
];
|
|
1556
|
+
};
|
|
1557
|
+
if (decl.arguments.length !== 1) return slow();
|
|
1558
|
+
|
|
1559
|
+
generate(scope, decl.arguments[0]); // generate first to get accurate type
|
|
1560
|
+
const type = knownTypeWithGuess(scope, getNodeType(scope, decl.arguments[0]));
|
|
1561
|
+
|
|
1562
|
+
// if we know the type skip the entire print logic, use type's func directly
|
|
1563
|
+
if (type === TYPES.string || type === TYPES.bytestring) {
|
|
1564
|
+
return fast('__Porffor_printString');
|
|
1565
|
+
} else if (type === TYPES.number) {
|
|
1566
|
+
return fast('print');
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
// one arg, skip most of console to avoid rest arg etc
|
|
1570
|
+
return fast('__Porffor_consolePrint');
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1414
1573
|
PrecompiledBuiltins.BuiltinFuncs(_);
|
|
1415
1574
|
return _;
|
|
1416
1575
|
};
|
package/compiler/codegen.js
CHANGED
|
@@ -79,7 +79,7 @@ const isFuncType = type =>
|
|
|
79
79
|
type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression' ||
|
|
80
80
|
type === 'ClassDeclaration' || type === 'ClassExpression';
|
|
81
81
|
const hasFuncWithName = name =>
|
|
82
|
-
name in funcIndex || name in builtinFuncs || name in importedFuncs
|
|
82
|
+
name in funcIndex || name in builtinFuncs || name in importedFuncs;
|
|
83
83
|
|
|
84
84
|
const astCache = new WeakMap();
|
|
85
85
|
const cacheAst = (decl, wasm) => {
|
|
@@ -614,9 +614,6 @@ const lookup = (scope, name, failEarly = false) => {
|
|
|
614
614
|
|
|
615
615
|
if (name in builtinFuncs) {
|
|
616
616
|
if (!(name in funcIndex)) includeBuiltin(scope, name);
|
|
617
|
-
} else if (name in internalConstrs) {
|
|
618
|
-
// todo: return an actual something
|
|
619
|
-
return [ number(1) ];
|
|
620
617
|
}
|
|
621
618
|
|
|
622
619
|
if (local?.idx === undefined) {
|
|
@@ -1528,8 +1525,8 @@ const asmFunc = (name, func) => {
|
|
|
1528
1525
|
func = { ...func };
|
|
1529
1526
|
let { wasm, params = [], locals: localTypes = [], localNames = [], table, usesTag, returnTypes, returnType } = func;
|
|
1530
1527
|
if (wasm == null) { // called with no built-in
|
|
1531
|
-
log.warning('codegen', `${name} has no built-in!`);
|
|
1532
|
-
wasm = [];
|
|
1528
|
+
if (!func.comptime) log.warning('codegen', `${name} has no built-in!`);
|
|
1529
|
+
wasm = () => [];
|
|
1533
1530
|
}
|
|
1534
1531
|
|
|
1535
1532
|
const existing = builtinFuncByName(name);
|
|
@@ -1782,7 +1779,6 @@ const getNodeType = (scope, node) => {
|
|
|
1782
1779
|
}
|
|
1783
1780
|
|
|
1784
1781
|
if (name in builtinFuncs && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
|
|
1785
|
-
if (name in internalConstrs && internalConstrs[name].type != null) return internalConstrs[name].type;
|
|
1786
1782
|
|
|
1787
1783
|
if (name.startsWith('__Porffor_wasm_')) {
|
|
1788
1784
|
// todo: return undefined for non-returning ops
|
|
@@ -2449,9 +2445,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
|
2449
2445
|
let idx;
|
|
2450
2446
|
if (decl._funcIdx) {
|
|
2451
2447
|
idx = decl._funcIdx;
|
|
2452
|
-
} else if (name in internalConstrs && !decl._noInternalConstr) {
|
|
2453
|
-
if (decl._new && internalConstrs[name].notConstr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
|
|
2454
|
-
return internalConstrs[name].generate(scope, decl, _global, _name);
|
|
2455
2448
|
} else if (name in funcIndex) {
|
|
2456
2449
|
idx = funcIndex[name];
|
|
2457
2450
|
} else if (scope.name === name) {
|
|
@@ -2462,6 +2455,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
|
2462
2455
|
scope.usesImports = true;
|
|
2463
2456
|
} else if (name in builtinFuncs) {
|
|
2464
2457
|
if (decl._new && !builtinFuncs[name].constr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
|
|
2458
|
+
if (builtinFuncs[name].comptime && !decl._noComptime) return builtinFuncs[name].comptime(scope, decl, { generate, getNodeType, knownTypeWithGuess, makeString, printStaticStr });
|
|
2465
2459
|
|
|
2466
2460
|
includeBuiltin(scope, name);
|
|
2467
2461
|
idx = funcIndex[name];
|
|
@@ -7166,187 +7160,6 @@ const generateBlock = (scope, decl) => {
|
|
|
7166
7160
|
return out;
|
|
7167
7161
|
};
|
|
7168
7162
|
|
|
7169
|
-
const internalConstrs = {
|
|
7170
|
-
__proto__: null,
|
|
7171
|
-
__Array_of: {
|
|
7172
|
-
// this is not a constructor but best fits internal structure here
|
|
7173
|
-
generate: (scope, decl, global, name) => {
|
|
7174
|
-
// Array.of(i0, i1, ...)
|
|
7175
|
-
return generateArray(scope, {
|
|
7176
|
-
elements: decl.arguments
|
|
7177
|
-
}, global, name);
|
|
7178
|
-
},
|
|
7179
|
-
type: TYPES.array,
|
|
7180
|
-
notConstr: true
|
|
7181
|
-
},
|
|
7182
|
-
|
|
7183
|
-
__Porffor_fastOr: {
|
|
7184
|
-
generate: (scope, decl) => {
|
|
7185
|
-
const out = [];
|
|
7186
|
-
|
|
7187
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
|
7188
|
-
out.push(
|
|
7189
|
-
...generate(scope, decl.arguments[i]),
|
|
7190
|
-
Opcodes.i32_to_u,
|
|
7191
|
-
...(i > 0 ? [ [ Opcodes.i32_or ] ] : [])
|
|
7192
|
-
);
|
|
7193
|
-
}
|
|
7194
|
-
|
|
7195
|
-
out.push(Opcodes.i32_from_u);
|
|
7196
|
-
|
|
7197
|
-
return out;
|
|
7198
|
-
},
|
|
7199
|
-
type: TYPES.boolean,
|
|
7200
|
-
notConstr: true
|
|
7201
|
-
},
|
|
7202
|
-
|
|
7203
|
-
__Porffor_fastAnd: {
|
|
7204
|
-
generate: (scope, decl) => {
|
|
7205
|
-
const out = [];
|
|
7206
|
-
|
|
7207
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
|
7208
|
-
out.push(
|
|
7209
|
-
...generate(scope, decl.arguments[i]),
|
|
7210
|
-
Opcodes.i32_to_u,
|
|
7211
|
-
...(i > 0 ? [ [ Opcodes.i32_and ] ] : [])
|
|
7212
|
-
);
|
|
7213
|
-
}
|
|
7214
|
-
|
|
7215
|
-
out.push(Opcodes.i32_from_u);
|
|
7216
|
-
|
|
7217
|
-
return out;
|
|
7218
|
-
},
|
|
7219
|
-
type: TYPES.boolean,
|
|
7220
|
-
notConstr: true
|
|
7221
|
-
},
|
|
7222
|
-
|
|
7223
|
-
__Math_max: {
|
|
7224
|
-
generate: (scope, decl) => {
|
|
7225
|
-
const out = [
|
|
7226
|
-
number(-Infinity)
|
|
7227
|
-
];
|
|
7228
|
-
|
|
7229
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
|
7230
|
-
out.push(
|
|
7231
|
-
...generate(scope, decl.arguments[i]),
|
|
7232
|
-
[ Opcodes.f64_max ]
|
|
7233
|
-
);
|
|
7234
|
-
}
|
|
7235
|
-
|
|
7236
|
-
return out;
|
|
7237
|
-
},
|
|
7238
|
-
type: TYPES.number,
|
|
7239
|
-
notConstr: true
|
|
7240
|
-
},
|
|
7241
|
-
|
|
7242
|
-
__Math_min: {
|
|
7243
|
-
generate: (scope, decl) => {
|
|
7244
|
-
const out = [
|
|
7245
|
-
number(Infinity)
|
|
7246
|
-
];
|
|
7247
|
-
|
|
7248
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
|
7249
|
-
out.push(
|
|
7250
|
-
...generate(scope, decl.arguments[i]),
|
|
7251
|
-
[ Opcodes.f64_min ]
|
|
7252
|
-
);
|
|
7253
|
-
}
|
|
7254
|
-
|
|
7255
|
-
return out;
|
|
7256
|
-
},
|
|
7257
|
-
type: TYPES.number,
|
|
7258
|
-
notConstr: true
|
|
7259
|
-
},
|
|
7260
|
-
|
|
7261
|
-
__Porffor_printStatic: {
|
|
7262
|
-
generate: (scope, decl) => {
|
|
7263
|
-
const str = decl.arguments[0].value;
|
|
7264
|
-
const out = printStaticStr(scope, str);
|
|
7265
|
-
out.push(number(UNDEFINED));
|
|
7266
|
-
return out;
|
|
7267
|
-
},
|
|
7268
|
-
type: TYPES.undefined,
|
|
7269
|
-
notConstr: true
|
|
7270
|
-
},
|
|
7271
|
-
|
|
7272
|
-
__Porffor_type: {
|
|
7273
|
-
generate: (scope, decl) => [
|
|
7274
|
-
...getNodeType(scope, decl.arguments[0]),
|
|
7275
|
-
Opcodes.i32_from_u
|
|
7276
|
-
],
|
|
7277
|
-
type: TYPES.number,
|
|
7278
|
-
notConstr: true
|
|
7279
|
-
},
|
|
7280
|
-
|
|
7281
|
-
__Porffor_compileType: {
|
|
7282
|
-
generate: (scope, decl) => makeString(scope, TYPE_NAMES[knownType(scope, getNodeType(scope, decl.arguments[0]))] ?? 'unknown'),
|
|
7283
|
-
type: TYPES.bytestring,
|
|
7284
|
-
notConstr: true
|
|
7285
|
-
},
|
|
7286
|
-
|
|
7287
|
-
__Porffor_call: {
|
|
7288
|
-
// Porffor.call(func, argArray, this, newTarget)
|
|
7289
|
-
generate: (scope, decl) => generate(scope, {
|
|
7290
|
-
type: 'CallExpression',
|
|
7291
|
-
callee: decl.arguments[0],
|
|
7292
|
-
arguments: [ {
|
|
7293
|
-
type: 'SpreadElement',
|
|
7294
|
-
argument: decl.arguments[1],
|
|
7295
|
-
} ],
|
|
7296
|
-
_thisWasm: decl.arguments[2].value === null ? null : [
|
|
7297
|
-
...generate(scope, decl.arguments[2]),
|
|
7298
|
-
...getNodeType(scope, decl.arguments[2])
|
|
7299
|
-
],
|
|
7300
|
-
_newTargetWasm: decl.arguments[3].value === null ? null : [
|
|
7301
|
-
...generate(scope, decl.arguments[3]),
|
|
7302
|
-
...getNodeType(scope, decl.arguments[3])
|
|
7303
|
-
],
|
|
7304
|
-
_new: decl.arguments[3].value !== null,
|
|
7305
|
-
_forceCreateThis: true
|
|
7306
|
-
}),
|
|
7307
|
-
notConstr: true
|
|
7308
|
-
},
|
|
7309
|
-
|
|
7310
|
-
__console_log: {
|
|
7311
|
-
// compile-time aware console.log to optimize fast paths
|
|
7312
|
-
// todo: this breaks console.group, etc - disable this if those are used but edge case for now
|
|
7313
|
-
generate: (scope, decl) => {
|
|
7314
|
-
const slow = () => {
|
|
7315
|
-
decl._noInternalConstr = true;
|
|
7316
|
-
return generate(scope, decl);
|
|
7317
|
-
};
|
|
7318
|
-
const fast = name => {
|
|
7319
|
-
return [
|
|
7320
|
-
...generate(scope, {
|
|
7321
|
-
...decl,
|
|
7322
|
-
callee: {
|
|
7323
|
-
type: 'Identifier',
|
|
7324
|
-
name
|
|
7325
|
-
}
|
|
7326
|
-
}),
|
|
7327
|
-
...printStaticStr(scope, '\n')
|
|
7328
|
-
];
|
|
7329
|
-
};
|
|
7330
|
-
if (decl.arguments.length !== 1) return slow();
|
|
7331
|
-
|
|
7332
|
-
generate(scope, decl.arguments[0]); // generate first to get accurate type
|
|
7333
|
-
const type = knownTypeWithGuess(scope, getNodeType(scope, decl.arguments[0]));
|
|
7334
|
-
|
|
7335
|
-
// if we know the type skip the entire print logic, use type's func directly
|
|
7336
|
-
if (type === TYPES.string || type === TYPES.bytestring) {
|
|
7337
|
-
return fast('__Porffor_printString');
|
|
7338
|
-
} else if (type === TYPES.number) {
|
|
7339
|
-
return fast('print');
|
|
7340
|
-
}
|
|
7341
|
-
|
|
7342
|
-
// one arg, skip most of console to avoid rest arg etc
|
|
7343
|
-
return fast('__Porffor_consolePrint');
|
|
7344
|
-
},
|
|
7345
|
-
type: TYPES.undefined,
|
|
7346
|
-
notConstr: true
|
|
7347
|
-
}
|
|
7348
|
-
};
|
|
7349
|
-
|
|
7350
7163
|
let globals, tags, exceptions, funcs, indirectFuncs, funcIndex, currentFuncIndex, depth, pages, data, typeswitchDepth, usedTypes, coctc, globalInfer, builtinFuncs, builtinVars, lastValtype;
|
|
7351
7164
|
export default program => {
|
|
7352
7165
|
globals = Object.create(null);
|
package/jsr.json
CHANGED
package/package.json
CHANGED