@markw65/monkeyc-optimizer 1.0.37 → 1.0.38
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 +12 -0
- package/build/api.cjs +142 -17
- package/build/optimizer.cjs +144 -19
- package/build/src/inliner.d.ts +2 -1
- package/build/src/variable-renamer.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -420,3 +420,15 @@ Bug Fixes
|
|
|
420
420
|
- Update to [@markw65/prettier-plugin-monkeyc@1.0.35](https://github.com/markw65/prettier-plugin-monkeyc#1035).
|
|
421
421
|
- Fixes [prettier-plugin-monkeyc#1](https://github.com/markw65/prettier-plugin-monkeyc/issues/1)
|
|
422
422
|
- Fixes [monkeyc-optimizer#1](https://github.com/markw65/monkeyc-optimizer/issues/1)
|
|
423
|
+
|
|
424
|
+
### 1.0.37
|
|
425
|
+
|
|
426
|
+
- Update the testing framework to launch the simulator before each test run, rather than start it once at the beginning. This is because the latest beta crashes after successfully completing.
|
|
427
|
+
- Update launchSimulator to check if the simulator is already running. This avoids lots of screen switching when the simulator is running on a separate desktop.
|
|
428
|
+
- Add optimizerVersion and extensionVersion to build-info.json.
|
|
429
|
+
|
|
430
|
+
### 1.0.38
|
|
431
|
+
|
|
432
|
+
- Allow inlining the argument to an if-statement, with the same constraints as inlining in assignment context
|
|
433
|
+
- Expand `assignment`, `declaration` and `if` contexts to include (recursively) the left operand of any binary operator, the operand of any unary operator, the `test` operand of any conditional operator or the `object` of a member-expression. So now it will inline `inlinableFunction` in:
|
|
434
|
+
- `var x = !((inlinableFunction() + 4) == 42 ? foo() : bar());`
|
package/build/api.cjs
CHANGED
|
@@ -655,8 +655,13 @@ function function_info_findCalleesForNew(lookupDefs) {
|
|
|
655
655
|
|
|
656
656
|
function variable_renamer_renameVariable(state, locals, declName) {
|
|
657
657
|
const map = locals.map;
|
|
658
|
-
if (
|
|
659
|
-
|
|
658
|
+
if (declName) {
|
|
659
|
+
if (!hasProperty(map, declName))
|
|
660
|
+
return null;
|
|
661
|
+
}
|
|
662
|
+
else {
|
|
663
|
+
declName = "tmp";
|
|
664
|
+
}
|
|
660
665
|
let suffix = 0;
|
|
661
666
|
let node_name = declName;
|
|
662
667
|
const match = node_name.match(/^pmcr_(.*)_(\d+)$/);
|
|
@@ -711,6 +716,69 @@ function variable_renamer_renameVariable(state, locals, declName) {
|
|
|
711
716
|
|
|
712
717
|
|
|
713
718
|
|
|
719
|
+
// Note: Keep in sync with replaceInlinedSubExpression below
|
|
720
|
+
function inliner_inlinableSubExpression(expr) {
|
|
721
|
+
while (true) {
|
|
722
|
+
if (expr.type === "BinaryExpression" || expr.type === "LogicalExpression") {
|
|
723
|
+
expr = expr.left;
|
|
724
|
+
}
|
|
725
|
+
else if (expr.type === "UnaryExpression") {
|
|
726
|
+
expr = expr.argument;
|
|
727
|
+
}
|
|
728
|
+
else if (expr.type === "ConditionalExpression") {
|
|
729
|
+
expr = expr.test;
|
|
730
|
+
}
|
|
731
|
+
else if (expr.type === "MemberExpression") {
|
|
732
|
+
expr = expr.object;
|
|
733
|
+
}
|
|
734
|
+
else if (expr.type === "CallExpression") {
|
|
735
|
+
return expr;
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
// Note: Keep in sync with inlinableSubExpression above
|
|
743
|
+
function replaceInlinedSubExpression(top, call, repl) {
|
|
744
|
+
if (top === call)
|
|
745
|
+
return repl;
|
|
746
|
+
let expr = top;
|
|
747
|
+
while (true) {
|
|
748
|
+
if (expr.type === "LogicalExpression" || expr.type === "BinaryExpression") {
|
|
749
|
+
if (expr.left === call) {
|
|
750
|
+
expr.left = repl;
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
expr = expr.left;
|
|
754
|
+
}
|
|
755
|
+
else if (expr.type === "UnaryExpression") {
|
|
756
|
+
if (expr.argument === call) {
|
|
757
|
+
expr.argument = repl;
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
expr = expr.argument;
|
|
761
|
+
}
|
|
762
|
+
else if (expr.type === "ConditionalExpression") {
|
|
763
|
+
if (expr.test === call) {
|
|
764
|
+
expr.test = repl;
|
|
765
|
+
break;
|
|
766
|
+
}
|
|
767
|
+
expr = expr.test;
|
|
768
|
+
}
|
|
769
|
+
else if (expr.type === "MemberExpression") {
|
|
770
|
+
if (expr.object === call) {
|
|
771
|
+
expr.object = repl;
|
|
772
|
+
break;
|
|
773
|
+
}
|
|
774
|
+
expr = expr.object;
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
throw new Error("Internal error: Didn't find CallExpression");
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
return top;
|
|
781
|
+
}
|
|
714
782
|
function getArgSafety(state, func, args, requireAll) {
|
|
715
783
|
// determine whether decl might be changed by a function call
|
|
716
784
|
// or assignment during the evaluation of FunctionStateNode.
|
|
@@ -938,7 +1006,7 @@ function inliner_shouldInline(state, func, call, context) {
|
|
|
938
1006
|
}
|
|
939
1007
|
}
|
|
940
1008
|
if (!context && requested) {
|
|
941
|
-
inlineDiagnostic(state, func, call, "This function can only be inlined in statement, assignment, or return contexts");
|
|
1009
|
+
inlineDiagnostic(state, func, call, "This function can only be inlined in statement, assignment, if or return contexts");
|
|
942
1010
|
}
|
|
943
1011
|
return context != null;
|
|
944
1012
|
}
|
|
@@ -1198,7 +1266,8 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
1198
1266
|
inlineDiagnostic(state, func, call, "Function had more than one return statement");
|
|
1199
1267
|
}
|
|
1200
1268
|
else if ((context.type === "AssignmentExpression" ||
|
|
1201
|
-
context.type === "VariableDeclarator"
|
|
1269
|
+
context.type === "VariableDeclarator" ||
|
|
1270
|
+
context.type === "IfStatement") &&
|
|
1202
1271
|
retStmtCount !== 1) {
|
|
1203
1272
|
inlineDiagnostic(state, func, call, "Function did not have a return statement");
|
|
1204
1273
|
return null;
|
|
@@ -1208,7 +1277,8 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
1208
1277
|
if (!last ||
|
|
1209
1278
|
last.type !== "ReturnStatement" ||
|
|
1210
1279
|
((context.type === "AssignmentExpression" ||
|
|
1211
|
-
context.type === "VariableDeclarator"
|
|
1280
|
+
context.type === "VariableDeclarator" ||
|
|
1281
|
+
context.type === "IfStatement") &&
|
|
1212
1282
|
!last.argument)) {
|
|
1213
1283
|
inlineDiagnostic(state, func, call, "There was a return statement, but not at the end of the function");
|
|
1214
1284
|
return null;
|
|
@@ -1235,14 +1305,15 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
1235
1305
|
}
|
|
1236
1306
|
if (last.argument) {
|
|
1237
1307
|
if (context.type === "AssignmentExpression") {
|
|
1238
|
-
context.right = last.argument;
|
|
1308
|
+
context.right = replaceInlinedSubExpression(context.right, call, last.argument);
|
|
1239
1309
|
block.body[block.body.length - 1] = {
|
|
1240
1310
|
type: "ExpressionStatement",
|
|
1241
1311
|
expression: context,
|
|
1242
1312
|
};
|
|
1243
1313
|
}
|
|
1244
1314
|
else if (context.type === "VariableDeclarator") {
|
|
1245
|
-
const { id, init
|
|
1315
|
+
const { id, init, kind: _kind, ...rest } = context;
|
|
1316
|
+
const right = replaceInlinedSubExpression(init, call, last.argument);
|
|
1246
1317
|
block.body[block.body.length - 1] = {
|
|
1247
1318
|
...rest,
|
|
1248
1319
|
type: "ExpressionStatement",
|
|
@@ -1251,9 +1322,52 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
1251
1322
|
type: "AssignmentExpression",
|
|
1252
1323
|
operator: "=",
|
|
1253
1324
|
left: id.type === "Identifier" ? id : id.left,
|
|
1325
|
+
right,
|
|
1326
|
+
},
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
else if (context.type === "IfStatement") {
|
|
1330
|
+
// Generate a pmcr_tmp name that doesn't conflict with anything
|
|
1331
|
+
const locals = state.localsStack[state.localsStack.length - 1];
|
|
1332
|
+
const name = renameVariable(state, locals, null);
|
|
1333
|
+
locals.map[name] = true;
|
|
1334
|
+
// Replace the inlined function's return statement
|
|
1335
|
+
// with an assignment to pmcr_tmp
|
|
1336
|
+
block.body[block.body.length - 1] = {
|
|
1337
|
+
type: "ExpressionStatement",
|
|
1338
|
+
expression: {
|
|
1339
|
+
type: "AssignmentExpression",
|
|
1340
|
+
operator: "=",
|
|
1341
|
+
left: { type: "Identifier", name },
|
|
1254
1342
|
right: last.argument,
|
|
1255
1343
|
},
|
|
1256
1344
|
};
|
|
1345
|
+
// The IfStatement either has the call as its test, or as
|
|
1346
|
+
// the leftmost argument to a series of Binary/Logical expressions
|
|
1347
|
+
// Either way, replace the call with pmcr_tmp
|
|
1348
|
+
const repl = { type: "Identifier", name };
|
|
1349
|
+
context.test = replaceInlinedSubExpression(context.test, call, repl);
|
|
1350
|
+
// Wrap the inlined body so it looks like
|
|
1351
|
+
// {
|
|
1352
|
+
// var pmcr_tmp;
|
|
1353
|
+
// { /* inlined body, with assignment to pmcr_tmp */ }
|
|
1354
|
+
// if (context) {} // original if statement
|
|
1355
|
+
// }
|
|
1356
|
+
body.body = [
|
|
1357
|
+
{
|
|
1358
|
+
type: "VariableDeclaration",
|
|
1359
|
+
kind: "var",
|
|
1360
|
+
declarations: [
|
|
1361
|
+
{
|
|
1362
|
+
type: "VariableDeclarator",
|
|
1363
|
+
kind: "var",
|
|
1364
|
+
id: { type: "Identifier", name },
|
|
1365
|
+
},
|
|
1366
|
+
],
|
|
1367
|
+
},
|
|
1368
|
+
{ type: "BlockStatement", body: body.body },
|
|
1369
|
+
context,
|
|
1370
|
+
];
|
|
1257
1371
|
}
|
|
1258
1372
|
else {
|
|
1259
1373
|
const side_exprs = inliner_unused(last.argument);
|
|
@@ -1427,7 +1541,7 @@ function pragma_checker_pragmaChecker(state, ast, diagnostics) {
|
|
|
1427
1541
|
if (quote == '"') {
|
|
1428
1542
|
return haystack.includes(needle);
|
|
1429
1543
|
}
|
|
1430
|
-
const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
|
|
1544
|
+
const re = new RegExp(needle.replace(/@([\d\w]+)/g, "(pre_)?$1(_\\d+)?"));
|
|
1431
1545
|
return re.test(haystack);
|
|
1432
1546
|
};
|
|
1433
1547
|
next();
|
|
@@ -4048,11 +4162,18 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
4048
4162
|
return false;
|
|
4049
4163
|
return replace(rep, rep);
|
|
4050
4164
|
}
|
|
4051
|
-
else if (node.type === "IfStatement"
|
|
4052
|
-
node.alternate &&
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4165
|
+
else if (node.type === "IfStatement") {
|
|
4166
|
+
if (node.alternate &&
|
|
4167
|
+
node.alternate.type === "BlockStatement" &&
|
|
4168
|
+
!node.alternate.body.length) {
|
|
4169
|
+
delete node.alternate;
|
|
4170
|
+
}
|
|
4171
|
+
else {
|
|
4172
|
+
const call = inlinableSubExpression(node.test);
|
|
4173
|
+
if (call) {
|
|
4174
|
+
return replace(optimizeCall(state, call, node), node.test);
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4056
4177
|
}
|
|
4057
4178
|
break;
|
|
4058
4179
|
case "WhileStatement":
|
|
@@ -4095,8 +4216,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
4095
4216
|
let j = 0;
|
|
4096
4217
|
while (i < node.declarations.length) {
|
|
4097
4218
|
const decl = declarations[i++];
|
|
4098
|
-
if (decl.init
|
|
4099
|
-
|
|
4219
|
+
if (!decl.init)
|
|
4220
|
+
continue;
|
|
4221
|
+
const call = inlinableSubExpression(decl.init);
|
|
4222
|
+
if (call) {
|
|
4223
|
+
const inlined = replace(optimizeCall(state, call, decl), decl.init);
|
|
4100
4224
|
if (!inlined)
|
|
4101
4225
|
continue;
|
|
4102
4226
|
if (Array.isArray(inlined) || inlined.type != "BlockStatement") {
|
|
@@ -4131,7 +4255,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
4131
4255
|
return replace(optimizeCall(state, node.expression, node), node.expression);
|
|
4132
4256
|
}
|
|
4133
4257
|
else if (node.expression.type === "AssignmentExpression") {
|
|
4134
|
-
|
|
4258
|
+
const call = inlinableSubExpression(node.expression.right);
|
|
4259
|
+
if (call) {
|
|
4135
4260
|
let ok = false;
|
|
4136
4261
|
if (node.expression.left.type === "Identifier") {
|
|
4137
4262
|
if (hasProperty(topLocals().map, node.expression.left.type)) {
|
|
@@ -4143,7 +4268,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
4143
4268
|
ok = !!result;
|
|
4144
4269
|
}
|
|
4145
4270
|
if (ok) {
|
|
4146
|
-
return replace(optimizeCall(state,
|
|
4271
|
+
return replace(optimizeCall(state, call, node.expression), node.expression.right);
|
|
4147
4272
|
}
|
|
4148
4273
|
}
|
|
4149
4274
|
}
|
package/build/optimizer.cjs
CHANGED
|
@@ -11370,8 +11370,13 @@ function findCalleesForNew(lookupDefs) {
|
|
|
11370
11370
|
|
|
11371
11371
|
function renameVariable(state, locals, declName) {
|
|
11372
11372
|
const map = locals.map;
|
|
11373
|
-
if (
|
|
11374
|
-
|
|
11373
|
+
if (declName) {
|
|
11374
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(map, declName))
|
|
11375
|
+
return null;
|
|
11376
|
+
}
|
|
11377
|
+
else {
|
|
11378
|
+
declName = "tmp";
|
|
11379
|
+
}
|
|
11375
11380
|
let suffix = 0;
|
|
11376
11381
|
let node_name = declName;
|
|
11377
11382
|
const match = node_name.match(/^pmcr_(.*)_(\d+)$/);
|
|
@@ -11426,6 +11431,69 @@ function renameVariable(state, locals, declName) {
|
|
|
11426
11431
|
|
|
11427
11432
|
|
|
11428
11433
|
|
|
11434
|
+
// Note: Keep in sync with replaceInlinedSubExpression below
|
|
11435
|
+
function inlinableSubExpression(expr) {
|
|
11436
|
+
while (true) {
|
|
11437
|
+
if (expr.type === "BinaryExpression" || expr.type === "LogicalExpression") {
|
|
11438
|
+
expr = expr.left;
|
|
11439
|
+
}
|
|
11440
|
+
else if (expr.type === "UnaryExpression") {
|
|
11441
|
+
expr = expr.argument;
|
|
11442
|
+
}
|
|
11443
|
+
else if (expr.type === "ConditionalExpression") {
|
|
11444
|
+
expr = expr.test;
|
|
11445
|
+
}
|
|
11446
|
+
else if (expr.type === "MemberExpression") {
|
|
11447
|
+
expr = expr.object;
|
|
11448
|
+
}
|
|
11449
|
+
else if (expr.type === "CallExpression") {
|
|
11450
|
+
return expr;
|
|
11451
|
+
}
|
|
11452
|
+
else {
|
|
11453
|
+
return null;
|
|
11454
|
+
}
|
|
11455
|
+
}
|
|
11456
|
+
}
|
|
11457
|
+
// Note: Keep in sync with inlinableSubExpression above
|
|
11458
|
+
function replaceInlinedSubExpression(top, call, repl) {
|
|
11459
|
+
if (top === call)
|
|
11460
|
+
return repl;
|
|
11461
|
+
let expr = top;
|
|
11462
|
+
while (true) {
|
|
11463
|
+
if (expr.type === "LogicalExpression" || expr.type === "BinaryExpression") {
|
|
11464
|
+
if (expr.left === call) {
|
|
11465
|
+
expr.left = repl;
|
|
11466
|
+
break;
|
|
11467
|
+
}
|
|
11468
|
+
expr = expr.left;
|
|
11469
|
+
}
|
|
11470
|
+
else if (expr.type === "UnaryExpression") {
|
|
11471
|
+
if (expr.argument === call) {
|
|
11472
|
+
expr.argument = repl;
|
|
11473
|
+
break;
|
|
11474
|
+
}
|
|
11475
|
+
expr = expr.argument;
|
|
11476
|
+
}
|
|
11477
|
+
else if (expr.type === "ConditionalExpression") {
|
|
11478
|
+
if (expr.test === call) {
|
|
11479
|
+
expr.test = repl;
|
|
11480
|
+
break;
|
|
11481
|
+
}
|
|
11482
|
+
expr = expr.test;
|
|
11483
|
+
}
|
|
11484
|
+
else if (expr.type === "MemberExpression") {
|
|
11485
|
+
if (expr.object === call) {
|
|
11486
|
+
expr.object = repl;
|
|
11487
|
+
break;
|
|
11488
|
+
}
|
|
11489
|
+
expr = expr.object;
|
|
11490
|
+
}
|
|
11491
|
+
else {
|
|
11492
|
+
throw new Error("Internal error: Didn't find CallExpression");
|
|
11493
|
+
}
|
|
11494
|
+
}
|
|
11495
|
+
return top;
|
|
11496
|
+
}
|
|
11429
11497
|
function getArgSafety(state, func, args, requireAll) {
|
|
11430
11498
|
// determine whether decl might be changed by a function call
|
|
11431
11499
|
// or assignment during the evaluation of FunctionStateNode.
|
|
@@ -11653,7 +11721,7 @@ function shouldInline(state, func, call, context) {
|
|
|
11653
11721
|
}
|
|
11654
11722
|
}
|
|
11655
11723
|
if (!context && requested) {
|
|
11656
|
-
inlineDiagnostic(state, func, call, "This function can only be inlined in statement, assignment, or return contexts");
|
|
11724
|
+
inlineDiagnostic(state, func, call, "This function can only be inlined in statement, assignment, if or return contexts");
|
|
11657
11725
|
}
|
|
11658
11726
|
return context != null;
|
|
11659
11727
|
}
|
|
@@ -11913,7 +11981,8 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11913
11981
|
inlineDiagnostic(state, func, call, "Function had more than one return statement");
|
|
11914
11982
|
}
|
|
11915
11983
|
else if ((context.type === "AssignmentExpression" ||
|
|
11916
|
-
context.type === "VariableDeclarator"
|
|
11984
|
+
context.type === "VariableDeclarator" ||
|
|
11985
|
+
context.type === "IfStatement") &&
|
|
11917
11986
|
retStmtCount !== 1) {
|
|
11918
11987
|
inlineDiagnostic(state, func, call, "Function did not have a return statement");
|
|
11919
11988
|
return null;
|
|
@@ -11923,7 +11992,8 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11923
11992
|
if (!last ||
|
|
11924
11993
|
last.type !== "ReturnStatement" ||
|
|
11925
11994
|
((context.type === "AssignmentExpression" ||
|
|
11926
|
-
context.type === "VariableDeclarator"
|
|
11995
|
+
context.type === "VariableDeclarator" ||
|
|
11996
|
+
context.type === "IfStatement") &&
|
|
11927
11997
|
!last.argument)) {
|
|
11928
11998
|
inlineDiagnostic(state, func, call, "There was a return statement, but not at the end of the function");
|
|
11929
11999
|
return null;
|
|
@@ -11950,14 +12020,15 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11950
12020
|
}
|
|
11951
12021
|
if (last.argument) {
|
|
11952
12022
|
if (context.type === "AssignmentExpression") {
|
|
11953
|
-
context.right = last.argument;
|
|
12023
|
+
context.right = replaceInlinedSubExpression(context.right, call, last.argument);
|
|
11954
12024
|
block.body[block.body.length - 1] = {
|
|
11955
12025
|
type: "ExpressionStatement",
|
|
11956
12026
|
expression: context,
|
|
11957
12027
|
};
|
|
11958
12028
|
}
|
|
11959
12029
|
else if (context.type === "VariableDeclarator") {
|
|
11960
|
-
const { id, init
|
|
12030
|
+
const { id, init, kind: _kind, ...rest } = context;
|
|
12031
|
+
const right = replaceInlinedSubExpression(init, call, last.argument);
|
|
11961
12032
|
block.body[block.body.length - 1] = {
|
|
11962
12033
|
...rest,
|
|
11963
12034
|
type: "ExpressionStatement",
|
|
@@ -11966,9 +12037,52 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
11966
12037
|
type: "AssignmentExpression",
|
|
11967
12038
|
operator: "=",
|
|
11968
12039
|
left: id.type === "Identifier" ? id : id.left,
|
|
12040
|
+
right,
|
|
12041
|
+
},
|
|
12042
|
+
};
|
|
12043
|
+
}
|
|
12044
|
+
else if (context.type === "IfStatement") {
|
|
12045
|
+
// Generate a pmcr_tmp name that doesn't conflict with anything
|
|
12046
|
+
const locals = state.localsStack[state.localsStack.length - 1];
|
|
12047
|
+
const name = renameVariable(state, locals, null);
|
|
12048
|
+
locals.map[name] = true;
|
|
12049
|
+
// Replace the inlined function's return statement
|
|
12050
|
+
// with an assignment to pmcr_tmp
|
|
12051
|
+
block.body[block.body.length - 1] = {
|
|
12052
|
+
type: "ExpressionStatement",
|
|
12053
|
+
expression: {
|
|
12054
|
+
type: "AssignmentExpression",
|
|
12055
|
+
operator: "=",
|
|
12056
|
+
left: { type: "Identifier", name },
|
|
11969
12057
|
right: last.argument,
|
|
11970
12058
|
},
|
|
11971
12059
|
};
|
|
12060
|
+
// The IfStatement either has the call as its test, or as
|
|
12061
|
+
// the leftmost argument to a series of Binary/Logical expressions
|
|
12062
|
+
// Either way, replace the call with pmcr_tmp
|
|
12063
|
+
const repl = { type: "Identifier", name };
|
|
12064
|
+
context.test = replaceInlinedSubExpression(context.test, call, repl);
|
|
12065
|
+
// Wrap the inlined body so it looks like
|
|
12066
|
+
// {
|
|
12067
|
+
// var pmcr_tmp;
|
|
12068
|
+
// { /* inlined body, with assignment to pmcr_tmp */ }
|
|
12069
|
+
// if (context) {} // original if statement
|
|
12070
|
+
// }
|
|
12071
|
+
body.body = [
|
|
12072
|
+
{
|
|
12073
|
+
type: "VariableDeclaration",
|
|
12074
|
+
kind: "var",
|
|
12075
|
+
declarations: [
|
|
12076
|
+
{
|
|
12077
|
+
type: "VariableDeclarator",
|
|
12078
|
+
kind: "var",
|
|
12079
|
+
id: { type: "Identifier", name },
|
|
12080
|
+
},
|
|
12081
|
+
],
|
|
12082
|
+
},
|
|
12083
|
+
{ type: "BlockStatement", body: body.body },
|
|
12084
|
+
context,
|
|
12085
|
+
];
|
|
11972
12086
|
}
|
|
11973
12087
|
else {
|
|
11974
12088
|
const side_exprs = unused(last.argument);
|
|
@@ -12142,7 +12256,7 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
12142
12256
|
if (quote == '"') {
|
|
12143
12257
|
return haystack.includes(needle);
|
|
12144
12258
|
}
|
|
12145
|
-
const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
|
|
12259
|
+
const re = new RegExp(needle.replace(/@([\d\w]+)/g, "(pre_)?$1(_\\d+)?"));
|
|
12146
12260
|
return re.test(haystack);
|
|
12147
12261
|
};
|
|
12148
12262
|
next();
|
|
@@ -14760,11 +14874,18 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14760
14874
|
return false;
|
|
14761
14875
|
return replace(rep, rep);
|
|
14762
14876
|
}
|
|
14763
|
-
else if (node.type === "IfStatement"
|
|
14764
|
-
node.alternate &&
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14877
|
+
else if (node.type === "IfStatement") {
|
|
14878
|
+
if (node.alternate &&
|
|
14879
|
+
node.alternate.type === "BlockStatement" &&
|
|
14880
|
+
!node.alternate.body.length) {
|
|
14881
|
+
delete node.alternate;
|
|
14882
|
+
}
|
|
14883
|
+
else {
|
|
14884
|
+
const call = inlinableSubExpression(node.test);
|
|
14885
|
+
if (call) {
|
|
14886
|
+
return replace(optimizeCall(state, call, node), node.test);
|
|
14887
|
+
}
|
|
14888
|
+
}
|
|
14768
14889
|
}
|
|
14769
14890
|
break;
|
|
14770
14891
|
case "WhileStatement":
|
|
@@ -14807,8 +14928,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14807
14928
|
let j = 0;
|
|
14808
14929
|
while (i < node.declarations.length) {
|
|
14809
14930
|
const decl = declarations[i++];
|
|
14810
|
-
if (decl.init
|
|
14811
|
-
|
|
14931
|
+
if (!decl.init)
|
|
14932
|
+
continue;
|
|
14933
|
+
const call = inlinableSubExpression(decl.init);
|
|
14934
|
+
if (call) {
|
|
14935
|
+
const inlined = replace(optimizeCall(state, call, decl), decl.init);
|
|
14812
14936
|
if (!inlined)
|
|
14813
14937
|
continue;
|
|
14814
14938
|
if (Array.isArray(inlined) || inlined.type != "BlockStatement") {
|
|
@@ -14843,7 +14967,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14843
14967
|
return replace(optimizeCall(state, node.expression, node), node.expression);
|
|
14844
14968
|
}
|
|
14845
14969
|
else if (node.expression.type === "AssignmentExpression") {
|
|
14846
|
-
|
|
14970
|
+
const call = inlinableSubExpression(node.expression.right);
|
|
14971
|
+
if (call) {
|
|
14847
14972
|
let ok = false;
|
|
14848
14973
|
if (node.expression.left.type === "Identifier") {
|
|
14849
14974
|
if ((0,external_api_cjs_namespaceObject.hasProperty)(topLocals().map, node.expression.left.type)) {
|
|
@@ -14855,7 +14980,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
|
14855
14980
|
ok = !!result;
|
|
14856
14981
|
}
|
|
14857
14982
|
if (ok) {
|
|
14858
|
-
return replace(optimizeCall(state,
|
|
14983
|
+
return replace(optimizeCall(state, call, node.expression), node.expression.right);
|
|
14859
14984
|
}
|
|
14860
14985
|
}
|
|
14861
14986
|
}
|
|
@@ -15509,7 +15634,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
|
|
|
15509
15634
|
// the oldest optimized file, we don't need to regenerate
|
|
15510
15635
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
15511
15636
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
15512
|
-
if (source_time < opt_time &&
|
|
15637
|
+
if (source_time < opt_time && 1666827670006 < opt_time) {
|
|
15513
15638
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
15514
15639
|
}
|
|
15515
15640
|
}
|
|
@@ -15534,7 +15659,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
|
|
|
15534
15659
|
return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
|
|
15535
15660
|
hasTests,
|
|
15536
15661
|
diagnostics,
|
|
15537
|
-
optimizerVersion: "1.0.
|
|
15662
|
+
optimizerVersion: "1.0.38",
|
|
15538
15663
|
...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
|
|
15539
15664
|
}))
|
|
15540
15665
|
.then(() => ({ hasTests, diagnostics }));
|
package/build/src/inliner.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { mctree } from "@markw65/prettier-plugin-monkeyc";
|
|
2
2
|
import { FunctionStateNode, ProgramStateAnalysis, ProgramStateLive } from "./optimizer-types";
|
|
3
|
+
export declare function inlinableSubExpression(expr: mctree.Expression): mctree.SimpleCallExpression | null;
|
|
3
4
|
export declare function shouldInline(state: ProgramStateAnalysis, func: FunctionStateNode, call: mctree.CallExpression, context: InlineContext | null): boolean;
|
|
4
5
|
declare type InlineBody = mctree.BlockStatement | mctree.ExpressionStatement["expression"];
|
|
5
6
|
export declare function unused(expression: mctree.ExpressionStatement["expression"]): mctree.Statement[];
|
|
6
7
|
export declare function unused(expression: mctree.ExpressionStatement["expression"], top: true): mctree.Statement[] | null;
|
|
7
8
|
export declare function diagnostic(state: ProgramStateLive, loc: mctree.Node["loc"], message: string | null, type?: NonNullable<ProgramStateAnalysis["diagnostics"]>[string][number]["type"]): void;
|
|
8
|
-
export declare type InlineContext = mctree.ReturnStatement | mctree.AssignmentExpression | mctree.ExpressionStatement | mctree.VariableDeclarator;
|
|
9
|
+
export declare type InlineContext = mctree.ReturnStatement | mctree.IfStatement | mctree.AssignmentExpression | mctree.ExpressionStatement | mctree.VariableDeclarator;
|
|
9
10
|
export declare function inlineFunction(state: ProgramStateAnalysis, func: FunctionStateNode, call: mctree.CallExpression, context: InlineContext | null): InlineBody | null;
|
|
10
11
|
export declare function applyTypeIfNeeded(node: mctree.Node): mctree.Node;
|
|
11
12
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ProgramStateAnalysis } from "./optimizer-types";
|
|
2
|
-
export declare function renameVariable(state: ProgramStateAnalysis, locals: NonNullable<ProgramStateAnalysis["localsStack"]>[number], declName: string): string | null;
|
|
2
|
+
export declare function renameVariable(state: ProgramStateAnalysis, locals: NonNullable<ProgramStateAnalysis["localsStack"]>[number], declName: string | null): string | null;
|
package/package.json
CHANGED