@markw65/monkeyc-optimizer 1.0.39 → 1.0.40

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.
@@ -3977,7 +3977,7 @@ async function resolve_literals(qualifier, default_source, deviceInfo) {
3977
3977
  qualifier.annotations = annotations;
3978
3978
  return qualifier;
3979
3979
  }
3980
- async function read_resource_files(targets) {
3980
+ async function read_resource_files(targets, cache) {
3981
3981
  const resourceGroups = {};
3982
3982
  const resources = {};
3983
3983
  await Promise.all(targets.map(async (p) => {
@@ -3993,8 +3993,16 @@ async function read_resource_files(targets) {
3993
3993
  .flat()
3994
3994
  .filter((file) => file.endsWith(".xml"))
3995
3995
  .map((file) => {
3996
- if ((0,external_api_cjs_namespaceObject.hasProperty)(resources, file)) {
3997
- return { path: file, resources: resources[file] };
3996
+ if (!cache.resources) {
3997
+ cache.resources = {};
3998
+ }
3999
+ else if ((0,external_api_cjs_namespaceObject.hasProperty)(cache.resources, file)) {
4000
+ const rez = cache.resources[file];
4001
+ resources[file] = rez;
4002
+ return {
4003
+ path: file,
4004
+ resources: rez,
4005
+ };
3998
4006
  }
3999
4007
  return promises_namespaceObject.readFile(file)
4000
4008
  .then((data) => external_sdk_util_cjs_namespaceObject.xmlUtil.parseXml(data.toString(), file))
@@ -4002,7 +4010,7 @@ async function read_resource_files(targets) {
4002
4010
  ? e
4003
4011
  : new Error("An unknown error occurred"))
4004
4012
  .then((rez) => {
4005
- resources[file] = rez;
4013
+ cache.resources[file] = resources[file] = rez;
4006
4014
  return {
4007
4015
  path: file,
4008
4016
  resources: rez,
@@ -4408,13 +4416,13 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options, cac
4408
4416
  }
4409
4417
  });
4410
4418
  await promise;
4411
- const { resourceGroups, resources } = await read_resource_files(targets);
4419
+ const { resourceGroups, resources } = await read_resource_files(targets, cache);
4412
4420
  await find_build_instructions(targets, resourceGroups);
4413
4421
  return { manifest, targets, xml, annotations, jungles, resources };
4414
4422
  }
4415
- async function get_jungle(jungles, options) {
4423
+ async function get_jungle(jungles, options, resources) {
4416
4424
  options = options || {};
4417
- const cache = {};
4425
+ const cache = resources ? { resources: { ...resources } } : {};
4418
4426
  const result = await get_jungle_and_barrels(jungles, null, options, cache);
4419
4427
  identify_optimizer_groups(result.targets, options);
4420
4428
  return result;
@@ -4460,8 +4468,12 @@ function checkIfSimulatorRunningOn(port) {
4460
4468
  }
4461
4469
  function simulateProgram(prg, device, test = false, logger) {
4462
4470
  const args = [prg, device];
4463
- if (test)
4471
+ if (test) {
4464
4472
  args.push(external_sdk_util_cjs_namespaceObject.isWin ? "/t" : "-t");
4473
+ if (typeof test === "string") {
4474
+ args.push(test);
4475
+ }
4476
+ }
4465
4477
  return (0,external_sdk_util_cjs_namespaceObject.getSdkPath)().then((sdk) => (0,external_util_cjs_namespaceObject.spawnByLine)(external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "monkeydo.bat" : "monkeydo"), args, logger || ((line) => console.log(line))).then(() => {
4466
4478
  return;
4467
4479
  }));
@@ -4835,6 +4847,15 @@ function findCalleesForNew(lookupDefs) {
4835
4847
  .filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
4836
4848
  }
4837
4849
 
4850
+ ;// CONCATENATED MODULE: ./src/optimizer-types.ts
4851
+ var StateNodeAttributes;
4852
+ (function (StateNodeAttributes) {
4853
+ StateNodeAttributes[StateNodeAttributes["PUBLIC"] = 1] = "PUBLIC";
4854
+ StateNodeAttributes[StateNodeAttributes["PROTECTED"] = 2] = "PROTECTED";
4855
+ StateNodeAttributes[StateNodeAttributes["PRIVATE"] = 4] = "PRIVATE";
4856
+ StateNodeAttributes[StateNodeAttributes["STATIC"] = 8] = "STATIC";
4857
+ })(StateNodeAttributes || (StateNodeAttributes = {}));
4858
+
4838
4859
  ;// CONCATENATED MODULE: ./src/variable-renamer.ts
4839
4860
 
4840
4861
 
@@ -4901,6 +4922,7 @@ function renameVariable(state, locals, declName) {
4901
4922
 
4902
4923
 
4903
4924
 
4925
+
4904
4926
  // Note: Keep in sync with replaceInlinedSubExpression below
4905
4927
  function inlinableSubExpression(expr) {
4906
4928
  while (true) {
@@ -5220,6 +5242,12 @@ function processInlineBody(state, func, call, root, params) {
5220
5242
  state.inlining = true;
5221
5243
  let insertedVariableDecls = null;
5222
5244
  const replacements = new Set();
5245
+ // lookup determines static-ness of the lookup context based on seeing
5246
+ // a static FunctionDeclaration, but the FunctionDeclaration's stack
5247
+ // doesn't include the FunctionDeclaration itself.
5248
+ const stack = func.attributes & StateNodeAttributes.STATIC
5249
+ ? func.stack.concat(func)
5250
+ : func.stack;
5223
5251
  try {
5224
5252
  state.pre = (node) => {
5225
5253
  if (failed)
@@ -5269,7 +5297,7 @@ function processInlineBody(state, func, call, root, params) {
5269
5297
  }
5270
5298
  return null;
5271
5299
  }
5272
- const replacement = fixNodeScope(state, node, func.stack);
5300
+ const replacement = fixNodeScope(state, node, stack);
5273
5301
  if (!replacement) {
5274
5302
  failed = true;
5275
5303
  inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
@@ -5324,7 +5352,7 @@ function processInlineBody(state, func, call, root, params) {
5324
5352
  delete state.inlining;
5325
5353
  }
5326
5354
  }
5327
- function unused(expression, top) {
5355
+ function unused(state, expression, top) {
5328
5356
  const estmt = (expression) => withLoc({
5329
5357
  type: "ExpressionStatement",
5330
5358
  expression,
@@ -5338,19 +5366,19 @@ function unused(expression, top) {
5338
5366
  return [];
5339
5367
  case "BinaryExpression":
5340
5368
  if (expression.operator === "as") {
5341
- return unused(expression.left);
5369
+ return unused(state, expression.left);
5342
5370
  }
5343
- return unused(expression.left).concat(unused(expression.right));
5371
+ return unused(state, expression.left).concat(unused(state, expression.right));
5344
5372
  case "LogicalExpression": {
5345
- const right = unused(expression.right);
5373
+ const right = unused(state, expression.right);
5346
5374
  if (!right.length)
5347
- return unused(expression.left);
5375
+ return unused(state, expression.left);
5348
5376
  const consequent = withLoc({
5349
5377
  type: "BlockStatement",
5350
5378
  body: [estmt(expression.right)],
5351
5379
  }, expression.right);
5352
5380
  let alternate;
5353
- if (expression.operator == "||") {
5381
+ if (expression.operator == "||" || expression.operator == "or") {
5354
5382
  alternate = { ...consequent };
5355
5383
  consequent.body = [];
5356
5384
  }
@@ -5364,10 +5392,10 @@ function unused(expression, top) {
5364
5392
  ];
5365
5393
  }
5366
5394
  case "ConditionalExpression": {
5367
- const consequentExprs = unused(expression.consequent);
5368
- const alternateExprs = unused(expression.alternate);
5395
+ const consequentExprs = unused(state, expression.consequent);
5396
+ const alternateExprs = unused(state, expression.alternate);
5369
5397
  if (!consequentExprs.length && !alternateExprs.length) {
5370
- return unused(expression.test);
5398
+ return unused(state, expression.test);
5371
5399
  }
5372
5400
  return [
5373
5401
  withLoc({
@@ -5385,20 +5413,24 @@ function unused(expression, top) {
5385
5413
  ];
5386
5414
  }
5387
5415
  case "UnaryExpression":
5388
- return unused(expression.argument);
5416
+ return unused(state, expression.argument);
5389
5417
  case "MemberExpression":
5390
5418
  if (expression.computed) {
5391
- return unused(expression.object).concat(unused(expression.property));
5419
+ return unused(state, expression.object).concat(unused(state, expression.property));
5392
5420
  }
5393
- if (expression.object.type === "NewExpression") {
5421
+ if ((state.sdkVersion || 0) < 4001007 &&
5422
+ expression.object.type === "NewExpression") {
5423
+ // prior to 4.1.7 top level new expressions were discarded,
5424
+ // but (new X()).a was not. After 4.1.7, top level new is
5425
+ // executed, but top level (new X()).a is an error.
5394
5426
  break;
5395
5427
  }
5396
- return unused(expression.object);
5428
+ return unused(state, expression.object);
5397
5429
  case "ArrayExpression":
5398
- return expression.elements.map((e) => unused(e)).flat(1);
5430
+ return expression.elements.map((e) => unused(state, e)).flat(1);
5399
5431
  case "ObjectExpression":
5400
5432
  return expression.properties
5401
- .map((p) => unused(p.key).concat(unused(p.value)))
5433
+ .map((p) => unused(state, p.key).concat(unused(state, p.value)))
5402
5434
  .flat(1);
5403
5435
  }
5404
5436
  return top ? null : [estmt(expression)];
@@ -5558,7 +5590,7 @@ function inlineWithArgs(state, func, call, context) {
5558
5590
  ];
5559
5591
  }
5560
5592
  else {
5561
- const side_exprs = unused(last.argument);
5593
+ const side_exprs = unused(state, last.argument);
5562
5594
  block.body.splice(block.body.length - 1, 1, ...side_exprs);
5563
5595
  }
5564
5596
  }
@@ -5693,7 +5725,7 @@ function pragmaChecker(state, ast, diagnostics) {
5693
5725
  return;
5694
5726
  diagnostics = diagnostics
5695
5727
  ?.slice()
5696
- .sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
5728
+ .sort((d1, d2) => d1.loc.start.offset - d2.loc.start.offset);
5697
5729
  let diagIndex = 0;
5698
5730
  let index = -1;
5699
5731
  let comment;
@@ -5706,6 +5738,12 @@ function pragmaChecker(state, ast, diagnostics) {
5706
5738
  continue;
5707
5739
  const kind = match[1];
5708
5740
  let str = match[2];
5741
+ const verCheck = (0,external_api_cjs_namespaceObject.checkCompilerVersion)(str.replace(/\s.*/, ""), state.sdkVersion || 0);
5742
+ if (verCheck === false)
5743
+ continue;
5744
+ if (verCheck === true) {
5745
+ str = str.replace(/^\S+\s+/, "");
5746
+ }
5709
5747
  matchers = [];
5710
5748
  while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
5711
5749
  matchers.push({ kind, quote: match[1], needle: match[2] });
@@ -7258,7 +7296,7 @@ function cleanupUnusedVars(state, node) {
7258
7296
  if (node.expression.type === "AssignmentExpression") {
7259
7297
  if (node.expression.left.type === "Identifier" &&
7260
7298
  hasProperty(toRemove, node.expression.left.name)) {
7261
- return unused(node.expression.right);
7299
+ return unused(state, node.expression.right);
7262
7300
  }
7263
7301
  }
7264
7302
  else if (node.expression.type === "UpdateExpression" &&
@@ -7273,7 +7311,7 @@ function cleanupUnusedVars(state, node) {
7273
7311
  if (expr.type === "AssignmentExpression") {
7274
7312
  if (expr.left.type === "Identifier" &&
7275
7313
  hasProperty(toRemove, expr.left.name)) {
7276
- const rep = unused(expr.right);
7314
+ const rep = unused(state, expr.right);
7277
7315
  if (!rep.length) {
7278
7316
  node.expressions.splice(i, 1);
7279
7317
  }
@@ -7303,13 +7341,16 @@ function cleanupUnusedVars(state, node) {
7303
7341
  const vdecl = decl.declarations[i];
7304
7342
  const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id);
7305
7343
  if (hasProperty(toRemove, name)) {
7306
- const rep = vdecl.init ? unused(vdecl.init) : [];
7344
+ const rep = vdecl.init ? unused(state, vdecl.init) : [];
7307
7345
  if (rep.length) {
7308
- if (rep.find((s) => s.type === "ExpressionStatement" &&
7309
- (s.expression.type === "NewExpression" ||
7310
- (s.expression.type === "MemberExpression" &&
7311
- !s.expression.computed &&
7312
- s.expression.object.type === "NewExpression")))) {
7346
+ if ((state.sdkVersion || 0) < 4001007 &&
7347
+ rep.find((s) => s.type === "ExpressionStatement" &&
7348
+ (s.expression.type === "NewExpression" ||
7349
+ (s.expression.type === "MemberExpression" &&
7350
+ !s.expression.computed &&
7351
+ s.expression.object.type === "NewExpression")))) {
7352
+ // prior to 4.1.7 vanilla new expressions were discarded,
7353
+ // so don't create top level new expressions.
7313
7354
  continue;
7314
7355
  }
7315
7356
  if (parent.node.type === "ForStatement") {
@@ -7373,6 +7414,7 @@ function cleanupUnusedVars(state, node) {
7373
7414
 
7374
7415
 
7375
7416
 
7417
+
7376
7418
  function collectClassInfo(state) {
7377
7419
  const toybox = state.stack[0].decls["Toybox"][0];
7378
7420
  const lang = toybox.decls["Lang"][0];
@@ -7448,7 +7490,8 @@ function collectClassInfo(state) {
7448
7490
  if (elm.hasInvoke && elm.decls) {
7449
7491
  Object.values(elm.decls).forEach((funcs) => {
7450
7492
  funcs.forEach((f) => {
7451
- if (f.type === "FunctionDeclaration" && !f.isStatic) {
7493
+ if (f.type === "FunctionDeclaration" &&
7494
+ !(f.attributes & StateNodeAttributes.STATIC)) {
7452
7495
  (0,external_api_cjs_namespaceObject.markInvokeClassMethod)(f);
7453
7496
  }
7454
7497
  });
@@ -7527,11 +7570,6 @@ async function analyze(fnMap, resourcesMap, config) {
7527
7570
  const [scope] = state.stack.slice(-1);
7528
7571
  scope.stack = state.stackClone().slice(0, -1);
7529
7572
  if (scope.type == "FunctionDeclaration") {
7530
- scope.isStatic =
7531
- scope.stack.slice(-1)[0].type !== "ClassDeclaration" ||
7532
- (scope.node.attrs &&
7533
- scope.node.attrs.access &&
7534
- scope.node.attrs.access.includes("static"));
7535
7573
  if (markApi) {
7536
7574
  node.body = null;
7537
7575
  scope.info = (0,external_api_cjs_namespaceObject.getApiFunctionInfo)(scope);
@@ -7578,18 +7616,45 @@ function reportMissingSymbols(state, config) {
7578
7616
  const diagnosticType = config?.checkInvalidSymbols !== "OFF"
7579
7617
  ? config?.checkInvalidSymbols || "WARNING"
7580
7618
  : null;
7619
+ const compiler2DiagnosticType = config?.checkCompilerLookupRules !== "OFF"
7620
+ ? config?.checkCompilerLookupRules || "WARNING"
7621
+ : null;
7581
7622
  if (diagnosticType &&
7582
7623
  !config?.compilerOptions?.includes("--Eno-invalid-symbol")) {
7583
7624
  const checkTypes = config?.typeCheckLevel && config.typeCheckLevel !== "Off";
7584
7625
  Object.entries(state.fnMap).forEach(([, v]) => {
7585
7626
  (0,external_api_cjs_namespaceObject.visitReferences)(state, v.ast, null, false, (node, results, error) => {
7586
- if (!error)
7587
- return undefined;
7588
7627
  if (node.type === "BinaryExpression" && node.operator === "has") {
7589
7628
  // Its not an error to check whether a property exists...
7590
7629
  return undefined;
7591
7630
  }
7592
7631
  const nodeStr = (0,external_api_cjs_namespaceObject.formatAst)(node);
7632
+ if (!error) {
7633
+ if (state.sdkVersion === 4001006 &&
7634
+ compiler2DiagnosticType &&
7635
+ node.type === "MemberExpression" &&
7636
+ (node.object.type === "Identifier" ||
7637
+ node.object.type === "MemberExpression") &&
7638
+ results.some((result) => {
7639
+ const parent = result.parent;
7640
+ if (!parent || parent.type !== "ClassDeclaration") {
7641
+ return false;
7642
+ }
7643
+ return result.results.some((sn) => {
7644
+ switch (sn.type) {
7645
+ case "VariableDeclarator":
7646
+ case "FunctionDeclaration":
7647
+ return (sn.attributes &
7648
+ (StateNodeAttributes.PRIVATE |
7649
+ StateNodeAttributes.PROTECTED));
7650
+ }
7651
+ return false;
7652
+ });
7653
+ })) {
7654
+ diagnostic(state, node.loc, `The expression ${nodeStr} will fail at runtime using sdk-4.1.6`, compiler2DiagnosticType);
7655
+ }
7656
+ return undefined;
7657
+ }
7593
7658
  if (state.inType) {
7594
7659
  if (!checkTypes || nodeStr.match(/^Void|Null$/)) {
7595
7660
  return undefined;
@@ -7803,7 +7868,7 @@ function optimizeNode(state, node) {
7803
7868
  left.value === null ||
7804
7869
  ((left_type === "Number" || left_type === "Long") &&
7805
7870
  (left.value === 0 || left.value === 0n));
7806
- if (falsy === (node.operator === "&&")) {
7871
+ if (falsy === (node.operator === "&&" || node.operator === "and")) {
7807
7872
  return left;
7808
7873
  }
7809
7874
  if (left_type !== "Boolean" &&
@@ -7813,10 +7878,12 @@ function optimizeNode(state, node) {
7813
7878
  }
7814
7879
  const [right, right_type] = getNodeValue(node.right);
7815
7880
  if (right && right_type === left_type) {
7816
- if (left_type === "Boolean" || node.operator === "||") {
7881
+ if (left_type === "Boolean" ||
7882
+ node.operator === "||" ||
7883
+ node.operator === "or") {
7817
7884
  return right;
7818
7885
  }
7819
- if (node.operator !== "&&") {
7886
+ if (node.operator !== "&&" && node.operator !== "and") {
7820
7887
  throw new Error(`Unexpected operator "${node.operator}"`);
7821
7888
  }
7822
7889
  return { ...node, type: "BinaryExpression", operator: "&" };
@@ -8306,7 +8373,6 @@ async function optimizeMonkeyC(fnMap, resourcesMap, config) {
8306
8373
  if ((obj.type === "ModuleDeclaration" ||
8307
8374
  obj.type === "Program" ||
8308
8375
  obj.type === "ClassDeclaration") &&
8309
- obj.decls &&
8310
8376
  obj.stack) {
8311
8377
  const exists = (0,external_api_cjs_namespaceObject.hasProperty)(obj.decls, node.right.argument.name) ||
8312
8378
  // This is overkill, since we've already looked up
@@ -8407,7 +8473,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, config) {
8407
8473
  }
8408
8474
  }
8409
8475
  else {
8410
- const ret = unused(node.expression, true);
8476
+ const ret = unused(state, node.expression, true);
8411
8477
  if (ret) {
8412
8478
  return ret
8413
8479
  .map((r) => replace(r, r))
@@ -8811,11 +8877,8 @@ async function generateOptimizedProject(options) {
8811
8877
  const error = new Error(xml.body.children("iq:barrel").length()
8812
8878
  ? "Optimize the project that uses this barrel, not the barrel itself"
8813
8879
  : "Manifest is missing an `iq:application` tag");
8814
- error.location = {
8815
- start: { line: 1, column: 1 },
8816
- end: { line: 1, column: 1 },
8817
- source: manifest,
8818
- };
8880
+ error.location =
8881
+ xml.body.elements[0].loc || undefined;
8819
8882
  throw error;
8820
8883
  }
8821
8884
  const dependencyFiles = [manifest, ...jungles];
@@ -9019,6 +9082,7 @@ const configOptionsToCheck = [
9019
9082
  "ignoredAnnotations",
9020
9083
  "ignoredSourcePaths",
9021
9084
  "checkInvalidSymbols",
9085
+ "checkCompilerLookupRules",
9022
9086
  "sizeBasedPRE",
9023
9087
  "extensionVersion",
9024
9088
  ];
@@ -9079,7 +9143,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
9079
9143
  // the oldest optimized file, we don't need to regenerate
9080
9144
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
9081
9145
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
9082
- if (source_time < opt_time && 1668132957835 < opt_time) {
9146
+ if (source_time < opt_time && 1669424079462 < opt_time) {
9083
9147
  return { hasTests, diagnostics: prevDiagnostics };
9084
9148
  }
9085
9149
  }
@@ -9104,7 +9168,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
9104
9168
  return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
9105
9169
  hasTests,
9106
9170
  diagnostics,
9107
- optimizerVersion: "1.0.39",
9171
+ optimizerVersion: "1.0.40",
9108
9172
  ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
9109
9173
  }))
9110
9174
  .then(() => ({ hasTests, diagnostics }));
@@ -73,10 +73,11 @@ function peg$subclass(t,u){function r(){this.constructor=t}r.prototype=u.prototy
73
73
  ;// CONCATENATED MODULE: ./src/xml-util.ts
74
74
 
75
75
  class Document {
76
- constructor(prolog, body, misc) {
76
+ constructor(prolog, body, misc, source) {
77
77
  this.prolog = prolog;
78
78
  this.body = body;
79
79
  this.misc = misc;
80
+ this.source = source;
80
81
  }
81
82
  }
82
83
  function elementKids(e) {
@@ -155,7 +156,7 @@ function parseXml(content, fileName = null) {
155
156
  const [prolog, body, misc] = peg$parse(content, {
156
157
  grammarSource: fileName || "unknown",
157
158
  });
158
- return new Document(prolog, new Nodes(body), misc);
159
+ return new Document(prolog, new Nodes(body), misc, content);
159
160
  }
160
161
  function reference(s) {
161
162
  if (typeof s === "string")
@@ -1,9 +1,11 @@
1
1
  import { mctree } from "@markw65/prettier-plugin-monkeyc";
2
2
  import { hasProperty, traverseAst } from "./ast";
3
3
  import { JungleResourceMap } from "./jungles";
4
- import { FunctionInfo, FunctionStateNode, LookupDefinition, ProgramState, ProgramStateLive, ProgramStateNode, ProgramStateStack, StateNode, StateNodeDecl } from "./optimizer-types";
4
+ import { FunctionInfo, FunctionStateNode, LookupDefinition, ModuleStateNode, ProgramState, ProgramStateLive, ProgramStateNode, ProgramStateStack, StateNode, StateNodeDecl } from "./optimizer-types";
5
5
  export { visitorNode, visitReferences } from "./visitor";
6
6
  export { traverseAst, hasProperty };
7
+ export declare function parseSdkVersion(version: string | undefined): number;
8
+ export declare function checkCompilerVersion(version: string, sdkVer: number): boolean | undefined;
7
9
  export declare function getApiMapping(state?: ProgramState, resourcesMap?: Record<string, JungleResourceMap>): Promise<ProgramStateNode | null>;
8
10
  export declare function isStateNode(node: StateNodeDecl): node is StateNode;
9
11
  export declare function variableDeclarationName(node: mctree.TypedIdentifier | mctree.InstanceofIdentifier): string;
@@ -11,6 +13,12 @@ export declare function sameLookupResult(a: LookupDefinition[], b: LookupDefinit
11
13
  export declare function isLookupCandidate(node: mctree.MemberExpression): false | mctree.Identifier;
12
14
  export declare function collectNamespaces(ast: mctree.Program, stateIn?: ProgramState): ProgramStateNode;
13
15
  export declare function formatAst(node: mctree.Node, monkeyCSource?: string | null, options?: Record<string, unknown> | null): string;
14
- export declare function findUsingForNode(state: ProgramStateLive, stack: ProgramStateStack, i: number, node: mctree.Identifier, isType: boolean): StateNodeDecl[] | null;
16
+ export declare function findUsingForNode(state: ProgramStateLive, stack: ProgramStateStack, i: number, node: mctree.Identifier): ModuleStateNode | {
17
+ name: string;
18
+ decls: {
19
+ parent: StateNode;
20
+ results: StateNodeDecl[];
21
+ };
22
+ }[] | null;
15
23
  export declare function getApiFunctionInfo(func: FunctionStateNode): FunctionInfo;
16
24
  export declare function markInvokeClassMethod(func: FunctionStateNode): void;
@@ -3,8 +3,8 @@ import { FunctionStateNode, ProgramStateAnalysis, ProgramStateLive } from "./opt
3
3
  export declare function inlinableSubExpression(expr: mctree.Expression): mctree.SimpleCallExpression | null;
4
4
  export declare function shouldInline(state: ProgramStateAnalysis, func: FunctionStateNode, call: mctree.CallExpression, context: InlineContext | null): boolean;
5
5
  declare type InlineBody = mctree.BlockStatement | mctree.ExpressionStatement["expression"];
6
- export declare function unused(expression: mctree.ExpressionStatement["expression"]): mctree.Statement[];
7
- export declare function unused(expression: mctree.ExpressionStatement["expression"], top: true): mctree.Statement[] | null;
6
+ export declare function unused(state: ProgramStateAnalysis, expression: mctree.ExpressionStatement["expression"]): mctree.Statement[];
7
+ export declare function unused(state: ProgramStateAnalysis, expression: mctree.ExpressionStatement["expression"], top: true): mctree.Statement[] | null;
8
8
  export declare function diagnostic(state: ProgramStateLive, loc: mctree.Node["loc"], message: string | null, type?: NonNullable<ProgramStateAnalysis["diagnostics"]>[string][number]["type"]): void;
9
9
  export declare type InlineContext = mctree.ReturnStatement | mctree.IfStatement | mctree.AssignmentExpression | mctree.ExpressionStatement | mctree.VariableDeclarator;
10
10
  export declare function inlineFunction(state: ProgramStateAnalysis, func: FunctionStateNode, call: mctree.CallExpression, context: InlineContext | null): InlineBody | null;
@@ -52,5 +52,5 @@ export declare type ResolvedJungle = JungleInfoBase & {
52
52
  export declare type ResolvedBarrel = JungleInfoBase & {
53
53
  qualifier: JungleQualifier;
54
54
  };
55
- export declare function get_jungle(jungles: string, options: BuildConfig): Promise<ResolvedJungle>;
55
+ export declare function get_jungle(jungles: string, options: BuildConfig, resources?: JungleResourceMap | undefined): Promise<ResolvedJungle>;
56
56
  export {};
@@ -2,4 +2,4 @@ import { LineHandler } from "./util";
2
2
  export declare function launchSimulator(force?: boolean): Promise<void>;
3
3
  export declare function checkIfSimulatorRunning(): Promise<boolean>;
4
4
  export declare function checkIfSimulatorRunningOn(port: number): Promise<boolean>;
5
- export declare function simulateProgram(prg: string, device: string, test?: boolean, logger?: LineHandler | LineHandler[]): Promise<void>;
5
+ export declare function simulateProgram(prg: string, device: string, test?: boolean | string, logger?: LineHandler | LineHandler[]): Promise<void>;
@@ -1,5 +1,7 @@
1
1
  import { mctree } from "@markw65/prettier-plugin-monkeyc";
2
2
  export declare type DiagnosticType = "ERROR" | "WARNING" | "INFO";
3
+ export declare type LookupRules = "COMPILER1" | "COMPILER2" | "DEFAULT";
4
+ export declare type EnforceStatic = "YES" | "NO";
3
5
  export declare type BuildConfig = {
4
6
  workspace?: string;
5
7
  jungleFiles?: string;
@@ -23,6 +25,9 @@ export declare type BuildConfig = {
23
25
  returnCommand?: boolean;
24
26
  checkBuildPragmas?: boolean;
25
27
  checkInvalidSymbols?: DiagnosticType | "OFF";
28
+ checkCompilerLookupRules?: DiagnosticType | "OFF";
29
+ compilerLookupRules?: LookupRules;
30
+ enforceStatic?: EnforceStatic;
26
31
  sizeBasedPRE?: boolean | string;
27
32
  prettier?: Record<string, unknown>;
28
33
  extensionVersion?: string;
@@ -35,6 +40,12 @@ export declare type ImportUsing = {
35
40
  node: mctree.Using | mctree.ImportModule;
36
41
  module?: ModuleStateNode | null | undefined;
37
42
  };
43
+ export declare enum StateNodeAttributes {
44
+ PUBLIC = 1,
45
+ PROTECTED = 2,
46
+ PRIVATE = 4,
47
+ STATIC = 8
48
+ }
38
49
  interface BaseStateNode {
39
50
  type: string;
40
51
  node: mctree.Node | null | undefined;
@@ -45,6 +56,7 @@ interface BaseStateNode {
45
56
  stack?: ProgramStateStack | undefined;
46
57
  usings?: Record<string, ImportUsing>;
47
58
  imports?: ImportUsing[];
59
+ attributes: StateNodeAttributes;
48
60
  }
49
61
  export interface ProgramStateNode extends BaseStateNode {
50
62
  type: "Program";
@@ -82,7 +94,6 @@ export interface FunctionStateNode extends BaseStateNode {
82
94
  fullName: string;
83
95
  stack?: ProgramStateStack;
84
96
  decls?: undefined;
85
- isStatic?: boolean;
86
97
  info?: FunctionInfo;
87
98
  next_info?: FunctionInfo;
88
99
  }
@@ -133,6 +144,9 @@ export declare type ProgramState = {
133
144
  inType?: number;
134
145
  inlining?: true;
135
146
  config?: BuildConfig;
147
+ sdk?: string;
148
+ sdkVersion?: number;
149
+ lookupRules?: LookupRules;
136
150
  nextExposed?: Record<string, true>;
137
151
  exposed?: Record<string, true>;
138
152
  usedByName?: Record<string, true>;
@@ -166,7 +180,7 @@ export declare type ProgramState = {
166
180
  declare type Finalized<T, Keys extends keyof T> = T & {
167
181
  [key in Keys]-?: NonNullable<T[key]>;
168
182
  };
169
- export declare type ProgramStateLive = Finalized<ProgramState, "stack" | "lookup" | "lookupValue" | "lookupType" | "lookupNonlocal" | "stackClone" | "traverse" | "index" | "constants" | "removeNodeComments" | "inType" | "nextExposed">;
183
+ export declare type ProgramStateLive = Finalized<ProgramState, "stack" | "lookup" | "lookupValue" | "lookupType" | "lookupNonlocal" | "stackClone" | "traverse" | "index" | "constants" | "removeNodeComments" | "inType" | "nextExposed" | "lookupRules">;
170
184
  export declare type ProgramStateAnalysis = Finalized<ProgramStateLive, "allClasses" | "allFunctions" | "fnMap">;
171
185
  export declare type ProgramStateOptimizer = Finalized<ProgramStateAnalysis, "localsStack" | "exposed" | "calledFunctions" | "usedByName">;
172
186
  export declare type ExcludeAnnotationsMap = {
@@ -12,10 +12,12 @@ export declare type RemoteProject = string | {
12
12
  include?: string;
13
13
  sourcePath?: string;
14
14
  jungleContent?: string[];
15
+ garminOptLevel?: number;
15
16
  };
16
17
  export declare const githubProjects: RemoteProject[];
17
18
  export declare function fetchGitProjects(projects: RemoteProject[]): Promise<(string | {
18
19
  jungle: string;
19
20
  build: boolean | null;
20
21
  options: BuildConfig | null;
22
+ garminOptLevel: number | null;
21
23
  })[]>;
@@ -118,7 +118,8 @@ export declare class Document {
118
118
  prolog: Prolog;
119
119
  body: Nodes;
120
120
  misc: Array<Misc>;
121
- constructor(prolog: Prolog, body: Nodes, misc: Array<Misc>);
121
+ source?: string | undefined;
122
+ constructor(prolog: Prolog, body: Nodes, misc: Array<Misc>, source?: string | undefined);
122
123
  }
123
124
  export declare function elementKids(e: Element): Element[];
124
125
  declare type ElementMatcher = string | ((c: Element) => boolean);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.0.39",
4
+ "version": "1.0.40",
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",
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "scripts": {
19
19
  "watch": "webpack --mode development --watch",
20
+ "prettier-live": "test -z \"$(git status --untracked-files=no --porcelain || echo dirty)\" && npm install ../prettier-plugin-monkeyc && git commit -am 'prettier-plugin-monkeyc-live'",
20
21
  "build-debug": "webpack --mode development",
21
22
  "build-release": "webpack --mode production",
22
23
  "prepack": "webpack --mode production",
@@ -37,7 +38,7 @@
37
38
  "author": "markw65",
38
39
  "license": "MIT",
39
40
  "dependencies": {
40
- "@markw65/prettier-plugin-monkeyc": "^1.0.36"
41
+ "@markw65/prettier-plugin-monkeyc": "^1.0.37"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/glob": "^8.0.0",