@markw65/monkeyc-optimizer 1.1.5 → 1.1.7

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
@@ -642,3 +642,15 @@ Bug Fixes
642
642
  - Bug fixes
643
643
  - Always evaluate a constant's initializer to determine its type
644
644
  - Fix a bug refining the object type based on the properties it accesses that could lose the type of the object.
645
+
646
+ ### 1.1.6
647
+
648
+ - Bug fixes
649
+ - Fix an issue in restrictByEquality when restricting a union including an Enum, to a specific value of the enum.
650
+ - Fix the display of Method types to match the syntax used in MonkeyC.
651
+ - Infer the type of `method(:symbol)` by looking up symbol.
652
+
653
+ ### 1.1.7
654
+
655
+ - Bug fixes
656
+ - Fix a problem with inlining that could inadvertently make locals from the callee function appear to belong to the callee's class or module. This could sometimes block optimizations, and also cause confusion for the type checker.
package/build/api.cjs CHANGED
@@ -1851,9 +1851,7 @@ function findCalleesByNode(state, callee) {
1851
1851
  /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
1852
1852
  /* harmony import */ var _ast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6652);
1853
1853
  /* harmony import */ var _function_info__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(819);
1854
- /* harmony import */ var _optimizer_types__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9697);
1855
- /* harmony import */ var _variable_renamer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4405);
1856
-
1854
+ /* harmony import */ var _variable_renamer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4405);
1857
1855
 
1858
1856
 
1859
1857
 
@@ -2075,7 +2073,7 @@ function getArgSafety(state, func, args, requireAll) {
2075
2073
  }
2076
2074
  return null;
2077
2075
  };
2078
- state.stack = func.stack;
2076
+ state.stack = func.stack.concat(func);
2079
2077
  state.traverse(func.node.body);
2080
2078
  }
2081
2079
  finally {
@@ -2186,9 +2184,7 @@ function processInlineBody(state, func, call, root, params) {
2186
2184
  // lookup determines static-ness of the lookup context based on seeing
2187
2185
  // a static FunctionDeclaration, but the FunctionDeclaration's stack
2188
2186
  // doesn't include the FunctionDeclaration itself.
2189
- const stack = func.attributes & StateNodeAttributes.STATIC
2190
- ? func.stack.concat(func)
2191
- : func.stack;
2187
+ const lookupStack = func.stack.concat(func);
2192
2188
  try {
2193
2189
  state.pre = (node) => {
2194
2190
  if (failed)
@@ -2244,7 +2240,7 @@ function processInlineBody(state, func, call, root, params) {
2244
2240
  }
2245
2241
  return null;
2246
2242
  }
2247
- const replacement = fixNodeScope(state, node, stack);
2243
+ const replacement = fixNodeScope(state, node, lookupStack);
2248
2244
  if (!replacement) {
2249
2245
  failed = true;
2250
2246
  inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
@@ -3380,7 +3376,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
3380
3376
  const info = sysCallInfo(callee);
3381
3377
  if (!info)
3382
3378
  return false;
3383
- const result = info(callee, calleeObj, () => node.arguments.map((arg) => evaluateExpr(state, arg, typeMap).value));
3379
+ const result = info(istate.state, callee, calleeObj, () => node.arguments.map((arg) => evaluateExpr(state, arg, typeMap).value));
3384
3380
  if (result.calleeObj) {
3385
3381
  setStateEvent(curState, calleeObjDecl, result.calleeObj, false);
3386
3382
  }
@@ -4702,14 +4698,18 @@ function evaluateLogicalTypes(op, left, right) {
4702
4698
 
4703
4699
  "use strict";
4704
4700
  /* unused harmony exports evaluateCall, checkCallArgs, sysCallInfo */
4705
- /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6817);
4706
- /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_0__);
4707
- /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6906);
4708
- /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_1__);
4709
- /* harmony import */ var _interp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7161);
4710
- /* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9234);
4711
- /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7255);
4712
- /* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(757);
4701
+ /* harmony import */ var _optimizer_types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9697);
4702
+ /* harmony import */ var _type_flow__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4859);
4703
+ /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6817);
4704
+ /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_api__WEBPACK_IMPORTED_MODULE_2__);
4705
+ /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6906);
4706
+ /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_util__WEBPACK_IMPORTED_MODULE_3__);
4707
+ /* harmony import */ var _interp__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7161);
4708
+ /* harmony import */ var _sub_type__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9234);
4709
+ /* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7255);
4710
+ /* harmony import */ var _union_type__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(757);
4711
+
4712
+
4713
4713
 
4714
4714
 
4715
4715
 
@@ -4738,6 +4738,20 @@ function evaluateCall(istate, node, callee, args) {
4738
4738
  }
4739
4739
  return checkCallArgs(istate, node, callee.value, args);
4740
4740
  }
4741
+ function calleeObjectType(istate, callee) {
4742
+ if (callee.type === "MemberExpression") {
4743
+ return (istate.typeMap?.get(callee.object) || {
4744
+ type: 524287 /* TypeTag.Any */,
4745
+ });
4746
+ }
4747
+ if (callee.type === "Identifier" && istate.func) {
4748
+ const func = istate.func;
4749
+ const [self] = func.stack.slice(-1);
4750
+ return typeFromTypeStateNode(istate.state, self, (func.attributes & StateNodeAttributes.STATIC) !== 0 ||
4751
+ self.type !== "ClassDeclaration");
4752
+ }
4753
+ return null;
4754
+ }
4741
4755
  function checkCallArgs(istate, node, callees, args) {
4742
4756
  const allDiags = [];
4743
4757
  const resultType = reduce(callees, (result, cur) => {
@@ -4747,13 +4761,11 @@ function checkCallArgs(istate, node, callees, args) {
4747
4761
  let returnType = null;
4748
4762
  let effects = true;
4749
4763
  let argEffects = true;
4750
- if (node.callee.type === "MemberExpression") {
4751
- const object = istate.typeMap?.get(node.callee.object) || {
4752
- type: 524287 /* TypeTag.Any */,
4753
- };
4764
+ const object = calleeObjectType(istate, node.callee);
4765
+ if (object) {
4754
4766
  const info = sysCallInfo(cur);
4755
4767
  if (info) {
4756
- const result = info(cur, object, () => args);
4768
+ const result = info(istate.state, cur, object, () => args);
4757
4769
  if (result.argTypes)
4758
4770
  argTypes = result.argTypes;
4759
4771
  if (result.returnType)
@@ -4892,7 +4904,7 @@ function sysCallInfo(func) {
4892
4904
  function getSystemCallTable() {
4893
4905
  if (systemCallInfo)
4894
4906
  return systemCallInfo;
4895
- const arrayAdd = (callee, calleeObj, getArgs) => {
4907
+ const arrayAdd = (state, callee, calleeObj, getArgs) => {
4896
4908
  const ret = {};
4897
4909
  if (calleeObj.type & 512 /* TypeTag.Array */) {
4898
4910
  const adata = getUnionComponent(calleeObj, 512 /* TypeTag.Array */);
@@ -4924,7 +4936,7 @@ function getSystemCallTable() {
4924
4936
  }
4925
4937
  return ret;
4926
4938
  };
4927
- const arrayRet = (callee, calleeObj, _getArgs) => {
4939
+ const arrayRet = (state, callee, calleeObj, _getArgs) => {
4928
4940
  const ret = { effectFree: true };
4929
4941
  if (calleeObj.type & 512 /* TypeTag.Array */) {
4930
4942
  const adata = getUnionComponent(calleeObj, 512 /* TypeTag.Array */);
@@ -4934,7 +4946,7 @@ function getSystemCallTable() {
4934
4946
  }
4935
4947
  return ret;
4936
4948
  };
4937
- const dictionaryGet = (callee, calleeObj, getArgs) => {
4949
+ const dictionaryGet = (state, callee, calleeObj, getArgs) => {
4938
4950
  const ret = { effectFree: true };
4939
4951
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
4940
4952
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -4948,7 +4960,7 @@ function getSystemCallTable() {
4948
4960
  }
4949
4961
  return ret;
4950
4962
  };
4951
- const dictionaryValues = (callee, calleeObj) => {
4963
+ const dictionaryValues = (state, callee, calleeObj) => {
4952
4964
  const ret = { effectFree: true };
4953
4965
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
4954
4966
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -4958,7 +4970,7 @@ function getSystemCallTable() {
4958
4970
  }
4959
4971
  return ret;
4960
4972
  };
4961
- const dictionaryKeys = (callee, calleeObj) => {
4973
+ const dictionaryKeys = (state, callee, calleeObj) => {
4962
4974
  const ret = { effectFree: true };
4963
4975
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
4964
4976
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -4968,7 +4980,7 @@ function getSystemCallTable() {
4968
4980
  }
4969
4981
  return ret;
4970
4982
  };
4971
- const dictionaryPut = (callee, calleeObj, getArgs) => {
4983
+ const dictionaryPut = (state, callee, calleeObj, getArgs) => {
4972
4984
  const ret = {};
4973
4985
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
4974
4986
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -4999,7 +5011,7 @@ function getSystemCallTable() {
4999
5011
  }
5000
5012
  return ret;
5001
5013
  };
5002
- const methodInvoke = (callee, calleeObj, getArgs) => {
5014
+ const methodInvoke = (state, callee, calleeObj, getArgs) => {
5003
5015
  const ret = { argEffects: true };
5004
5016
  if (calleeObj.type & 2048 /* TypeTag.Method */) {
5005
5017
  const data = getUnionComponent(calleeObj, 2048 /* TypeTag.Method */);
@@ -5012,9 +5024,49 @@ function getSystemCallTable() {
5012
5024
  ret.argTypes = getArgs();
5013
5025
  return ret;
5014
5026
  };
5027
+ const method = (state, callee, calleeObj, getArgs) => {
5028
+ const ret = {};
5029
+ const args = getArgs();
5030
+ if (args.length === 1 &&
5031
+ hasValue(args[0]) &&
5032
+ args[0].type === 131072 /* TypeTag.Symbol */) {
5033
+ const symbol = {
5034
+ type: "Identifier",
5035
+ name: args[0].value,
5036
+ };
5037
+ const next = {
5038
+ type: "MemberExpression",
5039
+ object: symbol,
5040
+ property: symbol,
5041
+ computed: false,
5042
+ };
5043
+ const [, trueDecls] = findObjectDeclsByProperty(state, calleeObj, next);
5044
+ if (!trueDecls)
5045
+ return ret;
5046
+ const callees = trueDecls
5047
+ .flatMap((decl) => decl.decls?.[symbol.name])
5048
+ .filter((decl) => decl?.type === "FunctionDeclaration");
5049
+ if (!callees.length)
5050
+ return ret;
5051
+ ret.returnType = callees.reduce((type, callee) => {
5052
+ const result = callee.node.returnType
5053
+ ? typeFromTypespec(state, callee.node.returnType.argument, callee.stack)
5054
+ : { type: 524287 /* TypeTag.Any */ };
5055
+ const args = callee.node.params.map((param) => param.type === "BinaryExpression"
5056
+ ? typeFromTypespec(state, param.right, callee.stack)
5057
+ : { type: 524287 /* TypeTag.Any */ });
5058
+ unionInto(type, {
5059
+ type: 2048 /* TypeTag.Method */,
5060
+ value: { result, args },
5061
+ });
5062
+ return type;
5063
+ }, { type: 0 /* TypeTag.Never */ });
5064
+ }
5065
+ return ret;
5066
+ };
5015
5067
  const nop = () => ({ effectFree: true });
5016
5068
  const mod = () => ({});
5017
- const rounder = (callee, calleeObj, getArgs) => {
5069
+ const rounder = (state, callee, calleeObj, getArgs) => {
5018
5070
  const results = {};
5019
5071
  const fn = Math[callee.name];
5020
5072
  results.effectFree = true;
@@ -5032,7 +5084,7 @@ function getSystemCallTable() {
5032
5084
  : { type: 120 /* TypeTag.Numeric */ };
5033
5085
  return results;
5034
5086
  };
5035
- const mathHelper = (callee, calleeObj, getArgs, helper) => {
5087
+ const mathHelper = (state, callee, calleeObj, getArgs, helper) => {
5036
5088
  const results = {};
5037
5089
  const fn = helper && typeof helper === "function"
5038
5090
  ? helper
@@ -5091,6 +5143,7 @@ function getSystemCallTable() {
5091
5143
  "$.Toybox.Lang.Dictionary.toString": nop,
5092
5144
  "$.Toybox.Lang.Dictionary.values": dictionaryValues,
5093
5145
  "$.Toybox.Lang.Method.invoke": methodInvoke,
5146
+ "$.Toybox.Lang.Object.method": method,
5094
5147
  "$.Toybox.Math.acos": mathHelper,
5095
5148
  "$.Toybox.Math.asin": mathHelper,
5096
5149
  "$.Toybox.Math.atan": mathHelper,
@@ -5098,15 +5151,15 @@ function getSystemCallTable() {
5098
5151
  "$.Toybox.Math.ceil": rounder,
5099
5152
  "$.Toybox.Math.cos": mathHelper,
5100
5153
  "$.Toybox.Math.floor": rounder,
5101
- "$.Toybox.Math.ln": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, "log"),
5102
- "$.Toybox.Math.log": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (x, base) => Math.log(x) / Math.log(base)),
5154
+ "$.Toybox.Math.ln": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, "log"),
5155
+ "$.Toybox.Math.log": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (x, base) => Math.log(x) / Math.log(base)),
5103
5156
  "$.Toybox.Math.pow": mathHelper,
5104
5157
  "$.Toybox.Math.round": rounder,
5105
5158
  "$.Toybox.Math.sin": mathHelper,
5106
5159
  "$.Toybox.Math.sqrt": mathHelper,
5107
5160
  "$.Toybox.Math.tan": mathHelper,
5108
- "$.Toybox.Math.toDegrees": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (arg) => (arg * 180) / Math.PI),
5109
- "$.Toybox.Math.toRadians": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (arg) => (arg * Math.PI) / 180),
5161
+ "$.Toybox.Math.toDegrees": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (arg) => (arg * 180) / Math.PI),
5162
+ "$.Toybox.Math.toRadians": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (arg) => (arg * Math.PI) / 180),
5110
5163
  "$.Toybox.Math.mean": nop,
5111
5164
  "$.Toybox.Math.mode": nop,
5112
5165
  "$.Toybox.Math.stdev": nop,
@@ -7312,8 +7365,8 @@ function display(type) {
7312
7365
  case 1024 /* TypeTag.Dictionary */:
7313
7366
  return `${display(tv.value.key)}, ${display(tv.value.value)}`;
7314
7367
  case 2048 /* TypeTag.Method */:
7315
- return `(${tv.value.args
7316
- .map((arg) => display(arg))
7368
+ return `Method(${tv.value.args
7369
+ .map((arg, i) => `a${i + 1} as ${display(arg)}`)
7317
7370
  .join(", ")}) as ${display(tv.value.result)}`;
7318
7371
  case 4096 /* TypeTag.Module */:
7319
7372
  case 8192 /* TypeTag.Function */:
@@ -7373,6 +7426,7 @@ function display(type) {
7373
7426
  65536 /* TypeTag.Enum */ |
7374
7427
  262144 /* TypeTag.Typedef */ |
7375
7428
  131072 /* TypeTag.Symbol */ |
7429
+ 2048 /* TypeTag.Method */ |
7376
7430
  256 /* TypeTag.String */)) {
7377
7431
  parts.push(valueStr);
7378
7432
  }
@@ -7400,7 +7454,7 @@ function forEachUnionComponent(v, bits, fn) {
7400
7454
  bits &= ~SingleTonTypeTagsConst;
7401
7455
  if (!bits)
7402
7456
  return;
7403
- if (v.type & UnionDataTypeTagsConst) {
7457
+ if ((v.type | bits) & UnionDataTypeTagsConst) {
7404
7458
  // Don't iterate the value type bits if any union bit is set
7405
7459
  bits &= ~ValueTypeTagsConst;
7406
7460
  }
@@ -5035,15 +5035,6 @@ function findCalleesByNode(state, callee) {
5035
5035
  return ((hasProperty(state.allFunctions, name) && state.allFunctions[name]) || null);
5036
5036
  }
5037
5037
 
5038
- ;// CONCATENATED MODULE: ./src/optimizer-types.ts
5039
- var StateNodeAttributes;
5040
- (function (StateNodeAttributes) {
5041
- StateNodeAttributes[StateNodeAttributes["PUBLIC"] = 1] = "PUBLIC";
5042
- StateNodeAttributes[StateNodeAttributes["PROTECTED"] = 2] = "PROTECTED";
5043
- StateNodeAttributes[StateNodeAttributes["PRIVATE"] = 4] = "PRIVATE";
5044
- StateNodeAttributes[StateNodeAttributes["STATIC"] = 8] = "STATIC";
5045
- })(StateNodeAttributes || (StateNodeAttributes = {}));
5046
-
5047
5038
  ;// CONCATENATED MODULE: ./src/variable-renamer.ts
5048
5039
 
5049
5040
 
@@ -5110,7 +5101,6 @@ function renameVariable(state, locals, declName) {
5110
5101
 
5111
5102
 
5112
5103
 
5113
-
5114
5104
  // Note: Keep in sync with replaceInlinedSubExpression below
5115
5105
  function inlinableSubExpression(expr) {
5116
5106
  while (true) {
@@ -5328,7 +5318,7 @@ function getArgSafety(state, func, args, requireAll) {
5328
5318
  }
5329
5319
  return null;
5330
5320
  };
5331
- state.stack = func.stack;
5321
+ state.stack = func.stack.concat(func);
5332
5322
  state.traverse(func.node.body);
5333
5323
  }
5334
5324
  finally {
@@ -5439,9 +5429,7 @@ function processInlineBody(state, func, call, root, params) {
5439
5429
  // lookup determines static-ness of the lookup context based on seeing
5440
5430
  // a static FunctionDeclaration, but the FunctionDeclaration's stack
5441
5431
  // doesn't include the FunctionDeclaration itself.
5442
- const stack = func.attributes & StateNodeAttributes.STATIC
5443
- ? func.stack.concat(func)
5444
- : func.stack;
5432
+ const lookupStack = func.stack.concat(func);
5445
5433
  try {
5446
5434
  state.pre = (node) => {
5447
5435
  if (failed)
@@ -5497,7 +5485,7 @@ function processInlineBody(state, func, call, root, params) {
5497
5485
  }
5498
5486
  return null;
5499
5487
  }
5500
- const replacement = fixNodeScope(state, node, stack);
5488
+ const replacement = fixNodeScope(state, node, lookupStack);
5501
5489
  if (!replacement) {
5502
5490
  failed = true;
5503
5491
  inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
@@ -5953,6 +5941,15 @@ function fixNodeScope(state, lookupNode, nodeStack) {
5953
5941
  return null;
5954
5942
  }
5955
5943
 
5944
+ ;// CONCATENATED MODULE: ./src/optimizer-types.ts
5945
+ var StateNodeAttributes;
5946
+ (function (StateNodeAttributes) {
5947
+ StateNodeAttributes[StateNodeAttributes["PUBLIC"] = 1] = "PUBLIC";
5948
+ StateNodeAttributes[StateNodeAttributes["PROTECTED"] = 2] = "PROTECTED";
5949
+ StateNodeAttributes[StateNodeAttributes["PRIVATE"] = 4] = "PRIVATE";
5950
+ StateNodeAttributes[StateNodeAttributes["STATIC"] = 8] = "STATIC";
5951
+ })(StateNodeAttributes || (StateNodeAttributes = {}));
5952
+
5956
5953
  ;// CONCATENATED MODULE: ./src/pragma-checker.ts
5957
5954
 
5958
5955
 
@@ -9848,8 +9845,8 @@ function display(type) {
9848
9845
  case 1024 /* TypeTag.Dictionary */:
9849
9846
  return `${display(tv.value.key)}, ${display(tv.value.value)}`;
9850
9847
  case 2048 /* TypeTag.Method */:
9851
- return `(${tv.value.args
9852
- .map((arg) => display(arg))
9848
+ return `Method(${tv.value.args
9849
+ .map((arg, i) => `a${i + 1} as ${display(arg)}`)
9853
9850
  .join(", ")}) as ${display(tv.value.result)}`;
9854
9851
  case 4096 /* TypeTag.Module */:
9855
9852
  case 8192 /* TypeTag.Function */:
@@ -9909,6 +9906,7 @@ function display(type) {
9909
9906
  65536 /* TypeTag.Enum */ |
9910
9907
  262144 /* TypeTag.Typedef */ |
9911
9908
  131072 /* TypeTag.Symbol */ |
9909
+ 2048 /* TypeTag.Method */ |
9912
9910
  256 /* TypeTag.String */)) {
9913
9911
  parts.push(valueStr);
9914
9912
  }
@@ -9936,7 +9934,7 @@ function forEachUnionComponent(v, bits, fn) {
9936
9934
  bits &= ~SingleTonTypeTagsConst;
9937
9935
  if (!bits)
9938
9936
  return;
9939
- if (v.type & UnionDataTypeTagsConst) {
9937
+ if ((v.type | bits) & UnionDataTypeTagsConst) {
9940
9938
  // Don't iterate the value type bits if any union bit is set
9941
9939
  bits &= ~ValueTypeTagsConst;
9942
9940
  }
@@ -10604,6 +10602,8 @@ function evaluateLogicalTypes(op, left, right) {
10604
10602
 
10605
10603
 
10606
10604
 
10605
+
10606
+
10607
10607
  function evaluateCall(istate, node, callee, args) {
10608
10608
  while (!hasValue(callee) || callee.type !== 8192 /* TypeTag.Function */) {
10609
10609
  const name = node.callee.type === "Identifier"
@@ -10626,6 +10626,20 @@ function evaluateCall(istate, node, callee, args) {
10626
10626
  }
10627
10627
  return checkCallArgs(istate, node, callee.value, args);
10628
10628
  }
10629
+ function calleeObjectType(istate, callee) {
10630
+ if (callee.type === "MemberExpression") {
10631
+ return (istate.typeMap?.get(callee.object) || {
10632
+ type: 524287 /* TypeTag.Any */,
10633
+ });
10634
+ }
10635
+ if (callee.type === "Identifier" && istate.func) {
10636
+ const func = istate.func;
10637
+ const [self] = func.stack.slice(-1);
10638
+ return typeFromTypeStateNode(istate.state, self, (func.attributes & StateNodeAttributes.STATIC) !== 0 ||
10639
+ self.type !== "ClassDeclaration");
10640
+ }
10641
+ return null;
10642
+ }
10629
10643
  function checkCallArgs(istate, node, callees, args) {
10630
10644
  const allDiags = [];
10631
10645
  const resultType = (0,external_util_cjs_namespaceObject.reduce)(callees, (result, cur) => {
@@ -10635,13 +10649,11 @@ function checkCallArgs(istate, node, callees, args) {
10635
10649
  let returnType = null;
10636
10650
  let effects = true;
10637
10651
  let argEffects = true;
10638
- if (node.callee.type === "MemberExpression") {
10639
- const object = istate.typeMap?.get(node.callee.object) || {
10640
- type: 524287 /* TypeTag.Any */,
10641
- };
10652
+ const object = calleeObjectType(istate, node.callee);
10653
+ if (object) {
10642
10654
  const info = sysCallInfo(cur);
10643
10655
  if (info) {
10644
- const result = info(cur, object, () => args);
10656
+ const result = info(istate.state, cur, object, () => args);
10645
10657
  if (result.argTypes)
10646
10658
  argTypes = result.argTypes;
10647
10659
  if (result.returnType)
@@ -10780,7 +10792,7 @@ function sysCallInfo(func) {
10780
10792
  function getSystemCallTable() {
10781
10793
  if (systemCallInfo)
10782
10794
  return systemCallInfo;
10783
- const arrayAdd = (callee, calleeObj, getArgs) => {
10795
+ const arrayAdd = (state, callee, calleeObj, getArgs) => {
10784
10796
  const ret = {};
10785
10797
  if (calleeObj.type & 512 /* TypeTag.Array */) {
10786
10798
  const adata = getUnionComponent(calleeObj, 512 /* TypeTag.Array */);
@@ -10812,7 +10824,7 @@ function getSystemCallTable() {
10812
10824
  }
10813
10825
  return ret;
10814
10826
  };
10815
- const arrayRet = (callee, calleeObj, _getArgs) => {
10827
+ const arrayRet = (state, callee, calleeObj, _getArgs) => {
10816
10828
  const ret = { effectFree: true };
10817
10829
  if (calleeObj.type & 512 /* TypeTag.Array */) {
10818
10830
  const adata = getUnionComponent(calleeObj, 512 /* TypeTag.Array */);
@@ -10822,7 +10834,7 @@ function getSystemCallTable() {
10822
10834
  }
10823
10835
  return ret;
10824
10836
  };
10825
- const dictionaryGet = (callee, calleeObj, getArgs) => {
10837
+ const dictionaryGet = (state, callee, calleeObj, getArgs) => {
10826
10838
  const ret = { effectFree: true };
10827
10839
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
10828
10840
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -10836,7 +10848,7 @@ function getSystemCallTable() {
10836
10848
  }
10837
10849
  return ret;
10838
10850
  };
10839
- const dictionaryValues = (callee, calleeObj) => {
10851
+ const dictionaryValues = (state, callee, calleeObj) => {
10840
10852
  const ret = { effectFree: true };
10841
10853
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
10842
10854
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -10846,7 +10858,7 @@ function getSystemCallTable() {
10846
10858
  }
10847
10859
  return ret;
10848
10860
  };
10849
- const dictionaryKeys = (callee, calleeObj) => {
10861
+ const dictionaryKeys = (state, callee, calleeObj) => {
10850
10862
  const ret = { effectFree: true };
10851
10863
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
10852
10864
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -10856,7 +10868,7 @@ function getSystemCallTable() {
10856
10868
  }
10857
10869
  return ret;
10858
10870
  };
10859
- const dictionaryPut = (callee, calleeObj, getArgs) => {
10871
+ const dictionaryPut = (state, callee, calleeObj, getArgs) => {
10860
10872
  const ret = {};
10861
10873
  if (calleeObj.type & 1024 /* TypeTag.Dictionary */) {
10862
10874
  const ddata = getUnionComponent(calleeObj, 1024 /* TypeTag.Dictionary */);
@@ -10887,7 +10899,7 @@ function getSystemCallTable() {
10887
10899
  }
10888
10900
  return ret;
10889
10901
  };
10890
- const methodInvoke = (callee, calleeObj, getArgs) => {
10902
+ const methodInvoke = (state, callee, calleeObj, getArgs) => {
10891
10903
  const ret = { argEffects: true };
10892
10904
  if (calleeObj.type & 2048 /* TypeTag.Method */) {
10893
10905
  const data = getUnionComponent(calleeObj, 2048 /* TypeTag.Method */);
@@ -10900,9 +10912,49 @@ function getSystemCallTable() {
10900
10912
  ret.argTypes = getArgs();
10901
10913
  return ret;
10902
10914
  };
10915
+ const method = (state, callee, calleeObj, getArgs) => {
10916
+ const ret = {};
10917
+ const args = getArgs();
10918
+ if (args.length === 1 &&
10919
+ hasValue(args[0]) &&
10920
+ args[0].type === 131072 /* TypeTag.Symbol */) {
10921
+ const symbol = {
10922
+ type: "Identifier",
10923
+ name: args[0].value,
10924
+ };
10925
+ const next = {
10926
+ type: "MemberExpression",
10927
+ object: symbol,
10928
+ property: symbol,
10929
+ computed: false,
10930
+ };
10931
+ const [, trueDecls] = findObjectDeclsByProperty(state, calleeObj, next);
10932
+ if (!trueDecls)
10933
+ return ret;
10934
+ const callees = trueDecls
10935
+ .flatMap((decl) => decl.decls?.[symbol.name])
10936
+ .filter((decl) => decl?.type === "FunctionDeclaration");
10937
+ if (!callees.length)
10938
+ return ret;
10939
+ ret.returnType = callees.reduce((type, callee) => {
10940
+ const result = callee.node.returnType
10941
+ ? typeFromTypespec(state, callee.node.returnType.argument, callee.stack)
10942
+ : { type: 524287 /* TypeTag.Any */ };
10943
+ const args = callee.node.params.map((param) => param.type === "BinaryExpression"
10944
+ ? typeFromTypespec(state, param.right, callee.stack)
10945
+ : { type: 524287 /* TypeTag.Any */ });
10946
+ unionInto(type, {
10947
+ type: 2048 /* TypeTag.Method */,
10948
+ value: { result, args },
10949
+ });
10950
+ return type;
10951
+ }, { type: 0 /* TypeTag.Never */ });
10952
+ }
10953
+ return ret;
10954
+ };
10903
10955
  const nop = () => ({ effectFree: true });
10904
10956
  const mod = () => ({});
10905
- const rounder = (callee, calleeObj, getArgs) => {
10957
+ const rounder = (state, callee, calleeObj, getArgs) => {
10906
10958
  const results = {};
10907
10959
  const fn = Math[callee.name];
10908
10960
  results.effectFree = true;
@@ -10920,7 +10972,7 @@ function getSystemCallTable() {
10920
10972
  : { type: 120 /* TypeTag.Numeric */ };
10921
10973
  return results;
10922
10974
  };
10923
- const mathHelper = (callee, calleeObj, getArgs, helper) => {
10975
+ const mathHelper = (state, callee, calleeObj, getArgs, helper) => {
10924
10976
  const results = {};
10925
10977
  const fn = helper && typeof helper === "function"
10926
10978
  ? helper
@@ -10979,6 +11031,7 @@ function getSystemCallTable() {
10979
11031
  "$.Toybox.Lang.Dictionary.toString": nop,
10980
11032
  "$.Toybox.Lang.Dictionary.values": dictionaryValues,
10981
11033
  "$.Toybox.Lang.Method.invoke": methodInvoke,
11034
+ "$.Toybox.Lang.Object.method": method,
10982
11035
  "$.Toybox.Math.acos": mathHelper,
10983
11036
  "$.Toybox.Math.asin": mathHelper,
10984
11037
  "$.Toybox.Math.atan": mathHelper,
@@ -10986,15 +11039,15 @@ function getSystemCallTable() {
10986
11039
  "$.Toybox.Math.ceil": rounder,
10987
11040
  "$.Toybox.Math.cos": mathHelper,
10988
11041
  "$.Toybox.Math.floor": rounder,
10989
- "$.Toybox.Math.ln": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, "log"),
10990
- "$.Toybox.Math.log": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (x, base) => Math.log(x) / Math.log(base)),
11042
+ "$.Toybox.Math.ln": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, "log"),
11043
+ "$.Toybox.Math.log": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (x, base) => Math.log(x) / Math.log(base)),
10991
11044
  "$.Toybox.Math.pow": mathHelper,
10992
11045
  "$.Toybox.Math.round": rounder,
10993
11046
  "$.Toybox.Math.sin": mathHelper,
10994
11047
  "$.Toybox.Math.sqrt": mathHelper,
10995
11048
  "$.Toybox.Math.tan": mathHelper,
10996
- "$.Toybox.Math.toDegrees": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (arg) => (arg * 180) / Math.PI),
10997
- "$.Toybox.Math.toRadians": (callee, calleeObj, getArgs) => mathHelper(callee, calleeObj, getArgs, (arg) => (arg * Math.PI) / 180),
11049
+ "$.Toybox.Math.toDegrees": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (arg) => (arg * 180) / Math.PI),
11050
+ "$.Toybox.Math.toRadians": (state, callee, calleeObj, getArgs) => mathHelper(state, callee, calleeObj, getArgs, (arg) => (arg * Math.PI) / 180),
10998
11051
  "$.Toybox.Math.mean": nop,
10999
11052
  "$.Toybox.Math.mode": nop,
11000
11053
  "$.Toybox.Math.stdev": nop,
@@ -12391,7 +12444,7 @@ function propagateTypes(state, func, graph, optimizeEquivalencies, logThisRun) {
12391
12444
  const info = sysCallInfo(callee);
12392
12445
  if (!info)
12393
12446
  return false;
12394
- const result = info(callee, calleeObj, () => node.arguments.map((arg) => evaluateExpr(state, arg, typeMap).value));
12447
+ const result = info(istate.state, callee, calleeObj, () => node.arguments.map((arg) => evaluateExpr(state, arg, typeMap).value));
12395
12448
  if (result.calleeObj) {
12396
12449
  setStateEvent(curState, calleeObjDecl, result.calleeObj, false);
12397
12450
  }
@@ -15325,7 +15378,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
15325
15378
  // the oldest optimized file, we don't need to regenerate
15326
15379
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
15327
15380
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
15328
- if (source_time < opt_time && 1674683508654 < opt_time) {
15381
+ if (source_time < opt_time && 1674746701563 < opt_time) {
15329
15382
  return { hasTests, diagnostics: prevDiagnostics };
15330
15383
  }
15331
15384
  }
@@ -15352,7 +15405,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
15352
15405
  return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
15353
15406
  hasTests,
15354
15407
  diagnostics,
15355
- optimizerVersion: "1.1.5",
15408
+ optimizerVersion: "1.1.7",
15356
15409
  ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
15357
15410
  }))
15358
15411
  .then(() => ({ hasTests, diagnostics }));
@@ -1,5 +1,5 @@
1
1
  import { mctree } from "@markw65/prettier-plugin-monkeyc";
2
- import { FunctionStateNode } from "src/optimizer-types";
2
+ import { FunctionStateNode, ProgramStateAnalysis } from "../optimizer-types";
3
3
  import { InterpStackElem, InterpState } from "./interp";
4
4
  import { ExactOrUnion } from "./types";
5
5
  export declare function evaluateCall(istate: InterpState, node: mctree.CallExpression, callee: ExactOrUnion, args: ExactOrUnion[]): InterpStackElem;
@@ -11,6 +11,6 @@ declare type SysCallHelperResult = {
11
11
  effectFree?: true;
12
12
  argEffects?: true;
13
13
  };
14
- declare type SysCallHelper = (func: FunctionStateNode, calleeObj: ExactOrUnion, getArgs: () => Array<ExactOrUnion>) => SysCallHelperResult;
14
+ declare type SysCallHelper = (state: ProgramStateAnalysis, func: FunctionStateNode, calleeObj: ExactOrUnion, getArgs: () => Array<ExactOrUnion>) => SysCallHelperResult;
15
15
  export declare function sysCallInfo(func: FunctionStateNode): SysCallHelper | null;
16
16
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.1.5",
4
+ "version": "1.1.7",
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",