@markw65/monkeyc-optimizer 1.0.2 → 1.0.6
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 +20 -0
- package/build/api.cjs +162 -148
- package/build/optimizer.cjs +135 -64
- package/build/util.cjs +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,4 +18,24 @@ Initial release
|
|
|
18
18
|
- Better error reporting when something goes wrong internally
|
|
19
19
|
- Fix an order dependency when processing imports. Previously, if the import statement was seen before the module being imported, we would fail to properly handle the import.
|
|
20
20
|
|
|
21
|
+
### 1.0.3
|
|
22
|
+
|
|
23
|
+
- Split the build into release and debug, so we can exclude code based on (:release) and (:debug)
|
|
24
|
+
- Optimize away `if (constant)`, `while (false)` and `constant ? E1 : E2`. Convert `do BODY while(false)` to `BODY`
|
|
25
|
+
|
|
26
|
+
### 1.0.4
|
|
27
|
+
|
|
28
|
+
- Fix a bug resulting in a failure to fully optimize constants initialized by constant conditional expressions
|
|
29
|
+
- Make the generated .cjs files work better with es modules (vscode doesn't work with es modules, so prettier-extension-monkeyc doesn't care - but for other projects importing this package it improves the behavior)
|
|
30
|
+
- Generate separate debug/release jungle files.
|
|
31
|
+
|
|
32
|
+
### 1.0.5
|
|
33
|
+
|
|
34
|
+
- Bump to version 1.0.11 of `@markw65/prettier-plugin-monkeyc` to fix an ObjectLiteral parsing issue.
|
|
35
|
+
|
|
36
|
+
### 1.0.6
|
|
37
|
+
|
|
38
|
+
- Bump to version 1.0.12 of `@markw65/prettier-plugin-monkeyc` to fix multiple parser bugs
|
|
39
|
+
- Add lots of open source projects as tests. For now, just verify that optimizing the sources succeeds, not that the generated source is actually correct.
|
|
40
|
+
|
|
21
41
|
---
|
package/build/api.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
0 && (module.exports = {LiteralIntegerRe,getApiMapping,hasProperty,collectNamespaces,traverseAst,formatAst});
|
|
1
2
|
/******/ (() => { // webpackBootstrap
|
|
2
3
|
/******/ "use strict";
|
|
3
4
|
/******/ // The require scope
|
|
@@ -217,169 +218,182 @@ function collectNamespaces(ast, state) {
|
|
|
217
218
|
return [null, null];
|
|
218
219
|
};
|
|
219
220
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
if (node.source) {
|
|
230
|
-
state.stack[0].source = node.source;
|
|
231
|
-
}
|
|
232
|
-
break;
|
|
233
|
-
case "BlockStatement": {
|
|
234
|
-
const [parent] = state.stack.slice(-1);
|
|
235
|
-
if (
|
|
236
|
-
parent.type != "FunctionDeclaration" &&
|
|
237
|
-
parent.type != "BlockStatement"
|
|
238
|
-
) {
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
// fall through
|
|
221
|
+
state.traverse = (root) =>
|
|
222
|
+
traverseAst(
|
|
223
|
+
root,
|
|
224
|
+
(node) => {
|
|
225
|
+
try {
|
|
226
|
+
if (state.shouldExclude && state.shouldExclude(node)) {
|
|
227
|
+
// don't visit any children, but do call post
|
|
228
|
+
return [];
|
|
242
229
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
230
|
+
switch (node.type) {
|
|
231
|
+
case "Program":
|
|
232
|
+
if (state.stack.length != 1) {
|
|
233
|
+
throw new Error("Unexpected stack length for Program node");
|
|
234
|
+
}
|
|
235
|
+
if (node.source) {
|
|
236
|
+
state.stack[0].source = node.source;
|
|
237
|
+
}
|
|
238
|
+
break;
|
|
239
|
+
case "BlockStatement": {
|
|
247
240
|
const [parent] = state.stack.slice(-1);
|
|
248
|
-
|
|
249
|
-
type
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
241
|
+
if (
|
|
242
|
+
parent.type != "FunctionDeclaration" &&
|
|
243
|
+
parent.type != "BlockStatement"
|
|
244
|
+
) {
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
// fall through
|
|
248
|
+
}
|
|
249
|
+
case "ClassDeclaration":
|
|
250
|
+
case "FunctionDeclaration":
|
|
251
|
+
case "ModuleDeclaration":
|
|
252
|
+
if (node.id || node.type == "BlockStatement") {
|
|
253
|
+
const [parent] = state.stack.slice(-1);
|
|
254
|
+
const elm = {
|
|
255
|
+
type: node.type,
|
|
256
|
+
name: node.id && node.id.name,
|
|
257
|
+
node,
|
|
258
|
+
};
|
|
259
|
+
state.stack.push(elm);
|
|
260
|
+
elm.fullName = state.stack
|
|
261
|
+
.map((e) => e.name)
|
|
262
|
+
.filter((e) => e != null)
|
|
263
|
+
.join(".");
|
|
264
|
+
if (elm.name) {
|
|
265
|
+
if (!parent.decls) parent.decls = {};
|
|
266
|
+
if (hasProperty(parent.decls, elm.name)) {
|
|
267
|
+
const what =
|
|
268
|
+
node.type == "ModuleDeclaration" ? "type" : "node";
|
|
269
|
+
const e = parent.decls[elm.name].find(
|
|
270
|
+
(d) => d[what] == elm[what]
|
|
271
|
+
);
|
|
272
|
+
if (e != null) {
|
|
273
|
+
e.node = node;
|
|
274
|
+
state.stack.splice(-1, 1, e);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
parent.decls[elm.name] = [];
|
|
270
279
|
}
|
|
271
|
-
|
|
272
|
-
parent.decls[elm.name] = [];
|
|
280
|
+
parent.decls[elm.name].push(elm);
|
|
273
281
|
}
|
|
274
|
-
parent.decls[elm.name].push(elm);
|
|
275
282
|
}
|
|
283
|
+
break;
|
|
284
|
+
// an EnumDeclaration doesn't create a scope, but
|
|
285
|
+
// it does create a type (if it has a name)
|
|
286
|
+
case "EnumDeclaration": {
|
|
287
|
+
if (!node.id) break;
|
|
288
|
+
const [parent] = state.stack.slice(-1);
|
|
289
|
+
const name = (parent.fullName + "." + node.id.name).replace(
|
|
290
|
+
/^\$\./,
|
|
291
|
+
""
|
|
292
|
+
);
|
|
293
|
+
node.body.members.forEach((m) => ((m.init || m).enumType = name));
|
|
276
294
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const name = (parent.fullName + "." + node.id.name).replace(
|
|
284
|
-
/^\$\./,
|
|
285
|
-
""
|
|
286
|
-
);
|
|
287
|
-
node.body.members.forEach((m) => ((m.init || m).enumType = name));
|
|
288
|
-
}
|
|
289
|
-
// fall through
|
|
290
|
-
case "TypedefDeclaration": {
|
|
291
|
-
const [parent] = state.stack.slice(-1);
|
|
292
|
-
if (!parent.decls) parent.decls = {};
|
|
293
|
-
if (!hasProperty(parent.decls, node.id.name)) {
|
|
294
|
-
parent.decls[node.id.name] = [];
|
|
295
|
-
}
|
|
296
|
-
(0,external_util_cjs_namespaceObject.pushUnique)(
|
|
297
|
-
parent.decls[node.id.name],
|
|
298
|
-
node.ts ? formatAst(node.ts.argument) : node.id.name
|
|
299
|
-
);
|
|
300
|
-
break;
|
|
301
|
-
}
|
|
302
|
-
case "VariableDeclaration": {
|
|
303
|
-
const [parent] = state.stack.slice(-1);
|
|
304
|
-
if (!parent.decls) parent.decls = {};
|
|
305
|
-
node.declarations.forEach((decl) => {
|
|
306
|
-
if (!hasProperty(parent.decls, decl.id.name)) {
|
|
307
|
-
parent.decls[decl.id.name] = [];
|
|
295
|
+
// fall through
|
|
296
|
+
case "TypedefDeclaration": {
|
|
297
|
+
const [parent] = state.stack.slice(-1);
|
|
298
|
+
if (!parent.decls) parent.decls = {};
|
|
299
|
+
if (!hasProperty(parent.decls, node.id.name)) {
|
|
300
|
+
parent.decls[node.id.name] = [];
|
|
308
301
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
302
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(
|
|
303
|
+
parent.decls[node.id.name],
|
|
304
|
+
node.ts ? formatAst(node.ts.argument) : node.id.name
|
|
305
|
+
);
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case "VariableDeclaration": {
|
|
309
|
+
const [parent] = state.stack.slice(-1);
|
|
310
|
+
if (!parent.decls) parent.decls = {};
|
|
311
|
+
node.declarations.forEach((decl) => {
|
|
312
|
+
if (!hasProperty(parent.decls, decl.id.name)) {
|
|
313
|
+
parent.decls[decl.id.name] = [];
|
|
313
314
|
}
|
|
314
|
-
(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const [parent] = state.stack.slice(-1);
|
|
326
|
-
const values = parent.decls || (parent.decls = {});
|
|
327
|
-
let prev = -1;
|
|
328
|
-
node.members.forEach((m) => {
|
|
329
|
-
let name, init;
|
|
330
|
-
if (m.type == "EnumStringMember") {
|
|
331
|
-
name = m.id.name;
|
|
332
|
-
init = m.init;
|
|
333
|
-
if (init.type == "Literal" && LiteralIntegerRe.test(init.raw)) {
|
|
334
|
-
prev = init.value;
|
|
315
|
+
if (node.kind == "const") {
|
|
316
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(parent.decls[decl.id.name], decl.init);
|
|
317
|
+
if (!hasProperty(state.index, decl.id.name)) {
|
|
318
|
+
state.index[decl.id.name] = [];
|
|
319
|
+
}
|
|
320
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(state.index[decl.id.name], parent);
|
|
321
|
+
} else if (decl.id.ts) {
|
|
322
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(
|
|
323
|
+
parent.decls[decl.id.name],
|
|
324
|
+
formatAst(decl.id.ts.argument)
|
|
325
|
+
);
|
|
335
326
|
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
327
|
+
});
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
case "EnumStringBody": {
|
|
331
|
+
const [parent] = state.stack.slice(-1);
|
|
332
|
+
const values = parent.decls || (parent.decls = {});
|
|
333
|
+
let prev = -1;
|
|
334
|
+
node.members.forEach((m) => {
|
|
335
|
+
let name, init;
|
|
336
|
+
if (m.type == "EnumStringMember") {
|
|
337
|
+
name = m.id.name;
|
|
338
|
+
init = m.init;
|
|
339
|
+
if (
|
|
340
|
+
init.type == "Literal" &&
|
|
341
|
+
LiteralIntegerRe.test(init.raw)
|
|
342
|
+
) {
|
|
343
|
+
prev = init.value;
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
name = m.name;
|
|
347
|
+
prev += 1;
|
|
348
|
+
if (!state.constants) {
|
|
349
|
+
state.constants = {};
|
|
350
|
+
}
|
|
351
|
+
const key = m.enumType ? `${m.enumType}:${prev}` : prev;
|
|
352
|
+
init = state.constants[key];
|
|
353
|
+
if (!init) {
|
|
354
|
+
init = state.constants[key] = {
|
|
355
|
+
type: "Literal",
|
|
356
|
+
value: prev,
|
|
357
|
+
raw: prev.toString(),
|
|
358
|
+
enumType: m.enumType,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
341
361
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (!init) {
|
|
345
|
-
init = state.constants[key] = {
|
|
346
|
-
type: "Literal",
|
|
347
|
-
value: prev,
|
|
348
|
-
raw: prev.toString(),
|
|
349
|
-
enumType: m.enumType,
|
|
350
|
-
};
|
|
362
|
+
if (!hasProperty(values, name)) {
|
|
363
|
+
values[name] = [];
|
|
351
364
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
(0,external_util_cjs_namespaceObject.pushUnique)(state.index[name], parent);
|
|
361
|
-
});
|
|
362
|
-
break;
|
|
365
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(values[name], init);
|
|
366
|
+
if (!hasProperty(state.index, name)) {
|
|
367
|
+
state.index[name] = [];
|
|
368
|
+
}
|
|
369
|
+
(0,external_util_cjs_namespaceObject.pushUnique)(state.index[name], parent);
|
|
370
|
+
});
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
363
373
|
}
|
|
374
|
+
if (state.pre) return state.pre(node);
|
|
375
|
+
} catch (e) {
|
|
376
|
+
handleException(state, node, e);
|
|
364
377
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
378
|
+
},
|
|
379
|
+
(node) => {
|
|
380
|
+
try {
|
|
381
|
+
let ret;
|
|
382
|
+
if (state.shouldExclude && state.shouldExclude(node)) {
|
|
383
|
+
// delete the node.
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
if (state.post) ret = state.post(node);
|
|
387
|
+
if (state.stack.slice(-1).pop().node === node) {
|
|
388
|
+
state.stack.pop();
|
|
389
|
+
}
|
|
390
|
+
return ret;
|
|
391
|
+
} catch (e) {
|
|
392
|
+
handleException(state, node, e);
|
|
376
393
|
}
|
|
377
|
-
return ret;
|
|
378
|
-
} catch (e) {
|
|
379
|
-
handleException(state, node, e);
|
|
380
394
|
}
|
|
381
|
-
|
|
382
|
-
);
|
|
395
|
+
);
|
|
396
|
+
state.traverse(ast);
|
|
383
397
|
if (state.stack.length != 1) {
|
|
384
398
|
throw new Error("Invalid AST!");
|
|
385
399
|
}
|
package/build/optimizer.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
0 && (module.exports = {copyRecursiveAsNeeded,launchSimulator,defaultConfig,buildOptimizedProject,generateOptimizedProject,generateApiMirTests});
|
|
1
2
|
/******/ (() => { // webpackBootstrap
|
|
2
3
|
/******/ var __webpack_modules__ = ({
|
|
3
4
|
|
|
@@ -7439,6 +7440,7 @@ function resolve_node(state, node) {
|
|
|
7439
7440
|
}
|
|
7440
7441
|
|
|
7441
7442
|
function resolve_filename(literal, default_source) {
|
|
7443
|
+
if (typeof literal === "string") return literal;
|
|
7442
7444
|
const root = external_path_namespaceObject.dirname(literal.source || default_source);
|
|
7443
7445
|
return external_path_namespaceObject.resolve(root, literal.value);
|
|
7444
7446
|
}
|
|
@@ -7479,10 +7481,14 @@ async function resolve_literals(qualifier, default_source) {
|
|
|
7479
7481
|
await resolve_one_file_list(qualifier, "resourcePath");
|
|
7480
7482
|
await resolve_one_file_list(qualifier, "barrelPath");
|
|
7481
7483
|
const lang = qualifier["lang"];
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7484
|
+
if (lang) {
|
|
7485
|
+
await Promise.all(
|
|
7486
|
+
Object.keys(lang).map((key) => resolve_one_file_list(lang, key))
|
|
7487
|
+
);
|
|
7488
|
+
if (Object.keys(lang).length === 0) delete qualifier["lang"];
|
|
7489
|
+
} else {
|
|
7490
|
+
delete qualifier["lang"];
|
|
7491
|
+
}
|
|
7486
7492
|
|
|
7487
7493
|
const resolve_literal_list = (base, name) => {
|
|
7488
7494
|
const literals = base[name];
|
|
@@ -7634,7 +7640,7 @@ const prettier_plugin_monkeyc_namespaceObject = require("@markw65/prettier-plugi
|
|
|
7634
7640
|
|
|
7635
7641
|
function processImports(allImports, lookup) {
|
|
7636
7642
|
allImports.forEach(({ node, stack }) => {
|
|
7637
|
-
const [name, module] = lookup(node.id, node.as && node.as.
|
|
7643
|
+
const [name, module] = lookup(node.id, node.as && node.as.name, stack);
|
|
7638
7644
|
if (name && module) {
|
|
7639
7645
|
const [parent] = stack.slice(-1);
|
|
7640
7646
|
if (!parent.decls) parent.decls = {};
|
|
@@ -7685,34 +7691,24 @@ async function analyze(fileNames, buildConfig) {
|
|
|
7685
7691
|
? Object.fromEntries(buildConfig.excludeAnnotations.map((a) => [a, true]))
|
|
7686
7692
|
: {};
|
|
7687
7693
|
|
|
7688
|
-
const shouldExclude = (node) => {
|
|
7689
|
-
if (node.attrs && node.attrs.attrs) {
|
|
7690
|
-
if (
|
|
7691
|
-
node.attrs.attrs.filter((attr) => {
|
|
7692
|
-
if (attr.type != "UnaryExpression") return false;
|
|
7693
|
-
if (attr.argument.type != "Identifier") return false;
|
|
7694
|
-
return (0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name);
|
|
7695
|
-
}).length
|
|
7696
|
-
) {
|
|
7697
|
-
return true;
|
|
7698
|
-
}
|
|
7699
|
-
}
|
|
7700
|
-
};
|
|
7701
7694
|
const allImports = [];
|
|
7702
7695
|
const state = {
|
|
7703
7696
|
allFunctions: [],
|
|
7704
7697
|
allClasses: [],
|
|
7705
|
-
|
|
7706
|
-
if (
|
|
7707
|
-
|
|
7708
|
-
|
|
7698
|
+
shouldExclude(node) {
|
|
7699
|
+
if (node.attrs && node.attrs.attrs) {
|
|
7700
|
+
if (
|
|
7701
|
+
node.attrs.attrs.filter((attr) => {
|
|
7702
|
+
if (attr.type != "UnaryExpression") return false;
|
|
7703
|
+
if (attr.argument.type != "Identifier") return false;
|
|
7704
|
+
return (0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name);
|
|
7705
|
+
}).length
|
|
7706
|
+
) {
|
|
7707
|
+
return true;
|
|
7708
|
+
}
|
|
7709
7709
|
}
|
|
7710
7710
|
},
|
|
7711
7711
|
post(node) {
|
|
7712
|
-
if (shouldExclude(node)) {
|
|
7713
|
-
// delete the node.
|
|
7714
|
-
return false;
|
|
7715
|
-
}
|
|
7716
7712
|
switch (node.type) {
|
|
7717
7713
|
case "FunctionDeclaration":
|
|
7718
7714
|
case "ClassDeclaration": {
|
|
@@ -7768,7 +7764,7 @@ async function analyze(fileNames, buildConfig) {
|
|
|
7768
7764
|
(0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
|
|
7769
7765
|
});
|
|
7770
7766
|
|
|
7771
|
-
delete state.
|
|
7767
|
+
delete state.shouldExclude;
|
|
7772
7768
|
delete state.post;
|
|
7773
7769
|
|
|
7774
7770
|
processImports(allImports, state.lookup);
|
|
@@ -8054,6 +8050,49 @@ async function optimizeMonkeyC(fileNames, buildConfig) {
|
|
|
8054
8050
|
state.calledFunctions = {};
|
|
8055
8051
|
state.pre = (node) => {
|
|
8056
8052
|
switch (node.type) {
|
|
8053
|
+
case "ConditionalExpression":
|
|
8054
|
+
case "IfStatement":
|
|
8055
|
+
case "DoWhileStatement":
|
|
8056
|
+
case "WhileStatement":
|
|
8057
|
+
state.traverse(node.test);
|
|
8058
|
+
const [value, type] = getNodeValue(node.test);
|
|
8059
|
+
if (value) {
|
|
8060
|
+
let result = null;
|
|
8061
|
+
if (type === "Null") {
|
|
8062
|
+
result = false;
|
|
8063
|
+
} else if (
|
|
8064
|
+
type === "Boolean" ||
|
|
8065
|
+
type === "Number" ||
|
|
8066
|
+
type === "Long"
|
|
8067
|
+
) {
|
|
8068
|
+
result = !!value.value;
|
|
8069
|
+
}
|
|
8070
|
+
if (result !== null) {
|
|
8071
|
+
if (
|
|
8072
|
+
node.type === "IfStatement" ||
|
|
8073
|
+
node.type === "ConditionalExpression"
|
|
8074
|
+
) {
|
|
8075
|
+
if (result === false) {
|
|
8076
|
+
node.consequent = null;
|
|
8077
|
+
} else {
|
|
8078
|
+
node.alternate = null;
|
|
8079
|
+
}
|
|
8080
|
+
node.test = result;
|
|
8081
|
+
} else if (node.type === "WhileStatement") {
|
|
8082
|
+
if (result === false) {
|
|
8083
|
+
node.body = null;
|
|
8084
|
+
}
|
|
8085
|
+
} else if (node.type === "DoWhileStatement") {
|
|
8086
|
+
if (result === false) {
|
|
8087
|
+
node.test = null;
|
|
8088
|
+
}
|
|
8089
|
+
} else {
|
|
8090
|
+
throw new Error("Unexpected Node type");
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
return;
|
|
8095
|
+
|
|
8057
8096
|
case "EnumDeclaration":
|
|
8058
8097
|
return false;
|
|
8059
8098
|
case "VariableDeclarator":
|
|
@@ -8088,6 +8127,8 @@ async function optimizeMonkeyC(fileNames, buildConfig) {
|
|
|
8088
8127
|
state.exposed[node.name] = true;
|
|
8089
8128
|
}
|
|
8090
8129
|
}
|
|
8130
|
+
// Don't optimize the property.
|
|
8131
|
+
return ["object"];
|
|
8091
8132
|
}
|
|
8092
8133
|
break;
|
|
8093
8134
|
case "FunctionDeclaration": {
|
|
@@ -8115,38 +8156,56 @@ async function optimizeMonkeyC(fileNames, buildConfig) {
|
|
|
8115
8156
|
replace(node, opt);
|
|
8116
8157
|
return;
|
|
8117
8158
|
}
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
(node
|
|
8125
|
-
if (n) {
|
|
8126
|
-
state.exposed[n] = true;
|
|
8127
|
-
} else {
|
|
8128
|
-
throw new Error("What?");
|
|
8159
|
+
switch (node.type) {
|
|
8160
|
+
case "ConditionalExpression":
|
|
8161
|
+
case "IfStatement":
|
|
8162
|
+
if (typeof node.test === "boolean") {
|
|
8163
|
+
const rep = node.test ? node.consequent : node.alternate;
|
|
8164
|
+
if (!rep) return false;
|
|
8165
|
+
replace(node, rep);
|
|
8129
8166
|
}
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8167
|
+
break;
|
|
8168
|
+
case "WhileStatement":
|
|
8169
|
+
if (!node.body) return false;
|
|
8170
|
+
break;
|
|
8171
|
+
case "DoWhileStatement":
|
|
8172
|
+
if (!node.test) return node.body;
|
|
8173
|
+
break;
|
|
8174
|
+
|
|
8175
|
+
case "CallExpression": {
|
|
8176
|
+
const [name, callees] = state.lookup(node.callee);
|
|
8177
|
+
if (!callees || !callees.length) {
|
|
8178
|
+
const n =
|
|
8179
|
+
name ||
|
|
8180
|
+
node.callee.name ||
|
|
8181
|
+
(node.callee.property && node.callee.property.name);
|
|
8182
|
+
if (n) {
|
|
8183
|
+
state.exposed[n] = true;
|
|
8184
|
+
} else {
|
|
8185
|
+
throw new Error("What?");
|
|
8143
8186
|
}
|
|
8187
|
+
return;
|
|
8144
8188
|
}
|
|
8189
|
+
if (callees.length == 1) {
|
|
8190
|
+
const callee = callees[0].node;
|
|
8191
|
+
if (
|
|
8192
|
+
callee.optimizable &&
|
|
8193
|
+
!callee.hasOverride &&
|
|
8194
|
+
node.arguments.every((n) => getNodeValue(n)[0] !== null)
|
|
8195
|
+
) {
|
|
8196
|
+
const ret = evaluateFunction(callee, node.arguments);
|
|
8197
|
+
if (ret) {
|
|
8198
|
+
replace(node, ret);
|
|
8199
|
+
return;
|
|
8200
|
+
}
|
|
8201
|
+
}
|
|
8202
|
+
}
|
|
8203
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.calledFunctions, name)) {
|
|
8204
|
+
state.calledFunctions[name] = [];
|
|
8205
|
+
}
|
|
8206
|
+
callees.forEach((c) => state.calledFunctions[name].push(c.node));
|
|
8207
|
+
break;
|
|
8145
8208
|
}
|
|
8146
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.calledFunctions, name)) {
|
|
8147
|
-
state.calledFunctions[name] = [];
|
|
8148
|
-
}
|
|
8149
|
-
callees.forEach((c) => state.calledFunctions[name].push(c.node));
|
|
8150
8209
|
}
|
|
8151
8210
|
};
|
|
8152
8211
|
files.forEach((f) => {
|
|
@@ -8248,7 +8307,7 @@ async function getVSCodeSettings(path) {
|
|
|
8248
8307
|
}
|
|
8249
8308
|
|
|
8250
8309
|
const defaultConfig = {
|
|
8251
|
-
outputPath: "optimized",
|
|
8310
|
+
outputPath: "bin/optimized",
|
|
8252
8311
|
workspace: "./",
|
|
8253
8312
|
};
|
|
8254
8313
|
|
|
@@ -8287,6 +8346,8 @@ async function buildOptimizedProject(product, options) {
|
|
|
8287
8346
|
const config = await getConfig(options);
|
|
8288
8347
|
if (product) {
|
|
8289
8348
|
config.products = [product];
|
|
8349
|
+
} else if (!(0,external_api_cjs_namespaceObject.hasProperty)(config, "releaseBuild")) {
|
|
8350
|
+
config.releaseBuild = true;
|
|
8290
8351
|
}
|
|
8291
8352
|
const { jungleFiles, program } = await generateOptimizedProject(config);
|
|
8292
8353
|
config.jungleFiles = jungleFiles;
|
|
@@ -8299,9 +8360,6 @@ async function buildOptimizedProject(product, options) {
|
|
|
8299
8360
|
} else {
|
|
8300
8361
|
bin = external_path_namespaceObject.join(bin, "exported");
|
|
8301
8362
|
name = `${program}.iq`;
|
|
8302
|
-
if (!(0,external_api_cjs_namespaceObject.hasProperty)(config, "releaseBuild")) {
|
|
8303
|
-
config.releaseBuild = true;
|
|
8304
|
-
}
|
|
8305
8363
|
}
|
|
8306
8364
|
config.program = external_path_namespaceObject.join(bin, name);
|
|
8307
8365
|
return build_project(product, config);
|
|
@@ -8314,11 +8372,21 @@ async function generateOptimizedProject(options) {
|
|
|
8314
8372
|
const { manifest, targets } = await get_jungle(config.jungleFiles, config);
|
|
8315
8373
|
const buildConfigs = {};
|
|
8316
8374
|
targets.forEach((p) => {
|
|
8317
|
-
|
|
8318
|
-
|
|
8375
|
+
const key = p.group.key + (config.releaseBuild ? "-release" : "-debug");
|
|
8376
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(buildConfigs, key)) {
|
|
8377
|
+
p.group.dir = key;
|
|
8378
|
+
buildConfigs[key] = null;
|
|
8379
|
+
if (p.group.optimizerConfig["excludeAnnotations"] == null) {
|
|
8380
|
+
p.group.optimizerConfig["excludeAnnotations"] = [];
|
|
8381
|
+
}
|
|
8382
|
+
// Note that we exclude (:debug) in release builds, and we
|
|
8383
|
+
// exclude (:release) in debug builds. This isn't backwards!
|
|
8384
|
+
p.group.optimizerConfig["excludeAnnotations"].push(
|
|
8385
|
+
config.releaseBuild ? "debug" : "release"
|
|
8386
|
+
);
|
|
8319
8387
|
}
|
|
8320
8388
|
if (!options.products || options.products.includes(p.product)) {
|
|
8321
|
-
buildConfigs[
|
|
8389
|
+
buildConfigs[key] = p.group.optimizerConfig;
|
|
8322
8390
|
}
|
|
8323
8391
|
});
|
|
8324
8392
|
|
|
@@ -8358,7 +8426,7 @@ async function generateOptimizedProject(options) {
|
|
|
8358
8426
|
const { product, qualifier, group } = jungle;
|
|
8359
8427
|
const prefix = `${product}.`;
|
|
8360
8428
|
process_field(prefix, qualifier, "sourcePath", (s) =>
|
|
8361
|
-
external_path_namespaceObject.join(group.
|
|
8429
|
+
external_path_namespaceObject.join(group.dir, external_path_namespaceObject.relative(workspace, s))
|
|
8362
8430
|
.replace(/(\/\*\*)\/\*/g, "$1")
|
|
8363
8431
|
);
|
|
8364
8432
|
process_field(prefix, qualifier, "resourcePath", relative_path);
|
|
@@ -8372,7 +8440,10 @@ async function generateOptimizedProject(options) {
|
|
|
8372
8440
|
}
|
|
8373
8441
|
});
|
|
8374
8442
|
|
|
8375
|
-
const jungleFiles = external_path_namespaceObject.join(
|
|
8443
|
+
const jungleFiles = external_path_namespaceObject.join(
|
|
8444
|
+
jungle_dir,
|
|
8445
|
+
`${config.releaseBuild ? "release" : "debug"}.jungle`
|
|
8446
|
+
);
|
|
8376
8447
|
promises.push(promises_namespaceObject.writeFile(jungleFiles, parts.join("\n")));
|
|
8377
8448
|
await Promise.all(promises);
|
|
8378
8449
|
return { jungleFiles, program: external_path_namespaceObject.basename(external_path_namespaceObject.dirname(manifest)) };
|
package/build/util.cjs
CHANGED
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.6",
|
|
5
5
|
"description": "Source to source optimizer for Garmin Monkey C code",
|
|
6
6
|
"main": "build/optimizer.cjs",
|
|
7
7
|
"exports": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "markw65",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@markw65/prettier-plugin-monkeyc": "^1.0.
|
|
26
|
+
"@markw65/prettier-plugin-monkeyc": "^1.0.12"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"eslint": "^8.12.0",
|