@markw65/monkeyc-optimizer 1.0.32 → 1.0.33

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,12 @@ 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.
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;
@@ -3371,7 +3411,7 @@ function getLiteralNode(node) {
3371
3411
  return null;
3372
3412
  switch (node.operator) {
3373
3413
  case "-": {
3374
- const [arg, type] = getNodeValue(node.argument);
3414
+ const [arg, type] = ast_getNodeValue(node.argument);
3375
3415
  if (type === "Number" || type === "Long") {
3376
3416
  return replacementLiteral(arg, -arg.value, type);
3377
3417
  }
@@ -3380,44 +3420,6 @@ function getLiteralNode(node) {
3380
3420
  }
3381
3421
  return null;
3382
3422
  }
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
3423
  function fullTypeName(state, tsp) {
3422
3424
  if (typeof tsp.name === "string") {
3423
3425
  return tsp.name;
@@ -4250,6 +4252,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
4250
4252
  break;
4251
4253
  case "FunctionDeclaration":
4252
4254
  if (!maybeCalled(node)) {
4255
+ if (node.attrs &&
4256
+ node.attrs.attributes &&
4257
+ node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" && attr.argument.name === "keep")) {
4258
+ break;
4259
+ }
4253
4260
  return false;
4254
4261
  }
4255
4262
  break;
@@ -10977,6 +10977,7 @@ function simulateProgram(prg, device, test = false, logger) {
10977
10977
  }
10978
10978
 
10979
10979
  ;// CONCATENATED MODULE: ./src/ast.ts
10980
+
10980
10981
  /*
10981
10982
  * This ensures that mctreeTypeInfo has every key of MCTreeTypeInfo,
10982
10983
  * and that the corresponding arrays contain every element of the
@@ -11178,6 +11179,44 @@ function withLocDeep(node, start, end, inplace) {
11178
11179
  function cloneDeep(node) {
11179
11180
  return withLocDeep(node, null);
11180
11181
  }
11182
+ function getNodeValue(node) {
11183
+ if (node.type == "BinaryExpression" &&
11184
+ node.operator == "as" &&
11185
+ node.right.type == "TypeSpecList" &&
11186
+ node.right.ts.length == 1 &&
11187
+ typeof node.right.ts[0] == "string") {
11188
+ // this is a cast we inserted to retain the type of an enum
11189
+ // any arithmetic on it will revert to "Number", or "Long",
11190
+ // so just ignore it.
11191
+ return getNodeValue(node.left);
11192
+ }
11193
+ if (node.type != "Literal") {
11194
+ return [null, null];
11195
+ }
11196
+ if (node.value === null) {
11197
+ return [node, "Null"];
11198
+ }
11199
+ const type = typeof node.value;
11200
+ if (type === "number") {
11201
+ const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
11202
+ if (match) {
11203
+ return match[2] === "l" || match[2] === "L"
11204
+ ? [node, "Long"]
11205
+ : [node, "Number"];
11206
+ }
11207
+ return [node, node.raw.endsWith("d") ? "Double" : "Float"];
11208
+ }
11209
+ if (type === "bigint") {
11210
+ return [node, "Long"];
11211
+ }
11212
+ if (type === "string") {
11213
+ return [node, "String"];
11214
+ }
11215
+ if (type === "boolean") {
11216
+ return [node, "Boolean"];
11217
+ }
11218
+ throw new Error(`Literal has unknown type '${type}'`);
11219
+ }
11181
11220
 
11182
11221
  ;// CONCATENATED MODULE: ./src/function-info.ts
11183
11222
 
@@ -12672,7 +12711,6 @@ var priorityqueuejs = __webpack_require__(2789);
12672
12711
 
12673
12712
 
12674
12713
 
12675
-
12676
12714
  /**
12677
12715
  * This implements a pseudo Partial Redundancy Elimination
12678
12716
  * pass. It isn't quite like traditional PRE because we're
@@ -12857,9 +12895,11 @@ function buildPREGraph(state, func) {
12857
12895
  break;
12858
12896
  case "Literal":
12859
12897
  if (refCost(node) > LocalRefCost) {
12860
- const key = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(node.raw)
12861
- ? BigInt(node.value)
12862
- : node.value;
12898
+ const result = getNodeValue(node);
12899
+ const key = result[1] +
12900
+ (result[0].value === null
12901
+ ? ""
12902
+ : "-" + result[0].value.toString());
12863
12903
  let decl = literals.get(key);
12864
12904
  if (!decl) {
12865
12905
  decl = node;
@@ -14071,44 +14111,6 @@ function getLiteralNode(node) {
14071
14111
  }
14072
14112
  return null;
14073
14113
  }
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
14114
  function fullTypeName(state, tsp) {
14113
14115
  if (typeof tsp.name === "string") {
14114
14116
  return tsp.name;
@@ -14941,6 +14943,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14941
14943
  break;
14942
14944
  case "FunctionDeclaration":
14943
14945
  if (!maybeCalled(node)) {
14946
+ if (node.attrs &&
14947
+ node.attrs.attributes &&
14948
+ node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" && attr.argument.name === "keep")) {
14949
+ break;
14950
+ }
14944
14951
  return false;
14945
14952
  }
14946
14953
  break;
@@ -15462,7 +15469,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
15462
15469
  // the oldest optimized file, we don't need to regenerate
15463
15470
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
15464
15471
  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) {
15472
+ if (source_time < opt_time && 1658088370253 < opt_time) {
15466
15473
  return { hasTests, diagnostics: prevDiagnostics };
15467
15474
  }
15468
15475
  }
@@ -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 {};
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.33",
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",