@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 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
- traverseAst(
221
- ast,
222
- (node) => {
223
- try {
224
- switch (node.type) {
225
- case "Program":
226
- if (state.stack.length != 1) {
227
- throw new Error("Unexpected stack length for Program node");
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
- case "ClassDeclaration":
244
- case "FunctionDeclaration":
245
- case "ModuleDeclaration":
246
- if (node.id || node.type == "BlockStatement") {
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
- const elm = {
249
- type: node.type,
250
- name: node.id && node.id.name,
251
- node,
252
- };
253
- state.stack.push(elm);
254
- elm.fullName = state.stack
255
- .map((e) => e.name)
256
- .filter((e) => e != null)
257
- .join(".");
258
- if (elm.name) {
259
- if (!parent.decls) parent.decls = {};
260
- if (hasProperty(parent.decls, elm.name)) {
261
- const what =
262
- node.type == "ModuleDeclaration" ? "type" : "node";
263
- const e = parent.decls[elm.name].find(
264
- (d) => d[what] == elm[what]
265
- );
266
- if (e != null) {
267
- e.node = node;
268
- state.stack.splice(-1, 1, e);
269
- break;
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
- } else {
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
- break;
278
- // an EnumDeclaration doesn't create a scope, but
279
- // it does create a type (if it has a name)
280
- case "EnumDeclaration": {
281
- if (!node.id) break;
282
- const [parent] = state.stack.slice(-1);
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
- if (node.kind == "const") {
310
- (0,external_util_cjs_namespaceObject.pushUnique)(parent.decls[decl.id.name], decl.init);
311
- if (!hasProperty(state.index, decl.id.name)) {
312
- state.index[decl.id.name] = [];
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
- (0,external_util_cjs_namespaceObject.pushUnique)(state.index[decl.id.name], parent);
315
- } else if (decl.id.ts) {
316
- (0,external_util_cjs_namespaceObject.pushUnique)(
317
- parent.decls[decl.id.name],
318
- formatAst(decl.id.ts.argument)
319
- );
320
- }
321
- });
322
- break;
323
- }
324
- case "EnumStringBody": {
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
- } else {
337
- name = m.name;
338
- prev += 1;
339
- if (!state.constants) {
340
- state.constants = {};
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
- const key = m.enumType ? `${m.enumType}:${prev}` : prev;
343
- init = state.constants[key];
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
- if (!hasProperty(values, name)) {
354
- values[name] = [];
355
- }
356
- (0,external_util_cjs_namespaceObject.pushUnique)(values[name], init);
357
- if (!hasProperty(state.index, name)) {
358
- state.index[name] = [];
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
- if (state.pre) return state.pre(node);
366
- } catch (e) {
367
- handleException(state, node, e);
368
- }
369
- },
370
- (node) => {
371
- try {
372
- let ret;
373
- if (state.post) ret = state.post(node);
374
- if (state.stack.slice(-1).pop().node === node) {
375
- state.stack.pop();
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
  }
@@ -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
- await Promise.all(
7483
- Object.keys(lang).map((key) => resolve_one_file_list(lang, key))
7484
- );
7485
- if (Object.keys(lang).length === 0) delete qualifier["lang"];
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.id.name, stack);
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
- pre(node) {
7706
- if (shouldExclude(node)) {
7707
- // don't visit any children, but do call post
7708
- return [];
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.pre;
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
- if (node.type == "CallExpression") {
8119
- const [name, callees] = state.lookup(node.callee);
8120
- if (!callees || !callees.length) {
8121
- const n =
8122
- name ||
8123
- node.callee.name ||
8124
- (node.callee.property && node.callee.property.name);
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
- return;
8131
- }
8132
- if (callees.length == 1) {
8133
- const callee = callees[0].node;
8134
- if (
8135
- callee.optimizable &&
8136
- !callee.hasOverride &&
8137
- node.arguments.every((n) => getNodeValue(n)[0] !== null)
8138
- ) {
8139
- const ret = evaluateFunction(callee, node.arguments);
8140
- if (ret) {
8141
- replace(node, ret);
8142
- return;
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
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(buildConfigs, p.group.key)) {
8318
- buildConfigs[p.group.key] = null;
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[p.group.key] = p.group.optimizerConfig;
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.key.toString(), external_path_namespaceObject.relative(workspace, s))
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(jungle_dir, "monkey.jungle");
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
@@ -1,3 +1,4 @@
1
+ 0 && (module.exports = {isWin,appSupport,connectiq,getSdkPath,globa,last_modified,first_modified,pushUnique,spawnByLine,readByLine,promiseAll,copyRecursiveAsNeeded});
1
2
  /******/ (() => { // webpackBootstrap
2
3
  /******/ var __webpack_modules__ = ({
3
4
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@markw65/monkeyc-optimizer",
3
3
  "type": "module",
4
- "version": "1.0.2",
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.10"
26
+ "@markw65/prettier-plugin-monkeyc": "^1.0.12"
27
27
  },
28
28
  "devDependencies": {
29
29
  "eslint": "^8.12.0",