@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 +30 -0
- package/build/api.cjs +79 -54
- package/build/optimizer.cjs +102 -68
- package/build/sdk-util.cjs +31 -2
- package/build/src/api.d.ts +1 -1
- package/build/src/ast.d.ts +19 -0
- package/build/src/driver.d.ts +2 -0
- package/build/src/mc-rewrite.d.ts +1 -1
- package/build/src/optimizer-types.d.ts +2 -1
- package/build/src/optimizer.d.ts +2 -2
- package/build/src/projects.d.ts +21 -0
- package/build/src/readprg.d.ts +5 -0
- package/build/src/sdk-util.d.ts +1 -0
- package/build/src/util.d.ts +1 -1
- package/package.json +2 -2
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
|
|
2169
|
-
|
|
2170
|
-
|
|
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
|
-
|
|
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
|
|
2890
|
-
if (
|
|
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,
|
|
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((
|
|
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.
|
|
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.
|
|
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] =
|
|
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",
|
package/build/optimizer.cjs
CHANGED
|
@@ -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
|
|
12861
|
-
|
|
12862
|
-
|
|
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
|
-
|
|
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
|
|
13582
|
-
if (
|
|
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,
|
|
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((
|
|
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.
|
|
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.
|
|
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 &&
|
|
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
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
const
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
}))
|
|
15486
|
-
.
|
|
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) {
|
package/build/sdk-util.cjs
CHANGED
|
@@ -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, "/")
|
package/build/src/api.d.ts
CHANGED
|
@@ -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;
|
package/build/src/ast.d.ts
CHANGED
|
@@ -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 {};
|
|
@@ -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: "
|
|
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>>;
|
package/build/src/optimizer.d.ts
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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
|
+
})[]>;
|
package/build/src/sdk-util.d.ts
CHANGED
package/build/src/util.d.ts
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
40
|
+
"@markw65/prettier-plugin-monkeyc": "^1.0.34"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/glob": "^7.2.0",
|