@markw65/monkeyc-optimizer 1.0.44 → 1.0.45
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 +18 -0
- package/build/api.cjs +905 -668
- package/build/optimizer.cjs +465 -214
- package/build/sdk-util.cjs +58 -0
- package/build/src/api.d.ts +3 -2
- package/build/src/ast.d.ts +26 -0
- package/build/src/data-flow.d.ts +45 -0
- package/build/src/function-info.d.ts +2 -0
- package/build/src/interp-binary.d.ts +4 -0
- package/build/src/interp-call.d.ts +3 -0
- package/build/src/interp.d.ts +23 -0
- package/build/src/jungles.d.ts +2 -1
- package/build/src/manifest.d.ts +1 -0
- package/build/src/mc-types.d.ts +166 -0
- package/build/src/optimizer-types.d.ts +12 -3
- package/build/src/pre.d.ts +1 -1
- package/build/src/projects.d.ts +2 -1
- package/build/src/type-flow.d.ts +4 -0
- package/build/src/util.d.ts +6 -1
- package/build/util.cjs +58 -2
- package/package.json +4 -3
package/build/optimizer.cjs
CHANGED
|
@@ -3585,6 +3585,17 @@ function manifestAnnotations(manifest) {
|
|
|
3585
3585
|
.children("iq:annotation")
|
|
3586
3586
|
.text();
|
|
3587
3587
|
}
|
|
3588
|
+
function manifestLanguages(manifest) {
|
|
3589
|
+
if (manifest.body instanceof Error) {
|
|
3590
|
+
throw manifest.body;
|
|
3591
|
+
}
|
|
3592
|
+
return manifest.body
|
|
3593
|
+
.children()
|
|
3594
|
+
.filter((c) => c.name === "iq:application" || c.name === "iq:barrel")
|
|
3595
|
+
.children("iq:languages")
|
|
3596
|
+
.children("iq:language")
|
|
3597
|
+
.text();
|
|
3598
|
+
}
|
|
3588
3599
|
async function checkManifest(manifest, products) {
|
|
3589
3600
|
if (manifest.body instanceof Error) {
|
|
3590
3601
|
throw manifest.body;
|
|
@@ -3973,10 +3984,6 @@ async function resolve_literals(qualifier, default_source, deviceInfo, cache) {
|
|
|
3973
3984
|
const lang = qualifier["lang"];
|
|
3974
3985
|
if (lang) {
|
|
3975
3986
|
await Promise.all(Object.keys(lang).map((key) => {
|
|
3976
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(deviceInfo.languages, key)) {
|
|
3977
|
-
delete lang[key];
|
|
3978
|
-
return null;
|
|
3979
|
-
}
|
|
3980
3987
|
return resolve_one_file_list(lang, key);
|
|
3981
3988
|
}));
|
|
3982
3989
|
if (Object.keys(lang).length === 0)
|
|
@@ -4479,6 +4486,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options, cac
|
|
|
4479
4486
|
jungles,
|
|
4480
4487
|
resources,
|
|
4481
4488
|
buildDependencies,
|
|
4489
|
+
devices,
|
|
4482
4490
|
};
|
|
4483
4491
|
}
|
|
4484
4492
|
catch (e) {
|
|
@@ -4509,17 +4517,22 @@ const external_child_process_namespaceObject = require("child_process");
|
|
|
4509
4517
|
|
|
4510
4518
|
|
|
4511
4519
|
async function launchSimulator(force = true) {
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
|
|
4515
|
-
const child = (0,external_child_process_namespaceObject.execFile)(external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "simulator" : "connectiq"));
|
|
4516
|
-
child.unref();
|
|
4517
|
-
for (let i = 0;; i++) {
|
|
4518
|
-
if (await checkIfSimulatorRunning())
|
|
4519
|
-
return;
|
|
4520
|
-
if (i === 5)
|
|
4520
|
+
try {
|
|
4521
|
+
if (!force && (await checkIfSimulatorRunning()))
|
|
4521
4522
|
return;
|
|
4522
|
-
|
|
4523
|
+
const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
|
|
4524
|
+
const child = (0,external_child_process_namespaceObject.execFile)(external_path_.resolve(sdk, "bin", external_sdk_util_cjs_namespaceObject.isWin ? "simulator" : "connectiq"));
|
|
4525
|
+
child.unref();
|
|
4526
|
+
for (let i = 0;; i++) {
|
|
4527
|
+
if (await checkIfSimulatorRunning())
|
|
4528
|
+
return;
|
|
4529
|
+
if (i === 5)
|
|
4530
|
+
return;
|
|
4531
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
catch (e) {
|
|
4535
|
+
console.log(e);
|
|
4523
4536
|
}
|
|
4524
4537
|
}
|
|
4525
4538
|
function checkIfSimulatorRunning() {
|
|
@@ -4534,7 +4547,7 @@ function checkIfSimulatorRunningOn(port) {
|
|
|
4534
4547
|
socket.on("end", () => resolve(listening));
|
|
4535
4548
|
socket.connect(port, "localhost");
|
|
4536
4549
|
socket.end();
|
|
4537
|
-
});
|
|
4550
|
+
}).catch(() => false);
|
|
4538
4551
|
}
|
|
4539
4552
|
function simulateProgram(prg, device, test = false, logger) {
|
|
4540
4553
|
const args = [prg, device];
|
|
@@ -4798,6 +4811,64 @@ function getNodeValue(node) {
|
|
|
4798
4811
|
}
|
|
4799
4812
|
throw new Error(`Literal has unknown type '${type}'`);
|
|
4800
4813
|
}
|
|
4814
|
+
function wrap(node, loc) {
|
|
4815
|
+
if (loc) {
|
|
4816
|
+
node.loc = loc;
|
|
4817
|
+
node.start = loc.start.offset;
|
|
4818
|
+
node.end = loc.end.offset;
|
|
4819
|
+
}
|
|
4820
|
+
return node;
|
|
4821
|
+
}
|
|
4822
|
+
function locRange(start, end) {
|
|
4823
|
+
return {
|
|
4824
|
+
source: start.source || end.source,
|
|
4825
|
+
start: start.start,
|
|
4826
|
+
end: end.end,
|
|
4827
|
+
};
|
|
4828
|
+
}
|
|
4829
|
+
function adjustLoc(loc, start = 1, end = -1) {
|
|
4830
|
+
return {
|
|
4831
|
+
source: loc.source,
|
|
4832
|
+
start: {
|
|
4833
|
+
offset: loc.start.offset + start,
|
|
4834
|
+
line: loc.start.line,
|
|
4835
|
+
column: loc.start.column + start,
|
|
4836
|
+
},
|
|
4837
|
+
end: {
|
|
4838
|
+
offset: loc.end.offset + end,
|
|
4839
|
+
line: loc.end.line,
|
|
4840
|
+
column: loc.end.column + end,
|
|
4841
|
+
},
|
|
4842
|
+
};
|
|
4843
|
+
}
|
|
4844
|
+
function makeIdentifier(name, loc) {
|
|
4845
|
+
return wrap({ type: "Identifier", name }, loc);
|
|
4846
|
+
}
|
|
4847
|
+
function makeMemberExpression(object, property) {
|
|
4848
|
+
return wrap({
|
|
4849
|
+
type: "MemberExpression",
|
|
4850
|
+
object,
|
|
4851
|
+
property,
|
|
4852
|
+
computed: false,
|
|
4853
|
+
}, object.loc && locRange(object.loc, property.loc));
|
|
4854
|
+
}
|
|
4855
|
+
function makeScopedName(dotted, l) {
|
|
4856
|
+
const loc = l && adjustLoc(l, 0, l.start.offset - l.end.offset);
|
|
4857
|
+
const result = dotted.split(/\s*\.\s*/).reduce(({ cur, offset }, next) => {
|
|
4858
|
+
const id = makeIdentifier(next, loc && adjustLoc(loc, offset, offset + next.length));
|
|
4859
|
+
if (!cur) {
|
|
4860
|
+
cur = id;
|
|
4861
|
+
}
|
|
4862
|
+
else {
|
|
4863
|
+
cur = makeMemberExpression(cur, id);
|
|
4864
|
+
}
|
|
4865
|
+
offset += next.length + 1;
|
|
4866
|
+
return { cur, offset };
|
|
4867
|
+
}, { cur: null, offset: 0 }).cur;
|
|
4868
|
+
if (!result)
|
|
4869
|
+
throw new Error("Failed to make a ScopedName");
|
|
4870
|
+
return result;
|
|
4871
|
+
}
|
|
4801
4872
|
|
|
4802
4873
|
;// CONCATENATED MODULE: ./src/function-info.ts
|
|
4803
4874
|
|
|
@@ -4850,6 +4921,8 @@ function recordCalledFuncs(func, callees) {
|
|
|
4850
4921
|
}
|
|
4851
4922
|
function functionMayModify(state, func, decl) {
|
|
4852
4923
|
const info = func.info;
|
|
4924
|
+
if (info === false)
|
|
4925
|
+
return false;
|
|
4853
4926
|
if (!info || info.modifiedUnknown)
|
|
4854
4927
|
return true;
|
|
4855
4928
|
if (info.resolvedDecls) {
|
|
@@ -4862,7 +4935,7 @@ function functionMayModify(state, func, decl) {
|
|
|
4862
4935
|
const visited = new Set();
|
|
4863
4936
|
const resolved = new Set();
|
|
4864
4937
|
const resolveDecls = (f) => {
|
|
4865
|
-
if (visited.has(f))
|
|
4938
|
+
if (f.info === false || visited.has(f))
|
|
4866
4939
|
return true;
|
|
4867
4940
|
if (!f.info)
|
|
4868
4941
|
return false;
|
|
@@ -4924,6 +4997,16 @@ function findCalleesForNew(lookupDefs) {
|
|
|
4924
4997
|
.flatMap(initializer)
|
|
4925
4998
|
.filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
|
|
4926
4999
|
}
|
|
5000
|
+
function findCalleesByNode(state, callee) {
|
|
5001
|
+
const name = callee.type === "Identifier"
|
|
5002
|
+
? callee.name
|
|
5003
|
+
: callee.type === "MemberExpression" && !callee.computed
|
|
5004
|
+
? callee.property.name
|
|
5005
|
+
: null;
|
|
5006
|
+
if (!name)
|
|
5007
|
+
return null;
|
|
5008
|
+
return ((hasProperty(state.allFunctions, name) && state.allFunctions[name]) || null);
|
|
5009
|
+
}
|
|
4927
5010
|
|
|
4928
5011
|
;// CONCATENATED MODULE: ./src/optimizer-types.ts
|
|
4929
5012
|
var StateNodeAttributes;
|
|
@@ -5887,13 +5970,17 @@ function pragmaChecker(state, ast, diagnostics) {
|
|
|
5887
5970
|
if (quote == '"') {
|
|
5888
5971
|
return haystack.includes(needle);
|
|
5889
5972
|
}
|
|
5890
|
-
const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat.replace(/
|
|
5973
|
+
const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat.replace(/\W/g, "_")}(?:_\\d+)?)`));
|
|
5891
5974
|
return re.test(haystack);
|
|
5892
5975
|
};
|
|
5893
5976
|
next();
|
|
5894
5977
|
traverseAst(ast, (node) => {
|
|
5895
|
-
if (index >= comments.length
|
|
5978
|
+
if (index >= comments.length ||
|
|
5979
|
+
node.type === "Line" ||
|
|
5980
|
+
node.type === "Block" ||
|
|
5981
|
+
node.type === "MultiLine") {
|
|
5896
5982
|
return false;
|
|
5983
|
+
}
|
|
5897
5984
|
if (node.start && node.start >= (comment.end || Infinity)) {
|
|
5898
5985
|
const { kind, quote, needle } = matchers.shift();
|
|
5899
5986
|
if (kind === "match") {
|
|
@@ -6039,7 +6126,7 @@ function buildReducedGraph(state, func, notice) {
|
|
|
6039
6126
|
try {
|
|
6040
6127
|
const localState = new LocalState(func.node);
|
|
6041
6128
|
const ret = localState.curBlock;
|
|
6042
|
-
state.stack = func.stack;
|
|
6129
|
+
state.stack = [...func.stack];
|
|
6043
6130
|
const stmtStack = [func.node];
|
|
6044
6131
|
let tryActive = 0;
|
|
6045
6132
|
state.pre = (node) => {
|
|
@@ -6054,6 +6141,8 @@ function buildReducedGraph(state, func, notice) {
|
|
|
6054
6141
|
stmtStack.push(node);
|
|
6055
6142
|
}
|
|
6056
6143
|
switch (node.type) {
|
|
6144
|
+
case "FunctionDeclaration":
|
|
6145
|
+
return ["body"];
|
|
6057
6146
|
case "AttributeList":
|
|
6058
6147
|
return [];
|
|
6059
6148
|
case "SwitchStatement": {
|
|
@@ -6270,11 +6359,6 @@ function buildReducedGraph(state, func, notice) {
|
|
|
6270
6359
|
}
|
|
6271
6360
|
case "VariableDeclarator":
|
|
6272
6361
|
return ["init"];
|
|
6273
|
-
case "MemberExpression":
|
|
6274
|
-
if (!node.computed) {
|
|
6275
|
-
return ["object"];
|
|
6276
|
-
}
|
|
6277
|
-
break;
|
|
6278
6362
|
case "UnaryExpression":
|
|
6279
6363
|
if (node.operator === ":") {
|
|
6280
6364
|
return [];
|
|
@@ -6310,6 +6394,14 @@ function buildReducedGraph(state, func, notice) {
|
|
|
6310
6394
|
case "ContinueStatement":
|
|
6311
6395
|
localState.terminal(node.type);
|
|
6312
6396
|
return [];
|
|
6397
|
+
case "CallExpression":
|
|
6398
|
+
if (node.callee.type === "Identifier") {
|
|
6399
|
+
const extra = state.stack.splice(func.stack.length);
|
|
6400
|
+
state.traverse(node.callee);
|
|
6401
|
+
state.stack.push(...extra);
|
|
6402
|
+
return ["arguments"];
|
|
6403
|
+
}
|
|
6404
|
+
break;
|
|
6313
6405
|
}
|
|
6314
6406
|
return null;
|
|
6315
6407
|
};
|
|
@@ -6471,142 +6563,94 @@ function getPreOrder(head) {
|
|
|
6471
6563
|
|
|
6472
6564
|
// EXTERNAL MODULE: ./node_modules/priorityqueuejs/index.js
|
|
6473
6565
|
var priorityqueuejs = __webpack_require__(2789);
|
|
6474
|
-
;// CONCATENATED MODULE: ./src/
|
|
6566
|
+
;// CONCATENATED MODULE: ./src/data-flow.ts
|
|
6567
|
+
|
|
6475
6568
|
|
|
6476
6569
|
|
|
6477
6570
|
|
|
6478
6571
|
|
|
6479
6572
|
|
|
6480
|
-
/**
|
|
6481
|
-
* This implements a pseudo Partial Redundancy Elimination
|
|
6482
|
-
* pass. It isn't quite like traditional PRE because we're
|
|
6483
|
-
* aiming to minimize size, not dynamic instructions. So
|
|
6484
|
-
* for us, its worthwhile to take something like:
|
|
6485
|
-
*
|
|
6486
|
-
* switch (x) {
|
|
6487
|
-
* case 1: foo(A.B); break;
|
|
6488
|
-
* case 2: foo(C); break;
|
|
6489
|
-
* case 3: bar(A.B); break;
|
|
6490
|
-
* }
|
|
6491
|
-
*
|
|
6492
|
-
* and rewrite it as
|
|
6493
|
-
*
|
|
6494
|
-
* var tmp = A.B;
|
|
6495
|
-
* switch (x) {
|
|
6496
|
-
* case 1: foo(tmp); break;
|
|
6497
|
-
* case 2: foo(C); break;
|
|
6498
|
-
* case 3: bar(tmp); break;
|
|
6499
|
-
* }
|
|
6500
|
-
*
|
|
6501
|
-
* because even though A.B wasn't used on all paths where we
|
|
6502
|
-
* inserted the temporary, we still reduced the code size.
|
|
6503
|
-
*/
|
|
6504
|
-
const logging = false;
|
|
6505
6573
|
function declFullName(decl) {
|
|
6574
|
+
if (Array.isArray(decl)) {
|
|
6575
|
+
decl = decl[0];
|
|
6576
|
+
}
|
|
6577
|
+
if (decl.type === "Literal") {
|
|
6578
|
+
return decl.raw || decl.value?.toString() || "null";
|
|
6579
|
+
}
|
|
6580
|
+
if ((0,external_api_cjs_namespaceObject.isStateNode)(decl))
|
|
6581
|
+
return decl.fullName;
|
|
6506
6582
|
switch (decl.type) {
|
|
6507
|
-
case "
|
|
6508
|
-
return decl.
|
|
6509
|
-
case "
|
|
6510
|
-
return decl.
|
|
6583
|
+
case "BinaryExpression":
|
|
6584
|
+
return decl.left.name;
|
|
6585
|
+
case "EnumStringMember":
|
|
6586
|
+
return decl.init
|
|
6587
|
+
? `${decl.id.name}:${(0,external_api_cjs_namespaceObject.formatAst)(decl.init)}`
|
|
6588
|
+
: decl.id.name;
|
|
6511
6589
|
default:
|
|
6512
6590
|
throw new Error(`Unexpected EventDecl type: ${decl.type}`);
|
|
6513
6591
|
}
|
|
6514
6592
|
}
|
|
6515
6593
|
function declName(decl) {
|
|
6594
|
+
if (Array.isArray(decl)) {
|
|
6595
|
+
decl = decl[0];
|
|
6596
|
+
}
|
|
6597
|
+
if (decl.type === "Literal") {
|
|
6598
|
+
return (decl.raw || decl.value?.toString() || "null").replace(/[^\w]/g, "_");
|
|
6599
|
+
}
|
|
6600
|
+
if ((0,external_api_cjs_namespaceObject.isStateNode)(decl))
|
|
6601
|
+
return decl.name;
|
|
6516
6602
|
switch (decl.type) {
|
|
6517
|
-
case "
|
|
6518
|
-
return
|
|
6519
|
-
case "
|
|
6520
|
-
return decl.name;
|
|
6603
|
+
case "BinaryExpression":
|
|
6604
|
+
return decl.left.name;
|
|
6605
|
+
case "EnumStringMember":
|
|
6606
|
+
return decl.id.name;
|
|
6521
6607
|
default:
|
|
6522
6608
|
throw new Error(`Unexpected EventDecl type: ${decl.type}`);
|
|
6523
6609
|
}
|
|
6524
6610
|
}
|
|
6525
|
-
function logAntState(s, decl) {
|
|
6526
|
-
const defs = Array.from(s.ant).reduce((defs, event) => {
|
|
6527
|
-
if (event.type === "def" || event.type === "mod")
|
|
6528
|
-
defs++;
|
|
6529
|
-
return defs;
|
|
6530
|
-
}, 0);
|
|
6531
|
-
console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live, ${s.isIsolated ? "" : "!"}isolated`);
|
|
6532
|
-
console.log(` - members: ${Array.from(s.members)
|
|
6533
|
-
.map(([block, live]) => block.order + (live ? "t" : "f"))
|
|
6534
|
-
.join(", ")}`);
|
|
6535
|
-
}
|
|
6536
|
-
function logAntDecls(antDecls) {
|
|
6537
|
-
antDecls.forEach(logAntState);
|
|
6538
|
-
}
|
|
6539
|
-
function sizeBasedPRE(state, func) {
|
|
6540
|
-
if (!func.node.body)
|
|
6541
|
-
return;
|
|
6542
|
-
if (!state.config ||
|
|
6543
|
-
!state.config.sizeBasedPRE ||
|
|
6544
|
-
(typeof state.config.sizeBasedPRE === "string" &&
|
|
6545
|
-
state.config.sizeBasedPRE !== func.fullName)) {
|
|
6546
|
-
return;
|
|
6547
|
-
}
|
|
6548
|
-
const { graph: head, identifiers } = buildPREGraph(state, func);
|
|
6549
|
-
const candidates = computeAttributes(state, head);
|
|
6550
|
-
if (candidates) {
|
|
6551
|
-
if (logging) {
|
|
6552
|
-
console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
|
|
6553
|
-
logAntDecls(candidates);
|
|
6554
|
-
}
|
|
6555
|
-
const nodeMap = new Map();
|
|
6556
|
-
const declMap = new Map();
|
|
6557
|
-
const variableDecl = withLoc({
|
|
6558
|
-
type: "VariableDeclaration",
|
|
6559
|
-
declarations: [],
|
|
6560
|
-
kind: "var",
|
|
6561
|
-
}, func.node.body);
|
|
6562
|
-
variableDecl.end = variableDecl.start;
|
|
6563
|
-
variableDecl.loc.end = variableDecl.loc.start;
|
|
6564
|
-
candidates.forEach((s, decl) => {
|
|
6565
|
-
let name;
|
|
6566
|
-
let i = 0;
|
|
6567
|
-
do {
|
|
6568
|
-
name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
|
|
6569
|
-
if (!identifiers.has(name)) {
|
|
6570
|
-
identifiers.add(name);
|
|
6571
|
-
break;
|
|
6572
|
-
}
|
|
6573
|
-
i++;
|
|
6574
|
-
} while (true);
|
|
6575
|
-
declMap.set(decl, name);
|
|
6576
|
-
variableDecl.declarations.push(withLoc({
|
|
6577
|
-
type: "VariableDeclarator",
|
|
6578
|
-
id: withLoc({ type: "Identifier", name }, variableDecl),
|
|
6579
|
-
kind: "var",
|
|
6580
|
-
}, variableDecl));
|
|
6581
|
-
s.ant.forEach((event) => {
|
|
6582
|
-
const events = nodeMap.get(event.node);
|
|
6583
|
-
if (!events) {
|
|
6584
|
-
nodeMap.set(event.node, [event]);
|
|
6585
|
-
}
|
|
6586
|
-
else {
|
|
6587
|
-
events.push(event);
|
|
6588
|
-
}
|
|
6589
|
-
});
|
|
6590
|
-
});
|
|
6591
|
-
applyReplacements(func.node, nodeMap, declMap);
|
|
6592
|
-
func.node.body.body.unshift(variableDecl);
|
|
6593
|
-
}
|
|
6594
|
-
}
|
|
6595
6611
|
function unhandledExpression(node) {
|
|
6596
6612
|
throw new Error(`Unhandled expression type: ${node.type}`);
|
|
6597
6613
|
}
|
|
6598
|
-
function
|
|
6614
|
+
function buildDataFlowGraph(state, func, wantsLiteral, trackInsertionPoints, wantsAllRefs) {
|
|
6615
|
+
const uniqueDeclMap = new Map();
|
|
6599
6616
|
const findDecl = (node) => {
|
|
6600
6617
|
if (node.type === "Identifier" ||
|
|
6601
6618
|
(node.type === "MemberExpression" && !node.computed)) {
|
|
6602
6619
|
const [, results] = state.lookup(node);
|
|
6603
|
-
|
|
6604
|
-
results.
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6620
|
+
const decls = (results &&
|
|
6621
|
+
results.reduce((decls, result) => result.results.reduce((decls, result) => {
|
|
6622
|
+
if (!wantsAllRefs &&
|
|
6623
|
+
(result.type !== "VariableDeclarator" || (0,external_api_cjs_namespaceObject.isLocal)(result))) {
|
|
6624
|
+
return decls;
|
|
6625
|
+
}
|
|
6626
|
+
if (!decls)
|
|
6627
|
+
return result;
|
|
6628
|
+
if (Array.isArray(decls)) {
|
|
6629
|
+
decls.push(result);
|
|
6630
|
+
return decls;
|
|
6631
|
+
}
|
|
6632
|
+
else {
|
|
6633
|
+
return [decls, result];
|
|
6634
|
+
}
|
|
6635
|
+
}, decls), null)) ||
|
|
6636
|
+
null;
|
|
6637
|
+
if (!Array.isArray(decls))
|
|
6638
|
+
return decls;
|
|
6639
|
+
// We use EventDecl as a Map key, so we need to
|
|
6640
|
+
// uniquify it. Note that from any given function,
|
|
6641
|
+
// if state.lookup finds a set of non locals, it will
|
|
6642
|
+
// always find the same set, so we can use the first
|
|
6643
|
+
// such as the unique identifier.
|
|
6644
|
+
const canon = uniqueDeclMap.get(decls[0]);
|
|
6645
|
+
if (!canon) {
|
|
6646
|
+
uniqueDeclMap.set(decls[0], decls);
|
|
6647
|
+
return decls;
|
|
6648
|
+
}
|
|
6649
|
+
if (canon.length != decls.length ||
|
|
6650
|
+
!canon.every((v, i) => v === decls[i])) {
|
|
6651
|
+
throw new Error(`Canonical representation of ${declFullName(canon)} did not match`);
|
|
6652
|
+
}
|
|
6653
|
+
return canon;
|
|
6610
6654
|
}
|
|
6611
6655
|
return null;
|
|
6612
6656
|
};
|
|
@@ -6614,18 +6658,22 @@ function buildPREGraph(state, func) {
|
|
|
6614
6658
|
const identifiers = new Set();
|
|
6615
6659
|
const liveDefs = new Map();
|
|
6616
6660
|
const liveStmts = new Map();
|
|
6617
|
-
const liveDef =
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6661
|
+
const liveDef = trackInsertionPoints
|
|
6662
|
+
? (def, stmt) => {
|
|
6663
|
+
let curNodes = liveDefs.get(def);
|
|
6664
|
+
if (!curNodes) {
|
|
6665
|
+
liveDefs.set(def, (curNodes = new Set()));
|
|
6666
|
+
}
|
|
6667
|
+
curNodes.add(stmt);
|
|
6668
|
+
let defs = liveStmts.get(stmt);
|
|
6669
|
+
if (!defs) {
|
|
6670
|
+
liveStmts.set(stmt, (defs = new Map()));
|
|
6671
|
+
}
|
|
6672
|
+
defs.set(def, (defs.get(def) || 0) + 1);
|
|
6626
6673
|
}
|
|
6627
|
-
|
|
6628
|
-
|
|
6674
|
+
: () => {
|
|
6675
|
+
/* do nothing */
|
|
6676
|
+
};
|
|
6629
6677
|
return {
|
|
6630
6678
|
identifiers,
|
|
6631
6679
|
graph: buildReducedGraph(state, func, (node, stmt, mayThrow) => {
|
|
@@ -6660,7 +6708,7 @@ function buildPREGraph(state, func) {
|
|
|
6660
6708
|
case "ParenthesizedExpression":
|
|
6661
6709
|
break;
|
|
6662
6710
|
case "Literal":
|
|
6663
|
-
if (
|
|
6711
|
+
if (wantsLiteral(node)) {
|
|
6664
6712
|
const result = getNodeValue(node);
|
|
6665
6713
|
const key = result[1] +
|
|
6666
6714
|
(result[0].value === null
|
|
@@ -6682,34 +6730,40 @@ function buildPREGraph(state, func) {
|
|
|
6682
6730
|
case "Identifier":
|
|
6683
6731
|
identifiers.add(node.name);
|
|
6684
6732
|
// fall through
|
|
6685
|
-
case "MemberExpression":
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
if (
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6733
|
+
case "MemberExpression": {
|
|
6734
|
+
const decls = findDecl(node);
|
|
6735
|
+
if (!decls)
|
|
6736
|
+
break;
|
|
6737
|
+
if (trackInsertionPoints &&
|
|
6738
|
+
(0,external_util_cjs_namespaceObject.some)(decls, (decl) => {
|
|
6739
|
+
if (decl.type === "VariableDeclarator") {
|
|
6740
|
+
const defStmts = (decl.node.kind === "var" && liveDefs.get(null)) ||
|
|
6741
|
+
liveDefs.get(decl);
|
|
6742
|
+
if (defStmts) {
|
|
6743
|
+
return true;
|
|
6744
|
+
/*
|
|
6745
|
+
// hold off on this for now. we need to communicate
|
|
6746
|
+
// which defs need to be fixed, which involves yet-another
|
|
6747
|
+
// table.
|
|
6748
|
+
|
|
6749
|
+
if (defStmts.size !== 1) break;
|
|
6750
|
+
const fixable = isFixableStmt([...defStmts][0]);
|
|
6751
|
+
if (fixable === false) break;
|
|
6752
|
+
cost += fixable;
|
|
6753
|
+
*/
|
|
6754
|
+
}
|
|
6703
6755
|
}
|
|
6704
|
-
return
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
decl,
|
|
6708
|
-
mayThrow,
|
|
6709
|
-
};
|
|
6710
|
-
}
|
|
6756
|
+
return false;
|
|
6757
|
+
})) {
|
|
6758
|
+
break;
|
|
6711
6759
|
}
|
|
6712
|
-
|
|
6760
|
+
return {
|
|
6761
|
+
type: "ref",
|
|
6762
|
+
node,
|
|
6763
|
+
decl: decls,
|
|
6764
|
+
mayThrow,
|
|
6765
|
+
};
|
|
6766
|
+
}
|
|
6713
6767
|
case "VariableDeclarator": {
|
|
6714
6768
|
const decl = findDecl(node.id.type === "BinaryExpression" ? node.id.left : node.id);
|
|
6715
6769
|
if (decl) {
|
|
@@ -6757,8 +6811,10 @@ function buildPREGraph(state, func) {
|
|
|
6757
6811
|
}
|
|
6758
6812
|
case "CallExpression": {
|
|
6759
6813
|
liveDef(null, stmt);
|
|
6760
|
-
const [, results] = state.
|
|
6761
|
-
const callees = results
|
|
6814
|
+
const [, results] = state.lookupNonlocal(node.callee);
|
|
6815
|
+
const callees = results
|
|
6816
|
+
? findCallees(results)
|
|
6817
|
+
: findCalleesByNode(state, node.callee);
|
|
6762
6818
|
return { type: "mod", node, mayThrow, callees };
|
|
6763
6819
|
}
|
|
6764
6820
|
default:
|
|
@@ -6773,6 +6829,132 @@ function buildPREGraph(state, func) {
|
|
|
6773
6829
|
}),
|
|
6774
6830
|
};
|
|
6775
6831
|
}
|
|
6832
|
+
class DataflowQueue {
|
|
6833
|
+
constructor() {
|
|
6834
|
+
this.enqueued = new Set();
|
|
6835
|
+
this.queue = new priorityqueuejs((b, a) => (a.order || 0) - (b.order || 0));
|
|
6836
|
+
}
|
|
6837
|
+
enqueue(block) {
|
|
6838
|
+
if (!this.enqueued.has(block)) {
|
|
6839
|
+
this.enqueued.add(block);
|
|
6840
|
+
this.queue.enq(block);
|
|
6841
|
+
}
|
|
6842
|
+
}
|
|
6843
|
+
dequeue() {
|
|
6844
|
+
const block = this.queue.deq();
|
|
6845
|
+
this.enqueued.delete(block);
|
|
6846
|
+
return block;
|
|
6847
|
+
}
|
|
6848
|
+
empty() {
|
|
6849
|
+
return this.queue.isEmpty();
|
|
6850
|
+
}
|
|
6851
|
+
}
|
|
6852
|
+
|
|
6853
|
+
;// CONCATENATED MODULE: ./src/pre.ts
|
|
6854
|
+
|
|
6855
|
+
|
|
6856
|
+
|
|
6857
|
+
|
|
6858
|
+
|
|
6859
|
+
|
|
6860
|
+
/**
|
|
6861
|
+
* This implements a pseudo Partial Redundancy Elimination
|
|
6862
|
+
* pass. It isn't quite like traditional PRE because we're
|
|
6863
|
+
* aiming to minimize size, not dynamic instructions. So
|
|
6864
|
+
* for us, its worthwhile to take something like:
|
|
6865
|
+
*
|
|
6866
|
+
* switch (x) {
|
|
6867
|
+
* case 1: foo(A.B); break;
|
|
6868
|
+
* case 2: foo(C); break;
|
|
6869
|
+
* case 3: bar(A.B); break;
|
|
6870
|
+
* }
|
|
6871
|
+
*
|
|
6872
|
+
* and rewrite it as
|
|
6873
|
+
*
|
|
6874
|
+
* var tmp = A.B;
|
|
6875
|
+
* switch (x) {
|
|
6876
|
+
* case 1: foo(tmp); break;
|
|
6877
|
+
* case 2: foo(C); break;
|
|
6878
|
+
* case 3: bar(tmp); break;
|
|
6879
|
+
* }
|
|
6880
|
+
*
|
|
6881
|
+
* because even though A.B wasn't used on all paths where we
|
|
6882
|
+
* inserted the temporary, we still reduced the code size.
|
|
6883
|
+
*/
|
|
6884
|
+
const logging = false;
|
|
6885
|
+
function logAntState(s, decl) {
|
|
6886
|
+
const defs = Array.from(s.ant).reduce((defs, event) => {
|
|
6887
|
+
if (event.type === "def" || event.type === "mod")
|
|
6888
|
+
defs++;
|
|
6889
|
+
return defs;
|
|
6890
|
+
}, 0);
|
|
6891
|
+
console.log(` - ${declFullName(decl)}: ${candidateCost(s)} bytes, ${s.ant.size - defs} refs, ${defs} defs, ${s.live ? "" : "!"}live, ${s.isIsolated ? "" : "!"}isolated`);
|
|
6892
|
+
console.log(` - members: ${Array.from(s.members)
|
|
6893
|
+
.map(([block, live]) => block.order + (live ? "t" : "f"))
|
|
6894
|
+
.join(", ")}`);
|
|
6895
|
+
}
|
|
6896
|
+
function logAntDecls(antDecls) {
|
|
6897
|
+
antDecls.forEach(logAntState);
|
|
6898
|
+
}
|
|
6899
|
+
function sizeBasedPRE(state, func) {
|
|
6900
|
+
if (!func.node.body)
|
|
6901
|
+
return;
|
|
6902
|
+
if (!state.config ||
|
|
6903
|
+
!state.config.sizeBasedPRE ||
|
|
6904
|
+
(typeof state.config.sizeBasedPRE === "string" &&
|
|
6905
|
+
state.config.sizeBasedPRE !== func.fullName)) {
|
|
6906
|
+
return;
|
|
6907
|
+
}
|
|
6908
|
+
const { graph: head, identifiers } = buildPREGraph(state, func);
|
|
6909
|
+
const candidates = computeAttributes(state, head);
|
|
6910
|
+
if (candidates) {
|
|
6911
|
+
if (logging) {
|
|
6912
|
+
console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
|
|
6913
|
+
logAntDecls(candidates);
|
|
6914
|
+
}
|
|
6915
|
+
const nodeMap = new Map();
|
|
6916
|
+
const declMap = new Map();
|
|
6917
|
+
const variableDecl = withLoc({
|
|
6918
|
+
type: "VariableDeclaration",
|
|
6919
|
+
declarations: [],
|
|
6920
|
+
kind: "var",
|
|
6921
|
+
}, func.node.body);
|
|
6922
|
+
variableDecl.end = variableDecl.start;
|
|
6923
|
+
variableDecl.loc.end = variableDecl.loc.start;
|
|
6924
|
+
candidates.forEach((s, decl) => {
|
|
6925
|
+
let name;
|
|
6926
|
+
let i = 0;
|
|
6927
|
+
do {
|
|
6928
|
+
name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
|
|
6929
|
+
if (!identifiers.has(name)) {
|
|
6930
|
+
identifiers.add(name);
|
|
6931
|
+
break;
|
|
6932
|
+
}
|
|
6933
|
+
i++;
|
|
6934
|
+
} while (true);
|
|
6935
|
+
declMap.set(decl, name);
|
|
6936
|
+
variableDecl.declarations.push(withLoc({
|
|
6937
|
+
type: "VariableDeclarator",
|
|
6938
|
+
id: withLoc({ type: "Identifier", name }, variableDecl),
|
|
6939
|
+
kind: "var",
|
|
6940
|
+
}, variableDecl));
|
|
6941
|
+
s.ant.forEach((event) => {
|
|
6942
|
+
const events = nodeMap.get(event.node);
|
|
6943
|
+
if (!events) {
|
|
6944
|
+
nodeMap.set(event.node, [event]);
|
|
6945
|
+
}
|
|
6946
|
+
else {
|
|
6947
|
+
events.push(event);
|
|
6948
|
+
}
|
|
6949
|
+
});
|
|
6950
|
+
});
|
|
6951
|
+
applyReplacements(func.node, nodeMap, declMap);
|
|
6952
|
+
func.node.body.body.unshift(variableDecl);
|
|
6953
|
+
}
|
|
6954
|
+
}
|
|
6955
|
+
function buildPREGraph(state, func) {
|
|
6956
|
+
return buildDataFlowGraph(state, func, (literal) => refCost(literal) > LocalRefCost, true, false);
|
|
6957
|
+
}
|
|
6776
6958
|
function anticipatedDecls() {
|
|
6777
6959
|
return new Map();
|
|
6778
6960
|
}
|
|
@@ -6928,26 +7110,18 @@ function computeAttributes(state, head) {
|
|
|
6928
7110
|
.join(", ")}`);
|
|
6929
7111
|
if (block.events) {
|
|
6930
7112
|
block.events.forEach((event) => event.type !== "exn" &&
|
|
6931
|
-
console.log(` ${event.type}: ${event.decl
|
|
7113
|
+
console.log(` ${event.type}: ${event.decl
|
|
7114
|
+
? declFullName(event.decl)
|
|
7115
|
+
: event.node
|
|
7116
|
+
? (0,external_api_cjs_namespaceObject.formatAst)(event.node)
|
|
7117
|
+
: "??"}`));
|
|
6932
7118
|
}
|
|
6933
7119
|
console.log(`Succs: ${(block.succs || [])
|
|
6934
7120
|
.map((block) => block.order)
|
|
6935
7121
|
.join(", ")} ExSucc: ${block.exsucc ? block.exsucc.order : ""}`);
|
|
6936
7122
|
});
|
|
6937
7123
|
}
|
|
6938
|
-
const
|
|
6939
|
-
const queue = new priorityqueuejs((b, a) => (a.order || 0) - (b.order || 0));
|
|
6940
|
-
const enqueue = (block) => {
|
|
6941
|
-
if (!enqueued.has(block)) {
|
|
6942
|
-
enqueued.add(block);
|
|
6943
|
-
queue.enq(block);
|
|
6944
|
-
}
|
|
6945
|
-
};
|
|
6946
|
-
const dequeue = () => {
|
|
6947
|
-
const block = queue.deq();
|
|
6948
|
-
enqueued.delete(block);
|
|
6949
|
-
return block;
|
|
6950
|
-
};
|
|
7124
|
+
const queue = new DataflowQueue();
|
|
6951
7125
|
const blockStates = [];
|
|
6952
7126
|
/*
|
|
6953
7127
|
Algorithm
|
|
@@ -6981,9 +7155,9 @@ function computeAttributes(state, head) {
|
|
|
6981
7155
|
}
|
|
6982
7156
|
return result;
|
|
6983
7157
|
};
|
|
6984
|
-
order.forEach((block) => enqueue(block));
|
|
6985
|
-
while (queue.
|
|
6986
|
-
const top = dequeue();
|
|
7158
|
+
order.forEach((block) => queue.enqueue(block));
|
|
7159
|
+
while (!queue.empty()) {
|
|
7160
|
+
const top = queue.dequeue();
|
|
6987
7161
|
if (top.order === undefined) {
|
|
6988
7162
|
throw new Error(`Unreachable block was visited!`);
|
|
6989
7163
|
}
|
|
@@ -7022,13 +7196,13 @@ function computeAttributes(state, head) {
|
|
|
7022
7196
|
break;
|
|
7023
7197
|
}
|
|
7024
7198
|
case "mod": {
|
|
7025
|
-
curState.forEach((candidates,
|
|
7026
|
-
if (decl.type === "VariableDeclarator" &&
|
|
7199
|
+
curState.forEach((candidates, decls) => {
|
|
7200
|
+
if ((0,external_util_cjs_namespaceObject.some)(decls, (decl) => decl.type === "VariableDeclarator" &&
|
|
7027
7201
|
decl.node.kind === "var" &&
|
|
7028
7202
|
candidates.live &&
|
|
7029
7203
|
(!event.callees ||
|
|
7030
|
-
event.callees.some((callee) => functionMayModify(state, callee, decl)))) {
|
|
7031
|
-
candidates.ant.add(getMod(event,
|
|
7204
|
+
event.callees.some((callee) => functionMayModify(state, callee, decl))))) {
|
|
7205
|
+
candidates.ant.add(getMod(event, decls, candidates.node));
|
|
7032
7206
|
candidates.live = false;
|
|
7033
7207
|
}
|
|
7034
7208
|
});
|
|
@@ -7080,7 +7254,7 @@ function computeAttributes(state, head) {
|
|
|
7080
7254
|
logAntDecls(curState);
|
|
7081
7255
|
}
|
|
7082
7256
|
if (top.preds) {
|
|
7083
|
-
top.preds.forEach((pred) => enqueue(pred));
|
|
7257
|
+
top.preds.forEach((pred) => queue.enqueue(pred));
|
|
7084
7258
|
}
|
|
7085
7259
|
}
|
|
7086
7260
|
const candidateDecls = anticipatedDecls();
|
|
@@ -7918,8 +8092,21 @@ function replacementLiteral(arg, value, type) {
|
|
|
7918
8092
|
else if (type === "Double") {
|
|
7919
8093
|
raw += "d";
|
|
7920
8094
|
}
|
|
7921
|
-
else if (type === "Float"
|
|
7922
|
-
raw
|
|
8095
|
+
else if (type === "Float") {
|
|
8096
|
+
if (prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(raw)) {
|
|
8097
|
+
raw += "f";
|
|
8098
|
+
}
|
|
8099
|
+
else {
|
|
8100
|
+
const match = raw.match(/^(-)?(\d*)\.(\d+)(e\d+)?/);
|
|
8101
|
+
if (match && match[2].length + match[3].length > 9) {
|
|
8102
|
+
for (let l = 9 - match[2].length; l > 0; l--) {
|
|
8103
|
+
const s = `${match[1] || ""}${match[2]}.${match[3].substring(0, l)}${match[4] || ""}`;
|
|
8104
|
+
if (value !== roundToFloat(parseFloat(s)))
|
|
8105
|
+
break;
|
|
8106
|
+
raw = s;
|
|
8107
|
+
}
|
|
8108
|
+
}
|
|
8109
|
+
}
|
|
7923
8110
|
}
|
|
7924
8111
|
const { start, end, loc } = arg;
|
|
7925
8112
|
return {
|
|
@@ -8007,6 +8194,20 @@ function shift_mod_types(left, right) {
|
|
|
8007
8194
|
}
|
|
8008
8195
|
return result;
|
|
8009
8196
|
}
|
|
8197
|
+
function equalsFn(left, right) {
|
|
8198
|
+
const lt = typeof left;
|
|
8199
|
+
const rt = typeof right;
|
|
8200
|
+
return lt === "string" || rt === "string"
|
|
8201
|
+
? // two string literals will compare unequal, becuase string
|
|
8202
|
+
// equality is object equality.
|
|
8203
|
+
false
|
|
8204
|
+
: (lt === "number" || lt === "bigint") &&
|
|
8205
|
+
(rt === "number" || rt === "bigint")
|
|
8206
|
+
? // numeric types are compared for value equality
|
|
8207
|
+
left == right
|
|
8208
|
+
: // otherwise types and values must match
|
|
8209
|
+
left === right;
|
|
8210
|
+
}
|
|
8010
8211
|
const operators = {
|
|
8011
8212
|
"+": {
|
|
8012
8213
|
typeFn: plus_types,
|
|
@@ -8058,14 +8259,11 @@ const operators = {
|
|
|
8058
8259
|
},
|
|
8059
8260
|
"==": {
|
|
8060
8261
|
typeFn: () => ["Boolean", (v) => v],
|
|
8061
|
-
valueFn:
|
|
8062
|
-
// two string literals will compare unequal, becuase string
|
|
8063
|
-
// equality is object equality.
|
|
8064
|
-
typeof left === "string" ? false : left === right,
|
|
8262
|
+
valueFn: equalsFn,
|
|
8065
8263
|
},
|
|
8066
8264
|
"!=": {
|
|
8067
8265
|
typeFn: () => ["Boolean", (v) => v],
|
|
8068
|
-
valueFn: (left, right) =>
|
|
8266
|
+
valueFn: (left, right) => !equalsFn(left, right),
|
|
8069
8267
|
},
|
|
8070
8268
|
"<=": {
|
|
8071
8269
|
typeFn: common_arith_types,
|
|
@@ -8592,7 +8790,7 @@ async function optimizeMonkeyC(fnMap, resourcesMap, manifestXML, config) {
|
|
|
8592
8790
|
if (!state.currentFunction) {
|
|
8593
8791
|
throw new Error(`Finished function ${state.stack.slice(-1)[0].fullName}, but it was not marked current`);
|
|
8594
8792
|
}
|
|
8595
|
-
state.currentFunction.info = state.currentFunction.next_info;
|
|
8793
|
+
state.currentFunction.info = state.currentFunction.next_info || false;
|
|
8596
8794
|
delete state.currentFunction.next_info;
|
|
8597
8795
|
delete state.currentFunction;
|
|
8598
8796
|
break;
|
|
@@ -9155,7 +9353,7 @@ async function createLocalBarrels(targets, options) {
|
|
|
9155
9353
|
async function generateOptimizedProject(options) {
|
|
9156
9354
|
const config = await getConfig(options);
|
|
9157
9355
|
const workspace = config.workspace;
|
|
9158
|
-
const { manifest, targets, xml,
|
|
9356
|
+
const { manifest, targets, xml, devices, resources, buildDependencies } = await get_jungle(config.jungleFiles, config);
|
|
9159
9357
|
if (xml.body instanceof Error) {
|
|
9160
9358
|
throw xml.body;
|
|
9161
9359
|
}
|
|
@@ -9167,7 +9365,7 @@ async function generateOptimizedProject(options) {
|
|
|
9167
9365
|
xml.body.elements[0].loc || undefined;
|
|
9168
9366
|
throw error;
|
|
9169
9367
|
}
|
|
9170
|
-
const dependencyFiles =
|
|
9368
|
+
const dependencyFiles = Object.keys(resources).concat(Object.keys(buildDependencies));
|
|
9171
9369
|
await createLocalBarrels(targets, config);
|
|
9172
9370
|
const buildConfigs = {};
|
|
9173
9371
|
const products = {};
|
|
@@ -9265,13 +9463,35 @@ async function generateOptimizedProject(options) {
|
|
|
9265
9463
|
relative_manifest = "manifest.xml";
|
|
9266
9464
|
}
|
|
9267
9465
|
const parts = [`project.manifest=${relative_manifest}`];
|
|
9268
|
-
const
|
|
9466
|
+
const map_field = (base, name, mapper = null) => {
|
|
9269
9467
|
const obj = base[name];
|
|
9270
9468
|
if (!obj)
|
|
9271
|
-
return;
|
|
9469
|
+
return null;
|
|
9272
9470
|
const map_one = (s) => (mapper ? mapper(s) : s);
|
|
9273
9471
|
const map = (s) => Array.isArray(s) ? `[${s.map(map_one).join(";")}]` : map_one(s);
|
|
9274
|
-
|
|
9472
|
+
return `${obj.map(map).join(";")}`;
|
|
9473
|
+
};
|
|
9474
|
+
const process_field = (prefix, base, name, mapper = null) => {
|
|
9475
|
+
const mapped = map_field(base, name, mapper);
|
|
9476
|
+
if (!mapped)
|
|
9477
|
+
return;
|
|
9478
|
+
parts.push(`${prefix}${name} = ${mapped}`);
|
|
9479
|
+
};
|
|
9480
|
+
const languagesToInclude = Object.fromEntries((manifestLanguages(xml) || []).map((lang) => [lang, true]));
|
|
9481
|
+
const unsupportedLangsCache = {};
|
|
9482
|
+
let availableDefaults = null;
|
|
9483
|
+
const nextAvailableDefault = () => {
|
|
9484
|
+
if (!availableDefaults) {
|
|
9485
|
+
availableDefaults = Object.keys(Object.values(devices).reduce((m, d) => {
|
|
9486
|
+
m[d.deviceFamily] = true;
|
|
9487
|
+
const match = d.deviceFamily.match(/^(\w+)-\d+x\d+/);
|
|
9488
|
+
if (match)
|
|
9489
|
+
m[match[1]] = true;
|
|
9490
|
+
return m;
|
|
9491
|
+
}, {})).sort();
|
|
9492
|
+
availableDefaults.unshift("base");
|
|
9493
|
+
}
|
|
9494
|
+
return availableDefaults.shift();
|
|
9275
9495
|
};
|
|
9276
9496
|
targets.forEach((target) => {
|
|
9277
9497
|
if (!buildConfigs[configKey(target)])
|
|
@@ -9308,8 +9528,39 @@ async function generateOptimizedProject(options) {
|
|
|
9308
9528
|
process_field(prefix, qualifier, "excludeAnnotations");
|
|
9309
9529
|
const qlang = qualifier.lang;
|
|
9310
9530
|
if (qlang) {
|
|
9531
|
+
const devLang = devices[product].languages;
|
|
9532
|
+
const unsupportedLangs = Object.keys(qlang)
|
|
9533
|
+
.sort()
|
|
9534
|
+
.map((key) => {
|
|
9535
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(devLang, key) ||
|
|
9536
|
+
!(0,external_api_cjs_namespaceObject.hasProperty)(languagesToInclude, key)) {
|
|
9537
|
+
return null;
|
|
9538
|
+
}
|
|
9539
|
+
const mapped = map_field(qlang, key, relative_path);
|
|
9540
|
+
if (!mapped)
|
|
9541
|
+
return null;
|
|
9542
|
+
return [key, mapped];
|
|
9543
|
+
})
|
|
9544
|
+
.filter((a) => a != null);
|
|
9545
|
+
let keysToSkip = null;
|
|
9546
|
+
if (unsupportedLangs.length) {
|
|
9547
|
+
const key = JSON.stringify(unsupportedLangs);
|
|
9548
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(unsupportedLangsCache, key)) {
|
|
9549
|
+
const base = nextAvailableDefault();
|
|
9550
|
+
if (base) {
|
|
9551
|
+
unsupportedLangs.forEach(([key, value]) => parts.push(`${base}.lang.${key} = ${value}`));
|
|
9552
|
+
unsupportedLangsCache[key] = `${base}.lang`;
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
if ((0,external_api_cjs_namespaceObject.hasProperty)(unsupportedLangsCache, key)) {
|
|
9556
|
+
keysToSkip = Object.fromEntries(unsupportedLangs);
|
|
9557
|
+
parts.push(`${prefix}lang = $(${unsupportedLangsCache[key]})`);
|
|
9558
|
+
}
|
|
9559
|
+
}
|
|
9311
9560
|
Object.keys(qlang).forEach((key) => {
|
|
9312
|
-
|
|
9561
|
+
(0,external_api_cjs_namespaceObject.hasProperty)(keysToSkip, key) ||
|
|
9562
|
+
!(0,external_api_cjs_namespaceObject.hasProperty)(languagesToInclude, key) ||
|
|
9563
|
+
process_field(`${prefix}lang.`, qlang, key, relative_path);
|
|
9313
9564
|
});
|
|
9314
9565
|
}
|
|
9315
9566
|
});
|
|
@@ -9429,7 +9680,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
9429
9680
|
// the oldest optimized file, we don't need to regenerate
|
|
9430
9681
|
const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
|
|
9431
9682
|
const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
|
|
9432
|
-
if (source_time < opt_time &&
|
|
9683
|
+
if (source_time < opt_time && 1672601827382 < opt_time) {
|
|
9433
9684
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
9434
9685
|
}
|
|
9435
9686
|
}
|
|
@@ -9456,7 +9707,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
9456
9707
|
return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
|
|
9457
9708
|
hasTests,
|
|
9458
9709
|
diagnostics,
|
|
9459
|
-
optimizerVersion: "1.0.
|
|
9710
|
+
optimizerVersion: "1.0.45",
|
|
9460
9711
|
...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
|
|
9461
9712
|
}))
|
|
9462
9713
|
.then(() => ({ hasTests, diagnostics }));
|