@markw65/monkeyc-optimizer 1.0.25 → 1.0.26

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 CHANGED
@@ -285,3 +285,10 @@ More fixes found via open source projects.
285
285
 
286
286
  - Bug fix
287
287
  - estree-types was missing the returnType on FunctionDeclaration. Update to latest prettier-plugin, and fix ast.ts.
288
+
289
+ ### 1.0.26
290
+
291
+ - Bug fixes
292
+ - Use `self.` rather than `ClassName.` to qualify names that would otherwise collide with locals, since that works with both public and private variables
293
+ - Fix a bug that caused the inliner to fail to qualify certain names, even if there was a collision with an existing local variables
294
+ - Fix some name lookup issues relating to whether the lookup is done as a type or a value.
package/build/api.cjs CHANGED
@@ -441,11 +441,28 @@ function inliner_shouldInline(state, func, call, context) {
441
441
  }
442
442
  return false;
443
443
  }
444
- function processInlineBody(state, func, call, root, insertedVariableDecls, params) {
444
+ // We still need to keep track of every local name that was
445
+ // already in use before we started inlining, but we don't want to
446
+ // use any of its renames. We also want to know whether a local is
447
+ // from the function being inlined, or the calling function, so
448
+ // set every element to false.
449
+ function fixupLocalsMap(state) {
450
+ if (!state.localsStack)
451
+ throw new Error("No local variable map!");
452
+ const locals = state.localsStack[state.localsStack.length - 1];
453
+ const { map } = locals;
454
+ if (!map)
455
+ throw new Error("No local variable map!");
456
+ const original = { ...map };
457
+ Object.keys(map).forEach((key) => (map[key] = false));
458
+ return original;
459
+ }
460
+ function processInlineBody(state, func, call, root, params) {
445
461
  let failed = false;
446
462
  const pre = state.pre;
447
463
  const post = state.post;
448
464
  state.inlining = true;
465
+ let insertedVariableDecls = null;
449
466
  try {
450
467
  state.pre = (node) => {
451
468
  if (failed)
@@ -457,15 +474,10 @@ function processInlineBody(state, func, call, root, insertedVariableDecls, param
457
474
  return false;
458
475
  const result = pre(node, state);
459
476
  if (!insertedVariableDecls && node.type === "BlockStatement") {
477
+ // the block just created a new locals map, so we don't
478
+ // need to restore it at the end.
479
+ fixupLocalsMap(state);
460
480
  const locals = state.localsStack[state.localsStack.length - 1];
461
- const { map } = locals;
462
- if (!map)
463
- throw new Error("No local variable map!");
464
- // We still need to keep track of every local name that was
465
- // already in use, but we don't want to use any of its renames.
466
- // We also want to know whether a local is from the function being
467
- // inlined, or the calling function, so set every element to false.
468
- Object.keys(map).forEach((key) => (map[key] = false));
469
481
  const declarations = func.node.params
470
482
  .map((param, i) => {
471
483
  const paramName = variableDeclarationName(param);
@@ -542,6 +554,8 @@ function inliner_unused(expression, top) {
542
554
  return [];
543
555
  case "Identifier":
544
556
  return [];
557
+ case "ThisExpression":
558
+ return [];
545
559
  case "BinaryExpression":
546
560
  if (expression.operator === "as") {
547
561
  return inliner_unused(expression.left);
@@ -644,7 +658,7 @@ function inlineWithArgs(state, func, call, context) {
644
658
  const name = variableDeclarationName(param);
645
659
  return [name, argnum];
646
660
  }));
647
- if (!processInlineBody(state, func, call, body, func.node.params.length ? false : true, params)) {
661
+ if (!processInlineBody(state, func, call, body, params)) {
648
662
  return null;
649
663
  }
650
664
  inliner_diagnostic(state, call.loc, null);
@@ -676,7 +690,10 @@ function inliner_inlineFunction(state, func, call, context) {
676
690
  }
677
691
  const retArg = JSON.parse(JSON.stringify(func.node.body.body[0].argument));
678
692
  const params = Object.fromEntries(func.node.params.map((param, i) => [variableDeclarationName(param), i]));
679
- return processInlineBody(state, func, call, retArg, true, params);
693
+ const map = fixupLocalsMap(state);
694
+ const ret = processInlineBody(state, func, call, retArg, params);
695
+ state.localsStack[state.localsStack.length - 1].map = map;
696
+ return ret;
680
697
  }
681
698
  function applyTypeIfNeeded(node) {
682
699
  if ("enumType" in node && node.enumType) {
@@ -729,6 +746,15 @@ function fixNodeScope(state, lookupNode, nodeStack) {
729
746
  return "";
730
747
  }))
731
748
  .flat();
749
+ const member = (object, property) => ({
750
+ type: "MemberExpression",
751
+ object,
752
+ property,
753
+ computed: false,
754
+ start: node.start,
755
+ end: node.end,
756
+ loc: node.loc,
757
+ });
732
758
  if (prefixes.length &&
733
759
  prefixes[0].startsWith("$.") &&
734
760
  prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
@@ -742,38 +768,32 @@ function fixNodeScope(state, lookupNode, nodeStack) {
742
768
  found = true;
743
769
  return current;
744
770
  }
745
- const object = typeof name === "string"
746
- ? {
747
- type: "Identifier",
748
- name,
749
- start: node.start,
750
- end: node.end,
751
- loc: node.loc,
752
- }
753
- : name;
754
- let root = null;
755
- let property = current;
756
- while (property.type !== "Identifier") {
757
- root = property;
758
- property = property.object;
759
- }
760
- const mb = {
761
- type: "MemberExpression",
762
- object,
763
- property,
764
- computed: false,
771
+ const object = {
772
+ type: "Identifier",
773
+ name,
765
774
  start: node.start,
766
775
  end: node.end,
767
776
  loc: node.loc,
768
777
  };
769
- if (root) {
770
- root.object = mb;
771
- }
772
- else {
773
- current = mb;
778
+ let root = null;
779
+ let property = current;
780
+ do {
781
+ root = property;
782
+ property = property.object;
783
+ } while (property.type === "MemberExpression");
784
+ if (property.type === "ThisExpression") {
785
+ root.object = object;
786
+ return root;
774
787
  }
788
+ root.object = member(object, property);
775
789
  return current;
776
- }, node);
790
+ }, member({
791
+ type: "ThisExpression",
792
+ text: "self",
793
+ start: node.start,
794
+ end: node.end,
795
+ loc: node.loc,
796
+ }, node));
777
797
  }
778
798
  return null;
779
799
  }
@@ -2213,6 +2233,7 @@ function api_collectNamespaces(ast, stateIn) {
2213
2233
  state.stack[0].node = node;
2214
2234
  break;
2215
2235
  case "TypeSpecList":
2236
+ case "TypeSpecPart":
2216
2237
  state.inType = true;
2217
2238
  break;
2218
2239
  case "ImportModule":
@@ -2454,6 +2475,11 @@ function api_collectNamespaces(ast, stateIn) {
2454
2475
  if (state.post)
2455
2476
  ret = state.post(node, state);
2456
2477
  switch (type) {
2478
+ // Don't clear inType for TypeSpecPart, since they
2479
+ // generally occur in TypeSpecLists. But do clear it for
2480
+ // SizedArrayExpression, since thats the only place they
2481
+ // happen on their own.
2482
+ case "SizedArrayExpression":
2457
2483
  case "TypeSpecList":
2458
2484
  case "TypedefDeclaration":
2459
2485
  case "EnumDeclaration":
@@ -11165,11 +11165,28 @@ function shouldInline(state, func, call, context) {
11165
11165
  }
11166
11166
  return false;
11167
11167
  }
11168
- function processInlineBody(state, func, call, root, insertedVariableDecls, params) {
11168
+ // We still need to keep track of every local name that was
11169
+ // already in use before we started inlining, but we don't want to
11170
+ // use any of its renames. We also want to know whether a local is
11171
+ // from the function being inlined, or the calling function, so
11172
+ // set every element to false.
11173
+ function fixupLocalsMap(state) {
11174
+ if (!state.localsStack)
11175
+ throw new Error("No local variable map!");
11176
+ const locals = state.localsStack[state.localsStack.length - 1];
11177
+ const { map } = locals;
11178
+ if (!map)
11179
+ throw new Error("No local variable map!");
11180
+ const original = { ...map };
11181
+ Object.keys(map).forEach((key) => (map[key] = false));
11182
+ return original;
11183
+ }
11184
+ function processInlineBody(state, func, call, root, params) {
11169
11185
  let failed = false;
11170
11186
  const pre = state.pre;
11171
11187
  const post = state.post;
11172
11188
  state.inlining = true;
11189
+ let insertedVariableDecls = null;
11173
11190
  try {
11174
11191
  state.pre = (node) => {
11175
11192
  if (failed)
@@ -11181,15 +11198,10 @@ function processInlineBody(state, func, call, root, insertedVariableDecls, param
11181
11198
  return false;
11182
11199
  const result = pre(node, state);
11183
11200
  if (!insertedVariableDecls && node.type === "BlockStatement") {
11201
+ // the block just created a new locals map, so we don't
11202
+ // need to restore it at the end.
11203
+ fixupLocalsMap(state);
11184
11204
  const locals = state.localsStack[state.localsStack.length - 1];
11185
- const { map } = locals;
11186
- if (!map)
11187
- throw new Error("No local variable map!");
11188
- // We still need to keep track of every local name that was
11189
- // already in use, but we don't want to use any of its renames.
11190
- // We also want to know whether a local is from the function being
11191
- // inlined, or the calling function, so set every element to false.
11192
- Object.keys(map).forEach((key) => (map[key] = false));
11193
11205
  const declarations = func.node.params
11194
11206
  .map((param, i) => {
11195
11207
  const paramName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(param);
@@ -11266,6 +11278,8 @@ function unused(expression, top) {
11266
11278
  return [];
11267
11279
  case "Identifier":
11268
11280
  return [];
11281
+ case "ThisExpression":
11282
+ return [];
11269
11283
  case "BinaryExpression":
11270
11284
  if (expression.operator === "as") {
11271
11285
  return unused(expression.left);
@@ -11368,7 +11382,7 @@ function inlineWithArgs(state, func, call, context) {
11368
11382
  const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(param);
11369
11383
  return [name, argnum];
11370
11384
  }));
11371
- if (!processInlineBody(state, func, call, body, func.node.params.length ? false : true, params)) {
11385
+ if (!processInlineBody(state, func, call, body, params)) {
11372
11386
  return null;
11373
11387
  }
11374
11388
  diagnostic(state, call.loc, null);
@@ -11400,7 +11414,10 @@ function inlineFunction(state, func, call, context) {
11400
11414
  }
11401
11415
  const retArg = JSON.parse(JSON.stringify(func.node.body.body[0].argument));
11402
11416
  const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
11403
- return processInlineBody(state, func, call, retArg, true, params);
11417
+ const map = fixupLocalsMap(state);
11418
+ const ret = processInlineBody(state, func, call, retArg, params);
11419
+ state.localsStack[state.localsStack.length - 1].map = map;
11420
+ return ret;
11404
11421
  }
11405
11422
  function applyTypeIfNeeded(node) {
11406
11423
  if ("enumType" in node && node.enumType) {
@@ -11453,6 +11470,15 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11453
11470
  return "";
11454
11471
  }))
11455
11472
  .flat();
11473
+ const member = (object, property) => ({
11474
+ type: "MemberExpression",
11475
+ object,
11476
+ property,
11477
+ computed: false,
11478
+ start: node.start,
11479
+ end: node.end,
11480
+ loc: node.loc,
11481
+ });
11456
11482
  if (prefixes.length &&
11457
11483
  prefixes[0].startsWith("$.") &&
11458
11484
  prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
@@ -11466,38 +11492,32 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11466
11492
  found = true;
11467
11493
  return current;
11468
11494
  }
11469
- const object = typeof name === "string"
11470
- ? {
11471
- type: "Identifier",
11472
- name,
11473
- start: node.start,
11474
- end: node.end,
11475
- loc: node.loc,
11476
- }
11477
- : name;
11478
- let root = null;
11479
- let property = current;
11480
- while (property.type !== "Identifier") {
11481
- root = property;
11482
- property = property.object;
11483
- }
11484
- const mb = {
11485
- type: "MemberExpression",
11486
- object,
11487
- property,
11488
- computed: false,
11495
+ const object = {
11496
+ type: "Identifier",
11497
+ name,
11489
11498
  start: node.start,
11490
11499
  end: node.end,
11491
11500
  loc: node.loc,
11492
11501
  };
11493
- if (root) {
11494
- root.object = mb;
11495
- }
11496
- else {
11497
- current = mb;
11502
+ let root = null;
11503
+ let property = current;
11504
+ do {
11505
+ root = property;
11506
+ property = property.object;
11507
+ } while (property.type === "MemberExpression");
11508
+ if (property.type === "ThisExpression") {
11509
+ root.object = object;
11510
+ return root;
11498
11511
  }
11512
+ root.object = member(object, property);
11499
11513
  return current;
11500
- }, node);
11514
+ }, member({
11515
+ type: "ThisExpression",
11516
+ text: "self",
11517
+ start: node.start,
11518
+ end: node.end,
11519
+ loc: node.loc,
11520
+ }, node));
11501
11521
  }
11502
11522
  return null;
11503
11523
  }
@@ -13085,7 +13105,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
13085
13105
  // the oldest optimized file, we don't need to regenerate
13086
13106
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
13087
13107
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
13088
- if (source_time < opt_time && 1655681973607 < opt_time) {
13108
+ if (source_time < opt_time && 1655771632397 < opt_time) {
13089
13109
  return { hasTests, diagnostics: prevDiagnostics };
13090
13110
  }
13091
13111
  }
@@ -0,0 +1 @@
1
+ export declare function sizeBasedPRE(state: ProgramStateAnalysis, func: FunctionStateNode): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.0.25",
4
+ "version": "1.0.26",
5
5
  "description": "Source to source optimizer for Garmin Monkey C code",
6
6
  "main": "build/optimizer.cjs",
7
7
  "types": "build/src/optimizer.d.ts",