@markw65/monkeyc-optimizer 1.0.21 → 1.0.22
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/README.md +20 -0
- package/build/api.cjs +542 -153
- package/build/optimizer.cjs +310 -126
- package/build/src/api.d.ts +5 -2
- package/build/src/inliner.d.ts +1 -5
- package/build/src/mc-rewrite.d.ts +4 -4
- package/build/src/optimizer.d.ts +25 -8
- package/build/src/pragma-checker.d.ts +1 -1
- package/build/src/util.d.ts +1 -0
- package/build/src/visitor.d.ts +2 -0
- package/build/util.cjs +5 -1
- package/package.json +2 -2
package/build/optimizer.cjs
CHANGED
|
@@ -10890,11 +10890,13 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
10890
10890
|
case "Identifier":
|
|
10891
10891
|
case "MemberExpression": {
|
|
10892
10892
|
const [, results] = state.lookup(arg);
|
|
10893
|
-
if (!results ||
|
|
10893
|
+
if (!results ||
|
|
10894
|
+
results.length !== 1 ||
|
|
10895
|
+
results[0].results.length !== 1) {
|
|
10894
10896
|
safeArgs.push(null);
|
|
10895
10897
|
return !requireAll;
|
|
10896
10898
|
}
|
|
10897
|
-
const safety = getSafety(results[0]);
|
|
10899
|
+
const safety = getSafety(results[0].results[0]);
|
|
10898
10900
|
safeArgs.push(safety);
|
|
10899
10901
|
if (!safety) {
|
|
10900
10902
|
allSafe = false;
|
|
@@ -10986,12 +10988,6 @@ function inliningLooksUseful(func, node) {
|
|
|
10986
10988
|
}
|
|
10987
10989
|
return false;
|
|
10988
10990
|
}
|
|
10989
|
-
var InlineStatus;
|
|
10990
|
-
(function (InlineStatus) {
|
|
10991
|
-
InlineStatus[InlineStatus["Never"] = 0] = "Never";
|
|
10992
|
-
InlineStatus[InlineStatus["AsExpression"] = 1] = "AsExpression";
|
|
10993
|
-
InlineStatus[InlineStatus["AsStatement"] = 2] = "AsStatement";
|
|
10994
|
-
})(InlineStatus || (InlineStatus = {}));
|
|
10995
10991
|
function inlineRequested(state, func) {
|
|
10996
10992
|
const excludeAnnotations = (func.node.loc?.source &&
|
|
10997
10993
|
state.fnMap[func.node.loc?.source]?.excludeAnnotations) ||
|
|
@@ -11001,7 +10997,7 @@ function inlineRequested(state, func) {
|
|
|
11001
10997
|
func.node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" &&
|
|
11002
10998
|
(attr.argument.name === "inline" ||
|
|
11003
10999
|
(attr.argument.name.startsWith("inline_") &&
|
|
11004
|
-
(0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7)))))) {
|
|
11000
|
+
!(0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7)))))) {
|
|
11005
11001
|
return true;
|
|
11006
11002
|
}
|
|
11007
11003
|
return false;
|
|
@@ -11171,7 +11167,7 @@ function unused(expression, top) {
|
|
|
11171
11167
|
},
|
|
11172
11168
|
];
|
|
11173
11169
|
}
|
|
11174
|
-
function diagnostic(state, loc, message) {
|
|
11170
|
+
function diagnostic(state, loc, message, type = "INFO") {
|
|
11175
11171
|
if (!loc || !loc.source)
|
|
11176
11172
|
return;
|
|
11177
11173
|
const source = loc.source;
|
|
@@ -11187,7 +11183,7 @@ function diagnostic(state, loc, message) {
|
|
|
11187
11183
|
if (message) {
|
|
11188
11184
|
if (index < 0)
|
|
11189
11185
|
index = diags.length;
|
|
11190
|
-
diags[index] = { type
|
|
11186
|
+
diags[index] = { type, loc, message };
|
|
11191
11187
|
}
|
|
11192
11188
|
else if (index >= 0) {
|
|
11193
11189
|
diags.splice(index, 1);
|
|
@@ -11306,23 +11302,25 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
11306
11302
|
// With a bit more work, we could find the guaranteed shortest
|
|
11307
11303
|
// reference, and then use this to optimize *all* symbols, not
|
|
11308
11304
|
// just fix inlined ones.
|
|
11309
|
-
if (current &&
|
|
11310
|
-
current.length === original.length &&
|
|
11311
|
-
current.every((item, index) => item == original[index])) {
|
|
11305
|
+
if (current && (0,external_api_cjs_namespaceObject.sameLookupResult)(original, current)) {
|
|
11312
11306
|
return lookupNode;
|
|
11313
11307
|
}
|
|
11314
11308
|
const node = lookupNode.type === "Identifier"
|
|
11315
11309
|
? lookupNode
|
|
11316
11310
|
: lookupNode.property;
|
|
11317
|
-
if (original.length === 1 &&
|
|
11318
|
-
|
|
11311
|
+
if (original.length === 1 &&
|
|
11312
|
+
original[0].results.length === 1 &&
|
|
11313
|
+
original[0].results[0].type === "EnumStringMember") {
|
|
11314
|
+
return applyTypeIfNeeded(original[0].results[0].init);
|
|
11319
11315
|
}
|
|
11320
|
-
const prefixes = original
|
|
11316
|
+
const prefixes = original
|
|
11317
|
+
.map((lookupDef) => lookupDef.results.map((sn) => {
|
|
11321
11318
|
if ((0,external_api_cjs_namespaceObject.isStateNode)(sn) && sn.fullName) {
|
|
11322
11319
|
return sn.fullName;
|
|
11323
11320
|
}
|
|
11324
11321
|
return "";
|
|
11325
|
-
})
|
|
11322
|
+
}))
|
|
11323
|
+
.flat();
|
|
11326
11324
|
if (prefixes.length &&
|
|
11327
11325
|
prefixes[0].startsWith("$.") &&
|
|
11328
11326
|
prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
|
|
@@ -11332,9 +11330,7 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
11332
11330
|
if (found)
|
|
11333
11331
|
return current;
|
|
11334
11332
|
const [, results] = state.lookup(current);
|
|
11335
|
-
if (results &&
|
|
11336
|
-
results.length === original.length &&
|
|
11337
|
-
results.every((result, i) => result === original[i])) {
|
|
11333
|
+
if (results && (0,external_api_cjs_namespaceObject.sameLookupResult)(original, results)) {
|
|
11338
11334
|
found = true;
|
|
11339
11335
|
return current;
|
|
11340
11336
|
}
|
|
@@ -11374,6 +11370,85 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
11374
11370
|
return null;
|
|
11375
11371
|
}
|
|
11376
11372
|
|
|
11373
|
+
;// CONCATENATED MODULE: ./src/visitor.ts
|
|
11374
|
+
|
|
11375
|
+
function visitReferences(state, ast, name, defn, callback) {
|
|
11376
|
+
const checkResults = ([name, results], node) => {
|
|
11377
|
+
if (name && results) {
|
|
11378
|
+
if (!defn || (0,external_api_cjs_namespaceObject.sameLookupResult)(results, defn)) {
|
|
11379
|
+
if (callback(node, results, false) === false) {
|
|
11380
|
+
return [];
|
|
11381
|
+
}
|
|
11382
|
+
}
|
|
11383
|
+
}
|
|
11384
|
+
else if (defn === false) {
|
|
11385
|
+
if (callback(node, [], results === null) === false) {
|
|
11386
|
+
return [];
|
|
11387
|
+
}
|
|
11388
|
+
}
|
|
11389
|
+
return null;
|
|
11390
|
+
};
|
|
11391
|
+
state.pre = (node) => {
|
|
11392
|
+
switch (node.type) {
|
|
11393
|
+
case "AttributeList":
|
|
11394
|
+
return [];
|
|
11395
|
+
case "UnaryExpression":
|
|
11396
|
+
// a bare symbol isn't a reference
|
|
11397
|
+
if (node.operator === ":")
|
|
11398
|
+
return [];
|
|
11399
|
+
break;
|
|
11400
|
+
case "BinaryExpression":
|
|
11401
|
+
/*
|
|
11402
|
+
* `expr has :symbol` can be treated as a reference
|
|
11403
|
+
* to expr.symbol.
|
|
11404
|
+
*/
|
|
11405
|
+
if (node.operator === "has") {
|
|
11406
|
+
if (node.right.type === "UnaryExpression" &&
|
|
11407
|
+
node.right.operator === ":") {
|
|
11408
|
+
if (!name || node.right.argument.name === name) {
|
|
11409
|
+
return checkResults(state.lookup({
|
|
11410
|
+
type: "MemberExpression",
|
|
11411
|
+
object: node.left,
|
|
11412
|
+
property: node.right.argument,
|
|
11413
|
+
computed: false,
|
|
11414
|
+
}), node.right.argument);
|
|
11415
|
+
}
|
|
11416
|
+
}
|
|
11417
|
+
}
|
|
11418
|
+
break;
|
|
11419
|
+
case "CallExpression":
|
|
11420
|
+
// A call expression whose callee is an identifier is looked
|
|
11421
|
+
// up as a non-local. ie even if there's a same named local,
|
|
11422
|
+
// it will be ignored, and the lookup will start as if the
|
|
11423
|
+
// call had been written self.foo() rather than foo().
|
|
11424
|
+
if (node.callee.type === "Identifier") {
|
|
11425
|
+
if (!name || node.callee.name === name) {
|
|
11426
|
+
/* ignore return value */
|
|
11427
|
+
checkResults(state.lookupNonlocal(node.callee), node.callee);
|
|
11428
|
+
}
|
|
11429
|
+
return ["arguments"];
|
|
11430
|
+
}
|
|
11431
|
+
break;
|
|
11432
|
+
case "Identifier":
|
|
11433
|
+
if (!name || node.name === name) {
|
|
11434
|
+
return checkResults(state.lookup(node), node);
|
|
11435
|
+
}
|
|
11436
|
+
break;
|
|
11437
|
+
case "MemberExpression":
|
|
11438
|
+
if (!node.computed && node.property.type === "Identifier") {
|
|
11439
|
+
if (!name || node.property.name === name) {
|
|
11440
|
+
return checkResults(state.lookup(node), node) || ["object"];
|
|
11441
|
+
}
|
|
11442
|
+
return ["object"];
|
|
11443
|
+
}
|
|
11444
|
+
break;
|
|
11445
|
+
}
|
|
11446
|
+
return null;
|
|
11447
|
+
};
|
|
11448
|
+
(0,external_api_cjs_namespaceObject.collectNamespaces)(ast, state);
|
|
11449
|
+
delete state.pre;
|
|
11450
|
+
}
|
|
11451
|
+
|
|
11377
11452
|
;// CONCATENATED MODULE: ./src/mc-rewrite.ts
|
|
11378
11453
|
|
|
11379
11454
|
|
|
@@ -11381,43 +11456,24 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
11381
11456
|
|
|
11382
11457
|
|
|
11383
11458
|
|
|
11384
|
-
|
|
11385
|
-
allImports.forEach(({ node, stack }) => {
|
|
11386
|
-
const [name, module] = lookup(node.id, ("as" in node && node.as && node.as.name) || null, stack);
|
|
11387
|
-
if (name && module) {
|
|
11388
|
-
const [parent] = stack.slice(-1);
|
|
11389
|
-
if (!parent.decls)
|
|
11390
|
-
parent.decls = {};
|
|
11391
|
-
const decls = parent.decls;
|
|
11392
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(decls, name))
|
|
11393
|
-
decls[name] = [];
|
|
11394
|
-
module.forEach((m) => {
|
|
11395
|
-
if ((0,external_api_cjs_namespaceObject.isStateNode)(m) && m.type == "ModuleDeclaration") {
|
|
11396
|
-
(0,external_util_cjs_namespaceObject.pushUnique)(decls[name], m);
|
|
11397
|
-
if (!parent.type_decls)
|
|
11398
|
-
parent.type_decls = {};
|
|
11399
|
-
const tdecls = parent.type_decls;
|
|
11400
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
|
|
11401
|
-
tdecls[name] = [];
|
|
11402
|
-
(0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], m);
|
|
11403
|
-
if (node.type == "ImportModule" && m.type_decls) {
|
|
11404
|
-
Object.entries(m.type_decls).forEach(([name, decls]) => {
|
|
11405
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
|
|
11406
|
-
tdecls[name] = [];
|
|
11407
|
-
decls.forEach((decl) => (0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], decl));
|
|
11408
|
-
});
|
|
11409
|
-
}
|
|
11410
|
-
}
|
|
11411
|
-
});
|
|
11412
|
-
}
|
|
11413
|
-
});
|
|
11414
|
-
}
|
|
11459
|
+
|
|
11415
11460
|
function collectClassInfo(state) {
|
|
11461
|
+
const toybox = state.stack[0].decls["Toybox"][0];
|
|
11462
|
+
const lang = toybox.decls["Lang"][0];
|
|
11463
|
+
const object = lang.decls["Object"];
|
|
11416
11464
|
state.allClasses.forEach((elm) => {
|
|
11465
|
+
if (elm.stack[elm.stack.length - 1].type === "ClassDeclaration") {
|
|
11466
|
+
// nested classes don't get access to their contained
|
|
11467
|
+
// context. Put them in the global scope instead.
|
|
11468
|
+
elm.stack = elm.stack.slice(0, 1);
|
|
11469
|
+
}
|
|
11417
11470
|
if (elm.node.superClass) {
|
|
11418
|
-
const [name,
|
|
11419
|
-
const superClass =
|
|
11420
|
-
|
|
11471
|
+
const [name, lookupDefns] = state.lookup(elm.node.superClass, null, elm.stack);
|
|
11472
|
+
const superClass = lookupDefns &&
|
|
11473
|
+
lookupDefns
|
|
11474
|
+
.map((lookupDefn) => lookupDefn.results)
|
|
11475
|
+
.flat()
|
|
11476
|
+
.filter((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && c.type === "ClassDeclaration");
|
|
11421
11477
|
// set it "true" if there is a superClass, but we can't find it.
|
|
11422
11478
|
elm.superClass = superClass && superClass.length ? superClass : true;
|
|
11423
11479
|
if (name && elm.superClass !== true) {
|
|
@@ -11449,6 +11505,9 @@ function collectClassInfo(state) {
|
|
|
11449
11505
|
elm.decls[name] = elm.superClass;
|
|
11450
11506
|
}
|
|
11451
11507
|
}
|
|
11508
|
+
else if (elm !== object[0]) {
|
|
11509
|
+
elm.superClass = object;
|
|
11510
|
+
}
|
|
11452
11511
|
});
|
|
11453
11512
|
const markOverrides = (cls, scls) => {
|
|
11454
11513
|
if (scls === true)
|
|
@@ -11501,11 +11560,12 @@ function getFileASTs(fnMap) {
|
|
|
11501
11560
|
return ok;
|
|
11502
11561
|
}, true));
|
|
11503
11562
|
}
|
|
11504
|
-
async function analyze(fnMap) {
|
|
11563
|
+
async function analyze(fnMap, barrelList, config) {
|
|
11505
11564
|
let hasTests = false;
|
|
11506
|
-
|
|
11565
|
+
let markApi = true;
|
|
11507
11566
|
const preState = {
|
|
11508
11567
|
fnMap,
|
|
11568
|
+
config,
|
|
11509
11569
|
allFunctions: [],
|
|
11510
11570
|
allClasses: [],
|
|
11511
11571
|
shouldExclude(node) {
|
|
@@ -11533,45 +11593,37 @@ async function analyze(fnMap) {
|
|
|
11533
11593
|
}
|
|
11534
11594
|
return false;
|
|
11535
11595
|
},
|
|
11536
|
-
|
|
11596
|
+
pre(node, state) {
|
|
11537
11597
|
switch (node.type) {
|
|
11538
11598
|
case "FunctionDeclaration":
|
|
11599
|
+
if (markApi) {
|
|
11600
|
+
node.body = null;
|
|
11601
|
+
break;
|
|
11602
|
+
}
|
|
11603
|
+
case "ModuleDeclaration":
|
|
11539
11604
|
case "ClassDeclaration": {
|
|
11540
11605
|
const [scope] = state.stack.slice(-1);
|
|
11541
|
-
|
|
11542
|
-
scope.stack = stack;
|
|
11606
|
+
scope.stack = state.stackClone().slice(0, -1);
|
|
11543
11607
|
if (scope.type == "FunctionDeclaration") {
|
|
11608
|
+
scope.isStatic =
|
|
11609
|
+
scope.stack.slice(-1)[0].type !== "ClassDeclaration" ||
|
|
11610
|
+
(scope.node.attrs &&
|
|
11611
|
+
scope.node.attrs.access &&
|
|
11612
|
+
scope.node.attrs.access.includes("static"));
|
|
11544
11613
|
state.allFunctions.push(scope);
|
|
11545
11614
|
}
|
|
11546
|
-
else {
|
|
11615
|
+
else if (scope.type === "ClassDeclaration") {
|
|
11547
11616
|
state.allClasses.push(scope);
|
|
11548
11617
|
}
|
|
11549
|
-
|
|
11618
|
+
break;
|
|
11550
11619
|
}
|
|
11551
|
-
case "Using":
|
|
11552
|
-
case "ImportModule":
|
|
11553
|
-
allImports.push({ node, stack: state.stack.slice() });
|
|
11554
|
-
return null;
|
|
11555
|
-
default:
|
|
11556
|
-
return null;
|
|
11557
11620
|
}
|
|
11621
|
+
return null;
|
|
11558
11622
|
},
|
|
11559
11623
|
};
|
|
11560
|
-
await (0,external_api_cjs_namespaceObject.getApiMapping)(preState);
|
|
11624
|
+
await (0,external_api_cjs_namespaceObject.getApiMapping)(preState, barrelList);
|
|
11625
|
+
markApi = false;
|
|
11561
11626
|
const state = preState;
|
|
11562
|
-
// Mark all functions from api.mir as "special" by
|
|
11563
|
-
// setting their bodies to null. In api.mir, they're
|
|
11564
|
-
// all empty, which makes it look like they're
|
|
11565
|
-
// do-nothing functions.
|
|
11566
|
-
const markApi = (node) => {
|
|
11567
|
-
if (node.type == "FunctionDeclaration") {
|
|
11568
|
-
node.node.body = null;
|
|
11569
|
-
}
|
|
11570
|
-
if ((0,external_api_cjs_namespaceObject.isStateNode)(node) && node.decls) {
|
|
11571
|
-
Object.values(node.decls).forEach((v) => v.forEach(markApi));
|
|
11572
|
-
}
|
|
11573
|
-
};
|
|
11574
|
-
markApi(state.stack[0]);
|
|
11575
11627
|
await getFileASTs(fnMap);
|
|
11576
11628
|
Object.entries(fnMap).forEach(([name, value]) => {
|
|
11577
11629
|
const { ast, parserError } = value;
|
|
@@ -11584,8 +11636,28 @@ async function analyze(fnMap) {
|
|
|
11584
11636
|
});
|
|
11585
11637
|
delete state.shouldExclude;
|
|
11586
11638
|
delete state.post;
|
|
11587
|
-
processImports(allImports, state.lookup);
|
|
11588
11639
|
collectClassInfo(state);
|
|
11640
|
+
const diagnosticType = config?.checkInvalidSymbols !== "OFF"
|
|
11641
|
+
? config?.checkInvalidSymbols || "WARNING"
|
|
11642
|
+
: null;
|
|
11643
|
+
if (diagnosticType &&
|
|
11644
|
+
!config?.compilerOptions?.includes("--Eno-invalid-symbol")) {
|
|
11645
|
+
const checkTypes = config?.typeCheckLevel && config.typeCheckLevel !== "Off";
|
|
11646
|
+
Object.entries(fnMap).forEach(([k, v]) => {
|
|
11647
|
+
visitReferences(state, v.ast, null, false, (node, results, error) => {
|
|
11648
|
+
if (!error)
|
|
11649
|
+
return undefined;
|
|
11650
|
+
const nodeStr = (0,external_api_cjs_namespaceObject.formatAst)(node);
|
|
11651
|
+
if (state.inType) {
|
|
11652
|
+
if (!checkTypes || nodeStr.match(/^Void|Null$/)) {
|
|
11653
|
+
return undefined;
|
|
11654
|
+
}
|
|
11655
|
+
}
|
|
11656
|
+
diagnostic(state, node.loc, `Undefined symbol ${nodeStr}`, diagnosticType);
|
|
11657
|
+
return false;
|
|
11658
|
+
});
|
|
11659
|
+
});
|
|
11660
|
+
}
|
|
11589
11661
|
return state;
|
|
11590
11662
|
}
|
|
11591
11663
|
function compareLiteralLike(a, b) {
|
|
@@ -11595,11 +11667,11 @@ function compareLiteralLike(a, b) {
|
|
|
11595
11667
|
b = b.left;
|
|
11596
11668
|
return a.type === "Literal" && b.type === "Literal" && a.value === b.value;
|
|
11597
11669
|
}
|
|
11598
|
-
function getLiteralFromDecls(
|
|
11599
|
-
if (!
|
|
11670
|
+
function getLiteralFromDecls(lookupDefns) {
|
|
11671
|
+
if (!lookupDefns.length)
|
|
11600
11672
|
return null;
|
|
11601
11673
|
let result = null;
|
|
11602
|
-
if (
|
|
11674
|
+
if (lookupDefns.every((lookupDefn) => lookupDefn.results.every((d) => {
|
|
11603
11675
|
if (d.type === "EnumStringMember" ||
|
|
11604
11676
|
(d.type === "VariableDeclarator" && d.node.kind === "const")) {
|
|
11605
11677
|
const init = getLiteralNode(d.type === "EnumStringMember" ? d.init : d.node.init);
|
|
@@ -11614,7 +11686,7 @@ function getLiteralFromDecls(decls) {
|
|
|
11614
11686
|
}
|
|
11615
11687
|
}
|
|
11616
11688
|
return false;
|
|
11617
|
-
})) {
|
|
11689
|
+
}))) {
|
|
11618
11690
|
return result;
|
|
11619
11691
|
}
|
|
11620
11692
|
return null;
|
|
@@ -11825,20 +11897,23 @@ function markFunctionCalled(state, func) {
|
|
|
11825
11897
|
}
|
|
11826
11898
|
(0,external_util_cjs_namespaceObject.pushUnique)(state.calledFunctions[func.id.name], func);
|
|
11827
11899
|
}
|
|
11828
|
-
async function optimizeMonkeyC(fnMap) {
|
|
11900
|
+
async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
11829
11901
|
const state = {
|
|
11830
|
-
...(await analyze(fnMap)),
|
|
11902
|
+
...(await analyze(fnMap, barrelList, config)),
|
|
11831
11903
|
localsStack: [{}],
|
|
11832
11904
|
exposed: {},
|
|
11833
11905
|
calledFunctions: {},
|
|
11834
11906
|
};
|
|
11835
|
-
const replace = (node) => {
|
|
11907
|
+
const replace = (node, old) => {
|
|
11836
11908
|
if (node === false || node === null)
|
|
11837
11909
|
return node;
|
|
11838
11910
|
const rep = state.traverse(node);
|
|
11839
|
-
|
|
11911
|
+
if (rep === false || Array.isArray(rep))
|
|
11912
|
+
return rep;
|
|
11913
|
+
return { ...(rep || node), loc: old.loc, start: old.start, end: old.end };
|
|
11840
11914
|
};
|
|
11841
11915
|
const inPlaceReplacement = (node, obj) => {
|
|
11916
|
+
const { start, end, loc } = node;
|
|
11842
11917
|
for (const k of Object.keys(node)) {
|
|
11843
11918
|
delete node[k];
|
|
11844
11919
|
}
|
|
@@ -11846,13 +11921,16 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
11846
11921
|
obj = {
|
|
11847
11922
|
type: "BinaryExpression",
|
|
11848
11923
|
operator: "as",
|
|
11849
|
-
left: obj,
|
|
11924
|
+
left: { ...obj, start, end, loc },
|
|
11850
11925
|
right: { type: "TypeSpecList", ts: [obj.enumType] },
|
|
11851
11926
|
};
|
|
11852
11927
|
}
|
|
11853
11928
|
for (const [k, v] of Object.entries(obj)) {
|
|
11854
11929
|
node[k] = v;
|
|
11855
11930
|
}
|
|
11931
|
+
node.loc = loc;
|
|
11932
|
+
node.start = start;
|
|
11933
|
+
node.end = end;
|
|
11856
11934
|
};
|
|
11857
11935
|
const lookupAndReplace = (node) => {
|
|
11858
11936
|
const [, objects] = state.lookup(node);
|
|
@@ -11971,6 +12049,37 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
11971
12049
|
}
|
|
11972
12050
|
return ["init"];
|
|
11973
12051
|
}
|
|
12052
|
+
case "CatchClause":
|
|
12053
|
+
if (node.param) {
|
|
12054
|
+
state.localsStack.push({ node, map: { ...(topLocals().map || {}) } });
|
|
12055
|
+
const locals = topLocals();
|
|
12056
|
+
const map = locals.map;
|
|
12057
|
+
const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.param);
|
|
12058
|
+
const name = renameVariable(state, locals, declName);
|
|
12059
|
+
if (name) {
|
|
12060
|
+
if (node.param.type === "Identifier") {
|
|
12061
|
+
node.param.name = name;
|
|
12062
|
+
}
|
|
12063
|
+
else {
|
|
12064
|
+
node.param.left.name = name;
|
|
12065
|
+
}
|
|
12066
|
+
}
|
|
12067
|
+
else {
|
|
12068
|
+
map[declName] = true;
|
|
12069
|
+
}
|
|
12070
|
+
return ["body"];
|
|
12071
|
+
}
|
|
12072
|
+
break;
|
|
12073
|
+
case "BinaryExpression":
|
|
12074
|
+
if (node.operator === "has") {
|
|
12075
|
+
if (node.right.type === "UnaryExpression" &&
|
|
12076
|
+
node.right.operator === ":") {
|
|
12077
|
+
// Using `expr has :symbol` doesn't "expose"
|
|
12078
|
+
// symbol. So skip the right operand.
|
|
12079
|
+
return ["left"];
|
|
12080
|
+
}
|
|
12081
|
+
}
|
|
12082
|
+
break;
|
|
11974
12083
|
case "UnaryExpression":
|
|
11975
12084
|
if (node.operator == ":") {
|
|
11976
12085
|
// If we produce a Symbol, for a given name,
|
|
@@ -12053,7 +12162,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12053
12162
|
}
|
|
12054
12163
|
const opt = optimizeNode(node);
|
|
12055
12164
|
if (opt) {
|
|
12056
|
-
return replace(opt);
|
|
12165
|
+
return replace(opt, node);
|
|
12057
12166
|
}
|
|
12058
12167
|
switch (node.type) {
|
|
12059
12168
|
case "ConditionalExpression":
|
|
@@ -12063,7 +12172,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12063
12172
|
const rep = node.test.value ? node.consequent : node.alternate;
|
|
12064
12173
|
if (!rep)
|
|
12065
12174
|
return false;
|
|
12066
|
-
return replace(rep);
|
|
12175
|
+
return replace(rep, rep);
|
|
12067
12176
|
}
|
|
12068
12177
|
break;
|
|
12069
12178
|
case "WhileStatement":
|
|
@@ -12078,11 +12187,11 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12078
12187
|
break;
|
|
12079
12188
|
case "ReturnStatement":
|
|
12080
12189
|
if (node.argument && node.argument.type === "CallExpression") {
|
|
12081
|
-
return replace(optimizeCall(state, node.argument, node));
|
|
12190
|
+
return replace(optimizeCall(state, node.argument, node), node.argument);
|
|
12082
12191
|
}
|
|
12083
12192
|
break;
|
|
12084
12193
|
case "CallExpression": {
|
|
12085
|
-
return replace(optimizeCall(state, node, null));
|
|
12194
|
+
return replace(optimizeCall(state, node, null), node);
|
|
12086
12195
|
}
|
|
12087
12196
|
case "AssignmentExpression":
|
|
12088
12197
|
if (node.operator === "=" &&
|
|
@@ -12094,7 +12203,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12094
12203
|
break;
|
|
12095
12204
|
case "ExpressionStatement":
|
|
12096
12205
|
if (node.expression.type === "CallExpression") {
|
|
12097
|
-
return replace(optimizeCall(state, node.expression, node));
|
|
12206
|
+
return replace(optimizeCall(state, node.expression, node), node.expression);
|
|
12098
12207
|
}
|
|
12099
12208
|
else if (node.expression.type === "AssignmentExpression") {
|
|
12100
12209
|
if (node.expression.right.type === "CallExpression") {
|
|
@@ -12106,10 +12215,10 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12106
12215
|
}
|
|
12107
12216
|
if (!ok && node.expression.operator == "=") {
|
|
12108
12217
|
const [, result] = state.lookup(node.expression.left);
|
|
12109
|
-
ok = result
|
|
12218
|
+
ok = !!result;
|
|
12110
12219
|
}
|
|
12111
12220
|
if (ok) {
|
|
12112
|
-
return replace(optimizeCall(state, node.expression.right, node.expression));
|
|
12221
|
+
return replace(optimizeCall(state, node.expression.right, node.expression), node.expression.right);
|
|
12113
12222
|
}
|
|
12114
12223
|
}
|
|
12115
12224
|
}
|
|
@@ -12117,7 +12226,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12117
12226
|
const ret = unused(node.expression, true);
|
|
12118
12227
|
if (ret) {
|
|
12119
12228
|
return ret
|
|
12120
|
-
.map(replace)
|
|
12229
|
+
.map((r) => replace(r, r))
|
|
12121
12230
|
.flat(1)
|
|
12122
12231
|
.filter((s) => !!s);
|
|
12123
12232
|
}
|
|
@@ -12138,6 +12247,9 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12138
12247
|
delete state.post;
|
|
12139
12248
|
const cleanup = (node) => {
|
|
12140
12249
|
switch (node.type) {
|
|
12250
|
+
case "ThisExpression":
|
|
12251
|
+
node.text = "self";
|
|
12252
|
+
break;
|
|
12141
12253
|
case "EnumStringBody":
|
|
12142
12254
|
if (node.members.every((m) => {
|
|
12143
12255
|
const name = "name" in m ? m.name : m.id.name;
|
|
@@ -12202,6 +12314,19 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12202
12314
|
return false;
|
|
12203
12315
|
}
|
|
12204
12316
|
break;
|
|
12317
|
+
case "ClassDeclaration":
|
|
12318
|
+
case "ModuleDeclaration":
|
|
12319
|
+
// none of the attributes means anything on classes and
|
|
12320
|
+
// modules, and the new compiler complains about some
|
|
12321
|
+
// of them. Just drop them all.
|
|
12322
|
+
if (node.attrs && node.attrs.access) {
|
|
12323
|
+
if (node.attrs.attributes) {
|
|
12324
|
+
delete node.attrs.access;
|
|
12325
|
+
}
|
|
12326
|
+
else {
|
|
12327
|
+
delete node.attrs;
|
|
12328
|
+
}
|
|
12329
|
+
}
|
|
12205
12330
|
}
|
|
12206
12331
|
return null;
|
|
12207
12332
|
};
|
|
@@ -12217,9 +12342,12 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
12217
12342
|
return state.diagnostics;
|
|
12218
12343
|
}
|
|
12219
12344
|
function optimizeCall(state, node, context) {
|
|
12220
|
-
const [name, results] = state.
|
|
12345
|
+
const [name, results] = state.lookupNonlocal(node.callee);
|
|
12221
12346
|
const callees = results &&
|
|
12222
|
-
results
|
|
12347
|
+
results
|
|
12348
|
+
.map((r) => r.results)
|
|
12349
|
+
.flat()
|
|
12350
|
+
.filter((c) => c.type === "FunctionDeclaration");
|
|
12223
12351
|
if (!callees || !callees.length) {
|
|
12224
12352
|
const n = name ||
|
|
12225
12353
|
("name" in node.callee && node.callee.name) ||
|
|
@@ -12260,23 +12388,28 @@ function optimizeCall(state, node, context) {
|
|
|
12260
12388
|
|
|
12261
12389
|
;// CONCATENATED MODULE: ./src/pragma-checker.ts
|
|
12262
12390
|
|
|
12263
|
-
function pragmaChecker(ast) {
|
|
12391
|
+
function pragmaChecker(ast, diagnostics) {
|
|
12264
12392
|
const comments = ast.comments;
|
|
12265
12393
|
if (!comments)
|
|
12266
12394
|
return;
|
|
12395
|
+
diagnostics = diagnostics
|
|
12396
|
+
?.slice()
|
|
12397
|
+
.sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
|
|
12398
|
+
let diagIndex = 0;
|
|
12267
12399
|
let index = -1;
|
|
12268
12400
|
let comment;
|
|
12269
12401
|
let matchers;
|
|
12270
12402
|
const next = () => {
|
|
12271
12403
|
while (++index < comments.length) {
|
|
12272
12404
|
comment = comments[index];
|
|
12273
|
-
let match = comment.value.match(/^\s*@match\s+(.+)/);
|
|
12405
|
+
let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
|
|
12274
12406
|
if (!match)
|
|
12275
12407
|
continue;
|
|
12276
|
-
|
|
12408
|
+
const kind = match[1];
|
|
12409
|
+
let str = match[2];
|
|
12277
12410
|
matchers = [];
|
|
12278
12411
|
while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
|
|
12279
|
-
matchers.push({ quote: match[1], needle: match[2] });
|
|
12412
|
+
matchers.push({ kind, quote: match[1], needle: match[2] });
|
|
12280
12413
|
str = str.substring(match[0].length);
|
|
12281
12414
|
if (!str.length)
|
|
12282
12415
|
break;
|
|
@@ -12286,35 +12419,79 @@ function pragmaChecker(ast) {
|
|
|
12286
12419
|
if (!matchers.length) {
|
|
12287
12420
|
match = str.match(/^(\S+)\s+$/);
|
|
12288
12421
|
if (match) {
|
|
12289
|
-
matchers.push({ quote: '"', needle: match[1] });
|
|
12422
|
+
matchers.push({ kind, quote: '"', needle: match[1] });
|
|
12290
12423
|
break;
|
|
12291
12424
|
}
|
|
12292
12425
|
}
|
|
12293
12426
|
throw new Error(`Build pragma '${comment.value}' is invalid. In ${comment.loc.source}:${comment.loc.start.line}`);
|
|
12294
12427
|
}
|
|
12295
12428
|
};
|
|
12429
|
+
const matcher = (quote, needle, haystack) => {
|
|
12430
|
+
if (quote == '"') {
|
|
12431
|
+
return haystack.includes(needle);
|
|
12432
|
+
}
|
|
12433
|
+
const re = new RegExp(needle);
|
|
12434
|
+
return re.test(haystack);
|
|
12435
|
+
};
|
|
12296
12436
|
next();
|
|
12297
12437
|
(0,external_api_cjs_namespaceObject.traverseAst)(ast, (node) => {
|
|
12298
12438
|
if (index >= comments.length)
|
|
12299
12439
|
return false;
|
|
12300
12440
|
if (node.start && node.start >= (comment.end || Infinity)) {
|
|
12301
|
-
const { quote, needle } = matchers.shift();
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
}
|
|
12307
|
-
else {
|
|
12308
|
-
const re = new RegExp(needle);
|
|
12309
|
-
found = re.test(haystack);
|
|
12441
|
+
const { kind, quote, needle } = matchers.shift();
|
|
12442
|
+
if (kind === "match") {
|
|
12443
|
+
if (!matcher(quote, needle, (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " "))) {
|
|
12444
|
+
throw new Error(`Didn't find '${needle}' at ${comment.loc.source}:${comment.loc.start.line}`);
|
|
12445
|
+
}
|
|
12310
12446
|
}
|
|
12311
|
-
if (
|
|
12312
|
-
|
|
12447
|
+
else if (kind === "expect") {
|
|
12448
|
+
const locCmp = (a, b) => {
|
|
12449
|
+
if (!b)
|
|
12450
|
+
return -1;
|
|
12451
|
+
if (a.start.line < b.start.line)
|
|
12452
|
+
return -1;
|
|
12453
|
+
if (a.start.line === b.start.line &&
|
|
12454
|
+
a.start.column < b.start.column) {
|
|
12455
|
+
return -1;
|
|
12456
|
+
}
|
|
12457
|
+
if (a.end.line > b.end.line)
|
|
12458
|
+
return 1;
|
|
12459
|
+
if (a.end.line === b.end.line && a.end.column >= b.end.column) {
|
|
12460
|
+
return 1;
|
|
12461
|
+
}
|
|
12462
|
+
return 0;
|
|
12463
|
+
};
|
|
12464
|
+
let found = false;
|
|
12465
|
+
if (diagnostics) {
|
|
12466
|
+
while (true) {
|
|
12467
|
+
if (diagIndex >= diagnostics.length) {
|
|
12468
|
+
diagnostics = null;
|
|
12469
|
+
break;
|
|
12470
|
+
}
|
|
12471
|
+
const diag = diagnostics[diagIndex];
|
|
12472
|
+
const cmp = locCmp(diag.loc, node.loc);
|
|
12473
|
+
if (cmp > 0) {
|
|
12474
|
+
break;
|
|
12475
|
+
}
|
|
12476
|
+
diagIndex++;
|
|
12477
|
+
if (cmp < 0)
|
|
12478
|
+
continue;
|
|
12479
|
+
if (matcher(quote, needle, diag.message)) {
|
|
12480
|
+
found = true;
|
|
12481
|
+
diag.type = "INFO";
|
|
12482
|
+
}
|
|
12483
|
+
}
|
|
12484
|
+
}
|
|
12485
|
+
if (!found) {
|
|
12486
|
+
throw new Error(`Missing error message '${needle} at ${comment.loc.source}:${comment.loc.start.line}`);
|
|
12487
|
+
}
|
|
12313
12488
|
}
|
|
12314
|
-
if (
|
|
12315
|
-
|
|
12489
|
+
if (matchers.length) {
|
|
12490
|
+
// if we're checking a series of nodes, we need
|
|
12491
|
+
// to skip over this one.
|
|
12492
|
+
return false;
|
|
12316
12493
|
}
|
|
12317
|
-
|
|
12494
|
+
next();
|
|
12318
12495
|
}
|
|
12319
12496
|
return null;
|
|
12320
12497
|
});
|
|
@@ -12702,6 +12879,7 @@ const configOptionsToCheck = [
|
|
|
12702
12879
|
"ignoredExcludeAnnotations",
|
|
12703
12880
|
"ignoredAnnotations",
|
|
12704
12881
|
"ignoredSourcePaths",
|
|
12882
|
+
"checkInvalidSymbols",
|
|
12705
12883
|
];
|
|
12706
12884
|
/**
|
|
12707
12885
|
* @param {BuildConfig} config
|
|
@@ -12753,21 +12931,21 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
|
|
|
12753
12931
|
// the oldest optimized file, we don't need to regenerate
|
|
12754
12932
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
12755
12933
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
12756
|
-
if (source_time < opt_time &&
|
|
12934
|
+
if (source_time < opt_time && 1655479110007 < opt_time) {
|
|
12757
12935
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
12758
12936
|
}
|
|
12759
12937
|
}
|
|
12760
12938
|
await promises_namespaceObject.rm(output, { recursive: true, force: true });
|
|
12761
12939
|
await promises_namespaceObject.mkdir(output, { recursive: true });
|
|
12762
|
-
const diagnostics = await optimizeMonkeyC(fnMap);
|
|
12763
|
-
return Promise.all(Object.
|
|
12940
|
+
const diagnostics = await optimizeMonkeyC(fnMap, Object.keys(buildConfig.barrelMap || {}), config);
|
|
12941
|
+
return Promise.all(Object.entries(fnMap).map(async ([inFile, info]) => {
|
|
12764
12942
|
const name = info.output;
|
|
12765
12943
|
const dir = external_path_.dirname(name);
|
|
12766
12944
|
await promises_namespaceObject.mkdir(dir, { recursive: true });
|
|
12767
12945
|
const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
|
|
12768
12946
|
await promises_namespaceObject.writeFile(name, opt_source);
|
|
12769
12947
|
if (config.checkBuildPragmas) {
|
|
12770
|
-
pragmaChecker(info.ast);
|
|
12948
|
+
pragmaChecker(info.ast, diagnostics?.[inFile]);
|
|
12771
12949
|
}
|
|
12772
12950
|
return info.hasTests;
|
|
12773
12951
|
})).then((results) => {
|
|
@@ -12802,7 +12980,13 @@ async function getProjectAnalysis(targets, analysis, options) {
|
|
|
12802
12980
|
if (!(await getFileASTs(fnMap))) {
|
|
12803
12981
|
return { fnMap, paths };
|
|
12804
12982
|
}
|
|
12805
|
-
const
|
|
12983
|
+
const barrelObj = {};
|
|
12984
|
+
targets.forEach((target) => {
|
|
12985
|
+
if (target.qualifier.barrelMap) {
|
|
12986
|
+
Object.keys(target.qualifier.barrelMap).forEach((key) => (barrelObj[key] = true));
|
|
12987
|
+
}
|
|
12988
|
+
});
|
|
12989
|
+
const state = await analyze(fnMap, Object.keys(barrelObj), options);
|
|
12806
12990
|
return { fnMap: fnMap, paths, state };
|
|
12807
12991
|
}
|
|
12808
12992
|
/**
|