@markw65/monkeyc-optimizer 1.1.11 → 1.1.12

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
@@ -703,3 +703,11 @@ Bug Fixes
703
703
  - Propagate any :typecheck annotations from inlined functions to their callers
704
704
  - Fix some issues keeping track of function calls used as arguments to inlined functions, that could result in bogus diagnostics.
705
705
  - Implement [Single Use Copy Propagation](https://github.com/markw65/monkeyc-optimizer/wiki/Local-variable-elimination#single-use-copy-propagation)
706
+
707
+ ### 1.1.12
708
+
709
+ - Update to [@markw65/prettier-plugin-monkeyc@1.0.45](https://github.com/markw65/prettier-plugin-monkeyc#1045)
710
+ - fixes some bugs that could cause comments to go missing, resulting in an internal error from the formatter
711
+ - Streamline some of the data structures used for `Minimise Locals` and `Single Copy Prop` to reduce memory use, and speed things up a little.
712
+ - Fix a bug that could cause incorrect copy propagation in loops
713
+ - Add support for update assignments in copy propagation (so that `var x = a; x += b; return x` goes to `return a + b`)
package/build/api.cjs CHANGED
@@ -1507,9 +1507,10 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
1507
1507
  decl,
1508
1508
  mayThrow,
1509
1509
  };
1510
- if (wantsAllRefs && node.operator === "=") {
1511
- if (node.right.type === "Identifier" ||
1512
- node.right.type === "MemberExpression") {
1510
+ if (wantsAllRefs) {
1511
+ if ((node.right.type === "Identifier" ||
1512
+ node.right.type === "MemberExpression") &&
1513
+ node.operator === "=") {
1513
1514
  const rhs = findDecl(node.right);
1514
1515
  if (rhs)
1515
1516
  def.rhs = rhs;
@@ -4955,74 +4956,43 @@ function addEquiv(ts, key, equiv) {
4955
4956
  if (!keyVal || !equivVal)
4956
4957
  return false;
4957
4958
  if (equivVal.equivSet) {
4958
- if (keyVal.equivSet) {
4959
- // key is already a member of a set, see if
4960
- // equiv is part of it.
4961
- let s = keyVal.equivSet.next;
4962
- do {
4963
- if (s === equiv) {
4964
- // these two are already equivalent
4965
- return true;
4966
- }
4967
- const next = ts.get(s);
4968
- if (!next || !next.equivSet) {
4969
- throw new Error(`Inconsistent equivSet for ${tsKey(key)}: missing value for ${tsKey(s)}`);
4970
- }
4971
- s = next.equivSet.next;
4972
- } while (s !== key);
4959
+ if (equivVal.equivSet.has(key)) {
4960
+ return true;
4973
4961
  }
4974
4962
  // equiv is already a member of a set. remove it
4975
4963
  removeEquiv(ts, equiv);
4976
4964
  }
4977
4965
  // equiv is not (or no longer) part of an equivSet
4978
- keyVal = { ...keyVal };
4979
4966
  if (!keyVal.equivSet) {
4980
- keyVal.equivSet = { next: key };
4967
+ keyVal = { ...keyVal };
4968
+ keyVal.equivSet = new Set([key, equiv]);
4969
+ ts.set(key, keyVal);
4970
+ }
4971
+ else {
4972
+ keyVal.equivSet.add(equiv);
4981
4973
  }
4982
4974
  equivVal = { ...equivVal, equivSet: keyVal.equivSet };
4983
- keyVal.equivSet = { next: equiv };
4984
- ts.set(key, keyVal);
4985
4975
  ts.set(equiv, equivVal);
4986
4976
  return false;
4987
4977
  }
4988
4978
  function removeEquiv(ts, equiv) {
4989
- const equivVal = ts.get(equiv);
4979
+ let equivVal = ts.get(equiv);
4990
4980
  if (!equivVal?.equivSet)
4991
4981
  return;
4992
- let s = equivVal.equivSet.next;
4993
- do {
4994
- const next = ts.get(s);
4995
- if (!next || !next.equivSet) {
4996
- throw new Error(`Inconsistent equivSet for ${tsKey(equiv)}: missing value for ${tsKey(s)}`);
4997
- }
4998
- if (next.equivSet.next === equiv) {
4999
- const { equivSet: _e, ...rest } = next;
5000
- if (equivVal.equivSet.next === s) {
5001
- // this is a pair. just kill both
5002
- ts.set(s, rest);
5003
- }
5004
- else {
5005
- ts.set(s, { ...rest, equivSet: equivVal.equivSet });
5006
- }
5007
- break;
5008
- }
5009
- s = next.equivSet.next;
5010
- } while (true);
5011
- const newVal = { ...equivVal };
5012
- delete newVal.equivSet;
5013
- ts.set(equiv, newVal);
4982
+ equivVal.equivSet.delete(equiv);
4983
+ if (equivVal.equivSet.size === 1) {
4984
+ const other = Array.from(equivVal.equivSet)[0];
4985
+ const otherVal = { ...ts.get(other) };
4986
+ delete otherVal.equivSet;
4987
+ ts.set(other, otherVal);
4988
+ }
4989
+ equivVal = { ...equivVal };
4990
+ delete equivVal.equivSet;
4991
+ ts.set(equiv, equivVal);
5014
4992
  }
5015
4993
  function getEquivSet(ts, k) {
5016
- const keys = new Set();
5017
- let s = k;
5018
- do {
5019
- const next = ts.get(s);
5020
- if (!next || !next.equivSet) {
5021
- throw new Error(`Inconsistent equivSet for ${tsKey(k)}: missing value for ${tsKey(s)}`);
5022
- }
5023
- keys.add(s);
5024
- s = next.equivSet.next;
5025
- } while (s !== k);
4994
+ const keys = ts.get(k)?.equivSet;
4995
+ assert(keys);
5026
4996
  return keys;
5027
4997
  }
5028
4998
  function intersectEquiv(ts1, ts2, k) {
@@ -5034,21 +5004,26 @@ function intersectEquiv(ts1, ts2, k) {
5034
5004
  removeEquiv(ts1, k);
5035
5005
  return true;
5036
5006
  }
5037
- const keys = getEquivSet(ts2, k);
5038
- let ret = false;
5039
- let s = eq1.equivSet.next;
5040
- do {
5041
- const next = ts1.get(s);
5042
- if (!next || !next.equivSet) {
5043
- throw new Error(`Inconsistent equivSet for ${tsKey(k)}: missing value for ${tsKey(s)}`);
5044
- }
5045
- if (!keys.has(s)) {
5046
- ret = true;
5047
- removeEquiv(ts1, s);
5007
+ let removed = null;
5008
+ eq1.equivSet.forEach((key) => {
5009
+ if (!eq2.equivSet.has(key)) {
5010
+ eq1.equivSet.delete(key);
5011
+ if (!removed) {
5012
+ removed = new Set();
5013
+ }
5014
+ removed.add(key);
5048
5015
  }
5049
- s = next.equivSet.next;
5050
- } while (s !== k);
5051
- return ret;
5016
+ });
5017
+ if (eq1.equivSet.size === 1) {
5018
+ assert(eq1.equivSet.has(k));
5019
+ delete eq1.equivSet;
5020
+ }
5021
+ if (removed) {
5022
+ removed.forEach((k) => removed.size === 1
5023
+ ? delete ts1.get(k).equivSet
5024
+ : (ts1.get(k).equivSet = removed));
5025
+ }
5026
+ return false;
5052
5027
  }
5053
5028
  function clearAssocPaths(blockState, decl, v) {
5054
5029
  if (v.assocPaths?.size) {
@@ -5066,6 +5041,12 @@ function clearAssocPaths(blockState, decl, v) {
5066
5041
  function cloneTypeState(blockState) {
5067
5042
  const { map, trackedMemberDecls, liveCopyPropEvents, ...rest } = blockState;
5068
5043
  const clone = { map: new Map(map), ...rest };
5044
+ clone.map.forEach((value, key) => {
5045
+ if (value.equivSet && key === Array.from(value.equivSet)[0]) {
5046
+ const equivSet = new Set(value.equivSet);
5047
+ equivSet.forEach((k) => clone.map.set(k, { ...clone.map.get(k), equivSet }));
5048
+ }
5049
+ });
5069
5050
  if (trackedMemberDecls) {
5070
5051
  clone.trackedMemberDecls = new Map();
5071
5052
  trackedMemberDecls.forEach((value, key) => {
@@ -5266,17 +5247,6 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
5266
5247
  });
5267
5248
  return changes;
5268
5249
  }
5269
- function tsEquivs(state, key) {
5270
- const result = [];
5271
- let s = key;
5272
- do {
5273
- result.push(tsKey(s));
5274
- const next = state.get(s);
5275
- assert(next && next.equivSet);
5276
- s = next.equivSet.next;
5277
- } while (s !== key);
5278
- return `[(${result.join(", ")})]`;
5279
- }
5280
5250
  function typeStateEntry(value, key) {
5281
5251
  return `${tsKey(key)} = ${display(value.curType)}`;
5282
5252
  }
@@ -5287,7 +5257,9 @@ function printBlockState(block, state, indent = "") {
5287
5257
  return;
5288
5258
  }
5289
5259
  state.map.forEach((value, key) => {
5290
- console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet ? " " + tsEquivs(state.map, key) : ""}`);
5260
+ console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet
5261
+ ? " " + `[(${Array.from(value.equivSet).map(tsKey).join(", ")})]`
5262
+ : ""}`);
5291
5263
  });
5292
5264
  }
5293
5265
  function updateAffected(blockState, objectType, baseDecl, assignedPath, affectedName, affected, assignedType) {
@@ -5565,15 +5537,11 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
5565
5537
  */
5566
5538
  const v = blockState.map.get(decl);
5567
5539
  if (v?.equivSet) {
5568
- let s = decl;
5569
- do {
5540
+ v.equivSet.forEach((s) => {
5570
5541
  const next = blockState.map.get(s);
5571
- if (!next || !next.equivSet) {
5572
- throw new Error(`Inconsistent equivSet for ${tsKey(decl)}: missing value for ${tsKey(s)}`);
5573
- }
5542
+ assert(next && next.equivSet?.has(s));
5574
5543
  blockState.map.set(s, { ...next, curType: value });
5575
- s = next.equivSet.next;
5576
- } while (s !== decl);
5544
+ });
5577
5545
  }
5578
5546
  else {
5579
5547
  blockState.map.set(decl, { ...v, curType: value });
@@ -5986,12 +5954,13 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
5986
5954
  }
5987
5955
  });
5988
5956
  }
5957
+ let calleeEffects;
5989
5958
  curState.map.forEach((tsv, decl) => {
5990
5959
  let type = tsv.curType;
5991
- if (!some(decl, (d) => d.type === "VariableDeclarator" &&
5992
- (d.node.kind === "var" ||
5993
- // even a "const" could have its "inner" type altered
5994
- (type.value != null && (type.type & 32768 /* TypeTag.Object */) !== 0)))) {
5960
+ if ((type.value == null ||
5961
+ !(type.type &
5962
+ (32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */))) &&
5963
+ !some(decl, (d) => d.type === "VariableDeclarator" && !isLocal(d))) {
5995
5964
  return;
5996
5965
  }
5997
5966
  if (modifiableDecl(decl, callees)) {
@@ -6007,9 +5976,14 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
6007
5976
  clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
6008
5977
  curState.map.set(decl, { curType: typeConstraint(decl) });
6009
5978
  }
6010
- else if (type.value != null &&
6011
- (!callees || !every(callees, (callee) => callee.info === false))) {
6012
- if (type.type & 32768 /* TypeTag.Object */) {
5979
+ else if (type.type &
5980
+ (32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */) &&
5981
+ (calleeEffects == null
5982
+ ? (calleeEffects =
5983
+ !callees ||
5984
+ !every(callees, (callee) => callee.info === false))
5985
+ : calleeEffects)) {
5986
+ if (type.value != null && type.type & 32768 /* TypeTag.Object */) {
6013
5987
  const odata = getObjectValue(tsv.curType);
6014
5988
  if (odata?.obj) {
6015
5989
  type = cloneType(type);
@@ -6020,15 +5994,10 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
6020
5994
  tsv = { ...tsv };
6021
5995
  delete tsv.assocPaths;
6022
5996
  }
6023
- if (tsv.copyPropItem) {
6024
- copyPropFailed(curState, tsv.copyPropItem, nodeCopyProp);
6025
- tsv = { ...tsv };
6026
- delete tsv.copyPropItem;
6027
- }
6028
- clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
6029
5997
  curState.map.set(decl, { ...tsv, curType: type });
6030
5998
  }
6031
5999
  }
6000
+ clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
6032
6001
  }
6033
6002
  });
6034
6003
  return true;
@@ -6147,22 +6116,41 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
6147
6116
  decl.type === "BinaryExpression" ||
6148
6117
  decl.type === "Identifier"))) {
6149
6118
  const key = event.decl ?? null;
6150
- if (key &&
6151
- declIsLocal(key) &&
6152
- nodeCopyProp.has(event.node)) {
6153
- // we might have
6154
- //
6155
- // var x = foo();
6156
- // var y = x + 1;
6157
- // bar();
6158
- // return y;
6159
- //
6160
- // In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
6161
- // OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
6162
- // But we can't do both, and rewrite as "bar(); return foo() + 1;"
6163
- // So just disable copy prop for *this* node. We'll re-run and have a
6164
- // second chance later.
6165
- return false;
6119
+ if (key && declIsLocal(key)) {
6120
+ if (nodeCopyProp.has(event.node)) {
6121
+ // we might have
6122
+ //
6123
+ // var x = foo();
6124
+ // var y = x + 1;
6125
+ // bar();
6126
+ // return y;
6127
+ //
6128
+ // In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
6129
+ // OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
6130
+ // But we can't do both, and rewrite as "bar(); return foo() + 1;"
6131
+ // So just disable copy prop for *this* node. We'll re-run and have a
6132
+ // second chance later.
6133
+ return false;
6134
+ }
6135
+ else if (event.node.type === "AssignmentExpression" &&
6136
+ event.node.operator !== "=" &&
6137
+ nodeCopyProp.has(event.node.left)) {
6138
+ // If we're copy proping into the lhs of an update
6139
+ // assignment, we're going to have to rewrite it.
6140
+ // similar to the above, don't also do forward copy
6141
+ // prop. eg
6142
+ //
6143
+ // var x = a + b;
6144
+ // x += c;
6145
+ // return x;
6146
+ //
6147
+ // becomes
6148
+ //
6149
+ // var x;
6150
+ // x = (a + b) + c;
6151
+ // return x; // <- dont propagate to here (yet), in case a+b has changed.
6152
+ return false;
6153
+ }
6166
6154
  }
6167
6155
  const item = contained.get(key);
6168
6156
  if (!item) {
@@ -6351,7 +6339,22 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
6351
6339
  }
6352
6340
  }
6353
6341
  }));
6354
- traverseAst(func.node.body, null, (node) => {
6342
+ traverseAst(func.node.body, (node) => {
6343
+ if (node.type === "AssignmentExpression" &&
6344
+ node.operator !== "=" &&
6345
+ nodeCopyProp.has(node.left)) {
6346
+ const left = cloneDeep(node.left);
6347
+ const right = withLoc({
6348
+ type: "BinaryExpression",
6349
+ operator: node.operator.slice(0, -1),
6350
+ left: withLocDeep(node.left, node.right, false, true),
6351
+ right: node.right,
6352
+ }, node.left, node.right);
6353
+ node.operator = "=";
6354
+ node.left = left;
6355
+ node.right = right;
6356
+ }
6357
+ }, (node) => {
6355
6358
  const copyNode = nodeCopyProp.get(node);
6356
6359
  if (copyNode) {
6357
6360
  if (node.type === "AssignmentExpression") {
@@ -6370,10 +6373,18 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
6370
6373
  return dup;
6371
6374
  }
6372
6375
  if (copyNode.type === "AssignmentExpression") {
6376
+ const replacement = copyNode.operator === "="
6377
+ ? copyNode.right
6378
+ : {
6379
+ type: "BinaryExpression",
6380
+ operator: copyNode.operator.slice(0, -1),
6381
+ left: copyNode.left,
6382
+ right: copyNode.right,
6383
+ };
6373
6384
  if (logThisRun) {
6374
- console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(copyNode.right)}`);
6385
+ console.log(`copy-prop ${formatAstLongLines(node)} => ${formatAstLongLines(replacement)}`);
6375
6386
  }
6376
- return withLocDeep(copyNode.right, node, node, false);
6387
+ return withLocDeep(replacement, node, node, false);
6377
6388
  }
6378
6389
  else if (copyNode.type === "VariableDeclarator") {
6379
6390
  assert(copyNode.init);
@@ -6715,18 +6726,18 @@ function couldBeObj(a, b) {
6715
6726
 
6716
6727
 
6717
6728
  function cloneAnt(antMap) {
6718
- const ant = new Map();
6719
- antMap.forEach((s, k) => ant.set(k, new Set(s)));
6720
- return ant;
6729
+ return new Map(antMap);
6721
6730
  }
6722
6731
  function addAnt(antMap, decl, node) {
6723
6732
  assert(node.type === "Identifier");
6724
6733
  const ant = antMap.get(decl);
6725
- if (!ant) {
6726
- antMap.set(decl, new Set([node]));
6734
+ if (ant === false || ant === node)
6735
+ return;
6736
+ if (ant === undefined) {
6737
+ antMap.set(decl, node);
6727
6738
  }
6728
6739
  else {
6729
- ant.add(node);
6740
+ antMap.set(decl, false);
6730
6741
  }
6731
6742
  }
6732
6743
  function cloneState(blockState) {
@@ -6762,18 +6773,10 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
6762
6773
  else {
6763
6774
  changed = Array.from(to.anticipated).reduce((changed, [decl, toant]) => {
6764
6775
  const fromant = from.anticipated.get(decl);
6765
- if (!fromant) {
6776
+ if (toant !== fromant) {
6766
6777
  to.anticipated.delete(decl);
6767
6778
  changed = true;
6768
6779
  }
6769
- else {
6770
- toant.forEach((node) => {
6771
- if (!fromant.has(node)) {
6772
- toant.delete(node);
6773
- changed = true;
6774
- }
6775
- });
6776
- }
6777
6780
  return changed;
6778
6781
  }, changed);
6779
6782
  }
@@ -6786,17 +6789,15 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
6786
6789
  else {
6787
6790
  changed = Array.from(from.partiallyAnticipated).reduce((changed, [decl, fromant]) => {
6788
6791
  const toant = to.partiallyAnticipated.get(decl);
6789
- if (!toant) {
6792
+ if (toant === undefined) {
6790
6793
  to.partiallyAnticipated.set(decl, fromant);
6791
6794
  changed = true;
6792
6795
  }
6793
6796
  else {
6794
- fromant.forEach((node) => {
6795
- if (!toant.has(node)) {
6796
- changed = true;
6797
- toant.add(node);
6798
- }
6799
- });
6797
+ if (toant !== fromant) {
6798
+ changed = true;
6799
+ to.partiallyAnticipated.set(decl, false);
6800
+ }
6800
6801
  }
6801
6802
  return changed;
6802
6803
  }, changed);
@@ -6860,7 +6861,7 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
6860
6861
  }
6861
6862
  addAnt(curState.partiallyAnticipated, event.decl, event.node);
6862
6863
  if (logThisRun) {
6863
- console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl)?.size ?? 0} ${curState.anticipated.get(event.decl)?.size ?? 0}`);
6864
+ console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl) !== false} ${curState.anticipated.get(event.decl) !== false}`);
6864
6865
  }
6865
6866
  }
6866
6867
  curState.dead.delete(event.decl);
@@ -6881,25 +6882,21 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
6881
6882
  }
6882
6883
  else {
6883
6884
  deadStores.delete(event.node);
6884
- if (assignNode &&
6885
- declIsLocal(event.decl) &&
6886
- curState.partiallyAnticipated) {
6885
+ copyPropStores.delete(event.node);
6886
+ if (declIsLocal(event.decl) && curState.partiallyAnticipated) {
6887
6887
  const pant = curState.partiallyAnticipated.get(event.decl);
6888
- if (pant && pant.size === 1) {
6888
+ if (pant) {
6889
6889
  if (logThisRun) {
6890
- console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl)?.size ?? 0}`);
6890
+ console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl) === pant}`);
6891
6891
  }
6892
6892
  copyPropStores.set(event.node, {
6893
- ref: Array.from(pant)[0],
6894
- ant: curState.anticipated?.get(event.decl)?.size === 1,
6893
+ ref: pant,
6894
+ ant: curState.anticipated?.get(event.decl) === pant,
6895
6895
  });
6896
6896
  }
6897
6897
  curState.partiallyAnticipated.delete(event.decl);
6898
6898
  curState.anticipated?.delete(event.decl);
6899
6899
  }
6900
- else {
6901
- copyPropStores.delete(event.node);
6902
- }
6903
6900
  }
6904
6901
  if (nodeConflicts) {
6905
6902
  const conflicts = new Set(locals);
@@ -10954,9 +10954,10 @@ function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wan
10954
10954
  decl,
10955
10955
  mayThrow,
10956
10956
  };
10957
- if (wantsAllRefs && node.operator === "=") {
10958
- if (node.right.type === "Identifier" ||
10959
- node.right.type === "MemberExpression") {
10957
+ if (wantsAllRefs) {
10958
+ if ((node.right.type === "Identifier" ||
10959
+ node.right.type === "MemberExpression") &&
10960
+ node.operator === "=") {
10960
10961
  const rhs = findDecl(node.right);
10961
10962
  if (rhs)
10962
10963
  def.rhs = rhs;
@@ -11183,18 +11184,18 @@ const external_node_assert_namespaceObject = require("node:assert");
11183
11184
 
11184
11185
 
11185
11186
  function cloneAnt(antMap) {
11186
- const ant = new Map();
11187
- antMap.forEach((s, k) => ant.set(k, new Set(s)));
11188
- return ant;
11187
+ return new Map(antMap);
11189
11188
  }
11190
11189
  function addAnt(antMap, decl, node) {
11191
11190
  external_node_assert_namespaceObject(node.type === "Identifier");
11192
11191
  const ant = antMap.get(decl);
11193
- if (!ant) {
11194
- antMap.set(decl, new Set([node]));
11192
+ if (ant === false || ant === node)
11193
+ return;
11194
+ if (ant === undefined) {
11195
+ antMap.set(decl, node);
11195
11196
  }
11196
11197
  else {
11197
- ant.add(node);
11198
+ antMap.set(decl, false);
11198
11199
  }
11199
11200
  }
11200
11201
  function cloneState(blockState) {
@@ -11230,18 +11231,10 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
11230
11231
  else {
11231
11232
  changed = Array.from(to.anticipated).reduce((changed, [decl, toant]) => {
11232
11233
  const fromant = from.anticipated.get(decl);
11233
- if (!fromant) {
11234
+ if (toant !== fromant) {
11234
11235
  to.anticipated.delete(decl);
11235
11236
  changed = true;
11236
11237
  }
11237
- else {
11238
- toant.forEach((node) => {
11239
- if (!fromant.has(node)) {
11240
- toant.delete(node);
11241
- changed = true;
11242
- }
11243
- });
11244
- }
11245
11238
  return changed;
11246
11239
  }, changed);
11247
11240
  }
@@ -11254,17 +11247,15 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
11254
11247
  else {
11255
11248
  changed = Array.from(from.partiallyAnticipated).reduce((changed, [decl, fromant]) => {
11256
11249
  const toant = to.partiallyAnticipated.get(decl);
11257
- if (!toant) {
11250
+ if (toant === undefined) {
11258
11251
  to.partiallyAnticipated.set(decl, fromant);
11259
11252
  changed = true;
11260
11253
  }
11261
11254
  else {
11262
- fromant.forEach((node) => {
11263
- if (!toant.has(node)) {
11264
- changed = true;
11265
- toant.add(node);
11266
- }
11267
- });
11255
+ if (toant !== fromant) {
11256
+ changed = true;
11257
+ to.partiallyAnticipated.set(decl, false);
11258
+ }
11268
11259
  }
11269
11260
  return changed;
11270
11261
  }, changed);
@@ -11328,7 +11319,7 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
11328
11319
  }
11329
11320
  addAnt(curState.partiallyAnticipated, event.decl, event.node);
11330
11321
  if (logThisRun) {
11331
- console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl)?.size ?? 0} ${curState.anticipated.get(event.decl)?.size ?? 0}`);
11322
+ console.log(` antrefs: ${curState.partiallyAnticipated.get(event.decl) !== false} ${curState.anticipated.get(event.decl) !== false}`);
11332
11323
  }
11333
11324
  }
11334
11325
  curState.dead.delete(event.decl);
@@ -11349,25 +11340,21 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
11349
11340
  }
11350
11341
  else {
11351
11342
  deadStores.delete(event.node);
11352
- if (assignNode &&
11353
- declIsLocal(event.decl) &&
11354
- curState.partiallyAnticipated) {
11343
+ copyPropStores.delete(event.node);
11344
+ if (declIsLocal(event.decl) && curState.partiallyAnticipated) {
11355
11345
  const pant = curState.partiallyAnticipated.get(event.decl);
11356
- if (pant && pant.size === 1) {
11346
+ if (pant) {
11357
11347
  if (logThisRun) {
11358
- console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl)?.size ?? 0}`);
11348
+ console.log(` is copy-prop-candidate ${curState.anticipated?.get(event.decl) === pant}`);
11359
11349
  }
11360
11350
  copyPropStores.set(event.node, {
11361
- ref: Array.from(pant)[0],
11362
- ant: curState.anticipated?.get(event.decl)?.size === 1,
11351
+ ref: pant,
11352
+ ant: curState.anticipated?.get(event.decl) === pant,
11363
11353
  });
11364
11354
  }
11365
11355
  curState.partiallyAnticipated.delete(event.decl);
11366
11356
  curState.anticipated?.delete(event.decl);
11367
11357
  }
11368
- else {
11369
- copyPropStores.delete(event.node);
11370
- }
11371
11358
  }
11372
11359
  if (nodeConflicts) {
11373
11360
  const conflicts = new Set(locals);
@@ -11596,74 +11583,43 @@ function addEquiv(ts, key, equiv) {
11596
11583
  if (!keyVal || !equivVal)
11597
11584
  return false;
11598
11585
  if (equivVal.equivSet) {
11599
- if (keyVal.equivSet) {
11600
- // key is already a member of a set, see if
11601
- // equiv is part of it.
11602
- let s = keyVal.equivSet.next;
11603
- do {
11604
- if (s === equiv) {
11605
- // these two are already equivalent
11606
- return true;
11607
- }
11608
- const next = ts.get(s);
11609
- if (!next || !next.equivSet) {
11610
- throw new Error(`Inconsistent equivSet for ${tsKey(key)}: missing value for ${tsKey(s)}`);
11611
- }
11612
- s = next.equivSet.next;
11613
- } while (s !== key);
11586
+ if (equivVal.equivSet.has(key)) {
11587
+ return true;
11614
11588
  }
11615
11589
  // equiv is already a member of a set. remove it
11616
11590
  removeEquiv(ts, equiv);
11617
11591
  }
11618
11592
  // equiv is not (or no longer) part of an equivSet
11619
- keyVal = { ...keyVal };
11620
11593
  if (!keyVal.equivSet) {
11621
- keyVal.equivSet = { next: key };
11594
+ keyVal = { ...keyVal };
11595
+ keyVal.equivSet = new Set([key, equiv]);
11596
+ ts.set(key, keyVal);
11597
+ }
11598
+ else {
11599
+ keyVal.equivSet.add(equiv);
11622
11600
  }
11623
11601
  equivVal = { ...equivVal, equivSet: keyVal.equivSet };
11624
- keyVal.equivSet = { next: equiv };
11625
- ts.set(key, keyVal);
11626
11602
  ts.set(equiv, equivVal);
11627
11603
  return false;
11628
11604
  }
11629
11605
  function removeEquiv(ts, equiv) {
11630
- const equivVal = ts.get(equiv);
11606
+ let equivVal = ts.get(equiv);
11631
11607
  if (!equivVal?.equivSet)
11632
11608
  return;
11633
- let s = equivVal.equivSet.next;
11634
- do {
11635
- const next = ts.get(s);
11636
- if (!next || !next.equivSet) {
11637
- throw new Error(`Inconsistent equivSet for ${tsKey(equiv)}: missing value for ${tsKey(s)}`);
11638
- }
11639
- if (next.equivSet.next === equiv) {
11640
- const { equivSet: _e, ...rest } = next;
11641
- if (equivVal.equivSet.next === s) {
11642
- // this is a pair. just kill both
11643
- ts.set(s, rest);
11644
- }
11645
- else {
11646
- ts.set(s, { ...rest, equivSet: equivVal.equivSet });
11647
- }
11648
- break;
11649
- }
11650
- s = next.equivSet.next;
11651
- } while (true);
11652
- const newVal = { ...equivVal };
11653
- delete newVal.equivSet;
11654
- ts.set(equiv, newVal);
11609
+ equivVal.equivSet.delete(equiv);
11610
+ if (equivVal.equivSet.size === 1) {
11611
+ const other = Array.from(equivVal.equivSet)[0];
11612
+ const otherVal = { ...ts.get(other) };
11613
+ delete otherVal.equivSet;
11614
+ ts.set(other, otherVal);
11615
+ }
11616
+ equivVal = { ...equivVal };
11617
+ delete equivVal.equivSet;
11618
+ ts.set(equiv, equivVal);
11655
11619
  }
11656
11620
  function getEquivSet(ts, k) {
11657
- const keys = new Set();
11658
- let s = k;
11659
- do {
11660
- const next = ts.get(s);
11661
- if (!next || !next.equivSet) {
11662
- throw new Error(`Inconsistent equivSet for ${tsKey(k)}: missing value for ${tsKey(s)}`);
11663
- }
11664
- keys.add(s);
11665
- s = next.equivSet.next;
11666
- } while (s !== k);
11621
+ const keys = ts.get(k)?.equivSet;
11622
+ external_node_assert_namespaceObject(keys);
11667
11623
  return keys;
11668
11624
  }
11669
11625
  function intersectEquiv(ts1, ts2, k) {
@@ -11675,21 +11631,26 @@ function intersectEquiv(ts1, ts2, k) {
11675
11631
  removeEquiv(ts1, k);
11676
11632
  return true;
11677
11633
  }
11678
- const keys = getEquivSet(ts2, k);
11679
- let ret = false;
11680
- let s = eq1.equivSet.next;
11681
- do {
11682
- const next = ts1.get(s);
11683
- if (!next || !next.equivSet) {
11684
- throw new Error(`Inconsistent equivSet for ${tsKey(k)}: missing value for ${tsKey(s)}`);
11685
- }
11686
- if (!keys.has(s)) {
11687
- ret = true;
11688
- removeEquiv(ts1, s);
11634
+ let removed = null;
11635
+ eq1.equivSet.forEach((key) => {
11636
+ if (!eq2.equivSet.has(key)) {
11637
+ eq1.equivSet.delete(key);
11638
+ if (!removed) {
11639
+ removed = new Set();
11640
+ }
11641
+ removed.add(key);
11689
11642
  }
11690
- s = next.equivSet.next;
11691
- } while (s !== k);
11692
- return ret;
11643
+ });
11644
+ if (eq1.equivSet.size === 1) {
11645
+ external_node_assert_namespaceObject(eq1.equivSet.has(k));
11646
+ delete eq1.equivSet;
11647
+ }
11648
+ if (removed) {
11649
+ removed.forEach((k) => removed.size === 1
11650
+ ? delete ts1.get(k).equivSet
11651
+ : (ts1.get(k).equivSet = removed));
11652
+ }
11653
+ return false;
11693
11654
  }
11694
11655
  function clearAssocPaths(blockState, decl, v) {
11695
11656
  if (v.assocPaths?.size) {
@@ -11707,6 +11668,12 @@ function clearAssocPaths(blockState, decl, v) {
11707
11668
  function cloneTypeState(blockState) {
11708
11669
  const { map, trackedMemberDecls, liveCopyPropEvents, ...rest } = blockState;
11709
11670
  const clone = { map: new Map(map), ...rest };
11671
+ clone.map.forEach((value, key) => {
11672
+ if (value.equivSet && key === Array.from(value.equivSet)[0]) {
11673
+ const equivSet = new Set(value.equivSet);
11674
+ equivSet.forEach((k) => clone.map.set(k, { ...clone.map.get(k), equivSet }));
11675
+ }
11676
+ });
11710
11677
  if (trackedMemberDecls) {
11711
11678
  clone.trackedMemberDecls = new Map();
11712
11679
  trackedMemberDecls.forEach((value, key) => {
@@ -11907,17 +11874,6 @@ function mergeTypeState(blockStates, index, from, nodeCopyProp) {
11907
11874
  });
11908
11875
  return changes;
11909
11876
  }
11910
- function tsEquivs(state, key) {
11911
- const result = [];
11912
- let s = key;
11913
- do {
11914
- result.push(tsKey(s));
11915
- const next = state.get(s);
11916
- external_node_assert_namespaceObject(next && next.equivSet);
11917
- s = next.equivSet.next;
11918
- } while (s !== key);
11919
- return `[(${result.join(", ")})]`;
11920
- }
11921
11877
  function typeStateEntry(value, key) {
11922
11878
  return `${tsKey(key)} = ${display(value.curType)}`;
11923
11879
  }
@@ -11928,7 +11884,9 @@ function printBlockState(block, state, indent = "") {
11928
11884
  return;
11929
11885
  }
11930
11886
  state.map.forEach((value, key) => {
11931
- console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet ? " " + tsEquivs(state.map, key) : ""}`);
11887
+ console.log(`${indent} - ${typeStateEntry(value, key)}${value.equivSet
11888
+ ? " " + `[(${Array.from(value.equivSet).map(tsKey).join(", ")})]`
11889
+ : ""}`);
11932
11890
  });
11933
11891
  }
11934
11892
  function updateAffected(blockState, objectType, baseDecl, assignedPath, affectedName, affected, assignedType) {
@@ -12206,15 +12164,11 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12206
12164
  */
12207
12165
  const v = blockState.map.get(decl);
12208
12166
  if (v?.equivSet) {
12209
- let s = decl;
12210
- do {
12167
+ v.equivSet.forEach((s) => {
12211
12168
  const next = blockState.map.get(s);
12212
- if (!next || !next.equivSet) {
12213
- throw new Error(`Inconsistent equivSet for ${tsKey(decl)}: missing value for ${tsKey(s)}`);
12214
- }
12169
+ external_node_assert_namespaceObject(next && next.equivSet?.has(s));
12215
12170
  blockState.map.set(s, { ...next, curType: value });
12216
- s = next.equivSet.next;
12217
- } while (s !== decl);
12171
+ });
12218
12172
  }
12219
12173
  else {
12220
12174
  blockState.map.set(decl, { ...v, curType: value });
@@ -12627,12 +12581,13 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12627
12581
  }
12628
12582
  });
12629
12583
  }
12584
+ let calleeEffects;
12630
12585
  curState.map.forEach((tsv, decl) => {
12631
12586
  let type = tsv.curType;
12632
- if (!(0,external_util_cjs_namespaceObject.some)(decl, (d) => d.type === "VariableDeclarator" &&
12633
- (d.node.kind === "var" ||
12634
- // even a "const" could have its "inner" type altered
12635
- (type.value != null && (type.type & 32768 /* TypeTag.Object */) !== 0)))) {
12587
+ if ((type.value == null ||
12588
+ !(type.type &
12589
+ (32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */))) &&
12590
+ !(0,external_util_cjs_namespaceObject.some)(decl, (d) => d.type === "VariableDeclarator" && !(0,external_api_cjs_namespaceObject.isLocal)(d))) {
12636
12591
  return;
12637
12592
  }
12638
12593
  if (modifiableDecl(decl, callees)) {
@@ -12648,9 +12603,14 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12648
12603
  clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
12649
12604
  curState.map.set(decl, { curType: typeConstraint(decl) });
12650
12605
  }
12651
- else if (type.value != null &&
12652
- (!callees || !(0,external_util_cjs_namespaceObject.every)(callees, (callee) => callee.info === false))) {
12653
- if (type.type & 32768 /* TypeTag.Object */) {
12606
+ else if (type.type &
12607
+ (32768 /* TypeTag.Object */ | 512 /* TypeTag.Array */ | 1024 /* TypeTag.Dictionary */) &&
12608
+ (calleeEffects == null
12609
+ ? (calleeEffects =
12610
+ !callees ||
12611
+ !(0,external_util_cjs_namespaceObject.every)(callees, (callee) => callee.info === false))
12612
+ : calleeEffects)) {
12613
+ if (type.value != null && type.type & 32768 /* TypeTag.Object */) {
12654
12614
  const odata = getObjectValue(tsv.curType);
12655
12615
  if (odata?.obj) {
12656
12616
  type = cloneType(type);
@@ -12661,15 +12621,10 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12661
12621
  tsv = { ...tsv };
12662
12622
  delete tsv.assocPaths;
12663
12623
  }
12664
- if (tsv.copyPropItem) {
12665
- copyPropFailed(curState, tsv.copyPropItem, nodeCopyProp);
12666
- tsv = { ...tsv };
12667
- delete tsv.copyPropItem;
12668
- }
12669
- clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
12670
12624
  curState.map.set(decl, { ...tsv, curType: type });
12671
12625
  }
12672
12626
  }
12627
+ clearRelatedCopyPropEvents(curState, decl, nodeCopyProp);
12673
12628
  }
12674
12629
  });
12675
12630
  return true;
@@ -12788,22 +12743,41 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12788
12743
  decl.type === "BinaryExpression" ||
12789
12744
  decl.type === "Identifier"))) {
12790
12745
  const key = event.decl ?? null;
12791
- if (key &&
12792
- declIsLocal(key) &&
12793
- nodeCopyProp.has(event.node)) {
12794
- // we might have
12795
- //
12796
- // var x = foo();
12797
- // var y = x + 1;
12798
- // bar();
12799
- // return y;
12800
- //
12801
- // In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
12802
- // OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
12803
- // But we can't do both, and rewrite as "bar(); return foo() + 1;"
12804
- // So just disable copy prop for *this* node. We'll re-run and have a
12805
- // second chance later.
12806
- return false;
12746
+ if (key && declIsLocal(key)) {
12747
+ if (nodeCopyProp.has(event.node)) {
12748
+ // we might have
12749
+ //
12750
+ // var x = foo();
12751
+ // var y = x + 1;
12752
+ // bar();
12753
+ // return y;
12754
+ //
12755
+ // In that case, its ok to drop "x = foo()" and rewrite as y = foo() + 1"
12756
+ // OR its ok to drop "y = x + 1" and rewrite as "return x + 1".
12757
+ // But we can't do both, and rewrite as "bar(); return foo() + 1;"
12758
+ // So just disable copy prop for *this* node. We'll re-run and have a
12759
+ // second chance later.
12760
+ return false;
12761
+ }
12762
+ else if (event.node.type === "AssignmentExpression" &&
12763
+ event.node.operator !== "=" &&
12764
+ nodeCopyProp.has(event.node.left)) {
12765
+ // If we're copy proping into the lhs of an update
12766
+ // assignment, we're going to have to rewrite it.
12767
+ // similar to the above, don't also do forward copy
12768
+ // prop. eg
12769
+ //
12770
+ // var x = a + b;
12771
+ // x += c;
12772
+ // return x;
12773
+ //
12774
+ // becomes
12775
+ //
12776
+ // var x;
12777
+ // x = (a + b) + c;
12778
+ // return x; // <- dont propagate to here (yet), in case a+b has changed.
12779
+ return false;
12780
+ }
12807
12781
  }
12808
12782
  const item = contained.get(key);
12809
12783
  if (!item) {
@@ -12992,7 +12966,22 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
12992
12966
  }
12993
12967
  }
12994
12968
  }));
12995
- (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, null, (node) => {
12969
+ (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, (node) => {
12970
+ if (node.type === "AssignmentExpression" &&
12971
+ node.operator !== "=" &&
12972
+ nodeCopyProp.has(node.left)) {
12973
+ const left = cloneDeep(node.left);
12974
+ const right = withLoc({
12975
+ type: "BinaryExpression",
12976
+ operator: node.operator.slice(0, -1),
12977
+ left: withLocDeep(node.left, node.right, false, true),
12978
+ right: node.right,
12979
+ }, node.left, node.right);
12980
+ node.operator = "=";
12981
+ node.left = left;
12982
+ node.right = right;
12983
+ }
12984
+ }, (node) => {
12996
12985
  const copyNode = nodeCopyProp.get(node);
12997
12986
  if (copyNode) {
12998
12987
  if (node.type === "AssignmentExpression") {
@@ -13011,10 +13000,18 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, copyPropStore
13011
13000
  return dup;
13012
13001
  }
13013
13002
  if (copyNode.type === "AssignmentExpression") {
13003
+ const replacement = copyNode.operator === "="
13004
+ ? copyNode.right
13005
+ : {
13006
+ type: "BinaryExpression",
13007
+ operator: copyNode.operator.slice(0, -1),
13008
+ left: copyNode.left,
13009
+ right: copyNode.right,
13010
+ };
13014
13011
  if (logThisRun) {
13015
- console.log(`copy-prop ${(0,external_api_cjs_namespaceObject.formatAstLongLines)(node)} => ${(0,external_api_cjs_namespaceObject.formatAstLongLines)(copyNode.right)}`);
13012
+ console.log(`copy-prop ${(0,external_api_cjs_namespaceObject.formatAstLongLines)(node)} => ${(0,external_api_cjs_namespaceObject.formatAstLongLines)(replacement)}`);
13016
13013
  }
13017
- return withLocDeep(copyNode.right, node, node, false);
13014
+ return withLocDeep(replacement, node, node, false);
13018
13015
  }
13019
13016
  else if (copyNode.type === "VariableDeclarator") {
13020
13017
  external_node_assert_namespaceObject(copyNode.init);
@@ -16640,7 +16637,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
16640
16637
  // the oldest optimized file, we don't need to regenerate
16641
16638
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
16642
16639
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
16643
- if (source_time < opt_time && 1676064117591 < opt_time) {
16640
+ if (source_time < opt_time && 1676156189652 < opt_time) {
16644
16641
  return { hasTests, diagnostics: prevDiagnostics };
16645
16642
  }
16646
16643
  }
@@ -16667,7 +16664,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
16667
16664
  return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
16668
16665
  hasTests,
16669
16666
  diagnostics,
16670
- optimizerVersion: "1.1.11",
16667
+ optimizerVersion: "1.1.12",
16671
16668
  ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
16672
16669
  }))
16673
16670
  .then(() => ({ hasTests, diagnostics }));
@@ -26,7 +26,7 @@ export declare function findNamesInScope(declStack: StateNode[][], pattern: stri
26
26
  parent: StateNode;
27
27
  depth: number;
28
28
  }][];
29
- export declare function mapVarDeclsByType(state: ProgramStateAnalysis, decls: StateNodeDecl[], node: mctree.Node, typeMap: TypeMap | null | undefined): (ModuleStateNode | FunctionStateNode | ClassStateNode | TypedefStateNode | ProgramStateNode | VariableStateNode | import("./optimizer-types").BlockStateNode | EnumStateNode | mctree.EnumStringMember | mctree.Identifier | mctree.AsIdentifier)[];
29
+ export declare function mapVarDeclsByType(state: ProgramStateAnalysis, decls: StateNodeDecl[], node: mctree.Node, typeMap: TypeMap | null | undefined): (ModuleStateNode | FunctionStateNode | ClassStateNode | TypedefStateNode | ProgramStateNode | mctree.Identifier | mctree.EnumStringMember | mctree.AsIdentifier | import("./optimizer-types").BlockStateNode | VariableStateNode | EnumStateNode)[];
30
30
  export declare function formatAstLongLines(node: mctree.Node): string;
31
31
  export declare function createDocumentationMap(functionDocumentation: {
32
32
  name: string;
@@ -17,7 +17,7 @@ export declare function printBlockHeader(block: TypeFlowBlock): void;
17
17
  export declare function describeEvent(event: Event): string;
18
18
  export declare function printBlockEvents(block: TypeFlowBlock, extra?: (event: Event) => string): void;
19
19
  export declare function printBlockTrailer(block: TypeFlowBlock): void;
20
- export declare function findObjectDeclsByProperty(state: ProgramStateAnalysis, object: ExactOrUnion, next: mctree.DottedMemberExpression): readonly [null, null] | [StateNode[], StateNode[]];
20
+ export declare function findObjectDeclsByProperty(state: ProgramStateAnalysis, object: ExactOrUnion, next: mctree.DottedMemberExpression): [StateNode[], StateNode[]] | readonly [null, null];
21
21
  export declare function refineObjectTypeByDecls(istate: InterpState, object: ExactOrUnion, trueDecls: StateNode[]): ExactOrUnion;
22
22
  export declare function findNextObjectType(istate: InterpState, trueDecls: StateNode[], next: mctree.DottedMemberExpression): import("./types").UnionType | import("./types").NumberType | import("./types").LongType | import("./types").FloatType | import("./types").DoubleType | import("./types").CharType | import("./types").StringType | import("./types").ArrayType | import("./types").DictionaryType | import("./types").MethodType | import("./types").ModuleType | import("./types").FunctionType | import("./types").ClassType | import("./types").ObjectType | import("./types").EnumType | import("./types").SymbolType | import("./types").TypedefType | null;
23
23
  export declare function resolveDottedMember(istate: InterpState, object: ExactOrUnion, next: mctree.DottedMemberExpression): {
@@ -26,7 +26,7 @@ export declare const enum TypeTag {
26
26
  Typedef = 262144,
27
27
  Any = 524287
28
28
  }
29
- export declare function typeTagName(tag: TypeTag): "Never" | "Null" | "False" | "True" | "Boolean" | "Number" | "Long" | "Float" | "Double" | "Decimal" | "Numeric" | "Char" | "String" | "Array" | "Dictionary" | "Method" | "Module" | "Function" | "Class" | "Object" | "Enum" | "Symbol" | "Typedef" | "Any";
29
+ export declare function typeTagName(tag: TypeTag): "Number" | "Float" | "Double" | "Long" | "String" | "Char" | "Boolean" | "Null" | "Object" | "Symbol" | "Never" | "False" | "True" | "Decimal" | "Numeric" | "Array" | "Dictionary" | "Method" | "Module" | "Function" | "Class" | "Enum" | "Typedef" | "Any";
30
30
  export declare const LastTypeTag = TypeTag.Typedef;
31
31
  export declare const SingletonTypeTagsConst: number;
32
32
  export declare const UnionDataTypeTagsConst: number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.1.11",
4
+ "version": "1.1.12",
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",
@@ -40,7 +40,7 @@
40
40
  "author": "markw65",
41
41
  "license": "MIT",
42
42
  "dependencies": {
43
- "@markw65/prettier-plugin-monkeyc": "^1.0.44"
43
+ "@markw65/prettier-plugin-monkeyc": "^1.0.45"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/chai": "^4.3.4",