@markw65/monkeyc-optimizer 1.0.29 → 1.0.32
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 +54 -0
- package/build/api.cjs +1049 -305
- package/build/optimizer.cjs +947 -393
- package/build/src/api.d.ts +5 -1
- package/build/src/ast.d.ts +2 -1
- package/build/src/build.d.ts +1 -0
- package/build/src/control-flow.d.ts +1 -0
- package/build/src/function-info.d.ts +12 -0
- package/build/src/inliner.d.ts +1 -0
- package/build/src/jungles.d.ts +1 -0
- package/build/src/mc-rewrite.d.ts +2 -1
- package/build/src/optimizer-types.d.ts +188 -0
- package/build/src/optimizer.d.ts +4 -174
- package/build/src/pragma-checker.d.ts +2 -1
- package/build/src/pre.d.ts +1 -0
- package/build/src/unused-exprs.d.ts +3 -0
- package/build/src/variable-renamer.d.ts +1 -0
- package/build/src/visitor.d.ts +1 -0
- package/package.json +6 -6
package/build/optimizer.cjs
CHANGED
|
@@ -11163,18 +11163,147 @@ function withLoc(node, start, end) {
|
|
|
11163
11163
|
}
|
|
11164
11164
|
return node;
|
|
11165
11165
|
}
|
|
11166
|
-
function withLocDeep(node, start, end) {
|
|
11167
|
-
node = withLoc({ ...node }, start, end);
|
|
11166
|
+
function withLocDeep(node, start, end, inplace) {
|
|
11167
|
+
node = withLoc(inplace ? node : { ...node }, start, end);
|
|
11168
11168
|
for (const key of mctreeTypeInfo[node.type].keys) {
|
|
11169
11169
|
const value = node[key];
|
|
11170
11170
|
if (!value)
|
|
11171
11171
|
continue;
|
|
11172
|
-
const fix = (v) => isMCTreeNode(v) ? withLocDeep(v, start, end) : v;
|
|
11172
|
+
const fix = (v) => isMCTreeNode(v) ? withLocDeep(v, start, end, inplace) : v;
|
|
11173
11173
|
const repl = Array.isArray(value) ? value.map(fix) : fix(value);
|
|
11174
|
-
node[key] = repl;
|
|
11174
|
+
inplace || (node[key] = repl);
|
|
11175
11175
|
}
|
|
11176
11176
|
return node;
|
|
11177
11177
|
}
|
|
11178
|
+
function cloneDeep(node) {
|
|
11179
|
+
return withLocDeep(node, null);
|
|
11180
|
+
}
|
|
11181
|
+
|
|
11182
|
+
;// CONCATENATED MODULE: ./src/function-info.ts
|
|
11183
|
+
|
|
11184
|
+
function cloneSet(ae) {
|
|
11185
|
+
return new Set(ae);
|
|
11186
|
+
}
|
|
11187
|
+
function mergeSet(a, b) {
|
|
11188
|
+
b.forEach((event) => a.add(event));
|
|
11189
|
+
}
|
|
11190
|
+
function recordModifiedDecl(func, decl) {
|
|
11191
|
+
if (!func.next_info) {
|
|
11192
|
+
func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
|
|
11193
|
+
}
|
|
11194
|
+
func.next_info.modifiedDecls.add(decl);
|
|
11195
|
+
return null;
|
|
11196
|
+
}
|
|
11197
|
+
function recordModifiedDecls(func, lookupDefs) {
|
|
11198
|
+
lookupDefs.forEach((lookupDef) => lookupDef.results.forEach((result) => {
|
|
11199
|
+
if (result.type == "VariableDeclarator" && result.node.kind === "var") {
|
|
11200
|
+
recordModifiedDecl(func, result);
|
|
11201
|
+
}
|
|
11202
|
+
}));
|
|
11203
|
+
}
|
|
11204
|
+
function recordModifiedName(func, name) {
|
|
11205
|
+
if (!func.next_info) {
|
|
11206
|
+
func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
|
|
11207
|
+
}
|
|
11208
|
+
if (!func.next_info.modifiedNames) {
|
|
11209
|
+
func.next_info.modifiedNames = new Set();
|
|
11210
|
+
}
|
|
11211
|
+
func.next_info.modifiedNames.add(name);
|
|
11212
|
+
}
|
|
11213
|
+
function recordModifiedUnknown(func) {
|
|
11214
|
+
if (!func.next_info) {
|
|
11215
|
+
func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
|
|
11216
|
+
}
|
|
11217
|
+
func.next_info.modifiedUnknown = true;
|
|
11218
|
+
}
|
|
11219
|
+
function recordCalledFunc(func, callee) {
|
|
11220
|
+
if (!func.next_info) {
|
|
11221
|
+
func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
|
|
11222
|
+
}
|
|
11223
|
+
func.next_info.calledFuncs.add(callee);
|
|
11224
|
+
return null;
|
|
11225
|
+
}
|
|
11226
|
+
function recordCalledFuncs(func, callees) {
|
|
11227
|
+
callees.forEach((callee) => {
|
|
11228
|
+
recordCalledFunc(func, callee);
|
|
11229
|
+
});
|
|
11230
|
+
}
|
|
11231
|
+
function functionMayModify(state, func, decl) {
|
|
11232
|
+
const info = func.info;
|
|
11233
|
+
if (!info || info.modifiedUnknown)
|
|
11234
|
+
return true;
|
|
11235
|
+
if (info.resolvedDecls) {
|
|
11236
|
+
return info.resolvedDecls.has(decl);
|
|
11237
|
+
}
|
|
11238
|
+
if (info.modifiedNames?.has(decl.name))
|
|
11239
|
+
return true;
|
|
11240
|
+
if (info.modifiedDecls.has(decl))
|
|
11241
|
+
return true;
|
|
11242
|
+
const visited = new Set();
|
|
11243
|
+
const resolved = new Set();
|
|
11244
|
+
const resolveDecls = (f) => {
|
|
11245
|
+
if (visited.has(f))
|
|
11246
|
+
return true;
|
|
11247
|
+
if (!f.info)
|
|
11248
|
+
return false;
|
|
11249
|
+
if (f.info.modifiedUnknown) {
|
|
11250
|
+
info.modifiedUnknown = true;
|
|
11251
|
+
return false;
|
|
11252
|
+
}
|
|
11253
|
+
if (f.info.modifiedNames) {
|
|
11254
|
+
if (info.modifiedNames) {
|
|
11255
|
+
mergeSet(info.modifiedNames, f.info.modifiedNames);
|
|
11256
|
+
}
|
|
11257
|
+
else {
|
|
11258
|
+
info.modifiedNames = cloneSet(f.info.modifiedNames);
|
|
11259
|
+
}
|
|
11260
|
+
}
|
|
11261
|
+
mergeSet(resolved, f.info.modifiedDecls);
|
|
11262
|
+
visited.add(f);
|
|
11263
|
+
const q = true;
|
|
11264
|
+
if (q &&
|
|
11265
|
+
f.info.callsExposed &&
|
|
11266
|
+
state.exposed &&
|
|
11267
|
+
!Object.keys(state.exposed).every((key) => !state.allFunctions[key] ||
|
|
11268
|
+
state.allFunctions[key].every(resolveDecls))) {
|
|
11269
|
+
return false;
|
|
11270
|
+
}
|
|
11271
|
+
return Array.from(f.info.calledFuncs).every(resolveDecls);
|
|
11272
|
+
};
|
|
11273
|
+
if (resolveDecls(func)) {
|
|
11274
|
+
info.resolvedDecls = resolved;
|
|
11275
|
+
return resolved.has(decl);
|
|
11276
|
+
}
|
|
11277
|
+
return true;
|
|
11278
|
+
}
|
|
11279
|
+
function findCallees(lookupDefs) {
|
|
11280
|
+
const decls = lookupDefs.reduce((decls, r) => (decls ? decls.concat(r.results) : r.results), null);
|
|
11281
|
+
return (decls &&
|
|
11282
|
+
decls.filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
|
|
11283
|
+
}
|
|
11284
|
+
function findCalleesForNew(lookupDefs) {
|
|
11285
|
+
const initializer = (decl) => {
|
|
11286
|
+
if (hasProperty(decl.decls, "initialize")) {
|
|
11287
|
+
return decl.decls["initialize"];
|
|
11288
|
+
}
|
|
11289
|
+
if (decl.superClass && decl.superClass !== true) {
|
|
11290
|
+
return decl.superClass.reduce((cur, cls) => {
|
|
11291
|
+
const init = initializer(cls);
|
|
11292
|
+
if (init) {
|
|
11293
|
+
if (!cur)
|
|
11294
|
+
return init;
|
|
11295
|
+
return cur.concat(init);
|
|
11296
|
+
}
|
|
11297
|
+
return cur;
|
|
11298
|
+
}, null);
|
|
11299
|
+
}
|
|
11300
|
+
return null;
|
|
11301
|
+
};
|
|
11302
|
+
return lookupDefs.flatMap((r) => r.results
|
|
11303
|
+
.filter((decl) => decl.type === "ClassDeclaration")
|
|
11304
|
+
.flatMap(initializer)
|
|
11305
|
+
.filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
|
|
11306
|
+
}
|
|
11178
11307
|
|
|
11179
11308
|
;// CONCATENATED MODULE: ./src/variable-renamer.ts
|
|
11180
11309
|
|
|
@@ -11236,6 +11365,7 @@ function renameVariable(state, locals, declName) {
|
|
|
11236
11365
|
|
|
11237
11366
|
|
|
11238
11367
|
|
|
11368
|
+
|
|
11239
11369
|
function getArgSafety(state, func, args, requireAll) {
|
|
11240
11370
|
// determine whether decl might be changed by a function call
|
|
11241
11371
|
// or assignment during the evaluation of FunctionStateNode.
|
|
@@ -11268,8 +11398,9 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
11268
11398
|
}
|
|
11269
11399
|
};
|
|
11270
11400
|
const safeArgs = [];
|
|
11401
|
+
const argDecls = [];
|
|
11271
11402
|
let allSafe = true;
|
|
11272
|
-
if (!args.every((arg) => {
|
|
11403
|
+
if (!args.every((arg, i) => {
|
|
11273
11404
|
switch (arg.type) {
|
|
11274
11405
|
case "Literal":
|
|
11275
11406
|
safeArgs.push(true);
|
|
@@ -11283,13 +11414,17 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
11283
11414
|
safeArgs.push(null);
|
|
11284
11415
|
return !requireAll;
|
|
11285
11416
|
}
|
|
11286
|
-
const
|
|
11417
|
+
const decl = results[0].results[0];
|
|
11418
|
+
const safety = getSafety(decl);
|
|
11287
11419
|
safeArgs.push(safety);
|
|
11288
11420
|
if (!safety) {
|
|
11289
11421
|
allSafe = false;
|
|
11290
11422
|
if (safety === null) {
|
|
11291
11423
|
return !requireAll;
|
|
11292
11424
|
}
|
|
11425
|
+
else if (decl.type === "VariableDeclarator") {
|
|
11426
|
+
argDecls[i] = decl;
|
|
11427
|
+
}
|
|
11293
11428
|
}
|
|
11294
11429
|
return true;
|
|
11295
11430
|
}
|
|
@@ -11302,34 +11437,91 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
11302
11437
|
}
|
|
11303
11438
|
if (allSafe && requireAll)
|
|
11304
11439
|
return true;
|
|
11305
|
-
|
|
11440
|
+
const callsSeen = new Set();
|
|
11441
|
+
const modifiedDecls = new Set();
|
|
11442
|
+
let modifiedUnknown = false;
|
|
11306
11443
|
const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
|
|
11307
11444
|
// look for uses of "unsafe" args that occur after a call.
|
|
11308
11445
|
// use post to do the checking, because arguments are evaluated
|
|
11309
11446
|
// prior to the call, so eg "return f(x.y);" is fine, but
|
|
11310
11447
|
// "return f()+x.y" is not.
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11448
|
+
const { pre, post, stack } = state;
|
|
11449
|
+
try {
|
|
11450
|
+
delete state.pre;
|
|
11451
|
+
state.post = (node) => {
|
|
11452
|
+
switch (node.type) {
|
|
11453
|
+
case "AssignmentExpression":
|
|
11454
|
+
case "UpdateExpression": {
|
|
11455
|
+
const v = node.type == "UpdateExpression" ? node.argument : node.left;
|
|
11456
|
+
if (v.type === "Identifier" && (0,external_api_cjs_namespaceObject.hasProperty)(params, v.name)) {
|
|
11457
|
+
// If a parameter is modified, we can't just substitute the
|
|
11458
|
+
// argument wherever the parameter is used.
|
|
11459
|
+
safeArgs[params[v.name]] = null;
|
|
11460
|
+
break;
|
|
11461
|
+
}
|
|
11462
|
+
if (modifiedUnknown)
|
|
11463
|
+
break;
|
|
11464
|
+
const [, results] = state.lookup(v);
|
|
11465
|
+
if (results) {
|
|
11466
|
+
results.forEach((r) => r.results.forEach((decl) => decl.type === "VariableDeclarator" && modifiedDecls.add(decl)));
|
|
11467
|
+
}
|
|
11468
|
+
else {
|
|
11469
|
+
modifiedUnknown = true;
|
|
11470
|
+
}
|
|
11471
|
+
break;
|
|
11318
11472
|
}
|
|
11473
|
+
case "CallExpression":
|
|
11474
|
+
case "NewExpression":
|
|
11475
|
+
if (!modifiedUnknown) {
|
|
11476
|
+
const [, results] = state.lookup(node.callee, null,
|
|
11477
|
+
// calls are looked up as non-locals, but new is not
|
|
11478
|
+
node.type === "CallExpression" ? func.stack : state.stack);
|
|
11479
|
+
if (!results) {
|
|
11480
|
+
const callee_name = node.callee.type === "Identifier"
|
|
11481
|
+
? node.callee
|
|
11482
|
+
: node.callee.type === "MemberExpression"
|
|
11483
|
+
? (0,external_api_cjs_namespaceObject.isLookupCandidate)(node.callee)
|
|
11484
|
+
: null;
|
|
11485
|
+
if (callee_name) {
|
|
11486
|
+
const callees = state.allFunctions[callee_name.name];
|
|
11487
|
+
if (callees) {
|
|
11488
|
+
callees.forEach((callee) => callsSeen.add(callee));
|
|
11489
|
+
}
|
|
11490
|
+
}
|
|
11491
|
+
else {
|
|
11492
|
+
modifiedUnknown = true;
|
|
11493
|
+
}
|
|
11494
|
+
}
|
|
11495
|
+
else {
|
|
11496
|
+
const callees = node.type === "CallExpression"
|
|
11497
|
+
? findCallees(results)
|
|
11498
|
+
: findCalleesForNew(results);
|
|
11499
|
+
if (callees) {
|
|
11500
|
+
callees.forEach((callee) => callsSeen.add(callee));
|
|
11501
|
+
}
|
|
11502
|
+
}
|
|
11503
|
+
}
|
|
11504
|
+
break;
|
|
11505
|
+
case "Identifier":
|
|
11506
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name) &&
|
|
11507
|
+
!safeArgs[params[node.name]] &&
|
|
11508
|
+
(modifiedUnknown ||
|
|
11509
|
+
!argDecls[params[node.name]] ||
|
|
11510
|
+
modifiedDecls.has(argDecls[params[node.name]]) ||
|
|
11511
|
+
Array.from(callsSeen).some((callee) => functionMayModify(state, callee, argDecls[params[node.name]])))) {
|
|
11512
|
+
safeArgs[params[node.name]] = null;
|
|
11513
|
+
}
|
|
11319
11514
|
}
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
}
|
|
11331
|
-
}
|
|
11332
|
-
});
|
|
11515
|
+
return null;
|
|
11516
|
+
};
|
|
11517
|
+
state.stack = func.stack;
|
|
11518
|
+
state.traverse(func.node.body);
|
|
11519
|
+
}
|
|
11520
|
+
finally {
|
|
11521
|
+
state.pre = pre;
|
|
11522
|
+
state.post = post;
|
|
11523
|
+
state.stack = stack;
|
|
11524
|
+
}
|
|
11333
11525
|
return safeArgs;
|
|
11334
11526
|
}
|
|
11335
11527
|
function canInline(state, func, args) {
|
|
@@ -11434,9 +11626,6 @@ function processInlineBody(state, func, call, root, params) {
|
|
|
11434
11626
|
state.pre = (node) => {
|
|
11435
11627
|
if (failed)
|
|
11436
11628
|
return [];
|
|
11437
|
-
node.start = call.start;
|
|
11438
|
-
node.end = call.end;
|
|
11439
|
-
node.loc = call.loc;
|
|
11440
11629
|
if (replacements.has(node))
|
|
11441
11630
|
return false;
|
|
11442
11631
|
const result = pre(node, state);
|
|
@@ -11451,6 +11640,7 @@ function processInlineBody(state, func, call, root, params) {
|
|
|
11451
11640
|
if (params[paramName] >= 0)
|
|
11452
11641
|
return null;
|
|
11453
11642
|
const name = renameVariable(state, locals, paramName) || paramName;
|
|
11643
|
+
locals.map[name] = true;
|
|
11454
11644
|
return {
|
|
11455
11645
|
type: "VariableDeclarator",
|
|
11456
11646
|
id: { type: "Identifier", name },
|
|
@@ -11469,31 +11659,49 @@ function processInlineBody(state, func, call, root, params) {
|
|
|
11469
11659
|
}
|
|
11470
11660
|
return result;
|
|
11471
11661
|
};
|
|
11662
|
+
const fixId = (node) => {
|
|
11663
|
+
if (state.inType)
|
|
11664
|
+
return null;
|
|
11665
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name)) {
|
|
11666
|
+
const ix = params[node.name];
|
|
11667
|
+
if (ix >= 0) {
|
|
11668
|
+
const replacement = { ...call.arguments[ix] };
|
|
11669
|
+
replacements.add(replacement);
|
|
11670
|
+
return replacement;
|
|
11671
|
+
}
|
|
11672
|
+
return null;
|
|
11673
|
+
}
|
|
11674
|
+
const replacement = fixNodeScope(state, node, func.stack);
|
|
11675
|
+
if (!replacement) {
|
|
11676
|
+
failed = true;
|
|
11677
|
+
inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
|
|
11678
|
+
}
|
|
11679
|
+
return replacement;
|
|
11680
|
+
};
|
|
11472
11681
|
state.post = (node) => {
|
|
11473
11682
|
if (failed)
|
|
11474
11683
|
return post(node, state);
|
|
11475
11684
|
let replacement = null;
|
|
11476
11685
|
switch (node.type) {
|
|
11477
|
-
case "
|
|
11478
|
-
if (
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
if (ix >= 0) {
|
|
11483
|
-
replacement = { ...call.arguments[ix] };
|
|
11484
|
-
replacements.add(replacement);
|
|
11485
|
-
return replacement;
|
|
11686
|
+
case "AssignmentExpression":
|
|
11687
|
+
if (node.left.type === "Identifier") {
|
|
11688
|
+
const rep = fixId(node.left);
|
|
11689
|
+
if (rep) {
|
|
11690
|
+
node.left = rep;
|
|
11486
11691
|
}
|
|
11487
|
-
break;
|
|
11488
11692
|
}
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11693
|
+
break;
|
|
11694
|
+
case "UpdateExpression":
|
|
11695
|
+
if (node.argument.type === "Identifier") {
|
|
11696
|
+
const rep = fixId(node.argument);
|
|
11697
|
+
if (rep) {
|
|
11698
|
+
node.argument = rep;
|
|
11699
|
+
}
|
|
11494
11700
|
}
|
|
11495
11701
|
break;
|
|
11496
|
-
|
|
11702
|
+
case "Identifier":
|
|
11703
|
+
replacement = fixId(node);
|
|
11704
|
+
break;
|
|
11497
11705
|
}
|
|
11498
11706
|
const ret = post(replacement || node, state);
|
|
11499
11707
|
return ret === false || ret ? ret : replacement;
|
|
@@ -11625,6 +11833,10 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11625
11833
|
if (!func.node || !func.node.body) {
|
|
11626
11834
|
return null;
|
|
11627
11835
|
}
|
|
11836
|
+
const lastStmt = (block) => {
|
|
11837
|
+
const last = block.body.slice(-1)[0];
|
|
11838
|
+
return last.type === "BlockStatement" ? lastStmt(last) : [last, block];
|
|
11839
|
+
};
|
|
11628
11840
|
let retStmtCount = 0;
|
|
11629
11841
|
if (context.type === "ReturnStatement") {
|
|
11630
11842
|
const last = func.node.body.body.slice(-1)[0];
|
|
@@ -11647,7 +11859,7 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11647
11859
|
return null;
|
|
11648
11860
|
}
|
|
11649
11861
|
if (retStmtCount === 1) {
|
|
11650
|
-
const last = func.node.body
|
|
11862
|
+
const [last] = lastStmt(func.node.body);
|
|
11651
11863
|
if (!last ||
|
|
11652
11864
|
last.type !== "ReturnStatement" ||
|
|
11653
11865
|
((context.type === "AssignmentExpression" ||
|
|
@@ -11658,7 +11870,7 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11658
11870
|
}
|
|
11659
11871
|
}
|
|
11660
11872
|
}
|
|
11661
|
-
const body =
|
|
11873
|
+
const body = cloneDeep(func.node.body);
|
|
11662
11874
|
const safeArgs = getArgSafety(state, func, call.arguments, false);
|
|
11663
11875
|
const params = Object.fromEntries(func.node.params.map((param, i) => {
|
|
11664
11876
|
const argnum = safeArgs === true || (safeArgs !== false && safeArgs[i] !== null)
|
|
@@ -11672,21 +11884,21 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11672
11884
|
}
|
|
11673
11885
|
diagnostic(state, call.loc, null);
|
|
11674
11886
|
if (context.type !== "ReturnStatement" && retStmtCount) {
|
|
11675
|
-
const last = body
|
|
11887
|
+
const [last, block] = lastStmt(body);
|
|
11676
11888
|
if (last.type != "ReturnStatement") {
|
|
11677
11889
|
throw new Error("ReturnStatement got lost!");
|
|
11678
11890
|
}
|
|
11679
11891
|
if (last.argument) {
|
|
11680
11892
|
if (context.type === "AssignmentExpression") {
|
|
11681
11893
|
context.right = last.argument;
|
|
11682
|
-
|
|
11894
|
+
block.body[block.body.length - 1] = {
|
|
11683
11895
|
type: "ExpressionStatement",
|
|
11684
11896
|
expression: context,
|
|
11685
11897
|
};
|
|
11686
11898
|
}
|
|
11687
11899
|
else if (context.type === "VariableDeclarator") {
|
|
11688
11900
|
const { id, init: _init, kind: _kind, ...rest } = context;
|
|
11689
|
-
|
|
11901
|
+
block.body[block.body.length - 1] = {
|
|
11690
11902
|
...rest,
|
|
11691
11903
|
type: "ExpressionStatement",
|
|
11692
11904
|
expression: {
|
|
@@ -11700,25 +11912,26 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11700
11912
|
}
|
|
11701
11913
|
else {
|
|
11702
11914
|
const side_exprs = unused(last.argument);
|
|
11703
|
-
|
|
11915
|
+
block.body.splice(block.body.length - 1, 1, ...side_exprs);
|
|
11704
11916
|
}
|
|
11705
11917
|
}
|
|
11706
11918
|
else {
|
|
11707
|
-
--
|
|
11919
|
+
--block.body.length;
|
|
11708
11920
|
}
|
|
11709
11921
|
}
|
|
11922
|
+
withLocDeep(body, context, context, true);
|
|
11710
11923
|
return body;
|
|
11711
11924
|
}
|
|
11712
11925
|
function inlineFunction(state, func, call, context) {
|
|
11713
11926
|
if (context) {
|
|
11714
11927
|
return inlineWithArgs(state, func, call, context);
|
|
11715
11928
|
}
|
|
11716
|
-
const retArg =
|
|
11929
|
+
const retArg = cloneDeep(func.node.body.body[0].argument);
|
|
11717
11930
|
const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
|
|
11718
11931
|
const map = fixupLocalsMap(state);
|
|
11719
11932
|
const ret = processInlineBody(state, func, call, retArg, params);
|
|
11720
11933
|
state.localsStack[state.localsStack.length - 1].map = map;
|
|
11721
|
-
return ret;
|
|
11934
|
+
return ret && withLocDeep(ret, call, call, true);
|
|
11722
11935
|
}
|
|
11723
11936
|
function applyTypeIfNeeded(node) {
|
|
11724
11937
|
if ("enumType" in node && node.enumType) {
|
|
@@ -11823,6 +12036,121 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
11823
12036
|
return null;
|
|
11824
12037
|
}
|
|
11825
12038
|
|
|
12039
|
+
;// CONCATENATED MODULE: ./src/pragma-checker.ts
|
|
12040
|
+
|
|
12041
|
+
|
|
12042
|
+
|
|
12043
|
+
function pragmaChecker(state, ast, diagnostics) {
|
|
12044
|
+
const comments = ast.comments;
|
|
12045
|
+
if (!comments)
|
|
12046
|
+
return;
|
|
12047
|
+
diagnostics = diagnostics
|
|
12048
|
+
?.slice()
|
|
12049
|
+
.sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
|
|
12050
|
+
let diagIndex = 0;
|
|
12051
|
+
let index = -1;
|
|
12052
|
+
let comment;
|
|
12053
|
+
let matchers;
|
|
12054
|
+
const next = () => {
|
|
12055
|
+
while (++index < comments.length) {
|
|
12056
|
+
comment = comments[index];
|
|
12057
|
+
let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
|
|
12058
|
+
if (!match)
|
|
12059
|
+
continue;
|
|
12060
|
+
const kind = match[1];
|
|
12061
|
+
let str = match[2];
|
|
12062
|
+
matchers = [];
|
|
12063
|
+
while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
|
|
12064
|
+
matchers.push({ kind, quote: match[1], needle: match[2] });
|
|
12065
|
+
str = str.substring(match[0].length);
|
|
12066
|
+
if (!str.length)
|
|
12067
|
+
break;
|
|
12068
|
+
}
|
|
12069
|
+
if (!str.length)
|
|
12070
|
+
break;
|
|
12071
|
+
if (!matchers.length) {
|
|
12072
|
+
match = str.match(/^(\S+)\s+$/);
|
|
12073
|
+
if (match) {
|
|
12074
|
+
matchers.push({ kind, quote: '"', needle: match[1] });
|
|
12075
|
+
break;
|
|
12076
|
+
}
|
|
12077
|
+
}
|
|
12078
|
+
diagnostic(state, comment.loc, `Build pragma '${comment.value}' is invalid`, "ERROR");
|
|
12079
|
+
}
|
|
12080
|
+
};
|
|
12081
|
+
const matcher = (quote, needle, haystack) => {
|
|
12082
|
+
if (quote == '"') {
|
|
12083
|
+
return haystack.includes(needle);
|
|
12084
|
+
}
|
|
12085
|
+
const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
|
|
12086
|
+
return re.test(haystack);
|
|
12087
|
+
};
|
|
12088
|
+
next();
|
|
12089
|
+
traverseAst(ast, (node) => {
|
|
12090
|
+
if (index >= comments.length)
|
|
12091
|
+
return false;
|
|
12092
|
+
if (node.start && node.start >= (comment.end || Infinity)) {
|
|
12093
|
+
const { kind, quote, needle } = matchers.shift();
|
|
12094
|
+
if (kind === "match") {
|
|
12095
|
+
const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " ");
|
|
12096
|
+
if (!matcher(quote, needle, haystack)) {
|
|
12097
|
+
matcher(quote, needle, haystack);
|
|
12098
|
+
diagnostic(state, comment.loc, `Didn't find '${needle}' in '${haystack}'`, "ERROR");
|
|
12099
|
+
}
|
|
12100
|
+
}
|
|
12101
|
+
else if (kind === "expect") {
|
|
12102
|
+
const locCmp = (a, b) => {
|
|
12103
|
+
if (!b)
|
|
12104
|
+
return -1;
|
|
12105
|
+
if (a.start.line < b.start.line)
|
|
12106
|
+
return -1;
|
|
12107
|
+
if (a.start.line === b.start.line &&
|
|
12108
|
+
a.start.column < b.start.column) {
|
|
12109
|
+
return -1;
|
|
12110
|
+
}
|
|
12111
|
+
if (a.end.line > b.end.line)
|
|
12112
|
+
return 1;
|
|
12113
|
+
if (a.end.line === b.end.line && a.end.column >= b.end.column) {
|
|
12114
|
+
return 1;
|
|
12115
|
+
}
|
|
12116
|
+
return 0;
|
|
12117
|
+
};
|
|
12118
|
+
let found = false;
|
|
12119
|
+
if (diagnostics) {
|
|
12120
|
+
while (true) {
|
|
12121
|
+
if (diagIndex >= diagnostics.length) {
|
|
12122
|
+
diagnostics = null;
|
|
12123
|
+
break;
|
|
12124
|
+
}
|
|
12125
|
+
const diag = diagnostics[diagIndex];
|
|
12126
|
+
const cmp = locCmp(diag.loc, node.loc);
|
|
12127
|
+
if (cmp > 0) {
|
|
12128
|
+
break;
|
|
12129
|
+
}
|
|
12130
|
+
diagIndex++;
|
|
12131
|
+
if (cmp < 0)
|
|
12132
|
+
continue;
|
|
12133
|
+
if (matcher(quote, needle, diag.message)) {
|
|
12134
|
+
found = true;
|
|
12135
|
+
diag.type = "INFO";
|
|
12136
|
+
}
|
|
12137
|
+
}
|
|
12138
|
+
}
|
|
12139
|
+
if (!found) {
|
|
12140
|
+
diagnostic(state, comment.loc, `Missing error message '${needle}`, "ERROR");
|
|
12141
|
+
}
|
|
12142
|
+
}
|
|
12143
|
+
if (matchers.length) {
|
|
12144
|
+
// if we're checking a series of nodes, we need
|
|
12145
|
+
// to skip over this one.
|
|
12146
|
+
return false;
|
|
12147
|
+
}
|
|
12148
|
+
next();
|
|
12149
|
+
}
|
|
12150
|
+
return null;
|
|
12151
|
+
});
|
|
12152
|
+
}
|
|
12153
|
+
|
|
11826
12154
|
;// CONCATENATED MODULE: ./src/control-flow.ts
|
|
11827
12155
|
|
|
11828
12156
|
|
|
@@ -11966,7 +12294,8 @@ function buildReducedGraph(state, func, notice) {
|
|
|
11966
12294
|
if (node.type === "WhileStatement") {
|
|
11967
12295
|
head = localState.newBlock(top.continue);
|
|
11968
12296
|
state.traverse(node.test);
|
|
11969
|
-
localState.addEdge(localState.
|
|
12297
|
+
localState.addEdge(localState.curBlock, top.break);
|
|
12298
|
+
localState.newBlock();
|
|
11970
12299
|
}
|
|
11971
12300
|
else {
|
|
11972
12301
|
head = localState.newBlock();
|
|
@@ -12287,6 +12616,8 @@ function cleanCfg(head) {
|
|
|
12287
12616
|
}
|
|
12288
12617
|
}));
|
|
12289
12618
|
}
|
|
12619
|
+
if (!cur.node)
|
|
12620
|
+
cur.node = succ.node;
|
|
12290
12621
|
}
|
|
12291
12622
|
}
|
|
12292
12623
|
});
|
|
@@ -12340,6 +12671,8 @@ var priorityqueuejs = __webpack_require__(2789);
|
|
|
12340
12671
|
|
|
12341
12672
|
|
|
12342
12673
|
|
|
12674
|
+
|
|
12675
|
+
|
|
12343
12676
|
/**
|
|
12344
12677
|
* This implements a pseudo Partial Redundancy Elimination
|
|
12345
12678
|
* pass. It isn't quite like traditional PRE because we're
|
|
@@ -12385,6 +12718,20 @@ function declName(decl) {
|
|
|
12385
12718
|
throw new Error(`Unexpected EventDecl type: ${decl.type}`);
|
|
12386
12719
|
}
|
|
12387
12720
|
}
|
|
12721
|
+
function logAntState(s, decl) {
|
|
12722
|
+
const defs = Array.from(s.ant).reduce((defs, event) => {
|
|
12723
|
+
if (event.type === "def" || event.type === "mod")
|
|
12724
|
+
defs++;
|
|
12725
|
+
return defs;
|
|
12726
|
+
}, 0);
|
|
12727
|
+
console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live, ${s.isIsolated ? "" : "!"}isolated`);
|
|
12728
|
+
console.log(` - members: ${Array.from(s.members)
|
|
12729
|
+
.map(([block, live]) => block.order + (live ? "t" : "f"))
|
|
12730
|
+
.join(", ")}`);
|
|
12731
|
+
}
|
|
12732
|
+
function logAntDecls(antDecls) {
|
|
12733
|
+
antDecls.forEach(logAntState);
|
|
12734
|
+
}
|
|
12388
12735
|
function sizeBasedPRE(state, func) {
|
|
12389
12736
|
if (!func.node.body)
|
|
12390
12737
|
return;
|
|
@@ -12395,18 +12742,11 @@ function sizeBasedPRE(state, func) {
|
|
|
12395
12742
|
return;
|
|
12396
12743
|
}
|
|
12397
12744
|
const { graph: head, identifiers } = buildPREGraph(state, func);
|
|
12398
|
-
const candidates = computeAttributes(head);
|
|
12745
|
+
const candidates = computeAttributes(state, head);
|
|
12399
12746
|
if (candidates) {
|
|
12400
12747
|
if (logging) {
|
|
12401
12748
|
console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
|
|
12402
|
-
candidates
|
|
12403
|
-
const defs = Array.from(s.ant).reduce((defs, event) => {
|
|
12404
|
-
if (event.type === "def")
|
|
12405
|
-
defs++;
|
|
12406
|
-
return defs;
|
|
12407
|
-
}, 0);
|
|
12408
|
-
console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live`);
|
|
12409
|
-
});
|
|
12749
|
+
logAntDecls(candidates);
|
|
12410
12750
|
}
|
|
12411
12751
|
const nodeMap = new Map();
|
|
12412
12752
|
const declMap = new Map();
|
|
@@ -12422,8 +12762,10 @@ function sizeBasedPRE(state, func) {
|
|
|
12422
12762
|
let i = 0;
|
|
12423
12763
|
do {
|
|
12424
12764
|
name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
|
|
12425
|
-
if (!identifiers.has(name))
|
|
12765
|
+
if (!identifiers.has(name)) {
|
|
12766
|
+
identifiers.add(name);
|
|
12426
12767
|
break;
|
|
12768
|
+
}
|
|
12427
12769
|
i++;
|
|
12428
12770
|
} while (true);
|
|
12429
12771
|
declMap.set(decl, name);
|
|
@@ -12514,11 +12856,14 @@ function buildPREGraph(state, func) {
|
|
|
12514
12856
|
case "ParenthesizedExpression":
|
|
12515
12857
|
break;
|
|
12516
12858
|
case "Literal":
|
|
12517
|
-
if (
|
|
12518
|
-
|
|
12859
|
+
if (refCost(node) > LocalRefCost) {
|
|
12860
|
+
const key = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(node.raw)
|
|
12861
|
+
? BigInt(node.value)
|
|
12862
|
+
: node.value;
|
|
12863
|
+
let decl = literals.get(key);
|
|
12519
12864
|
if (!decl) {
|
|
12520
12865
|
decl = node;
|
|
12521
|
-
literals.set(
|
|
12866
|
+
literals.set(key, decl);
|
|
12522
12867
|
}
|
|
12523
12868
|
return {
|
|
12524
12869
|
type: "ref",
|
|
@@ -12598,10 +12943,18 @@ function buildPREGraph(state, func) {
|
|
|
12598
12943
|
}
|
|
12599
12944
|
break;
|
|
12600
12945
|
}
|
|
12601
|
-
case "NewExpression":
|
|
12602
|
-
|
|
12946
|
+
case "NewExpression": {
|
|
12947
|
+
const [, results] = state.lookup(node.callee);
|
|
12948
|
+
const callees = results ? findCalleesForNew(results) : null;
|
|
12603
12949
|
liveDef(null, stmt);
|
|
12604
|
-
return { type: "mod", node, mayThrow };
|
|
12950
|
+
return { type: "mod", node, mayThrow, callees };
|
|
12951
|
+
}
|
|
12952
|
+
case "CallExpression": {
|
|
12953
|
+
liveDef(null, stmt);
|
|
12954
|
+
const [, results] = state.lookup(node.callee);
|
|
12955
|
+
const callees = results ? findCallees(results) : null;
|
|
12956
|
+
return { type: "mod", node, mayThrow, callees };
|
|
12957
|
+
}
|
|
12605
12958
|
default:
|
|
12606
12959
|
if (!isExpression(node))
|
|
12607
12960
|
break;
|
|
@@ -12617,12 +12970,6 @@ function buildPREGraph(state, func) {
|
|
|
12617
12970
|
function anticipatedDecls() {
|
|
12618
12971
|
return new Map();
|
|
12619
12972
|
}
|
|
12620
|
-
function cloneSet(ae) {
|
|
12621
|
-
return new Set(ae);
|
|
12622
|
-
}
|
|
12623
|
-
function mergeSet(a, b) {
|
|
12624
|
-
b.forEach((event) => a.add(event));
|
|
12625
|
-
}
|
|
12626
12973
|
function equalSet(a, b) {
|
|
12627
12974
|
if (a.size != b.size)
|
|
12628
12975
|
return false;
|
|
@@ -12652,21 +12999,28 @@ function cloneAnticipatedState(as) {
|
|
|
12652
12999
|
members: new Map(as.members),
|
|
12653
13000
|
};
|
|
12654
13001
|
}
|
|
13002
|
+
function mergeAnticipatedState(ae, be) {
|
|
13003
|
+
mergeSet(ae.ant, be.ant);
|
|
13004
|
+
be.members.forEach((live, block) => ae.members.set(block, live));
|
|
13005
|
+
if (be.live)
|
|
13006
|
+
ae.live = true;
|
|
13007
|
+
}
|
|
12655
13008
|
function cloneAnticipatedDecls(ad) {
|
|
12656
13009
|
const copy = anticipatedDecls();
|
|
12657
13010
|
for (const [k, v] of ad) {
|
|
12658
|
-
|
|
13011
|
+
if (!v.isIsolated) {
|
|
13012
|
+
copy.set(k, cloneAnticipatedState(v));
|
|
13013
|
+
}
|
|
12659
13014
|
}
|
|
12660
13015
|
return copy;
|
|
12661
13016
|
}
|
|
12662
13017
|
function mergeAnticipatedDecls(a, b) {
|
|
12663
13018
|
for (const [k, v] of b) {
|
|
13019
|
+
if (v.isIsolated)
|
|
13020
|
+
continue;
|
|
12664
13021
|
const ae = a.get(k);
|
|
12665
13022
|
if (ae) {
|
|
12666
|
-
|
|
12667
|
-
v.members.forEach((live, block) => ae.members.set(block, live));
|
|
12668
|
-
if (v.live)
|
|
12669
|
-
ae.live = true;
|
|
13023
|
+
mergeAnticipatedState(ae, v);
|
|
12670
13024
|
}
|
|
12671
13025
|
else {
|
|
12672
13026
|
a.set(k, cloneAnticipatedState(v));
|
|
@@ -12680,6 +13034,7 @@ function equalStates(a, b) {
|
|
|
12680
13034
|
const be = b.get(k);
|
|
12681
13035
|
if (!be ||
|
|
12682
13036
|
be.live != ae.live ||
|
|
13037
|
+
be.isIsolated != ae.isIsolated ||
|
|
12683
13038
|
!equalSet(ae.ant, be.ant) ||
|
|
12684
13039
|
!equalMap(ae.members, be.members)) {
|
|
12685
13040
|
return false;
|
|
@@ -12693,6 +13048,7 @@ function refCost(node) {
|
|
|
12693
13048
|
switch (typeof node.value) {
|
|
12694
13049
|
case "string":
|
|
12695
13050
|
return 5;
|
|
13051
|
+
case "bigint":
|
|
12696
13052
|
case "number":
|
|
12697
13053
|
return 5;
|
|
12698
13054
|
case "boolean":
|
|
@@ -12750,10 +13106,11 @@ function candidateCost(candState) {
|
|
|
12750
13106
|
cost += defCost(candState.node);
|
|
12751
13107
|
}
|
|
12752
13108
|
});
|
|
12753
|
-
|
|
13109
|
+
const boundarySize = candidateBoundary(candState).size;
|
|
13110
|
+
cost += defCost(candState.node) * boundarySize;
|
|
12754
13111
|
return cost;
|
|
12755
13112
|
}
|
|
12756
|
-
function computeAttributes(head) {
|
|
13113
|
+
function computeAttributes(state, head) {
|
|
12757
13114
|
const order = getPostOrder(head);
|
|
12758
13115
|
order.forEach((block, i) => {
|
|
12759
13116
|
block.order = i;
|
|
@@ -12862,7 +13219,9 @@ function computeAttributes(head) {
|
|
|
12862
13219
|
curState.forEach((candidates, decl) => {
|
|
12863
13220
|
if (decl.type === "VariableDeclarator" &&
|
|
12864
13221
|
decl.node.kind === "var" &&
|
|
12865
|
-
candidates.live
|
|
13222
|
+
candidates.live &&
|
|
13223
|
+
(!event.callees ||
|
|
13224
|
+
event.callees.some((callee) => functionMayModify(state, callee, decl)))) {
|
|
12866
13225
|
candidates.ant.add(getMod(event, decl, candidates.node));
|
|
12867
13226
|
candidates.live = false;
|
|
12868
13227
|
}
|
|
@@ -12888,9 +13247,7 @@ function computeAttributes(head) {
|
|
|
12888
13247
|
if (isUpdate || candidates.live) {
|
|
12889
13248
|
candidates.ant.add(event);
|
|
12890
13249
|
}
|
|
12891
|
-
|
|
12892
|
-
candidates.live = false;
|
|
12893
|
-
}
|
|
13250
|
+
candidates.live = isUpdate;
|
|
12894
13251
|
break;
|
|
12895
13252
|
}
|
|
12896
13253
|
}
|
|
@@ -12899,12 +13256,23 @@ function computeAttributes(head) {
|
|
|
12899
13256
|
curState.forEach((antState) => {
|
|
12900
13257
|
antState.head = top;
|
|
12901
13258
|
antState.members.set(top, antState.live);
|
|
13259
|
+
if (!antState.live && candidateBoundary(antState).size === 0) {
|
|
13260
|
+
// we found a group that's isolated from the rest
|
|
13261
|
+
// of the function. Don't merge it with earlier
|
|
13262
|
+
// refs and defs, because we can take it or leave
|
|
13263
|
+
// it based on its own cost.
|
|
13264
|
+
antState.isIsolated = true;
|
|
13265
|
+
}
|
|
12902
13266
|
});
|
|
12903
13267
|
const oldState = blockStates[top.order];
|
|
12904
13268
|
if (oldState && equalStates(oldState, curState)) {
|
|
12905
13269
|
continue;
|
|
12906
13270
|
}
|
|
12907
13271
|
blockStates[top.order] = curState;
|
|
13272
|
+
if (logging) {
|
|
13273
|
+
console.log(`Updated block ${top.order}`);
|
|
13274
|
+
logAntDecls(curState);
|
|
13275
|
+
}
|
|
12908
13276
|
if (top.preds) {
|
|
12909
13277
|
top.preds.forEach((pred) => enqueue(pred));
|
|
12910
13278
|
}
|
|
@@ -12917,7 +13285,9 @@ function computeAttributes(head) {
|
|
|
12917
13285
|
if (cost >= 0)
|
|
12918
13286
|
return;
|
|
12919
13287
|
const existing = candidateDecls.get(decl);
|
|
12920
|
-
if (!existing ||
|
|
13288
|
+
if (!existing ||
|
|
13289
|
+
existing.isIsolated ||
|
|
13290
|
+
candidateCost(existing) > cost) {
|
|
12921
13291
|
const boundary = candidateBoundary(events);
|
|
12922
13292
|
if (!Array.from(boundary).every((block) => {
|
|
12923
13293
|
if (block !== events.head && block.events) {
|
|
@@ -12957,7 +13327,11 @@ function computeAttributes(head) {
|
|
|
12957
13327
|
return;
|
|
12958
13328
|
}
|
|
12959
13329
|
events.live = false;
|
|
12960
|
-
if (
|
|
13330
|
+
if (existing && existing.isIsolated) {
|
|
13331
|
+
delete existing.isIsolated;
|
|
13332
|
+
mergeAnticipatedState(events, existing);
|
|
13333
|
+
}
|
|
13334
|
+
else if (candidateCost(events) != cost) {
|
|
12961
13335
|
throw new Error(`cost of block ${i} changed`);
|
|
12962
13336
|
}
|
|
12963
13337
|
candidateDecls.set(decl, events);
|
|
@@ -13036,28 +13410,34 @@ function applyReplacements(func, nodeMap, declMap) {
|
|
|
13036
13410
|
stmtStack.pop();
|
|
13037
13411
|
const events = nodeMap.get(node);
|
|
13038
13412
|
if (events) {
|
|
13039
|
-
|
|
13040
|
-
if (
|
|
13413
|
+
const ret = events.reduce((ret, event) => {
|
|
13414
|
+
if (event.type === "ref") {
|
|
13415
|
+
if (ret) {
|
|
13416
|
+
throw new Error(`ref found when there was already a replacement for this node`);
|
|
13417
|
+
}
|
|
13041
13418
|
if (node.type !== "Identifier" &&
|
|
13042
13419
|
node.type !== "MemberExpression" &&
|
|
13043
13420
|
node.type !== "Literal") {
|
|
13044
13421
|
throw new Error(`Ref found, but wrong type of node: ${node.type}`);
|
|
13045
13422
|
}
|
|
13046
|
-
const name = declMap.get(
|
|
13423
|
+
const name = declMap.get(event.decl);
|
|
13047
13424
|
if (!name) {
|
|
13048
13425
|
throw new Error(`No replacement found for "${(0,external_api_cjs_namespaceObject.formatAst)(node)}"`);
|
|
13049
13426
|
}
|
|
13050
13427
|
return ident(name, node);
|
|
13051
13428
|
}
|
|
13052
|
-
|
|
13053
|
-
if (
|
|
13429
|
+
if (event.type === "def") {
|
|
13430
|
+
if (ret) {
|
|
13431
|
+
throw new Error(`def found when there was already a replacement for this node`);
|
|
13432
|
+
}
|
|
13433
|
+
if (node.type !== "AssignmentExpression" &&
|
|
13054
13434
|
node.type !== "UpdateExpression") {
|
|
13055
13435
|
throw new Error(`Def found, but wrong type of node: ${node.type}`);
|
|
13056
13436
|
}
|
|
13057
13437
|
const target = node.type === "AssignmentExpression"
|
|
13058
13438
|
? node.left
|
|
13059
13439
|
: node.argument;
|
|
13060
|
-
const name = declMap.get(
|
|
13440
|
+
const name = declMap.get(event.decl);
|
|
13061
13441
|
if (!name) {
|
|
13062
13442
|
throw new Error(`No replacement found for "${(0,external_api_cjs_namespaceObject.formatAst)(target)}"`);
|
|
13063
13443
|
}
|
|
@@ -13076,20 +13456,24 @@ function applyReplacements(func, nodeMap, declMap) {
|
|
|
13076
13456
|
}
|
|
13077
13457
|
return withLoc({ type: "SequenceExpression", expressions: [node, assign] }, node);
|
|
13078
13458
|
}
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13459
|
+
if (event.type === "mod") {
|
|
13460
|
+
if (!event.decl) {
|
|
13461
|
+
throw new Error(`Unexpected null decl on mod event`);
|
|
13462
|
+
}
|
|
13463
|
+
let pending = pendingMap.get(stmt);
|
|
13464
|
+
if (!pending) {
|
|
13465
|
+
pendingMap.set(stmt, (pending = new Set()));
|
|
13466
|
+
}
|
|
13467
|
+
pending.add(event);
|
|
13086
13468
|
}
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
pendingMap.set(stmt, (pending = new Set()));
|
|
13469
|
+
else {
|
|
13470
|
+
throw new Error(`Unexpected ${event.type} found`);
|
|
13090
13471
|
}
|
|
13091
|
-
|
|
13092
|
-
});
|
|
13472
|
+
return ret;
|
|
13473
|
+
}, null);
|
|
13474
|
+
if (ret) {
|
|
13475
|
+
return ret;
|
|
13476
|
+
}
|
|
13093
13477
|
}
|
|
13094
13478
|
const pending = pendingMap.get(node);
|
|
13095
13479
|
if (node.type === "SequenceExpression") {
|
|
@@ -13163,6 +13547,148 @@ function applyReplacements(func, nodeMap, declMap) {
|
|
|
13163
13547
|
});
|
|
13164
13548
|
}
|
|
13165
13549
|
|
|
13550
|
+
;// CONCATENATED MODULE: ./src/unused-exprs.ts
|
|
13551
|
+
|
|
13552
|
+
|
|
13553
|
+
|
|
13554
|
+
function cleanupUnusedVars(state, node) {
|
|
13555
|
+
const [parent] = state.stack.slice(-1);
|
|
13556
|
+
if (parent.node !== node) {
|
|
13557
|
+
return;
|
|
13558
|
+
}
|
|
13559
|
+
if (parent.type != "BlockStatement") {
|
|
13560
|
+
throw new Error(`Unexpected parent type '${parent.type}' for local declaration`);
|
|
13561
|
+
}
|
|
13562
|
+
if (parent.decls) {
|
|
13563
|
+
let toRemove = null;
|
|
13564
|
+
Object.values(parent.decls).forEach((decls) => {
|
|
13565
|
+
if (decls.length === 1 &&
|
|
13566
|
+
decls[0].type === "VariableDeclarator" &&
|
|
13567
|
+
!decls[0].used) {
|
|
13568
|
+
if (!toRemove)
|
|
13569
|
+
toRemove = {};
|
|
13570
|
+
toRemove[decls[0].name] = decls[0];
|
|
13571
|
+
}
|
|
13572
|
+
});
|
|
13573
|
+
if (toRemove) {
|
|
13574
|
+
const varDeclarations = new Map();
|
|
13575
|
+
traverseAst(node, null, (node) => {
|
|
13576
|
+
switch (node.type) {
|
|
13577
|
+
case "VariableDeclaration": {
|
|
13578
|
+
node.declarations.forEach((decl, i) => {
|
|
13579
|
+
const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(decl.id);
|
|
13580
|
+
if (hasProperty(toRemove, name)) {
|
|
13581
|
+
const indices = varDeclarations.get(node);
|
|
13582
|
+
if (indices) {
|
|
13583
|
+
indices.push(i);
|
|
13584
|
+
}
|
|
13585
|
+
else {
|
|
13586
|
+
varDeclarations.set(node, [i]);
|
|
13587
|
+
}
|
|
13588
|
+
}
|
|
13589
|
+
});
|
|
13590
|
+
break;
|
|
13591
|
+
}
|
|
13592
|
+
case "ExpressionStatement":
|
|
13593
|
+
if (node.expression.type === "AssignmentExpression") {
|
|
13594
|
+
if (node.expression.left.type === "Identifier" &&
|
|
13595
|
+
hasProperty(toRemove, node.expression.left.name)) {
|
|
13596
|
+
return unused(node.expression.right);
|
|
13597
|
+
}
|
|
13598
|
+
}
|
|
13599
|
+
else if (node.expression.type === "UpdateExpression" &&
|
|
13600
|
+
node.expression.argument.type === "Identifier" &&
|
|
13601
|
+
hasProperty(toRemove, node.expression.argument.name)) {
|
|
13602
|
+
return false;
|
|
13603
|
+
}
|
|
13604
|
+
break;
|
|
13605
|
+
case "SequenceExpression": {
|
|
13606
|
+
for (let i = node.expressions.length; i--;) {
|
|
13607
|
+
const expr = node.expressions[i];
|
|
13608
|
+
if (expr.type === "AssignmentExpression") {
|
|
13609
|
+
if (expr.left.type === "Identifier" &&
|
|
13610
|
+
hasProperty(toRemove, expr.left.name)) {
|
|
13611
|
+
const rep = unused(expr.right);
|
|
13612
|
+
if (!rep.length) {
|
|
13613
|
+
node.expressions.splice(i, 1);
|
|
13614
|
+
}
|
|
13615
|
+
else {
|
|
13616
|
+
// Sequence expressions can only be assignments
|
|
13617
|
+
// or update expressions. Even calls aren't allowed
|
|
13618
|
+
toRemove[expr.left.name] = null;
|
|
13619
|
+
expr.operator = "=";
|
|
13620
|
+
}
|
|
13621
|
+
}
|
|
13622
|
+
}
|
|
13623
|
+
else if (expr.type === "UpdateExpression" &&
|
|
13624
|
+
expr.argument.type === "Identifier" &&
|
|
13625
|
+
hasProperty(toRemove, expr.argument.name)) {
|
|
13626
|
+
node.expressions.splice(i, 1);
|
|
13627
|
+
}
|
|
13628
|
+
}
|
|
13629
|
+
break;
|
|
13630
|
+
}
|
|
13631
|
+
}
|
|
13632
|
+
return null;
|
|
13633
|
+
});
|
|
13634
|
+
varDeclarations.forEach((indices, decl) => {
|
|
13635
|
+
let index = -1;
|
|
13636
|
+
for (let ii = indices.length, j = decl.declarations.length; ii--;) {
|
|
13637
|
+
const i = indices[ii];
|
|
13638
|
+
const vdecl = decl.declarations[i];
|
|
13639
|
+
const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id);
|
|
13640
|
+
if (hasProperty(toRemove, name)) {
|
|
13641
|
+
const rep = vdecl.init ? unused(vdecl.init) : [];
|
|
13642
|
+
if (rep.length) {
|
|
13643
|
+
if (parent.node.type === "ForStatement") {
|
|
13644
|
+
// declarations whose inits have side effects
|
|
13645
|
+
// can't be deleted from for statements.
|
|
13646
|
+
continue;
|
|
13647
|
+
}
|
|
13648
|
+
if (index < 0) {
|
|
13649
|
+
index = parent.node.body.findIndex((s) => s === decl);
|
|
13650
|
+
if (index < 0) {
|
|
13651
|
+
throw new Error(`Failed to find variable declaration for ${(0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id)}`);
|
|
13652
|
+
}
|
|
13653
|
+
}
|
|
13654
|
+
if (j > i + 1) {
|
|
13655
|
+
const tail = {
|
|
13656
|
+
...decl,
|
|
13657
|
+
declarations: decl.declarations.slice(i + 1, j),
|
|
13658
|
+
};
|
|
13659
|
+
if (decl.loc && vdecl.loc) {
|
|
13660
|
+
tail.loc = { ...decl.loc, start: vdecl.loc.end };
|
|
13661
|
+
tail.start = vdecl.end;
|
|
13662
|
+
}
|
|
13663
|
+
rep.push(tail);
|
|
13664
|
+
}
|
|
13665
|
+
if (decl.loc && vdecl.loc) {
|
|
13666
|
+
decl.loc = { ...decl.loc, end: vdecl.loc.start };
|
|
13667
|
+
decl.end = vdecl.start;
|
|
13668
|
+
}
|
|
13669
|
+
decl.declarations.splice(i);
|
|
13670
|
+
parent.node.body.splice(index + 1, 0, ...rep);
|
|
13671
|
+
j = i;
|
|
13672
|
+
continue;
|
|
13673
|
+
}
|
|
13674
|
+
if (toRemove[name]) {
|
|
13675
|
+
j--;
|
|
13676
|
+
decl.declarations.splice(i, 1);
|
|
13677
|
+
if (i === j && decl.loc && vdecl.loc) {
|
|
13678
|
+
decl.loc = { ...decl.loc, end: vdecl.loc.start };
|
|
13679
|
+
decl.end = vdecl.start;
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
else {
|
|
13683
|
+
delete vdecl.init;
|
|
13684
|
+
}
|
|
13685
|
+
}
|
|
13686
|
+
}
|
|
13687
|
+
});
|
|
13688
|
+
}
|
|
13689
|
+
}
|
|
13690
|
+
}
|
|
13691
|
+
|
|
13166
13692
|
;// CONCATENATED MODULE: ./src/visitor.ts
|
|
13167
13693
|
|
|
13168
13694
|
function visitReferences(state, ast, name, defn, callback) {
|
|
@@ -13227,14 +13753,16 @@ function visitReferences(state, ast, name, defn, callback) {
|
|
|
13227
13753
|
return checkResults(state.lookup(node), node);
|
|
13228
13754
|
}
|
|
13229
13755
|
break;
|
|
13230
|
-
case "MemberExpression":
|
|
13231
|
-
|
|
13232
|
-
|
|
13756
|
+
case "MemberExpression": {
|
|
13757
|
+
const property = (0,external_api_cjs_namespaceObject.isLookupCandidate)(node);
|
|
13758
|
+
if (property) {
|
|
13759
|
+
if (!name || property.name === name) {
|
|
13233
13760
|
return checkResults(state.lookup(node), node) || ["object"];
|
|
13234
13761
|
}
|
|
13235
13762
|
return ["object"];
|
|
13236
13763
|
}
|
|
13237
13764
|
break;
|
|
13765
|
+
}
|
|
13238
13766
|
case "MethodDefinition": {
|
|
13239
13767
|
if (!state.inType) {
|
|
13240
13768
|
throw new Error("Method definition outside of type!");
|
|
@@ -13243,7 +13771,6 @@ function visitReferences(state, ast, name, defn, callback) {
|
|
|
13243
13771
|
node.params.forEach((param) => {
|
|
13244
13772
|
if (param.type == "BinaryExpression") {
|
|
13245
13773
|
state.traverse(param.right);
|
|
13246
|
-
state.inType = true;
|
|
13247
13774
|
}
|
|
13248
13775
|
});
|
|
13249
13776
|
}
|
|
@@ -13266,6 +13793,9 @@ function visitReferences(state, ast, name, defn, callback) {
|
|
|
13266
13793
|
|
|
13267
13794
|
|
|
13268
13795
|
|
|
13796
|
+
|
|
13797
|
+
|
|
13798
|
+
|
|
13269
13799
|
function collectClassInfo(state) {
|
|
13270
13800
|
const toybox = state.stack[0].decls["Toybox"][0];
|
|
13271
13801
|
const lang = toybox.decls["Lang"][0];
|
|
@@ -13325,8 +13855,7 @@ function collectClassInfo(state) {
|
|
|
13325
13855
|
c.decls &&
|
|
13326
13856
|
Object.values(c.decls).forEach((funcs) => {
|
|
13327
13857
|
funcs.forEach((f) => {
|
|
13328
|
-
if (
|
|
13329
|
-
f.type === "FunctionDeclaration" &&
|
|
13858
|
+
if (f.type === "FunctionDeclaration" &&
|
|
13330
13859
|
(0,external_api_cjs_namespaceObject.hasProperty)(cls.decls, f.name)) {
|
|
13331
13860
|
f.node.hasOverride = true;
|
|
13332
13861
|
}
|
|
@@ -13339,6 +13868,15 @@ function collectClassInfo(state) {
|
|
|
13339
13868
|
state.allClasses.forEach((elm) => {
|
|
13340
13869
|
if (elm.superClass)
|
|
13341
13870
|
markOverrides(elm, elm.superClass);
|
|
13871
|
+
if (elm.hasInvoke && elm.decls) {
|
|
13872
|
+
Object.values(elm.decls).forEach((funcs) => {
|
|
13873
|
+
funcs.forEach((f) => {
|
|
13874
|
+
if (f.type === "FunctionDeclaration" && !f.isStatic) {
|
|
13875
|
+
(0,external_api_cjs_namespaceObject.markInvokeClassMethod)(f);
|
|
13876
|
+
}
|
|
13877
|
+
});
|
|
13878
|
+
});
|
|
13879
|
+
}
|
|
13342
13880
|
});
|
|
13343
13881
|
}
|
|
13344
13882
|
function getFileSources(fnMap) {
|
|
@@ -13377,7 +13915,7 @@ async function analyze(fnMap, barrelList, config) {
|
|
|
13377
13915
|
const preState = {
|
|
13378
13916
|
fnMap,
|
|
13379
13917
|
config,
|
|
13380
|
-
allFunctions:
|
|
13918
|
+
allFunctions: {},
|
|
13381
13919
|
allClasses: [],
|
|
13382
13920
|
shouldExclude(node) {
|
|
13383
13921
|
if ("attrs" in node &&
|
|
@@ -13407,11 +13945,6 @@ async function analyze(fnMap, barrelList, config) {
|
|
|
13407
13945
|
pre(node, state) {
|
|
13408
13946
|
switch (node.type) {
|
|
13409
13947
|
case "FunctionDeclaration":
|
|
13410
|
-
if (markApi) {
|
|
13411
|
-
node.body = null;
|
|
13412
|
-
break;
|
|
13413
|
-
}
|
|
13414
|
-
// falls through
|
|
13415
13948
|
case "ModuleDeclaration":
|
|
13416
13949
|
case "ClassDeclaration": {
|
|
13417
13950
|
const [scope] = state.stack.slice(-1);
|
|
@@ -13422,7 +13955,18 @@ async function analyze(fnMap, barrelList, config) {
|
|
|
13422
13955
|
(scope.node.attrs &&
|
|
13423
13956
|
scope.node.attrs.access &&
|
|
13424
13957
|
scope.node.attrs.access.includes("static"));
|
|
13425
|
-
|
|
13958
|
+
if (markApi) {
|
|
13959
|
+
node.body = null;
|
|
13960
|
+
scope.info = (0,external_api_cjs_namespaceObject.getApiFunctionInfo)(scope);
|
|
13961
|
+
delete scope.stack;
|
|
13962
|
+
}
|
|
13963
|
+
const allFuncs = state.allFunctions;
|
|
13964
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(allFuncs, scope.name)) {
|
|
13965
|
+
allFuncs[scope.name] = [scope];
|
|
13966
|
+
}
|
|
13967
|
+
else {
|
|
13968
|
+
allFuncs[scope.name].push(scope);
|
|
13969
|
+
}
|
|
13426
13970
|
}
|
|
13427
13971
|
else if (scope.type === "ClassDeclaration") {
|
|
13428
13972
|
state.allClasses.push(scope);
|
|
@@ -13447,7 +13991,7 @@ async function analyze(fnMap, barrelList, config) {
|
|
|
13447
13991
|
value.hasTests = hasTests;
|
|
13448
13992
|
});
|
|
13449
13993
|
delete state.shouldExclude;
|
|
13450
|
-
delete state.
|
|
13994
|
+
delete state.pre;
|
|
13451
13995
|
collectClassInfo(state);
|
|
13452
13996
|
const diagnosticType = config?.checkInvalidSymbols !== "OFF"
|
|
13453
13997
|
? config?.checkInvalidSymbols || "WARNING"
|
|
@@ -13470,6 +14014,8 @@ async function analyze(fnMap, barrelList, config) {
|
|
|
13470
14014
|
});
|
|
13471
14015
|
});
|
|
13472
14016
|
}
|
|
14017
|
+
state.exposed = state.nextExposed;
|
|
14018
|
+
state.nextExposed = {};
|
|
13473
14019
|
return state;
|
|
13474
14020
|
}
|
|
13475
14021
|
function compareLiteralLike(a, b) {
|
|
@@ -13515,15 +14061,12 @@ function getLiteralNode(node) {
|
|
|
13515
14061
|
if (node.argument.type != "Literal")
|
|
13516
14062
|
return null;
|
|
13517
14063
|
switch (node.operator) {
|
|
13518
|
-
case "-":
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
value: -node.argument.value,
|
|
13523
|
-
raw: "-" + node.argument.value,
|
|
13524
|
-
enumType: node.enumType,
|
|
13525
|
-
};
|
|
14064
|
+
case "-": {
|
|
14065
|
+
const [arg, type] = getNodeValue(node.argument);
|
|
14066
|
+
if (type === "Number" || type === "Long") {
|
|
14067
|
+
return replacementLiteral(arg, -arg.value, type);
|
|
13526
14068
|
}
|
|
14069
|
+
}
|
|
13527
14070
|
}
|
|
13528
14071
|
}
|
|
13529
14072
|
return null;
|
|
@@ -13542,29 +14085,29 @@ function getNodeValue(node) {
|
|
|
13542
14085
|
if (node.type != "Literal") {
|
|
13543
14086
|
return [null, null];
|
|
13544
14087
|
}
|
|
13545
|
-
|
|
14088
|
+
if (node.value === null) {
|
|
14089
|
+
return [node, "Null"];
|
|
14090
|
+
}
|
|
14091
|
+
const type = typeof node.value;
|
|
13546
14092
|
if (type === "number") {
|
|
13547
|
-
const match =
|
|
14093
|
+
const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
|
|
13548
14094
|
if (match) {
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
type = "Double";
|
|
13553
|
-
}
|
|
13554
|
-
else {
|
|
13555
|
-
type = "Float";
|
|
14095
|
+
return match[2] === "l" || match[2] === "L"
|
|
14096
|
+
? [node, "Long"]
|
|
14097
|
+
: [node, "Number"];
|
|
13556
14098
|
}
|
|
14099
|
+
return [node, node.raw.endsWith("d") ? "Double" : "Float"];
|
|
13557
14100
|
}
|
|
13558
|
-
|
|
13559
|
-
|
|
14101
|
+
if (type === "bigint") {
|
|
14102
|
+
return [node, "Long"];
|
|
13560
14103
|
}
|
|
13561
|
-
|
|
13562
|
-
|
|
14104
|
+
if (type === "string") {
|
|
14105
|
+
return [node, "String"];
|
|
13563
14106
|
}
|
|
13564
|
-
|
|
13565
|
-
|
|
14107
|
+
if (type === "boolean") {
|
|
14108
|
+
return [node, "Boolean"];
|
|
13566
14109
|
}
|
|
13567
|
-
|
|
14110
|
+
throw new Error(`Literal has unknown type '${type}'`);
|
|
13568
14111
|
}
|
|
13569
14112
|
function fullTypeName(state, tsp) {
|
|
13570
14113
|
if (typeof tsp.name === "string") {
|
|
@@ -13609,6 +14152,46 @@ function isBooleanExpression(state, node) {
|
|
|
13609
14152
|
}
|
|
13610
14153
|
return false;
|
|
13611
14154
|
}
|
|
14155
|
+
function replacementLiteral(arg, value, type) {
|
|
14156
|
+
if (typeof value === "boolean") {
|
|
14157
|
+
type = "Boolean";
|
|
14158
|
+
}
|
|
14159
|
+
else if (type === "Number") {
|
|
14160
|
+
value = Number(BigInt.asIntN(32, BigInt(value)));
|
|
14161
|
+
}
|
|
14162
|
+
else if (type === "Long") {
|
|
14163
|
+
value = BigInt.asIntN(64, BigInt(value));
|
|
14164
|
+
}
|
|
14165
|
+
return {
|
|
14166
|
+
...arg,
|
|
14167
|
+
value,
|
|
14168
|
+
raw: value.toString() + (type === "Long" ? "l" : ""),
|
|
14169
|
+
};
|
|
14170
|
+
}
|
|
14171
|
+
const operators = {
|
|
14172
|
+
"+": (left, right) => left + right,
|
|
14173
|
+
"-": (left, right) => left - right,
|
|
14174
|
+
"*": (left, right) => left * right,
|
|
14175
|
+
"/": (left, right) => left / right,
|
|
14176
|
+
"%": (left, right) => left % right,
|
|
14177
|
+
"&": (left, right) => left & right,
|
|
14178
|
+
"|": (left, right) => left | right,
|
|
14179
|
+
"^": (left, right) => left ^ right,
|
|
14180
|
+
"<<": (left, right) => left << (right & 127n),
|
|
14181
|
+
">>": (left, right) => left >> (right & 127n),
|
|
14182
|
+
"==": (left, right) =>
|
|
14183
|
+
// two string literals will compare unequal, becuase string
|
|
14184
|
+
// equality is object equality.
|
|
14185
|
+
typeof left === "string" ? false : left === right,
|
|
14186
|
+
"!=": (left, right) => typeof left === "string" ? true : left !== right,
|
|
14187
|
+
"<=": (left, right) => left <= right,
|
|
14188
|
+
">=": (left, right) => left >= right,
|
|
14189
|
+
"<": (left, right) => left < right,
|
|
14190
|
+
">": (left, right) => left > right,
|
|
14191
|
+
as: null,
|
|
14192
|
+
instanceof: null,
|
|
14193
|
+
has: null,
|
|
14194
|
+
};
|
|
13612
14195
|
function optimizeNode(state, node) {
|
|
13613
14196
|
switch (node.type) {
|
|
13614
14197
|
case "UnaryExpression": {
|
|
@@ -13623,29 +14206,17 @@ function optimizeNode(state, node) {
|
|
|
13623
14206
|
break;
|
|
13624
14207
|
case "-":
|
|
13625
14208
|
if (type === "Number" || type === "Long") {
|
|
13626
|
-
return
|
|
13627
|
-
...arg,
|
|
13628
|
-
value: -arg.value,
|
|
13629
|
-
raw: (-arg.value).toString() + (type === "Long" ? "l" : ""),
|
|
13630
|
-
};
|
|
14209
|
+
return replacementLiteral(arg, -arg.value, type);
|
|
13631
14210
|
}
|
|
13632
14211
|
break;
|
|
13633
14212
|
case "!":
|
|
13634
14213
|
case "~":
|
|
13635
14214
|
{
|
|
13636
|
-
let value;
|
|
13637
14215
|
if (type === "Number" || type === "Long") {
|
|
13638
|
-
|
|
14216
|
+
return replacementLiteral(arg, ~BigInt(arg.value), type);
|
|
13639
14217
|
}
|
|
13640
|
-
|
|
13641
|
-
|
|
13642
|
-
}
|
|
13643
|
-
if (value !== undefined) {
|
|
13644
|
-
return {
|
|
13645
|
-
...arg,
|
|
13646
|
-
value,
|
|
13647
|
-
raw: value.toString() + (type === "Long" ? "l" : ""),
|
|
13648
|
-
};
|
|
14218
|
+
if (type === "Boolean" && node.operator == "!") {
|
|
14219
|
+
return replacementLiteral(arg, !arg.value, type);
|
|
13649
14220
|
}
|
|
13650
14221
|
}
|
|
13651
14222
|
break;
|
|
@@ -13653,27 +14224,6 @@ function optimizeNode(state, node) {
|
|
|
13653
14224
|
break;
|
|
13654
14225
|
}
|
|
13655
14226
|
case "BinaryExpression": {
|
|
13656
|
-
const operators = {
|
|
13657
|
-
"+": (left, right) => left + right,
|
|
13658
|
-
"-": (left, right) => left - right,
|
|
13659
|
-
"*": (left, right) => left * right,
|
|
13660
|
-
"/": (left, right) => Math.trunc(left / right),
|
|
13661
|
-
"%": (left, right) => left % right,
|
|
13662
|
-
"&": (left, right, type) => type === "Number" ? left & right : null,
|
|
13663
|
-
"|": (left, right, type) => type === "Number" ? left | right : null,
|
|
13664
|
-
"^": (left, right, type) => type === "Number" ? left ^ right : null,
|
|
13665
|
-
"<<": (left, right, type) => type === "Number" ? left << right : null,
|
|
13666
|
-
">>": (left, right, type) => type === "Number" ? left >> right : null,
|
|
13667
|
-
"==": (left, right) => left == right,
|
|
13668
|
-
"!=": (left, right) => left != right,
|
|
13669
|
-
"<=": (left, right) => left <= right,
|
|
13670
|
-
">=": (left, right) => left >= right,
|
|
13671
|
-
"<": (left, right) => left < right,
|
|
13672
|
-
">": (left, right) => left > right,
|
|
13673
|
-
as: null,
|
|
13674
|
-
instanceof: null,
|
|
13675
|
-
has: null,
|
|
13676
|
-
};
|
|
13677
14227
|
const op = operators[node.operator];
|
|
13678
14228
|
if (op) {
|
|
13679
14229
|
const [left, left_type] = getNodeValue(node.left);
|
|
@@ -13681,23 +14231,22 @@ function optimizeNode(state, node) {
|
|
|
13681
14231
|
if (!left || !right)
|
|
13682
14232
|
break;
|
|
13683
14233
|
let value = null;
|
|
13684
|
-
|
|
13685
|
-
|
|
14234
|
+
let type;
|
|
14235
|
+
if ((left_type != "Number" && left_type != "Long") ||
|
|
14236
|
+
left_type != right_type) {
|
|
13686
14237
|
if (node.operator !== "==" && node.operator !== "!=") {
|
|
13687
14238
|
break;
|
|
13688
14239
|
}
|
|
13689
14240
|
value = operators[node.operator](left.value, right.value);
|
|
14241
|
+
type = "Boolean";
|
|
13690
14242
|
}
|
|
13691
14243
|
else {
|
|
13692
|
-
|
|
14244
|
+
type = left_type;
|
|
14245
|
+
value = op(BigInt(left.value), BigInt(right.value));
|
|
13693
14246
|
}
|
|
13694
14247
|
if (value === null)
|
|
13695
14248
|
break;
|
|
13696
|
-
return
|
|
13697
|
-
...left,
|
|
13698
|
-
value,
|
|
13699
|
-
raw: value.toString() + (left_type === "Long" ? "l" : ""),
|
|
13700
|
-
};
|
|
14249
|
+
return replacementLiteral(left, value, type);
|
|
13701
14250
|
}
|
|
13702
14251
|
break;
|
|
13703
14252
|
}
|
|
@@ -13707,7 +14256,8 @@ function optimizeNode(state, node) {
|
|
|
13707
14256
|
break;
|
|
13708
14257
|
const falsy = left.value === false ||
|
|
13709
14258
|
left.value === null ||
|
|
13710
|
-
(
|
|
14259
|
+
((left_type === "Number" || left_type === "Long") &&
|
|
14260
|
+
(left.value === 0 || left.value === 0n));
|
|
13711
14261
|
if (falsy === (node.operator === "&&")) {
|
|
13712
14262
|
return left;
|
|
13713
14263
|
}
|
|
@@ -13748,9 +14298,7 @@ function evaluateFunction(state, func, args) {
|
|
|
13748
14298
|
const paramValues = args &&
|
|
13749
14299
|
Object.fromEntries(func.params.map((p, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(p), args[i]]));
|
|
13750
14300
|
let ret = null;
|
|
13751
|
-
const body = args
|
|
13752
|
-
? JSON.parse(JSON.stringify(func.body))
|
|
13753
|
-
: func.body;
|
|
14301
|
+
const body = args ? cloneDeep(func.body) : func.body;
|
|
13754
14302
|
try {
|
|
13755
14303
|
traverseAst(body, (node) => {
|
|
13756
14304
|
switch (node.type) {
|
|
@@ -13801,12 +14349,10 @@ function markFunctionCalled(state, func) {
|
|
|
13801
14349
|
(0,external_util_cjs_namespaceObject.pushUnique)(state.calledFunctions[func.id.name], func);
|
|
13802
14350
|
}
|
|
13803
14351
|
async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
13804
|
-
const state =
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
calledFunctions: {},
|
|
13809
|
-
};
|
|
14352
|
+
const state = (await analyze(fnMap, barrelList, config));
|
|
14353
|
+
state.localsStack = [{}];
|
|
14354
|
+
state.calledFunctions = {};
|
|
14355
|
+
state.usedByName = {};
|
|
13810
14356
|
const replace = (node, old) => {
|
|
13811
14357
|
if (node === false || node === null)
|
|
13812
14358
|
return node;
|
|
@@ -13895,6 +14441,58 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
13895
14441
|
f.type == "FunctionDeclaration" &&
|
|
13896
14442
|
maybeCalled(f.node))) ||
|
|
13897
14443
|
(sc.superClass && checkInherited(sc, name))));
|
|
14444
|
+
const renamer = (idnode) => {
|
|
14445
|
+
const ident = idnode.type === "Identifier" ? idnode : idnode.left;
|
|
14446
|
+
const locals = topLocals();
|
|
14447
|
+
const { map } = locals;
|
|
14448
|
+
if (map) {
|
|
14449
|
+
const declName = ident.name;
|
|
14450
|
+
const name = renameVariable(state, locals, declName);
|
|
14451
|
+
if (name) {
|
|
14452
|
+
const [, results] = state.lookupValue(ident);
|
|
14453
|
+
if (!results) {
|
|
14454
|
+
throw new Error(`Didn't find local ${declName} which needed renaming`);
|
|
14455
|
+
}
|
|
14456
|
+
if (results.length !== 1) {
|
|
14457
|
+
throw new Error(`Lookup of local ${declName} found more than one result`);
|
|
14458
|
+
}
|
|
14459
|
+
const parent = results[0].parent;
|
|
14460
|
+
if (!parent) {
|
|
14461
|
+
throw new Error(`No parent in lookup of local ${declName}`);
|
|
14462
|
+
}
|
|
14463
|
+
const decls = parent.decls;
|
|
14464
|
+
if (!decls || !(0,external_api_cjs_namespaceObject.hasProperty)(decls, declName)) {
|
|
14465
|
+
throw new Error(`Missing decls in lookup of local ${declName}`);
|
|
14466
|
+
}
|
|
14467
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(decls, name)) {
|
|
14468
|
+
throw new Error(`While renaming ${declName} to ${name}, there was already a variable ${name}`);
|
|
14469
|
+
}
|
|
14470
|
+
if (decls[declName].length === 1) {
|
|
14471
|
+
decls[name] = decls[declName];
|
|
14472
|
+
delete decls[declName];
|
|
14473
|
+
}
|
|
14474
|
+
else {
|
|
14475
|
+
let i = decls[declName].length;
|
|
14476
|
+
while (i--) {
|
|
14477
|
+
const decl = decls[declName][i];
|
|
14478
|
+
if (decl === idnode ||
|
|
14479
|
+
(decl.type === "VariableDeclarator" && decl.node.id === idnode)) {
|
|
14480
|
+
decls[declName].splice(i, 1);
|
|
14481
|
+
decls[name] = [decl];
|
|
14482
|
+
break;
|
|
14483
|
+
}
|
|
14484
|
+
}
|
|
14485
|
+
if (i < 0) {
|
|
14486
|
+
throw new Error(`While renaming ${declName} to ${name}: Didn't find original declaration`);
|
|
14487
|
+
}
|
|
14488
|
+
}
|
|
14489
|
+
ident.name = name;
|
|
14490
|
+
}
|
|
14491
|
+
else {
|
|
14492
|
+
map[declName] = true;
|
|
14493
|
+
}
|
|
14494
|
+
}
|
|
14495
|
+
};
|
|
13898
14496
|
state.pre = (node) => {
|
|
13899
14497
|
switch (node.type) {
|
|
13900
14498
|
case "ConditionalExpression":
|
|
@@ -13915,7 +14513,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
13915
14513
|
result = !!value.value;
|
|
13916
14514
|
}
|
|
13917
14515
|
if (result !== null) {
|
|
13918
|
-
node.test = {
|
|
14516
|
+
node.test = {
|
|
14517
|
+
type: "Literal",
|
|
14518
|
+
value: result,
|
|
14519
|
+
raw: result.toString(),
|
|
14520
|
+
};
|
|
13919
14521
|
if (node.type === "IfStatement" ||
|
|
13920
14522
|
node.type === "ConditionalExpression") {
|
|
13921
14523
|
return [result ? "consequent" : "alternate"];
|
|
@@ -13934,7 +14536,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
13934
14536
|
return null;
|
|
13935
14537
|
}
|
|
13936
14538
|
case "EnumDeclaration":
|
|
13937
|
-
return
|
|
14539
|
+
return [];
|
|
13938
14540
|
case "ForStatement": {
|
|
13939
14541
|
const map = topLocals().map;
|
|
13940
14542
|
if (map) {
|
|
@@ -13943,43 +14545,13 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
13943
14545
|
break;
|
|
13944
14546
|
}
|
|
13945
14547
|
case "VariableDeclarator": {
|
|
13946
|
-
|
|
13947
|
-
const { map } = locals;
|
|
13948
|
-
if (map) {
|
|
13949
|
-
const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id);
|
|
13950
|
-
const name = renameVariable(state, locals, declName);
|
|
13951
|
-
if (name) {
|
|
13952
|
-
if (node.id.type === "Identifier") {
|
|
13953
|
-
node.id.name = name;
|
|
13954
|
-
}
|
|
13955
|
-
else {
|
|
13956
|
-
node.id.left.name = name;
|
|
13957
|
-
}
|
|
13958
|
-
}
|
|
13959
|
-
else {
|
|
13960
|
-
map[declName] = true;
|
|
13961
|
-
}
|
|
13962
|
-
}
|
|
14548
|
+
renamer(node.id);
|
|
13963
14549
|
return ["init"];
|
|
13964
14550
|
}
|
|
13965
14551
|
case "CatchClause":
|
|
13966
14552
|
if (node.param) {
|
|
13967
14553
|
state.localsStack.push({ node, map: { ...(topLocals().map || {}) } });
|
|
13968
|
-
|
|
13969
|
-
const map = locals.map;
|
|
13970
|
-
const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.param);
|
|
13971
|
-
const name = renameVariable(state, locals, declName);
|
|
13972
|
-
if (name) {
|
|
13973
|
-
if (node.param.type === "Identifier") {
|
|
13974
|
-
node.param.name = name;
|
|
13975
|
-
}
|
|
13976
|
-
else {
|
|
13977
|
-
node.param.left.name = name;
|
|
13978
|
-
}
|
|
13979
|
-
}
|
|
13980
|
-
else {
|
|
13981
|
-
map[declName] = true;
|
|
13982
|
-
}
|
|
14554
|
+
renamer(node.param);
|
|
13983
14555
|
return ["body"];
|
|
13984
14556
|
}
|
|
13985
14557
|
break;
|
|
@@ -13995,14 +14567,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
13995
14567
|
break;
|
|
13996
14568
|
case "UnaryExpression":
|
|
13997
14569
|
if (node.operator == ":") {
|
|
13998
|
-
//
|
|
13999
|
-
//
|
|
14000
|
-
// indirectly, so we can't remove any enums or
|
|
14001
|
-
// constants with that name (we can still replace
|
|
14002
|
-
// uses of those constants though).
|
|
14003
|
-
state.exposed[node.argument.name] = true;
|
|
14004
|
-
// In any case, we can't replace *this* use of the
|
|
14005
|
-
// symbol with its value...
|
|
14570
|
+
// node.argument is not a normal identifier.
|
|
14571
|
+
// don't visit it.
|
|
14006
14572
|
return [];
|
|
14007
14573
|
}
|
|
14008
14574
|
break;
|
|
@@ -14014,29 +14580,73 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14014
14580
|
if (typeof name === "string") {
|
|
14015
14581
|
node.name = name;
|
|
14016
14582
|
}
|
|
14583
|
+
const [, results] = state.lookupValue(node);
|
|
14584
|
+
if (results) {
|
|
14585
|
+
if (results.length !== 1 || results[0].results.length !== 1) {
|
|
14586
|
+
throw new Error(`Local ${node.name} had multiple lookup results`);
|
|
14587
|
+
}
|
|
14588
|
+
const parent = results[0].parent;
|
|
14589
|
+
if (!parent) {
|
|
14590
|
+
throw new Error(`Local ${node.name} had no parent`);
|
|
14591
|
+
}
|
|
14592
|
+
const decl = results[0].results[0];
|
|
14593
|
+
if (parent.type === "FunctionDeclaration" ||
|
|
14594
|
+
decl.type !== "VariableDeclarator") {
|
|
14595
|
+
// we can't optimize away function or catch parameters
|
|
14596
|
+
return [];
|
|
14597
|
+
}
|
|
14598
|
+
if (parent.type !== "BlockStatement") {
|
|
14599
|
+
throw new Error(`Local ${node.name} was not declared at block scope(??)`);
|
|
14600
|
+
}
|
|
14601
|
+
decl.used = true;
|
|
14602
|
+
}
|
|
14017
14603
|
}
|
|
14018
14604
|
}
|
|
14019
14605
|
if ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, node.name)) {
|
|
14020
14606
|
if (!lookupAndReplace(node)) {
|
|
14021
|
-
state.
|
|
14607
|
+
state.usedByName[node.name] = true;
|
|
14022
14608
|
}
|
|
14023
14609
|
}
|
|
14024
14610
|
return [];
|
|
14025
14611
|
}
|
|
14026
|
-
case "MemberExpression":
|
|
14027
|
-
|
|
14028
|
-
|
|
14612
|
+
case "MemberExpression": {
|
|
14613
|
+
const property = (0,external_api_cjs_namespaceObject.isLookupCandidate)(node);
|
|
14614
|
+
if (property) {
|
|
14615
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, property.name)) {
|
|
14029
14616
|
if (lookupAndReplace(node)) {
|
|
14030
14617
|
return false;
|
|
14031
14618
|
}
|
|
14032
14619
|
else {
|
|
14033
|
-
state.
|
|
14620
|
+
state.usedByName[property.name] = true;
|
|
14034
14621
|
}
|
|
14035
14622
|
}
|
|
14036
14623
|
// Don't optimize the property.
|
|
14037
14624
|
return ["object"];
|
|
14038
14625
|
}
|
|
14039
14626
|
break;
|
|
14627
|
+
}
|
|
14628
|
+
case "AssignmentExpression":
|
|
14629
|
+
case "UpdateExpression": {
|
|
14630
|
+
const lhs = node.type === "AssignmentExpression" ? node.left : node.argument;
|
|
14631
|
+
if (lhs.type === "Identifier") {
|
|
14632
|
+
const map = topLocals().map;
|
|
14633
|
+
if (map) {
|
|
14634
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(map, lhs.name)) {
|
|
14635
|
+
const name = map[lhs.name];
|
|
14636
|
+
if (typeof name === "string") {
|
|
14637
|
+
lhs.name = name;
|
|
14638
|
+
}
|
|
14639
|
+
}
|
|
14640
|
+
}
|
|
14641
|
+
}
|
|
14642
|
+
else if (lhs.type === "MemberExpression") {
|
|
14643
|
+
state.traverse(lhs.object);
|
|
14644
|
+
if (lhs.computed) {
|
|
14645
|
+
state.traverse(lhs.property);
|
|
14646
|
+
}
|
|
14647
|
+
}
|
|
14648
|
+
return node.type === "AssignmentExpression" ? ["right"] : [];
|
|
14649
|
+
}
|
|
14040
14650
|
case "BlockStatement": {
|
|
14041
14651
|
const map = topLocals().map;
|
|
14042
14652
|
if (map) {
|
|
@@ -14052,7 +14662,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14052
14662
|
node.params &&
|
|
14053
14663
|
node.params.forEach((p) => (map[(0,external_api_cjs_namespaceObject.variableDeclarationName)(p)] = true));
|
|
14054
14664
|
state.localsStack.push({ node, map });
|
|
14055
|
-
const [parent] = state.stack.slice(-2);
|
|
14665
|
+
const [parent, self] = state.stack.slice(-2);
|
|
14666
|
+
if (state.currentFunction) {
|
|
14667
|
+
throw new Error(`Nested functions: ${self.fullName} was activated during processing of ${state.currentFunction.fullName}`);
|
|
14668
|
+
}
|
|
14669
|
+
state.currentFunction = self;
|
|
14056
14670
|
if (parent.type == "ClassDeclaration" && !maybeCalled(node)) {
|
|
14057
14671
|
let used = false;
|
|
14058
14672
|
if (node.id.name == "initialize") {
|
|
@@ -14079,10 +14693,23 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14079
14693
|
return replace(opt, node);
|
|
14080
14694
|
}
|
|
14081
14695
|
switch (node.type) {
|
|
14696
|
+
case "FunctionDeclaration":
|
|
14697
|
+
if (!state.currentFunction) {
|
|
14698
|
+
throw new Error(`Finished function ${state.stack.slice(-1)[0].fullName}, but it was not marked current`);
|
|
14699
|
+
}
|
|
14700
|
+
state.currentFunction.info = state.currentFunction.next_info;
|
|
14701
|
+
delete state.currentFunction.next_info;
|
|
14702
|
+
delete state.currentFunction;
|
|
14703
|
+
break;
|
|
14082
14704
|
case "BlockStatement":
|
|
14083
14705
|
if (node.body.length === 1 && node.body[0].type === "BlockStatement") {
|
|
14084
14706
|
node.body.splice(0, 1, ...node.body[0].body);
|
|
14085
14707
|
}
|
|
14708
|
+
// fall through
|
|
14709
|
+
case "ForStatement":
|
|
14710
|
+
if (locals.map) {
|
|
14711
|
+
cleanupUnusedVars(state, node);
|
|
14712
|
+
}
|
|
14086
14713
|
break;
|
|
14087
14714
|
case "ConditionalExpression":
|
|
14088
14715
|
case "IfStatement":
|
|
@@ -14115,17 +14742,20 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14115
14742
|
return replace(optimizeCall(state, node.argument, node), node.argument);
|
|
14116
14743
|
}
|
|
14117
14744
|
break;
|
|
14745
|
+
case "NewExpression":
|
|
14746
|
+
if (state.currentFunction) {
|
|
14747
|
+
const [, results] = state.lookup(node.callee);
|
|
14748
|
+
if (results) {
|
|
14749
|
+
recordCalledFuncs(state.currentFunction, findCalleesForNew(results));
|
|
14750
|
+
}
|
|
14751
|
+
else {
|
|
14752
|
+
recordModifiedUnknown(state.currentFunction);
|
|
14753
|
+
}
|
|
14754
|
+
}
|
|
14755
|
+
break;
|
|
14118
14756
|
case "CallExpression": {
|
|
14119
14757
|
return replace(optimizeCall(state, node, null), node);
|
|
14120
14758
|
}
|
|
14121
|
-
case "AssignmentExpression":
|
|
14122
|
-
if (node.operator === "=" &&
|
|
14123
|
-
node.left.type === "Identifier" &&
|
|
14124
|
-
node.right.type === "Identifier" &&
|
|
14125
|
-
node.left.name === node.right.name) {
|
|
14126
|
-
return { type: "Literal", value: null, raw: "null" };
|
|
14127
|
-
}
|
|
14128
|
-
break;
|
|
14129
14759
|
case "VariableDeclaration": {
|
|
14130
14760
|
const locals = topLocals();
|
|
14131
14761
|
if (locals.map &&
|
|
@@ -14138,10 +14768,10 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14138
14768
|
while (i < node.declarations.length) {
|
|
14139
14769
|
const decl = declarations[i++];
|
|
14140
14770
|
if (decl.init && decl.init.type === "CallExpression") {
|
|
14141
|
-
const inlined = optimizeCall(state, decl.init, decl);
|
|
14771
|
+
const inlined = replace(optimizeCall(state, decl.init, decl), decl.init);
|
|
14142
14772
|
if (!inlined)
|
|
14143
14773
|
continue;
|
|
14144
|
-
if (inlined.type != "BlockStatement") {
|
|
14774
|
+
if (Array.isArray(inlined) || inlined.type != "BlockStatement") {
|
|
14145
14775
|
throw new Error("Unexpected inlined result");
|
|
14146
14776
|
}
|
|
14147
14777
|
if (!results) {
|
|
@@ -14199,6 +14829,32 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14199
14829
|
}
|
|
14200
14830
|
}
|
|
14201
14831
|
break;
|
|
14832
|
+
case "AssignmentExpression":
|
|
14833
|
+
if (node.operator === "=" &&
|
|
14834
|
+
node.left.type === "Identifier" &&
|
|
14835
|
+
node.right.type === "Identifier" &&
|
|
14836
|
+
node.left.name === node.right.name) {
|
|
14837
|
+
return { type: "Literal", value: null, raw: "null" };
|
|
14838
|
+
}
|
|
14839
|
+
// fall through;
|
|
14840
|
+
case "UpdateExpression":
|
|
14841
|
+
if (state.currentFunction) {
|
|
14842
|
+
const lhs = node.type === "AssignmentExpression" ? node.left : node.argument;
|
|
14843
|
+
const [, results] = state.lookup(lhs);
|
|
14844
|
+
if (results) {
|
|
14845
|
+
recordModifiedDecls(state.currentFunction, results);
|
|
14846
|
+
}
|
|
14847
|
+
else {
|
|
14848
|
+
const id = lhs.type === "Identifier" ? lhs : (0,external_api_cjs_namespaceObject.isLookupCandidate)(lhs);
|
|
14849
|
+
if (id) {
|
|
14850
|
+
recordModifiedName(state.currentFunction, id.name);
|
|
14851
|
+
}
|
|
14852
|
+
else {
|
|
14853
|
+
recordModifiedUnknown(state.currentFunction);
|
|
14854
|
+
}
|
|
14855
|
+
}
|
|
14856
|
+
}
|
|
14857
|
+
break;
|
|
14202
14858
|
}
|
|
14203
14859
|
return null;
|
|
14204
14860
|
};
|
|
@@ -14206,13 +14862,16 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14206
14862
|
(0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
|
|
14207
14863
|
});
|
|
14208
14864
|
state.calledFunctions = {};
|
|
14209
|
-
state.exposed =
|
|
14865
|
+
state.exposed = state.nextExposed;
|
|
14866
|
+
state.nextExposed = {};
|
|
14210
14867
|
Object.values(fnMap).forEach((f) => {
|
|
14211
14868
|
(0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
|
|
14212
14869
|
});
|
|
14870
|
+
state.exposed = state.nextExposed;
|
|
14871
|
+
state.nextExposed = {};
|
|
14213
14872
|
delete state.pre;
|
|
14214
14873
|
delete state.post;
|
|
14215
|
-
state.allFunctions.forEach((fn) => sizeBasedPRE(state, fn));
|
|
14874
|
+
Object.values(state.allFunctions).forEach((fns) => fns.forEach((fn) => sizeBasedPRE(state, fn)));
|
|
14216
14875
|
const cleanup = (node) => {
|
|
14217
14876
|
switch (node.type) {
|
|
14218
14877
|
case "ThisExpression":
|
|
@@ -14222,7 +14881,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14222
14881
|
if (node.members.every((m) => {
|
|
14223
14882
|
const name = "name" in m ? m.name : m.id.name;
|
|
14224
14883
|
return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
|
|
14225
|
-
!(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name)
|
|
14884
|
+
!(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name) &&
|
|
14885
|
+
!(0,external_api_cjs_namespaceObject.hasProperty)(state.usedByName, name));
|
|
14226
14886
|
})) {
|
|
14227
14887
|
node.enumType = [
|
|
14228
14888
|
...new Set(node.members.map((m) => {
|
|
@@ -14265,7 +14925,9 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14265
14925
|
case "VariableDeclaration": {
|
|
14266
14926
|
node.declarations = node.declarations.filter((d) => {
|
|
14267
14927
|
const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
|
|
14268
|
-
return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) ||
|
|
14928
|
+
return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) ||
|
|
14929
|
+
(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name) ||
|
|
14930
|
+
(0,external_api_cjs_namespaceObject.hasProperty)(state.usedByName, name));
|
|
14269
14931
|
});
|
|
14270
14932
|
if (!node.declarations.length) {
|
|
14271
14933
|
return false;
|
|
@@ -14298,7 +14960,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14298
14960
|
}
|
|
14299
14961
|
return null;
|
|
14300
14962
|
};
|
|
14301
|
-
Object.
|
|
14963
|
+
Object.entries(fnMap).forEach(([name, f]) => {
|
|
14302
14964
|
traverseAst(f.ast, undefined, (node) => {
|
|
14303
14965
|
const ret = cleanup(node);
|
|
14304
14966
|
if (ret === false) {
|
|
@@ -14306,16 +14968,15 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14306
14968
|
}
|
|
14307
14969
|
return ret;
|
|
14308
14970
|
});
|
|
14971
|
+
if (state.config && state.config.checkBuildPragmas) {
|
|
14972
|
+
pragmaChecker(state, f.ast, state.diagnostics?.[name]);
|
|
14973
|
+
}
|
|
14309
14974
|
});
|
|
14310
14975
|
return state.diagnostics;
|
|
14311
14976
|
}
|
|
14312
14977
|
function optimizeCall(state, node, context) {
|
|
14313
14978
|
const [name, results] = state.lookupNonlocal(node.callee);
|
|
14314
|
-
const callees = results
|
|
14315
|
-
results
|
|
14316
|
-
.map((r) => r.results)
|
|
14317
|
-
.flat()
|
|
14318
|
-
.filter((c) => c.type === "FunctionDeclaration");
|
|
14979
|
+
const callees = results ? findCallees(results) : null;
|
|
14319
14980
|
if (!callees || !callees.length) {
|
|
14320
14981
|
const n = name ||
|
|
14321
14982
|
("name" in node.callee && node.callee.name) ||
|
|
@@ -14324,14 +14985,24 @@ function optimizeCall(state, node, context) {
|
|
|
14324
14985
|
"name" in node.callee.property &&
|
|
14325
14986
|
node.callee.property.name);
|
|
14326
14987
|
if (n) {
|
|
14327
|
-
state.
|
|
14988
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(state.allFunctions, n)) {
|
|
14989
|
+
if (state.currentFunction) {
|
|
14990
|
+
recordCalledFuncs(state.currentFunction, state.allFunctions[n]);
|
|
14991
|
+
}
|
|
14992
|
+
state.allFunctions[n].forEach((fn) => markFunctionCalled(state, fn.node));
|
|
14993
|
+
}
|
|
14328
14994
|
}
|
|
14329
|
-
else {
|
|
14330
|
-
//
|
|
14331
|
-
//
|
|
14995
|
+
else if (state.currentFunction) {
|
|
14996
|
+
// I don't think this can happen: foo[x](args)
|
|
14997
|
+
// doesn't parse, so you can't even do things like
|
|
14998
|
+
// $.Toybox.Lang[:format]("fmt", [])
|
|
14999
|
+
recordModifiedUnknown(state.currentFunction);
|
|
14332
15000
|
}
|
|
14333
15001
|
return null;
|
|
14334
15002
|
}
|
|
15003
|
+
if (state.currentFunction) {
|
|
15004
|
+
recordCalledFuncs(state.currentFunction, callees);
|
|
15005
|
+
}
|
|
14335
15006
|
if (callees.length == 1 && callees[0].type === "FunctionDeclaration") {
|
|
14336
15007
|
const callee = callees[0].node;
|
|
14337
15008
|
if (!context &&
|
|
@@ -14354,120 +15025,6 @@ function optimizeCall(state, node, context) {
|
|
|
14354
15025
|
return null;
|
|
14355
15026
|
}
|
|
14356
15027
|
|
|
14357
|
-
;// CONCATENATED MODULE: ./src/pragma-checker.ts
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
function pragmaChecker(ast, diagnostics) {
|
|
14361
|
-
const comments = ast.comments;
|
|
14362
|
-
if (!comments)
|
|
14363
|
-
return;
|
|
14364
|
-
diagnostics = diagnostics
|
|
14365
|
-
?.slice()
|
|
14366
|
-
.sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
|
|
14367
|
-
let diagIndex = 0;
|
|
14368
|
-
let index = -1;
|
|
14369
|
-
let comment;
|
|
14370
|
-
let matchers;
|
|
14371
|
-
const next = () => {
|
|
14372
|
-
while (++index < comments.length) {
|
|
14373
|
-
comment = comments[index];
|
|
14374
|
-
let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
|
|
14375
|
-
if (!match)
|
|
14376
|
-
continue;
|
|
14377
|
-
const kind = match[1];
|
|
14378
|
-
let str = match[2];
|
|
14379
|
-
matchers = [];
|
|
14380
|
-
while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
|
|
14381
|
-
matchers.push({ kind, quote: match[1], needle: match[2] });
|
|
14382
|
-
str = str.substring(match[0].length);
|
|
14383
|
-
if (!str.length)
|
|
14384
|
-
break;
|
|
14385
|
-
}
|
|
14386
|
-
if (!str.length)
|
|
14387
|
-
break;
|
|
14388
|
-
if (!matchers.length) {
|
|
14389
|
-
match = str.match(/^(\S+)\s+$/);
|
|
14390
|
-
if (match) {
|
|
14391
|
-
matchers.push({ kind, quote: '"', needle: match[1] });
|
|
14392
|
-
break;
|
|
14393
|
-
}
|
|
14394
|
-
}
|
|
14395
|
-
throw new Error(`Build pragma '${comment.value}' is invalid. In ${comment.loc.source}:${comment.loc.start.line}`);
|
|
14396
|
-
}
|
|
14397
|
-
};
|
|
14398
|
-
const matcher = (quote, needle, haystack) => {
|
|
14399
|
-
if (quote == '"') {
|
|
14400
|
-
return haystack.includes(needle);
|
|
14401
|
-
}
|
|
14402
|
-
const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
|
|
14403
|
-
return re.test(haystack);
|
|
14404
|
-
};
|
|
14405
|
-
next();
|
|
14406
|
-
traverseAst(ast, (node) => {
|
|
14407
|
-
if (index >= comments.length)
|
|
14408
|
-
return false;
|
|
14409
|
-
if (node.start && node.start >= (comment.end || Infinity)) {
|
|
14410
|
-
const { kind, quote, needle } = matchers.shift();
|
|
14411
|
-
if (kind === "match") {
|
|
14412
|
-
const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " ");
|
|
14413
|
-
if (!matcher(quote, needle, haystack)) {
|
|
14414
|
-
matcher(quote, needle, haystack);
|
|
14415
|
-
throw new Error(`Didn't find '${needle}' in '${haystack}' at ${comment.loc.source}:${comment.loc.start.line}`);
|
|
14416
|
-
}
|
|
14417
|
-
}
|
|
14418
|
-
else if (kind === "expect") {
|
|
14419
|
-
const locCmp = (a, b) => {
|
|
14420
|
-
if (!b)
|
|
14421
|
-
return -1;
|
|
14422
|
-
if (a.start.line < b.start.line)
|
|
14423
|
-
return -1;
|
|
14424
|
-
if (a.start.line === b.start.line &&
|
|
14425
|
-
a.start.column < b.start.column) {
|
|
14426
|
-
return -1;
|
|
14427
|
-
}
|
|
14428
|
-
if (a.end.line > b.end.line)
|
|
14429
|
-
return 1;
|
|
14430
|
-
if (a.end.line === b.end.line && a.end.column >= b.end.column) {
|
|
14431
|
-
return 1;
|
|
14432
|
-
}
|
|
14433
|
-
return 0;
|
|
14434
|
-
};
|
|
14435
|
-
let found = false;
|
|
14436
|
-
if (diagnostics) {
|
|
14437
|
-
while (true) {
|
|
14438
|
-
if (diagIndex >= diagnostics.length) {
|
|
14439
|
-
diagnostics = null;
|
|
14440
|
-
break;
|
|
14441
|
-
}
|
|
14442
|
-
const diag = diagnostics[diagIndex];
|
|
14443
|
-
const cmp = locCmp(diag.loc, node.loc);
|
|
14444
|
-
if (cmp > 0) {
|
|
14445
|
-
break;
|
|
14446
|
-
}
|
|
14447
|
-
diagIndex++;
|
|
14448
|
-
if (cmp < 0)
|
|
14449
|
-
continue;
|
|
14450
|
-
if (matcher(quote, needle, diag.message)) {
|
|
14451
|
-
found = true;
|
|
14452
|
-
diag.type = "INFO";
|
|
14453
|
-
}
|
|
14454
|
-
}
|
|
14455
|
-
}
|
|
14456
|
-
if (!found) {
|
|
14457
|
-
throw new Error(`Missing error message '${needle} at ${comment.loc.source}:${comment.loc.start.line}`);
|
|
14458
|
-
}
|
|
14459
|
-
}
|
|
14460
|
-
if (matchers.length) {
|
|
14461
|
-
// if we're checking a series of nodes, we need
|
|
14462
|
-
// to skip over this one.
|
|
14463
|
-
return false;
|
|
14464
|
-
}
|
|
14465
|
-
next();
|
|
14466
|
-
}
|
|
14467
|
-
return null;
|
|
14468
|
-
});
|
|
14469
|
-
}
|
|
14470
|
-
|
|
14471
15028
|
;// CONCATENATED MODULE: ./src/optimizer.ts
|
|
14472
15029
|
|
|
14473
15030
|
|
|
@@ -14905,22 +15462,19 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
|
|
|
14905
15462
|
// the oldest optimized file, we don't need to regenerate
|
|
14906
15463
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
14907
15464
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
14908
|
-
if (source_time < opt_time &&
|
|
15465
|
+
if (source_time < opt_time && 1657744666168 < opt_time) {
|
|
14909
15466
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
14910
15467
|
}
|
|
14911
15468
|
}
|
|
14912
15469
|
await promises_namespaceObject.rm(output, { recursive: true, force: true });
|
|
14913
15470
|
await promises_namespaceObject.mkdir(output, { recursive: true });
|
|
14914
15471
|
const diagnostics = await optimizeMonkeyC(fnMap, Object.keys(buildConfig.barrelMap || {}), config);
|
|
14915
|
-
return Promise.all(Object.
|
|
15472
|
+
return Promise.all(Object.values(fnMap).map(async (info) => {
|
|
14916
15473
|
const name = info.output;
|
|
14917
15474
|
const dir = external_path_.dirname(name);
|
|
14918
15475
|
await promises_namespaceObject.mkdir(dir, { recursive: true });
|
|
14919
15476
|
const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
|
|
14920
15477
|
await promises_namespaceObject.writeFile(name, opt_source);
|
|
14921
|
-
if (config.checkBuildPragmas) {
|
|
14922
|
-
pragmaChecker(info.ast, diagnostics?.[inFile]);
|
|
14923
|
-
}
|
|
14924
15478
|
return info.hasTests;
|
|
14925
15479
|
})).then((results) => {
|
|
14926
15480
|
const hasTests = results.some((v) => v);
|