@markw65/monkeyc-optimizer 1.0.32 → 1.0.35

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
@@ -384,3 +384,33 @@ Bug Fixes
384
384
  - Bug fixes
385
385
  - Fixup the tests to run unoptimized again, and add running unoptimized to the standard test run
386
386
  - Fix PRE to not merge Numbers and Floats (ie 1 is not the same thing as 1.0), and add a test
387
+
388
+ ### 1.0.33
389
+
390
+ - New features
391
+
392
+ - Tagging a function with (:keep) will prevent the optimizer from removing it, even if it appears to be unused.
393
+
394
+ - Bug fixes
395
+ - Fix PRE to not merge values with different types. ie Number, Long, Float and Double literals should all be treated separately, even when the compare the same.
396
+
397
+ ### 1.0.34
398
+
399
+ - Bug fixes
400
+
401
+ - Fix parser to allow white space to separate attributes, in addition to comma
402
+ - Fix optimizer to respect prettier options when formatting the optimized code
403
+
404
+ - Testing
405
+ - rewrite test harness in typescript
406
+ - fix up tests to work with compiler2 again, and also with compiler2 at -O0
407
+
408
+ ### 1.0.35
409
+
410
+ - Testing
411
+
412
+ - Add a new open source project
413
+ - Fixup tests to work with compiler2beta2
414
+
415
+ - Bug fixes
416
+ - Fixed a bug that caused the optimizer to fail if a top level variable declared in a case statement had an initializer with side effects. This didn't produce incorrect results, the optimizer simply bailed out with an obscure error, and refused to optimize the project.
package/build/api.cjs CHANGED
@@ -281,6 +281,7 @@ const promises_namespaceObject = require("fs/promises");
281
281
  ;// CONCATENATED MODULE: external "prettier"
282
282
  const external_prettier_namespaceObject = require("prettier");
283
283
  ;// CONCATENATED MODULE: ./src/ast.ts
284
+
284
285
  /*
285
286
  * This ensures that mctreeTypeInfo has every key of MCTreeTypeInfo,
286
287
  * and that the corresponding arrays contain every element of the
@@ -482,6 +483,44 @@ function ast_withLocDeep(node, start, end, inplace) {
482
483
  function ast_cloneDeep(node) {
483
484
  return ast_withLocDeep(node, null);
484
485
  }
486
+ function ast_getNodeValue(node) {
487
+ if (node.type == "BinaryExpression" &&
488
+ node.operator == "as" &&
489
+ node.right.type == "TypeSpecList" &&
490
+ node.right.ts.length == 1 &&
491
+ typeof node.right.ts[0] == "string") {
492
+ // this is a cast we inserted to retain the type of an enum
493
+ // any arithmetic on it will revert to "Number", or "Long",
494
+ // so just ignore it.
495
+ return ast_getNodeValue(node.left);
496
+ }
497
+ if (node.type != "Literal") {
498
+ return [null, null];
499
+ }
500
+ if (node.value === null) {
501
+ return [node, "Null"];
502
+ }
503
+ const type = typeof node.value;
504
+ if (type === "number") {
505
+ const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
506
+ if (match) {
507
+ return match[2] === "l" || match[2] === "L"
508
+ ? [node, "Long"]
509
+ : [node, "Number"];
510
+ }
511
+ return [node, node.raw.endsWith("d") ? "Double" : "Float"];
512
+ }
513
+ if (type === "bigint") {
514
+ return [node, "Long"];
515
+ }
516
+ if (type === "string") {
517
+ return [node, "String"];
518
+ }
519
+ if (type === "boolean") {
520
+ return [node, "Boolean"];
521
+ }
522
+ throw new Error(`Literal has unknown type '${type}'`);
523
+ }
485
524
 
486
525
  ;// CONCATENATED MODULE: external "./api.cjs"
487
526
  const external_api_cjs_namespaceObject = require("./api.cjs");
@@ -1980,7 +2019,6 @@ var priorityqueuejs = __webpack_require__(2789);
1980
2019
 
1981
2020
 
1982
2021
 
1983
-
1984
2022
  /**
1985
2023
  * This implements a pseudo Partial Redundancy Elimination
1986
2024
  * pass. It isn't quite like traditional PRE because we're
@@ -2165,9 +2203,11 @@ function buildPREGraph(state, func) {
2165
2203
  break;
2166
2204
  case "Literal":
2167
2205
  if (refCost(node) > LocalRefCost) {
2168
- const key = LiteralIntegerRe.test(node.raw)
2169
- ? BigInt(node.value)
2170
- : node.value;
2206
+ const result = getNodeValue(node);
2207
+ const key = result[1] +
2208
+ (result[0].value === null
2209
+ ? ""
2210
+ : "-" + result[0].value.toString());
2171
2211
  let decl = literals.get(key);
2172
2212
  if (!decl) {
2173
2213
  decl = node;
@@ -2880,18 +2920,35 @@ function unused_exprs_cleanupUnusedVars(state, node) {
2880
2920
  });
2881
2921
  if (toRemove) {
2882
2922
  const varDeclarations = new Map();
2883
- traverseAst(node, null, (node) => {
2923
+ const stack = [];
2924
+ traverseAst(node, (node) => {
2925
+ switch (node.type) {
2926
+ case "SwitchCase":
2927
+ stack.push(node.consequent);
2928
+ break;
2929
+ case "BlockStatement":
2930
+ stack.push(node.body);
2931
+ break;
2932
+ }
2933
+ }, (node) => {
2884
2934
  switch (node.type) {
2935
+ case "SwitchCase":
2936
+ case "BlockStatement":
2937
+ stack.pop();
2938
+ break;
2885
2939
  case "VariableDeclaration": {
2886
2940
  node.declarations.forEach((decl, i) => {
2887
2941
  const name = variableDeclarationName(decl.id);
2888
2942
  if (hasProperty(toRemove, name)) {
2889
- const indices = varDeclarations.get(node);
2890
- if (indices) {
2891
- indices.push(i);
2943
+ const info = varDeclarations.get(node);
2944
+ if (info) {
2945
+ info.indices.push(i);
2892
2946
  }
2893
2947
  else {
2894
- varDeclarations.set(node, [i]);
2948
+ varDeclarations.set(node, {
2949
+ parent: stack[stack.length - 1],
2950
+ indices: [i],
2951
+ });
2895
2952
  }
2896
2953
  }
2897
2954
  });
@@ -2939,10 +2996,10 @@ function unused_exprs_cleanupUnusedVars(state, node) {
2939
2996
  }
2940
2997
  return null;
2941
2998
  });
2942
- varDeclarations.forEach((indices, decl) => {
2999
+ varDeclarations.forEach((info, decl) => {
2943
3000
  let index = -1;
2944
- for (let ii = indices.length, j = decl.declarations.length; ii--;) {
2945
- const i = indices[ii];
3001
+ for (let ii = info.indices.length, j = decl.declarations.length; ii--;) {
3002
+ const i = info.indices[ii];
2946
3003
  const vdecl = decl.declarations[i];
2947
3004
  const name = variableDeclarationName(vdecl.id);
2948
3005
  if (hasProperty(toRemove, name)) {
@@ -2954,7 +3011,7 @@ function unused_exprs_cleanupUnusedVars(state, node) {
2954
3011
  continue;
2955
3012
  }
2956
3013
  if (index < 0) {
2957
- index = parent.node.body.findIndex((s) => s === decl);
3014
+ index = info.parent.findIndex((s) => s === decl);
2958
3015
  if (index < 0) {
2959
3016
  throw new Error(`Failed to find variable declaration for ${variableDeclarationName(vdecl.id)}`);
2960
3017
  }
@@ -2975,7 +3032,7 @@ function unused_exprs_cleanupUnusedVars(state, node) {
2975
3032
  decl.end = vdecl.start;
2976
3033
  }
2977
3034
  decl.declarations.splice(i);
2978
- parent.node.body.splice(index + 1, 0, ...rep);
3035
+ info.parent.splice(index + 1, 0, ...rep);
2979
3036
  j = i;
2980
3037
  continue;
2981
3038
  }
@@ -3371,7 +3428,7 @@ function getLiteralNode(node) {
3371
3428
  return null;
3372
3429
  switch (node.operator) {
3373
3430
  case "-": {
3374
- const [arg, type] = getNodeValue(node.argument);
3431
+ const [arg, type] = ast_getNodeValue(node.argument);
3375
3432
  if (type === "Number" || type === "Long") {
3376
3433
  return replacementLiteral(arg, -arg.value, type);
3377
3434
  }
@@ -3380,44 +3437,6 @@ function getLiteralNode(node) {
3380
3437
  }
3381
3438
  return null;
3382
3439
  }
3383
- function getNodeValue(node) {
3384
- if (node.type == "BinaryExpression" &&
3385
- node.operator == "as" &&
3386
- node.right.type == "TypeSpecList" &&
3387
- node.right.ts.length == 1 &&
3388
- typeof node.right.ts[0] == "string") {
3389
- // this is a cast we inserted to retain the type of an enum
3390
- // any arithmetic on it will revert to "Number", or "Long",
3391
- // so just ignore it.
3392
- return getNodeValue(node.left);
3393
- }
3394
- if (node.type != "Literal") {
3395
- return [null, null];
3396
- }
3397
- if (node.value === null) {
3398
- return [node, "Null"];
3399
- }
3400
- const type = typeof node.value;
3401
- if (type === "number") {
3402
- const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
3403
- if (match) {
3404
- return match[2] === "l" || match[2] === "L"
3405
- ? [node, "Long"]
3406
- : [node, "Number"];
3407
- }
3408
- return [node, node.raw.endsWith("d") ? "Double" : "Float"];
3409
- }
3410
- if (type === "bigint") {
3411
- return [node, "Long"];
3412
- }
3413
- if (type === "string") {
3414
- return [node, "String"];
3415
- }
3416
- if (type === "boolean") {
3417
- return [node, "Boolean"];
3418
- }
3419
- throw new Error(`Literal has unknown type '${type}'`);
3420
- }
3421
3440
  function fullTypeName(state, tsp) {
3422
3441
  if (typeof tsp.name === "string") {
3423
3442
  return tsp.name;
@@ -4250,6 +4269,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
4250
4269
  break;
4251
4270
  case "FunctionDeclaration":
4252
4271
  if (!maybeCalled(node)) {
4272
+ if (node.attrs &&
4273
+ node.attrs.attributes &&
4274
+ node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" && attr.argument.name === "keep")) {
4275
+ break;
4276
+ }
4253
4277
  return false;
4254
4278
  }
4255
4279
  break;
@@ -5052,7 +5076,7 @@ function api_collectNamespaces(ast, stateIn) {
5052
5076
  }
5053
5077
  return state.stack[0];
5054
5078
  }
5055
- function api_formatAst(node, monkeyCSource = null) {
5079
+ function api_formatAst(node, monkeyCSource = null, options = null) {
5056
5080
  /*
5057
5081
  * The estree printer sometimes looks at the parent node without
5058
5082
  * checking that there *is* a parent node (eg it assumes all
@@ -5080,6 +5104,7 @@ function api_formatAst(node, monkeyCSource = null) {
5080
5104
  // looking for in the source.
5081
5105
  const source = (monkeyCSource || "") + "\n" + (0,prettier_plugin_monkeyc_namespaceObject.serializeMonkeyC)(node);
5082
5106
  return external_prettier_namespaceObject.format(source, {
5107
+ ...(options || {}),
5083
5108
  parser: "monkeyc-json",
5084
5109
  plugins: [(prettier_plugin_monkeyc_default())],
5085
5110
  endOfLine: "lf",
@@ -10024,6 +10024,8 @@ const external_crypto_namespaceObject = require("crypto");
10024
10024
  const promises_namespaceObject = require("fs/promises");
10025
10025
  // EXTERNAL MODULE: external "path"
10026
10026
  var external_path_ = __webpack_require__(1423);
10027
+ ;// CONCATENATED MODULE: external "prettier"
10028
+ const external_prettier_namespaceObject = require("prettier");
10027
10029
  ;// CONCATENATED MODULE: external "./api.cjs"
10028
10030
  const external_api_cjs_namespaceObject = require("./api.cjs");
10029
10031
  ;// CONCATENATED MODULE: external "./sdk-util.cjs"
@@ -10977,6 +10979,7 @@ function simulateProgram(prg, device, test = false, logger) {
10977
10979
  }
10978
10980
 
10979
10981
  ;// CONCATENATED MODULE: ./src/ast.ts
10982
+
10980
10983
  /*
10981
10984
  * This ensures that mctreeTypeInfo has every key of MCTreeTypeInfo,
10982
10985
  * and that the corresponding arrays contain every element of the
@@ -11178,6 +11181,44 @@ function withLocDeep(node, start, end, inplace) {
11178
11181
  function cloneDeep(node) {
11179
11182
  return withLocDeep(node, null);
11180
11183
  }
11184
+ function getNodeValue(node) {
11185
+ if (node.type == "BinaryExpression" &&
11186
+ node.operator == "as" &&
11187
+ node.right.type == "TypeSpecList" &&
11188
+ node.right.ts.length == 1 &&
11189
+ typeof node.right.ts[0] == "string") {
11190
+ // this is a cast we inserted to retain the type of an enum
11191
+ // any arithmetic on it will revert to "Number", or "Long",
11192
+ // so just ignore it.
11193
+ return getNodeValue(node.left);
11194
+ }
11195
+ if (node.type != "Literal") {
11196
+ return [null, null];
11197
+ }
11198
+ if (node.value === null) {
11199
+ return [node, "Null"];
11200
+ }
11201
+ const type = typeof node.value;
11202
+ if (type === "number") {
11203
+ const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
11204
+ if (match) {
11205
+ return match[2] === "l" || match[2] === "L"
11206
+ ? [node, "Long"]
11207
+ : [node, "Number"];
11208
+ }
11209
+ return [node, node.raw.endsWith("d") ? "Double" : "Float"];
11210
+ }
11211
+ if (type === "bigint") {
11212
+ return [node, "Long"];
11213
+ }
11214
+ if (type === "string") {
11215
+ return [node, "String"];
11216
+ }
11217
+ if (type === "boolean") {
11218
+ return [node, "Boolean"];
11219
+ }
11220
+ throw new Error(`Literal has unknown type '${type}'`);
11221
+ }
11181
11222
 
11182
11223
  ;// CONCATENATED MODULE: ./src/function-info.ts
11183
11224
 
@@ -12672,7 +12713,6 @@ var priorityqueuejs = __webpack_require__(2789);
12672
12713
 
12673
12714
 
12674
12715
 
12675
-
12676
12716
  /**
12677
12717
  * This implements a pseudo Partial Redundancy Elimination
12678
12718
  * pass. It isn't quite like traditional PRE because we're
@@ -12857,9 +12897,11 @@ function buildPREGraph(state, func) {
12857
12897
  break;
12858
12898
  case "Literal":
12859
12899
  if (refCost(node) > LocalRefCost) {
12860
- const key = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(node.raw)
12861
- ? BigInt(node.value)
12862
- : node.value;
12900
+ const result = getNodeValue(node);
12901
+ const key = result[1] +
12902
+ (result[0].value === null
12903
+ ? ""
12904
+ : "-" + result[0].value.toString());
12863
12905
  let decl = literals.get(key);
12864
12906
  if (!decl) {
12865
12907
  decl = node;
@@ -13572,18 +13614,35 @@ function cleanupUnusedVars(state, node) {
13572
13614
  });
13573
13615
  if (toRemove) {
13574
13616
  const varDeclarations = new Map();
13575
- traverseAst(node, null, (node) => {
13617
+ const stack = [];
13618
+ traverseAst(node, (node) => {
13619
+ switch (node.type) {
13620
+ case "SwitchCase":
13621
+ stack.push(node.consequent);
13622
+ break;
13623
+ case "BlockStatement":
13624
+ stack.push(node.body);
13625
+ break;
13626
+ }
13627
+ }, (node) => {
13576
13628
  switch (node.type) {
13629
+ case "SwitchCase":
13630
+ case "BlockStatement":
13631
+ stack.pop();
13632
+ break;
13577
13633
  case "VariableDeclaration": {
13578
13634
  node.declarations.forEach((decl, i) => {
13579
13635
  const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(decl.id);
13580
13636
  if (hasProperty(toRemove, name)) {
13581
- const indices = varDeclarations.get(node);
13582
- if (indices) {
13583
- indices.push(i);
13637
+ const info = varDeclarations.get(node);
13638
+ if (info) {
13639
+ info.indices.push(i);
13584
13640
  }
13585
13641
  else {
13586
- varDeclarations.set(node, [i]);
13642
+ varDeclarations.set(node, {
13643
+ parent: stack[stack.length - 1],
13644
+ indices: [i],
13645
+ });
13587
13646
  }
13588
13647
  }
13589
13648
  });
@@ -13631,10 +13690,10 @@ function cleanupUnusedVars(state, node) {
13631
13690
  }
13632
13691
  return null;
13633
13692
  });
13634
- varDeclarations.forEach((indices, decl) => {
13693
+ varDeclarations.forEach((info, decl) => {
13635
13694
  let index = -1;
13636
- for (let ii = indices.length, j = decl.declarations.length; ii--;) {
13637
- const i = indices[ii];
13695
+ for (let ii = info.indices.length, j = decl.declarations.length; ii--;) {
13696
+ const i = info.indices[ii];
13638
13697
  const vdecl = decl.declarations[i];
13639
13698
  const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id);
13640
13699
  if (hasProperty(toRemove, name)) {
@@ -13646,7 +13705,7 @@ function cleanupUnusedVars(state, node) {
13646
13705
  continue;
13647
13706
  }
13648
13707
  if (index < 0) {
13649
- index = parent.node.body.findIndex((s) => s === decl);
13708
+ index = info.parent.findIndex((s) => s === decl);
13650
13709
  if (index < 0) {
13651
13710
  throw new Error(`Failed to find variable declaration for ${(0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id)}`);
13652
13711
  }
@@ -13667,7 +13726,7 @@ function cleanupUnusedVars(state, node) {
13667
13726
  decl.end = vdecl.start;
13668
13727
  }
13669
13728
  decl.declarations.splice(i);
13670
- parent.node.body.splice(index + 1, 0, ...rep);
13729
+ info.parent.splice(index + 1, 0, ...rep);
13671
13730
  j = i;
13672
13731
  continue;
13673
13732
  }
@@ -14071,44 +14130,6 @@ function getLiteralNode(node) {
14071
14130
  }
14072
14131
  return null;
14073
14132
  }
14074
- function getNodeValue(node) {
14075
- if (node.type == "BinaryExpression" &&
14076
- node.operator == "as" &&
14077
- node.right.type == "TypeSpecList" &&
14078
- node.right.ts.length == 1 &&
14079
- typeof node.right.ts[0] == "string") {
14080
- // this is a cast we inserted to retain the type of an enum
14081
- // any arithmetic on it will revert to "Number", or "Long",
14082
- // so just ignore it.
14083
- return getNodeValue(node.left);
14084
- }
14085
- if (node.type != "Literal") {
14086
- return [null, null];
14087
- }
14088
- if (node.value === null) {
14089
- return [node, "Null"];
14090
- }
14091
- const type = typeof node.value;
14092
- if (type === "number") {
14093
- const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
14094
- if (match) {
14095
- return match[2] === "l" || match[2] === "L"
14096
- ? [node, "Long"]
14097
- : [node, "Number"];
14098
- }
14099
- return [node, node.raw.endsWith("d") ? "Double" : "Float"];
14100
- }
14101
- if (type === "bigint") {
14102
- return [node, "Long"];
14103
- }
14104
- if (type === "string") {
14105
- return [node, "String"];
14106
- }
14107
- if (type === "boolean") {
14108
- return [node, "Boolean"];
14109
- }
14110
- throw new Error(`Literal has unknown type '${type}'`);
14111
- }
14112
14133
  function fullTypeName(state, tsp) {
14113
14134
  if (typeof tsp.name === "string") {
14114
14135
  return tsp.name;
@@ -14941,6 +14962,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14941
14962
  break;
14942
14963
  case "FunctionDeclaration":
14943
14964
  if (!maybeCalled(node)) {
14965
+ if (node.attrs &&
14966
+ node.attrs.attributes &&
14967
+ node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" && attr.argument.name === "keep")) {
14968
+ break;
14969
+ }
14944
14970
  return false;
14945
14971
  }
14946
14972
  break;
@@ -15040,6 +15066,7 @@ function optimizeCall(state, node, context) {
15040
15066
 
15041
15067
 
15042
15068
 
15069
+
15043
15070
  function relative_path_no_dotdot(relative) {
15044
15071
  return relative.replace(/^(\.\.[\\/])+/, (str) => `__${"dot".repeat(str.length / 3)}__${str.slice(-1)}`);
15045
15072
  }
@@ -15462,28 +15489,35 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
15462
15489
  // the oldest optimized file, we don't need to regenerate
15463
15490
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
15464
15491
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
15465
- if (source_time < opt_time && 1657744666168 < opt_time) {
15492
+ if (source_time < opt_time && 1662140077916 < opt_time) {
15466
15493
  return { hasTests, diagnostics: prevDiagnostics };
15467
15494
  }
15468
15495
  }
15469
15496
  await promises_namespaceObject.rm(output, { recursive: true, force: true });
15470
15497
  await promises_namespaceObject.mkdir(output, { recursive: true });
15471
15498
  const diagnostics = await optimizeMonkeyC(fnMap, Object.keys(buildConfig.barrelMap || {}), config);
15472
- return Promise.all(Object.values(fnMap).map(async (info) => {
15473
- const name = info.output;
15474
- const dir = external_path_.dirname(name);
15475
- await promises_namespaceObject.mkdir(dir, { recursive: true });
15476
- const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
15477
- await promises_namespaceObject.writeFile(name, opt_source);
15478
- return info.hasTests;
15479
- })).then((results) => {
15480
- const hasTests = results.some((v) => v);
15481
- return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
15482
- hasTests,
15483
- diagnostics,
15484
- ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
15485
- }))
15486
- .then(() => ({ hasTests, diagnostics }));
15499
+ return external_prettier_namespaceObject.resolveConfig(config.workspace, {
15500
+ useCache: false,
15501
+ editorconfig: true,
15502
+ }).then((prettierConfig) => {
15503
+ const options = { ...prettierConfig, ...(config.prettier || {}) };
15504
+ return Promise.all(Object.values(fnMap).map(async (info) => {
15505
+ const name = info.output;
15506
+ const dir = external_path_.dirname(name);
15507
+ await promises_namespaceObject.mkdir(dir, { recursive: true });
15508
+ options.filepath = name;
15509
+ const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource, options);
15510
+ await promises_namespaceObject.writeFile(name, opt_source);
15511
+ return info.hasTests;
15512
+ })).then((results) => {
15513
+ const hasTests = results.some((v) => v);
15514
+ return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
15515
+ hasTests,
15516
+ diagnostics,
15517
+ ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
15518
+ }))
15519
+ .then(() => ({ hasTests, diagnostics }));
15520
+ });
15487
15521
  });
15488
15522
  }
15489
15523
  async function getProjectAnalysis(targets, analysis, options) {
@@ -1,4 +1,4 @@
1
- 0 && (module.exports = {appSupport,connectiq,getDeviceInfo,getLanguages,getSdkPath,isWin});
1
+ 0 && (module.exports = {SectionKinds,appSupport,connectiq,getDeviceInfo,getLanguages,getSdkPath,isWin,readPrg});
2
2
  /******/ (() => { // webpackBootstrap
3
3
  /******/ var __webpack_modules__ = ({
4
4
 
@@ -7171,12 +7171,14 @@ __webpack_require__.r(__webpack_exports__);
7171
7171
 
7172
7172
  // EXPORTS
7173
7173
  __webpack_require__.d(__webpack_exports__, {
7174
+ "SectionKinds": () => (/* reexport */ SectionKinds),
7174
7175
  "appSupport": () => (/* binding */ appSupport),
7175
7176
  "connectiq": () => (/* binding */ connectiq),
7176
7177
  "getDeviceInfo": () => (/* binding */ getDeviceInfo),
7177
7178
  "getLanguages": () => (/* binding */ getLanguages),
7178
7179
  "getSdkPath": () => (/* binding */ getSdkPath),
7179
- "isWin": () => (/* binding */ isWin)
7180
+ "isWin": () => (/* binding */ isWin),
7181
+ "readPrg": () => (/* reexport */ readPrg)
7180
7182
  });
7181
7183
 
7182
7184
  ;// CONCATENATED MODULE: external "fs/promises"
@@ -7187,11 +7189,38 @@ const external_path_namespaceObject = require("path");
7187
7189
  var xml2js = __webpack_require__(5055);
7188
7190
  ;// CONCATENATED MODULE: external "./util.cjs"
7189
7191
  const external_util_cjs_namespaceObject = require("./util.cjs");
7192
+ ;// CONCATENATED MODULE: ./src/readprg.ts
7193
+
7194
+ var SectionKinds;
7195
+ (function (SectionKinds) {
7196
+ SectionKinds[SectionKinds["TEXT"] = -1059145026] = "TEXT";
7197
+ SectionKinds[SectionKinds["DATA"] = -629491010] = "DATA";
7198
+ })(SectionKinds || (SectionKinds = {}));
7199
+ async function readPrg(path) {
7200
+ const data = await promises_namespaceObject.readFile(path);
7201
+ const view = new DataView(data.buffer);
7202
+ const sections = {};
7203
+ let offset = 0;
7204
+ while (view.byteLength - offset > 8) {
7205
+ const type = view.getInt32(offset);
7206
+ offset += 4;
7207
+ const length = view.getInt32(offset);
7208
+ offset += 4;
7209
+ if (length > view.byteLength - offset) {
7210
+ throw new Error(`Invalid length for section ${type}`);
7211
+ }
7212
+ sections[type] = length;
7213
+ offset += length;
7214
+ }
7215
+ return sections;
7216
+ }
7217
+
7190
7218
  ;// CONCATENATED MODULE: ./src/sdk-util.ts
7191
7219
 
7192
7220
 
7193
7221
 
7194
7222
 
7223
+
7195
7224
  const isWin = process.platform == "win32";
7196
7225
  const appSupport = isWin
7197
7226
  ? `${process.env.APPDATA}`.replace(/\\/g, "/")
@@ -9,7 +9,7 @@ export declare function variableDeclarationName(node: mctree.TypedIdentifier | m
9
9
  export declare function sameLookupResult(a: LookupDefinition[], b: LookupDefinition[]): boolean;
10
10
  export declare function isLookupCandidate(node: mctree.MemberExpression): false | mctree.Identifier;
11
11
  export declare function collectNamespaces(ast: mctree.Program, stateIn?: ProgramState): ProgramStateNode;
12
- export declare function formatAst(node: mctree.Node, monkeyCSource?: string | null): string;
12
+ export declare function formatAst(node: mctree.Node, monkeyCSource?: string | null, options?: Record<string, unknown> | null): string;
13
13
  export declare function findUsingForNode(state: ProgramStateLive, stack: ProgramStateStack, i: number, node: mctree.Identifier, isType: boolean): StateNodeDecl[] | null;
14
14
  export declare function getApiFunctionInfo(func: FunctionStateNode): FunctionInfo;
15
15
  export declare function markInvokeClassMethod(func: FunctionStateNode): void;
@@ -8,3 +8,22 @@ export declare function hasProperty<T>(obj: T, prop: string): boolean;
8
8
  export declare function withLoc<T extends mctree.Node>(node: T, start: mctree.Node | null, end?: mctree.Node | undefined): T;
9
9
  export declare function withLocDeep<T extends mctree.Node>(node: T, start: mctree.Node | null, end?: mctree.Node | undefined, inplace?: boolean): T;
10
10
  export declare function cloneDeep<T extends mctree.Node>(node: T): T;
11
+ interface NumberLiteral extends mctree.Literal {
12
+ value: number;
13
+ }
14
+ interface LongLiteral extends mctree.Literal {
15
+ value: number | bigint;
16
+ }
17
+ interface StringLiteral extends mctree.Literal {
18
+ value: string;
19
+ }
20
+ interface BooleanLiteral extends mctree.Literal {
21
+ value: boolean;
22
+ }
23
+ interface NullLiteral extends mctree.Literal {
24
+ value: null;
25
+ }
26
+ declare type LiteralValues = [NumberLiteral, "Number" | "Float" | "Double"] | [LongLiteral, "Long"] | [StringLiteral, "String"] | [BooleanLiteral, "Boolean"] | [NullLiteral, "Null"];
27
+ export declare function getNodeValue(node: mctree.Literal): LiteralValues;
28
+ export declare function getNodeValue(node: mctree.Node): LiteralValues | [null, null];
29
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function driver(): Promise<void>;
2
+ export declare function error(message: string): never;
@@ -6,7 +6,7 @@ export declare function analyze(fnMap: FilesToOptimizeMap, barrelList?: string[]
6
6
  export declare function getLiteralFromDecls(lookupDefns: LookupDefinition[]): mctree.Literal | mctree.AsExpression | null;
7
7
  export declare function getLiteralNode(node: mctree.Node | null | undefined): null | mctree.Literal | mctree.AsExpression;
8
8
  export declare function optimizeMonkeyC(fnMap: FilesToOptimizeMap, barrelList?: string[], config?: BuildConfig): Promise<Record<string, {
9
- type: "ERROR" | "WARNING" | "INFO";
9
+ type: import("./optimizer-types").DiagnosticType;
10
10
  loc: {
11
11
  start: mctree.Position;
12
12
  end: mctree.Position;
@@ -1,6 +1,6 @@
1
1
  import { mctree } from "@markw65/prettier-plugin-monkeyc";
2
2
  import { ResolvedJungle } from "./jungles";
3
- declare type DiagnosticType = "ERROR" | "WARNING" | "INFO";
3
+ export declare type DiagnosticType = "ERROR" | "WARNING" | "INFO";
4
4
  export declare type BuildConfig = {
5
5
  workspace?: string;
6
6
  jungleFiles?: string;
@@ -25,6 +25,7 @@ export declare type BuildConfig = {
25
25
  checkBuildPragmas?: boolean;
26
26
  checkInvalidSymbols?: DiagnosticType | "OFF";
27
27
  sizeBasedPRE?: boolean | string;
28
+ prettier?: Record<string, unknown>;
28
29
  _cache?: {
29
30
  barrels?: Record<string, ResolvedJungle>;
30
31
  barrelMap?: Record<string, Record<string, ResolvedJungle>>;
@@ -30,7 +30,7 @@ export declare function buildOptimizedProject(product: string | null, options: B
30
30
  product: string | null;
31
31
  hasTests: boolean;
32
32
  diagnostics: Record<string, {
33
- type: "ERROR" | "WARNING" | "INFO";
33
+ type: import("./optimizer-types").DiagnosticType;
34
34
  loc: {
35
35
  start: mctree.Position;
36
36
  end: mctree.Position;
@@ -50,7 +50,7 @@ export declare function generateOptimizedProject(options: BuildConfig): Promise<
50
50
  program: string;
51
51
  hasTests: boolean;
52
52
  diagnostics: Record<string, {
53
- type: "ERROR" | "WARNING" | "INFO";
53
+ type: import("./optimizer-types").DiagnosticType;
54
54
  loc: {
55
55
  start: mctree.Position;
56
56
  end: mctree.Position;
@@ -0,0 +1,21 @@
1
+ import { BuildConfig } from "./optimizer-types";
2
+ export declare type RemoteProject = string | {
3
+ root: string;
4
+ options?: BuildConfig;
5
+ rename?: {
6
+ from: string;
7
+ to: string;
8
+ }[];
9
+ build?: boolean;
10
+ comment?: string;
11
+ exclude?: string;
12
+ include?: string;
13
+ sourcePath?: string;
14
+ jungleContent?: string[];
15
+ };
16
+ export declare const githubProjects: RemoteProject[];
17
+ export declare function fetchGitProjects(projects: RemoteProject[]): Promise<(string | {
18
+ jungle: string;
19
+ build: boolean | null;
20
+ options: BuildConfig | null;
21
+ })[]>;
@@ -0,0 +1,5 @@
1
+ export declare enum SectionKinds {
2
+ TEXT = -1059145026,
3
+ DATA = -629491010
4
+ }
5
+ export declare function readPrg(path: string): Promise<Record<number, number>>;
@@ -1,3 +1,4 @@
1
+ export { readPrg, SectionKinds } from "./readprg";
1
2
  export declare const isWin: boolean;
2
3
  export declare const appSupport: string;
3
4
  export declare const connectiq: string;
@@ -9,5 +9,5 @@ export declare function spawnByLine(command: string, args: string[], lineHandler
9
9
  [key: string]: unknown;
10
10
  }): Promise<void>;
11
11
  export declare function readByLine(file: string, lineHandler: LineHandler): Promise<unknown>;
12
- export declare function promiseAll<T>(promiseFn: (i: number) => Promise<T>, parallelism: number): Promise<T[]>;
12
+ export declare function promiseAll<T>(promiseFn: (i: number) => Promise<T> | null, parallelism: number): Promise<T[]>;
13
13
  export declare function copyRecursiveAsNeeded(source: string, target: string, filter?: (src: string, tgt: string) => boolean): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.0.32",
4
+ "version": "1.0.35",
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",
@@ -37,7 +37,7 @@
37
37
  "author": "markw65",
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@markw65/prettier-plugin-monkeyc": "^1.0.33"
40
+ "@markw65/prettier-plugin-monkeyc": "^1.0.34"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/glob": "^7.2.0",