@markw65/monkeyc-optimizer 1.0.13 → 1.0.16

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.
@@ -1289,7 +1289,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
1289
1289
  const debug = __webpack_require__(1227)('extract-zip')
1290
1290
  // eslint-disable-next-line node/no-unsupported-features/node-builtins
1291
1291
  const { createWriteStream, promises: fs } = __webpack_require__(6231)
1292
- const getStream = __webpack_require__(7491)
1292
+ const getStream = __webpack_require__(31)
1293
1293
  const path = __webpack_require__(1423)
1294
1294
  const { promisify } = __webpack_require__(6464)
1295
1295
  const stream = __webpack_require__(8311)
@@ -1461,134 +1461,6 @@ module.exports = async function (zipPath, opts) {
1461
1461
  }
1462
1462
 
1463
1463
 
1464
- /***/ }),
1465
-
1466
- /***/ 2297:
1467
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1468
-
1469
- "use strict";
1470
-
1471
- const {PassThrough: PassThroughStream} = __webpack_require__(8311);
1472
-
1473
- module.exports = options => {
1474
- options = {...options};
1475
-
1476
- const {array} = options;
1477
- let {encoding} = options;
1478
- const isBuffer = encoding === 'buffer';
1479
- let objectMode = false;
1480
-
1481
- if (array) {
1482
- objectMode = !(encoding || isBuffer);
1483
- } else {
1484
- encoding = encoding || 'utf8';
1485
- }
1486
-
1487
- if (isBuffer) {
1488
- encoding = null;
1489
- }
1490
-
1491
- const stream = new PassThroughStream({objectMode});
1492
-
1493
- if (encoding) {
1494
- stream.setEncoding(encoding);
1495
- }
1496
-
1497
- let length = 0;
1498
- const chunks = [];
1499
-
1500
- stream.on('data', chunk => {
1501
- chunks.push(chunk);
1502
-
1503
- if (objectMode) {
1504
- length = chunks.length;
1505
- } else {
1506
- length += chunk.length;
1507
- }
1508
- });
1509
-
1510
- stream.getBufferedValue = () => {
1511
- if (array) {
1512
- return chunks;
1513
- }
1514
-
1515
- return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
1516
- };
1517
-
1518
- stream.getBufferedLength = () => length;
1519
-
1520
- return stream;
1521
- };
1522
-
1523
-
1524
- /***/ }),
1525
-
1526
- /***/ 7491:
1527
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1528
-
1529
- "use strict";
1530
-
1531
- const {constants: BufferConstants} = __webpack_require__(871);
1532
- const pump = __webpack_require__(4286);
1533
- const bufferStream = __webpack_require__(2297);
1534
-
1535
- class MaxBufferError extends Error {
1536
- constructor() {
1537
- super('maxBuffer exceeded');
1538
- this.name = 'MaxBufferError';
1539
- }
1540
- }
1541
-
1542
- async function getStream(inputStream, options) {
1543
- if (!inputStream) {
1544
- return Promise.reject(new Error('Expected a stream'));
1545
- }
1546
-
1547
- options = {
1548
- maxBuffer: Infinity,
1549
- ...options
1550
- };
1551
-
1552
- const {maxBuffer} = options;
1553
-
1554
- let stream;
1555
- await new Promise((resolve, reject) => {
1556
- const rejectPromise = error => {
1557
- // Don't retrieve an oversized buffer.
1558
- if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
1559
- error.bufferedData = stream.getBufferedValue();
1560
- }
1561
-
1562
- reject(error);
1563
- };
1564
-
1565
- stream = pump(inputStream, bufferStream(options), error => {
1566
- if (error) {
1567
- rejectPromise(error);
1568
- return;
1569
- }
1570
-
1571
- resolve();
1572
- });
1573
-
1574
- stream.on('data', () => {
1575
- if (stream.getBufferedLength() > maxBuffer) {
1576
- rejectPromise(new MaxBufferError());
1577
- }
1578
- });
1579
- });
1580
-
1581
- return stream.getBufferedValue();
1582
- }
1583
-
1584
- module.exports = getStream;
1585
- // TODO: Remove this for the next major release
1586
- module.exports["default"] = getStream;
1587
- module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
1588
- module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
1589
- module.exports.MaxBufferError = MaxBufferError;
1590
-
1591
-
1592
1464
  /***/ }),
1593
1465
 
1594
1466
  /***/ 8913:
@@ -1892,6 +1764,134 @@ function createFromFd(fd, options) {
1892
1764
  }
1893
1765
 
1894
1766
 
1767
+ /***/ }),
1768
+
1769
+ /***/ 5105:
1770
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1771
+
1772
+ "use strict";
1773
+
1774
+ const {PassThrough: PassThroughStream} = __webpack_require__(8311);
1775
+
1776
+ module.exports = options => {
1777
+ options = {...options};
1778
+
1779
+ const {array} = options;
1780
+ let {encoding} = options;
1781
+ const isBuffer = encoding === 'buffer';
1782
+ let objectMode = false;
1783
+
1784
+ if (array) {
1785
+ objectMode = !(encoding || isBuffer);
1786
+ } else {
1787
+ encoding = encoding || 'utf8';
1788
+ }
1789
+
1790
+ if (isBuffer) {
1791
+ encoding = null;
1792
+ }
1793
+
1794
+ const stream = new PassThroughStream({objectMode});
1795
+
1796
+ if (encoding) {
1797
+ stream.setEncoding(encoding);
1798
+ }
1799
+
1800
+ let length = 0;
1801
+ const chunks = [];
1802
+
1803
+ stream.on('data', chunk => {
1804
+ chunks.push(chunk);
1805
+
1806
+ if (objectMode) {
1807
+ length = chunks.length;
1808
+ } else {
1809
+ length += chunk.length;
1810
+ }
1811
+ });
1812
+
1813
+ stream.getBufferedValue = () => {
1814
+ if (array) {
1815
+ return chunks;
1816
+ }
1817
+
1818
+ return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
1819
+ };
1820
+
1821
+ stream.getBufferedLength = () => length;
1822
+
1823
+ return stream;
1824
+ };
1825
+
1826
+
1827
+ /***/ }),
1828
+
1829
+ /***/ 31:
1830
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
1831
+
1832
+ "use strict";
1833
+
1834
+ const {constants: BufferConstants} = __webpack_require__(871);
1835
+ const pump = __webpack_require__(4286);
1836
+ const bufferStream = __webpack_require__(5105);
1837
+
1838
+ class MaxBufferError extends Error {
1839
+ constructor() {
1840
+ super('maxBuffer exceeded');
1841
+ this.name = 'MaxBufferError';
1842
+ }
1843
+ }
1844
+
1845
+ async function getStream(inputStream, options) {
1846
+ if (!inputStream) {
1847
+ return Promise.reject(new Error('Expected a stream'));
1848
+ }
1849
+
1850
+ options = {
1851
+ maxBuffer: Infinity,
1852
+ ...options
1853
+ };
1854
+
1855
+ const {maxBuffer} = options;
1856
+
1857
+ let stream;
1858
+ await new Promise((resolve, reject) => {
1859
+ const rejectPromise = error => {
1860
+ // Don't retrieve an oversized buffer.
1861
+ if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
1862
+ error.bufferedData = stream.getBufferedValue();
1863
+ }
1864
+
1865
+ reject(error);
1866
+ };
1867
+
1868
+ stream = pump(inputStream, bufferStream(options), error => {
1869
+ if (error) {
1870
+ rejectPromise(error);
1871
+ return;
1872
+ }
1873
+
1874
+ resolve();
1875
+ });
1876
+
1877
+ stream.on('data', () => {
1878
+ if (stream.getBufferedLength() > maxBuffer) {
1879
+ rejectPromise(new MaxBufferError());
1880
+ }
1881
+ });
1882
+ });
1883
+
1884
+ return stream.getBufferedValue();
1885
+ }
1886
+
1887
+ module.exports = getStream;
1888
+ // TODO: Remove this for the next major release
1889
+ module.exports["default"] = getStream;
1890
+ module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
1891
+ module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
1892
+ module.exports.MaxBufferError = MaxBufferError;
1893
+
1894
+
1895
1895
  /***/ }),
1896
1896
 
1897
1897
  /***/ 7824:
@@ -10077,7 +10077,8 @@ async function default_jungle() {
10077
10077
  }
10078
10078
  rezAndLang(deviceId, `resources-${deviceId}`, deviceFamily);
10079
10079
  });
10080
- return process_assignments(assignments, {});
10080
+ const state = await process_assignments(assignments, {});
10081
+ return { state, devices };
10081
10082
  }
10082
10083
  function process_assignments(assignments, current) {
10083
10084
  return assignments.reduce((state, a) => {
@@ -10179,9 +10180,9 @@ async function process_jungles(sources) {
10179
10180
  sources = [sources];
10180
10181
  }
10181
10182
  const results = await Promise.all(sources.map(parse_one));
10182
- const state = await default_jungle();
10183
+ const { state, devices } = await default_jungle();
10183
10184
  results.forEach((r) => process_assignments(r, state));
10184
- return state;
10185
+ return { state, devices };
10185
10186
  }
10186
10187
  function resolve_node_list(state, list) {
10187
10188
  if (!Array.isArray(list)) {
@@ -10303,7 +10304,7 @@ function resolve_filename(literal, default_source = null) {
10303
10304
  const root = external_path_.dirname(literal.source || default_source);
10304
10305
  return external_path_.resolve(root, literal.value);
10305
10306
  }
10306
- async function resolve_literals(qualifier, default_source) {
10307
+ async function resolve_literals(qualifier, default_source, deviceInfo) {
10307
10308
  const resolve_file_list = async (literals) => literals &&
10308
10309
  (await Promise.all(literals.map(async (v) => {
10309
10310
  if (!isJNode(v)) {
@@ -10346,7 +10347,13 @@ async function resolve_literals(qualifier, default_source) {
10346
10347
  await resolve_one_file_list(qualifier, "barrelPath");
10347
10348
  const lang = qualifier["lang"];
10348
10349
  if (lang) {
10349
- await Promise.all(Object.keys(lang).map((key) => resolve_one_file_list(lang, key)));
10350
+ await Promise.all(Object.keys(lang).map((key) => {
10351
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(deviceInfo.languages, key)) {
10352
+ delete lang[key];
10353
+ return null;
10354
+ }
10355
+ return resolve_one_file_list(lang, key);
10356
+ }));
10350
10357
  if (Object.keys(lang).length === 0)
10351
10358
  delete qualifier["lang"];
10352
10359
  }
@@ -10704,7 +10711,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10704
10711
  jungles.push(barrels_jungle);
10705
10712
  }
10706
10713
  }
10707
- const state = await process_jungles(jungles);
10714
+ const { state, devices } = await process_jungles(jungles);
10708
10715
  // apparently square_watch is an alias for rectangle_watch
10709
10716
  state["square_watch"] = state["rectangle_watch"];
10710
10717
  const manifest_node = resolve_node(state, resolve_node_by_path(state, ["project", "manifest"]));
@@ -10719,15 +10726,21 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10719
10726
  const barrels = manifestBarrels(xml);
10720
10727
  const annotations = manifestAnnotations(xml);
10721
10728
  const products = manifestProducts(xml);
10722
- if (products.length === 0)
10723
- products.push(...defaultProducts);
10729
+ if (products.length === 0) {
10730
+ if (defaultProducts) {
10731
+ products.push(...defaultProducts);
10732
+ }
10733
+ else if (xml["iq:manifest"]["iq:barrel"]) {
10734
+ products.push(...Object.keys(devices).sort());
10735
+ }
10736
+ }
10724
10737
  let promise = Promise.resolve();
10725
10738
  const add_one = (product, shape = undefined) => {
10726
10739
  const rawQualifier = resolve_node(state, state[product]);
10727
10740
  if (!rawQualifier || Array.isArray(rawQualifier))
10728
10741
  return;
10729
10742
  promise = promise
10730
- .then(() => resolve_literals(rawQualifier, manifest))
10743
+ .then(() => resolve_literals(rawQualifier, manifest, devices[product]))
10731
10744
  .then((qualifier) => {
10732
10745
  targets.push({ product, qualifier, shape });
10733
10746
  return resolve_barrels(product, qualifier, barrels, products, options);
@@ -10753,7 +10766,7 @@ async function get_jungle_and_barrels(jungleFiles, defaultProducts, options) {
10753
10766
  }
10754
10767
  async function get_jungle(jungles, options) {
10755
10768
  options = options || {};
10756
- const result = await get_jungle_and_barrels(jungles, [], options);
10769
+ const result = await get_jungle_and_barrels(jungles, null, options);
10757
10770
  identify_optimizer_groups(result.targets, options);
10758
10771
  return result;
10759
10772
  }
@@ -10778,11 +10791,282 @@ function simulateProgram(prg, device, test) {
10778
10791
  return (0,external_sdk_util_cjs_namespaceObject.getSdkPath)().then((sdk) => (0,external_util_cjs_namespaceObject.spawnByLine)(external_path_.resolve(sdk, "bin", "monkeydo"), args, (line) => console.log(line)).then(() => { }));
10779
10792
  }
10780
10793
 
10794
+ ;// CONCATENATED MODULE: ./src/inliner.ts
10795
+
10796
+ function canInline(state, func, args) {
10797
+ // determine whether decl might be changed by a function call
10798
+ // during the evaluation of FunctionStateNode.
10799
+ const getSafety = (decl) => {
10800
+ // enums are constant, they cant change
10801
+ if (decl.type === "EnumStringMember")
10802
+ return true;
10803
+ if (decl.type === "VariableDeclarator") {
10804
+ // constants also can't change
10805
+ if (decl.node.kind === "const")
10806
+ return true;
10807
+ // if decl is a local, it also can't be changed
10808
+ // by a call to another function.
10809
+ for (let i = 0;; i++) {
10810
+ if (!state.stack[i] || decl.stack[i] !== state.stack[i])
10811
+ return false;
10812
+ if (state.stack[i].type === "FunctionDeclaration")
10813
+ return true;
10814
+ }
10815
+ }
10816
+ return null;
10817
+ };
10818
+ const safeArgs = [];
10819
+ let allSafe = true;
10820
+ if (!args.every((arg) => {
10821
+ switch (arg.type) {
10822
+ case "Literal":
10823
+ safeArgs.push(true);
10824
+ return true;
10825
+ case "Identifier":
10826
+ case "MemberExpression": {
10827
+ const [, results] = state.lookup(arg);
10828
+ if (!results || results.length !== 1)
10829
+ return false;
10830
+ const safety = getSafety(results[0]);
10831
+ if (safety === null)
10832
+ return false;
10833
+ if (!safety)
10834
+ allSafe = false;
10835
+ safeArgs.push(safety);
10836
+ return true;
10837
+ }
10838
+ }
10839
+ return false;
10840
+ })) {
10841
+ return false;
10842
+ }
10843
+ if (allSafe)
10844
+ return true;
10845
+ let callSeen = false;
10846
+ let ok = true;
10847
+ const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
10848
+ const getLoc = (node) => (Array.isArray(node) ? node[0].start : node.start) || 0;
10849
+ // look for uses of "unsafe" args that occur after a call.
10850
+ // use post to do the checking, because arguments are evaluated
10851
+ // prior to the call, so eg "return f(x.y);" is fine, but
10852
+ // "return f()+x.y" is not.
10853
+ //
10854
+ // We also have to use a "pre" to ensure that child nodes are
10855
+ // visited in source order (otherwise we could visit x.y before f()
10856
+ // in the above example)
10857
+ (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, (node) => {
10858
+ return Object.entries(node)
10859
+ .filter((kv) => Array.isArray(kv[1])
10860
+ ? kv[1].length !== 0 && (0,external_api_cjs_namespaceObject.hasProperty)(kv[1][0], "type")
10861
+ : (0,external_api_cjs_namespaceObject.hasProperty)(kv[1], "type"))
10862
+ .sort(([, a], [, b]) => getLoc(a) - getLoc(b))
10863
+ .map(([key]) => key);
10864
+ }, (node) => {
10865
+ switch (node.type) {
10866
+ case "CallExpression":
10867
+ case "NewExpression":
10868
+ callSeen = true;
10869
+ break;
10870
+ case "Identifier":
10871
+ if (callSeen &&
10872
+ (0,external_api_cjs_namespaceObject.hasProperty)(params, node.name) &&
10873
+ !safeArgs[params[node.name]]) {
10874
+ ok = false;
10875
+ }
10876
+ }
10877
+ });
10878
+ return ok;
10879
+ }
10880
+ function inliningLooksUseful(func, node) {
10881
+ while (true) {
10882
+ if (node.type === "BinaryExpression" && node.operator === "as") {
10883
+ node = node.left;
10884
+ }
10885
+ else if (node.type === "UnaryExpression" && node.operator === " as") {
10886
+ node = node.argument;
10887
+ }
10888
+ else {
10889
+ break;
10890
+ }
10891
+ }
10892
+ if (node.type === "Literal")
10893
+ return true;
10894
+ if (node.type === "Identifier") {
10895
+ if (func.params.length === 1 &&
10896
+ (0,external_api_cjs_namespaceObject.variableDeclarationName)(func.params[0]) === node.name) {
10897
+ return 1;
10898
+ }
10899
+ return true;
10900
+ }
10901
+ return false;
10902
+ }
10903
+ function shouldInline(state, func, args) {
10904
+ if (!func.node.body ||
10905
+ func.node.body.body.length !== 1 ||
10906
+ func.node.body.body[0].type !== "ReturnStatement" ||
10907
+ !func.node.body.body[0].argument ||
10908
+ func.node.params.length !== args.length) {
10909
+ return false;
10910
+ }
10911
+ const autoInline = inliningLooksUseful(func.node, func.node.body.body[0].argument);
10912
+ const excludeAnnotations = (func.node.loc?.source &&
10913
+ state.fnMap[func.node.loc?.source].excludeAnnotations) ||
10914
+ {};
10915
+ return ((autoInline ||
10916
+ (func.node.attrs &&
10917
+ func.node.attrs.attrs &&
10918
+ func.node.attrs.attrs.some((attr) => attr.type === "UnaryExpression" &&
10919
+ (attr.argument.name === "inline" ||
10920
+ (attr.argument.name.startsWith("inline_") &&
10921
+ (0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7))))))) &&
10922
+ (autoInline === 1 || canInline(state, func, args)));
10923
+ }
10924
+ function inlineFunction(state, func, call) {
10925
+ const retArg = JSON.parse(JSON.stringify(func.node.body.body[0].argument));
10926
+ const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
10927
+ try {
10928
+ const result = (0,external_api_cjs_namespaceObject.traverseAst)(retArg, (node) => {
10929
+ switch (node.type) {
10930
+ case "MemberExpression":
10931
+ if (!node.computed) {
10932
+ return ["object"];
10933
+ }
10934
+ break;
10935
+ case "BinaryExpression":
10936
+ if (node.operator === "as") {
10937
+ return ["left"];
10938
+ }
10939
+ break;
10940
+ case "UnaryExpression":
10941
+ if (node.operator === " as") {
10942
+ return [];
10943
+ }
10944
+ }
10945
+ return null;
10946
+ }, (node) => {
10947
+ switch (node.type) {
10948
+ case "Identifier": {
10949
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name)) {
10950
+ return call.arguments[params[node.name]];
10951
+ }
10952
+ const rep = fixNodeScope(state, node, func.stack);
10953
+ if (!rep) {
10954
+ throw new Error(`Inliner: Couldn't fix the scope of '${node.name}`);
10955
+ }
10956
+ return rep;
10957
+ }
10958
+ }
10959
+ return null;
10960
+ }) || retArg;
10961
+ result.loc = call.loc;
10962
+ result.start = call.start;
10963
+ result.end = call.end;
10964
+ return result;
10965
+ }
10966
+ catch (ex) {
10967
+ if (ex instanceof Error) {
10968
+ if (ex.message.startsWith("Inliner: ")) {
10969
+ return null;
10970
+ }
10971
+ }
10972
+ throw ex;
10973
+ }
10974
+ }
10975
+ function applyTypeIfNeeded(node) {
10976
+ if ("enumType" in node && node.enumType) {
10977
+ node = {
10978
+ type: "BinaryExpression",
10979
+ operator: "as",
10980
+ left: node,
10981
+ right: { type: "TypeSpecList", ts: [node.enumType] },
10982
+ };
10983
+ }
10984
+ return node;
10985
+ }
10986
+ function fixNodeScope(state, lookupNode, nodeStack) {
10987
+ const [, original] = state.lookup(lookupNode, null, nodeStack);
10988
+ if (!original) {
10989
+ return null;
10990
+ }
10991
+ const [, current] = state.lookup(lookupNode);
10992
+ // For now, leave it alone if it already maps to the same thing.
10993
+ // With a bit more work, we could find the guaranteed shortest
10994
+ // reference, and then use this to optimize *all* symbols, not
10995
+ // just fix inlined ones.
10996
+ if (current &&
10997
+ current.length === original.length &&
10998
+ current.every((item, index) => item == original[index])) {
10999
+ return lookupNode;
11000
+ }
11001
+ const node = lookupNode.type === "Identifier"
11002
+ ? lookupNode
11003
+ : lookupNode.property;
11004
+ if (original.length === 1 && original[0].type === "EnumStringMember") {
11005
+ return applyTypeIfNeeded(original[0].init);
11006
+ }
11007
+ const prefixes = original.map((sn) => {
11008
+ if ((0,external_api_cjs_namespaceObject.isStateNode)(sn) && sn.fullName) {
11009
+ return sn.fullName;
11010
+ }
11011
+ return "";
11012
+ });
11013
+ if (prefixes.length &&
11014
+ prefixes[0].startsWith("$.") &&
11015
+ prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
11016
+ const prefix = prefixes[0].split(".").slice(0, -1).reverse();
11017
+ let found = false;
11018
+ return prefix.reduce((current, name) => {
11019
+ if (found)
11020
+ return current;
11021
+ const [, results] = state.lookup(current);
11022
+ if (results &&
11023
+ results.length === original.length &&
11024
+ results.every((result, i) => result === original[i])) {
11025
+ found = true;
11026
+ return current;
11027
+ }
11028
+ const object = typeof name === "string"
11029
+ ? {
11030
+ type: "Identifier",
11031
+ name,
11032
+ start: node.start,
11033
+ end: node.end,
11034
+ loc: node.loc,
11035
+ }
11036
+ : name;
11037
+ let root = null;
11038
+ let property = current;
11039
+ while (property.type !== "Identifier") {
11040
+ root = property;
11041
+ property = property.object;
11042
+ }
11043
+ const mb = {
11044
+ type: "MemberExpression",
11045
+ object,
11046
+ property,
11047
+ computed: false,
11048
+ start: node.start,
11049
+ end: node.end,
11050
+ loc: node.loc,
11051
+ };
11052
+ if (root) {
11053
+ root.object = mb;
11054
+ }
11055
+ else {
11056
+ current = mb;
11057
+ }
11058
+ return current;
11059
+ }, node);
11060
+ }
11061
+ return null;
11062
+ }
11063
+
10781
11064
  ;// CONCATENATED MODULE: ./src/mc-rewrite.ts
10782
11065
 
10783
11066
 
10784
11067
 
10785
11068
 
11069
+
10786
11070
  function processImports(allImports, lookup) {
10787
11071
  allImports.forEach(({ node, stack }) => {
10788
11072
  const [name, module] = lookup(node.id, ("as" in node && node.as && node.as.name) || null, stack);
@@ -10791,11 +11075,21 @@ function processImports(allImports, lookup) {
10791
11075
  if (!parent.decls)
10792
11076
  parent.decls = {};
10793
11077
  const decls = parent.decls;
10794
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(parent.decls, name))
10795
- parent.decls[name] = [];
11078
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(decls, name))
11079
+ decls[name] = [];
10796
11080
  module.forEach((m) => {
10797
11081
  if ((0,external_api_cjs_namespaceObject.isStateNode)(m) && m.type == "ModuleDeclaration") {
10798
11082
  (0,external_util_cjs_namespaceObject.pushUnique)(decls[name], m);
11083
+ if (node.type == "ImportModule" && m.type_decls) {
11084
+ if (!parent.type_decls)
11085
+ parent.type_decls = {};
11086
+ const tdecls = parent.type_decls;
11087
+ Object.entries(m.type_decls).forEach(([name, decls]) => {
11088
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
11089
+ tdecls[name] = [];
11090
+ decls.forEach((decl) => (0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], decl));
11091
+ });
11092
+ }
10799
11093
  }
10800
11094
  });
10801
11095
  }
@@ -10804,11 +11098,39 @@ function processImports(allImports, lookup) {
10804
11098
  function collectClassInfo(state) {
10805
11099
  state.allClasses.forEach((elm) => {
10806
11100
  if (elm.node.superClass) {
10807
- const [, classes] = state.lookup(elm.node.superClass, null, elm.stack);
11101
+ const [name, classes] = state.lookup(elm.node.superClass, null, elm.stack);
10808
11102
  const superClass = classes &&
10809
11103
  classes.filter((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && c.type === "ClassDeclaration");
10810
11104
  // set it "true" if there is a superClass, but we can't find it.
10811
11105
  elm.superClass = superClass && superClass.length ? superClass : true;
11106
+ if (name && elm.superClass !== true) {
11107
+ /*
11108
+ * The runtime behavior of monkeyc is strange. Lookups
11109
+ * of the name of the superclass, either bare, or via self.<name>
11110
+ * always find the superclass, even if there's a member variable
11111
+ * or method of the same name. So its ok to just overwrite
11112
+ * elm.decls[name] here.
11113
+ *
11114
+ * ie
11115
+ *
11116
+ * class A { function foo() as Number { return 1; } }
11117
+ * class B { function foo() as String { return "B"; } }
11118
+ * class C extends A {
11119
+ * var A as B = new B();
11120
+ * function initialize() {
11121
+ * A.initialize(); // class A's initialize
11122
+ * A.foo(); // returns 1
11123
+ * self.A.foo(); // still returns 1
11124
+ * }
11125
+ * }
11126
+ *
11127
+ * The typechecker seems to get confused in some circumstances
11128
+ * though (ie it doesn't always use the same rules)
11129
+ */
11130
+ if (!elm.decls)
11131
+ elm.decls = {};
11132
+ elm.decls[name] = elm.superClass;
11133
+ }
10812
11134
  }
10813
11135
  });
10814
11136
  const markOverrides = (cls, scls) => {
@@ -10863,32 +11185,36 @@ function getFileASTs(fnMap) {
10863
11185
  }, true));
10864
11186
  }
10865
11187
  async function analyze(fnMap) {
10866
- let excludeAnnotations;
10867
11188
  let hasTests = false;
10868
11189
  const allImports = [];
10869
11190
  const preState = {
11191
+ fnMap,
10870
11192
  allFunctions: [],
10871
11193
  allClasses: [],
10872
11194
  shouldExclude(node) {
10873
11195
  if ("attrs" in node &&
10874
11196
  node.attrs &&
10875
11197
  "attrs" in node.attrs &&
10876
- node.attrs.attrs) {
10877
- return node.attrs.attrs.reduce((drop, attr) => {
10878
- if (attr.type != "UnaryExpression")
10879
- return drop;
10880
- if (attr.argument.type != "Identifier")
11198
+ node.attrs.attrs &&
11199
+ node.loc?.source) {
11200
+ const excludeAnnotations = fnMap[node.loc.source].excludeAnnotations;
11201
+ if (excludeAnnotations) {
11202
+ return node.attrs.attrs.reduce((drop, attr) => {
11203
+ if (attr.type != "UnaryExpression")
11204
+ return drop;
11205
+ if (attr.argument.type != "Identifier")
11206
+ return drop;
11207
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name)) {
11208
+ return true;
11209
+ }
11210
+ if (attr.argument.name == "test") {
11211
+ hasTests = true;
11212
+ }
10881
11213
  return drop;
10882
- if ((0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name)) {
10883
- return true;
10884
- }
10885
- if (attr.argument.name == "test") {
10886
- hasTests = true;
10887
- }
10888
- return drop;
10889
- }, false);
11214
+ }, false);
11215
+ }
10890
11216
  }
10891
- return null;
11217
+ return false;
10892
11218
  },
10893
11219
  post(node, state) {
10894
11220
  switch (node.type) {
@@ -10935,7 +11261,6 @@ async function analyze(fnMap) {
10935
11261
  if (!ast) {
10936
11262
  throw parserError || new Error(`Failed to parse ${name}`);
10937
11263
  }
10938
- excludeAnnotations = value.excludeAnnotations;
10939
11264
  hasTests = false;
10940
11265
  (0,external_api_cjs_namespaceObject.collectNamespaces)(ast, state);
10941
11266
  value.hasTests = hasTests;
@@ -10959,8 +11284,8 @@ function getLiteralFromDecls(decls) {
10959
11284
  let result = null;
10960
11285
  if (decls.every((d) => {
10961
11286
  if (d.type === "EnumStringMember" ||
10962
- (d.type === "VariableDeclarator" && d.kind === "const")) {
10963
- const init = getLiteralNode(d.init);
11287
+ (d.type === "VariableDeclarator" && d.node.kind === "const")) {
11288
+ const init = getLiteralNode(d.type === "EnumStringMember" ? d.init : d.node.init);
10964
11289
  if (!init)
10965
11290
  return false;
10966
11291
  if (!result) {
@@ -11242,11 +11567,12 @@ async function optimizeMonkeyC(fnMap) {
11242
11567
  * anywhere in its superClass chain.
11243
11568
  */
11244
11569
  const checkInherited = (elm, name) => elm.superClass === true ||
11245
- elm.superClass.some((sc) => ((0,external_api_cjs_namespaceObject.hasProperty)(sc.decls, name) &&
11246
- sc.decls[name].some((f) => (0,external_api_cjs_namespaceObject.isStateNode)(f) &&
11247
- f.type == "FunctionDeclaration" &&
11248
- maybeCalled(f.node))) ||
11249
- (sc.superClass && checkInherited(sc, name)));
11570
+ (elm.superClass != null &&
11571
+ elm.superClass.some((sc) => ((0,external_api_cjs_namespaceObject.hasProperty)(sc.decls, name) &&
11572
+ sc.decls[name].some((f) => (0,external_api_cjs_namespaceObject.isStateNode)(f) &&
11573
+ f.type == "FunctionDeclaration" &&
11574
+ maybeCalled(f.node))) ||
11575
+ (sc.superClass && checkInherited(sc, name))));
11250
11576
  state.pre = (node) => {
11251
11577
  switch (node.type) {
11252
11578
  case "ConditionalExpression":
@@ -11489,11 +11815,9 @@ async function optimizeMonkeyC(fnMap) {
11489
11815
  }
11490
11816
  return null;
11491
11817
  }
11492
- if (callees.length == 1) {
11493
- const callee = (0,external_api_cjs_namespaceObject.isStateNode)(callees[0]) && callees[0].node;
11494
- if (callee &&
11495
- callee.type == "FunctionDeclaration" &&
11496
- callee.optimizable &&
11818
+ if (callees.length == 1 && callees[0].type === "FunctionDeclaration") {
11819
+ const callee = callees[0].node;
11820
+ if (callee.optimizable &&
11497
11821
  !callee.hasOverride &&
11498
11822
  node.arguments.every((n) => getNodeValue(n)[0] !== null)) {
11499
11823
  const ret = evaluateFunction(callee, node.arguments);
@@ -11502,6 +11826,13 @@ async function optimizeMonkeyC(fnMap) {
11502
11826
  return null;
11503
11827
  }
11504
11828
  }
11829
+ if (shouldInline(state, callees[0], node.arguments)) {
11830
+ const ret = inlineFunction(state, callees[0], node);
11831
+ if (ret) {
11832
+ replace(node, ret);
11833
+ return null;
11834
+ }
11835
+ }
11505
11836
  }
11506
11837
  if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.calledFunctions, name)) {
11507
11838
  state.calledFunctions[name] = [];
@@ -11515,71 +11846,79 @@ async function optimizeMonkeyC(fnMap) {
11515
11846
  Object.values(fnMap).forEach((f) => {
11516
11847
  (0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
11517
11848
  });
11518
- Object.values(fnMap).forEach((f) => {
11519
- (0,external_api_cjs_namespaceObject.traverseAst)(f.ast, undefined, (node) => {
11520
- switch (node.type) {
11521
- case "EnumStringBody":
11522
- if (node.members.every((m) => {
11523
- const name = "name" in m ? m.name : m.id.name;
11524
- return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
11525
- !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11526
- })) {
11527
- node.enumType = [
11528
- ...new Set(node.members.map((m) => {
11529
- if (!("init" in m))
11530
- return "Number";
11531
- const [node, type] = getNodeValue(m.init);
11532
- if (!node) {
11533
- throw new Error("Failed to get type for eliminated enum");
11534
- }
11535
- return type;
11536
- })),
11537
- ].join(" or ");
11538
- node.members.splice(0);
11539
- }
11540
- break;
11541
- case "EnumDeclaration":
11542
- if (!node.body.members.length) {
11543
- if (!node.id)
11544
- return false;
11545
- if (!node.body["enumType"]) {
11546
- throw new Error("Missing enumType on optimized enum");
11547
- }
11548
- replace(node, {
11549
- type: "TypedefDeclaration",
11550
- id: node.id,
11551
- ts: {
11552
- type: "UnaryExpression",
11553
- argument: { type: "TypeSpecList", ts: [node.body.enumType] },
11554
- prefix: true,
11555
- operator: " as",
11556
- },
11557
- });
11558
- }
11559
- break;
11560
- case "VariableDeclaration": {
11561
- node.declarations = node.declarations.filter((d) => {
11562
- const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
11563
- return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) ||
11564
- (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11565
- });
11566
- if (!node.declarations.length) {
11567
- return false;
11568
- }
11569
- break;
11849
+ delete state.pre;
11850
+ delete state.post;
11851
+ const cleanup = (node) => {
11852
+ switch (node.type) {
11853
+ case "EnumStringBody":
11854
+ if (node.members.every((m) => {
11855
+ const name = "name" in m ? m.name : m.id.name;
11856
+ return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
11857
+ !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11858
+ })) {
11859
+ node.enumType = [
11860
+ ...new Set(node.members.map((m) => {
11861
+ if (!("init" in m))
11862
+ return "Number";
11863
+ const [node, type] = getNodeValue(m.init);
11864
+ if (!node) {
11865
+ throw new Error("Failed to get type for eliminated enum");
11866
+ }
11867
+ return type;
11868
+ })),
11869
+ ].join(" or ");
11870
+ node.members.splice(0);
11570
11871
  }
11571
- case "ClassElement":
11572
- if (!node.item) {
11573
- return false;
11574
- }
11575
- break;
11576
- case "FunctionDeclaration":
11577
- if (!maybeCalled(node)) {
11872
+ break;
11873
+ case "EnumDeclaration":
11874
+ if (!node.body.members.length) {
11875
+ if (!node.id)
11578
11876
  return false;
11877
+ if (!node.body["enumType"]) {
11878
+ throw new Error("Missing enumType on optimized enum");
11579
11879
  }
11580
- break;
11880
+ replace(node, {
11881
+ type: "TypedefDeclaration",
11882
+ id: node.id,
11883
+ ts: {
11884
+ type: "UnaryExpression",
11885
+ argument: { type: "TypeSpecList", ts: [node.body.enumType] },
11886
+ prefix: true,
11887
+ operator: " as",
11888
+ },
11889
+ });
11890
+ }
11891
+ break;
11892
+ case "VariableDeclaration": {
11893
+ node.declarations = node.declarations.filter((d) => {
11894
+ const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
11895
+ return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) || (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
11896
+ });
11897
+ if (!node.declarations.length) {
11898
+ return false;
11899
+ }
11900
+ break;
11581
11901
  }
11582
- return null;
11902
+ case "ClassElement":
11903
+ if (!node.item) {
11904
+ return false;
11905
+ }
11906
+ break;
11907
+ case "FunctionDeclaration":
11908
+ if (!maybeCalled(node)) {
11909
+ return false;
11910
+ }
11911
+ break;
11912
+ }
11913
+ return null;
11914
+ };
11915
+ Object.values(fnMap).forEach((f) => {
11916
+ (0,external_api_cjs_namespaceObject.traverseAst)(f.ast, undefined, (node) => {
11917
+ const ret = cleanup(node);
11918
+ if (ret === false) {
11919
+ state.removeNodeComments(node, f.ast);
11920
+ }
11921
+ return ret;
11583
11922
  });
11584
11923
  });
11585
11924
  }
@@ -11996,6 +12335,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
11996
12335
  // might have altered it), and that the options we care about haven't
11997
12336
  // changed
11998
12337
  if (hasTests != null &&
12338
+ !config.checkBuildPragmas &&
11999
12339
  configOptionsToCheck.every((option) => prevOptions[option] === config[option]) &&
12000
12340
  actualOptimizedFiles.length == Object.values(fnMap).length &&
12001
12341
  Object.values(fnMap)
@@ -12006,7 +12346,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12006
12346
  // the oldest optimized file, we don't need to regenerate
12007
12347
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
12008
12348
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
12009
- if (source_time < opt_time && 1653671578547 < opt_time) {
12349
+ if (source_time < opt_time && 1654222986123 < opt_time) {
12010
12350
  return hasTests;
12011
12351
  }
12012
12352
  }
@@ -12018,6 +12358,14 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12018
12358
  const dir = external_path_.dirname(name);
12019
12359
  await promises_namespaceObject.mkdir(dir, { recursive: true });
12020
12360
  const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
12361
+ if (config.checkBuildPragmas) {
12362
+ const matches = opt_source.matchAll(/^.*\/\*\s*@match\s+(\S+)\s+\*\/(.*)$/gm);
12363
+ for (const [line, needle, haystack] of matches) {
12364
+ if (!haystack.includes(needle)) {
12365
+ throw new Error(`Checking build pragmas in ${name} failed at \n\n${line}\n\n - Didn't find '${needle}'`);
12366
+ }
12367
+ }
12368
+ }
12021
12369
  await promises_namespaceObject.writeFile(name, opt_source);
12022
12370
  return info.hasTests;
12023
12371
  })).then((results) => {
@@ -12075,11 +12423,12 @@ async function generateApiMirTests(options) {
12075
12423
  return;
12076
12424
  const d = decl[0];
12077
12425
  if (d.type === "EnumStringMember" ||
12078
- (d.type === "VariableDeclarator" && d.kind === "const")) {
12079
- if (!d.init) {
12426
+ (d.type === "VariableDeclarator" && d.node.kind === "const")) {
12427
+ const init = (0,external_api_cjs_namespaceObject.isStateNode)(d) ? d.node.init : d.init;
12428
+ if (!init) {
12080
12429
  throw new Error(`Missing init for ${node.fullName}.${key}`);
12081
12430
  }
12082
- tests.push([`${node.fullName}.${key}`, (0,external_api_cjs_namespaceObject.formatAst)(d.init)]);
12431
+ tests.push([`${node.fullName}.${key}`, (0,external_api_cjs_namespaceObject.formatAst)(init)]);
12083
12432
  }
12084
12433
  else if ((0,external_api_cjs_namespaceObject.isStateNode)(d)) {
12085
12434
  findConstants(d);