@markw65/monkeyc-optimizer 1.0.30 → 1.0.31

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.
@@ -11163,18 +11163,147 @@ function withLoc(node, start, end) {
11163
11163
  }
11164
11164
  return node;
11165
11165
  }
11166
- function withLocDeep(node, start, end) {
11167
- node = withLoc({ ...node }, start, end);
11166
+ function withLocDeep(node, start, end, inplace) {
11167
+ node = withLoc(inplace ? node : { ...node }, start, end);
11168
11168
  for (const key of mctreeTypeInfo[node.type].keys) {
11169
11169
  const value = node[key];
11170
11170
  if (!value)
11171
11171
  continue;
11172
- const fix = (v) => isMCTreeNode(v) ? withLocDeep(v, start, end) : v;
11172
+ const fix = (v) => isMCTreeNode(v) ? withLocDeep(v, start, end, inplace) : v;
11173
11173
  const repl = Array.isArray(value) ? value.map(fix) : fix(value);
11174
- node[key] = repl;
11174
+ inplace || (node[key] = repl);
11175
11175
  }
11176
11176
  return node;
11177
11177
  }
11178
+ function cloneDeep(node) {
11179
+ return withLocDeep(node, null);
11180
+ }
11181
+
11182
+ ;// CONCATENATED MODULE: ./src/function-info.ts
11183
+
11184
+ function cloneSet(ae) {
11185
+ return new Set(ae);
11186
+ }
11187
+ function mergeSet(a, b) {
11188
+ b.forEach((event) => a.add(event));
11189
+ }
11190
+ function recordModifiedDecl(func, decl) {
11191
+ if (!func.next_info) {
11192
+ func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
11193
+ }
11194
+ func.next_info.modifiedDecls.add(decl);
11195
+ return null;
11196
+ }
11197
+ function recordModifiedDecls(func, lookupDefs) {
11198
+ lookupDefs.forEach((lookupDef) => lookupDef.results.forEach((result) => {
11199
+ if (result.type == "VariableDeclarator" && result.node.kind === "var") {
11200
+ recordModifiedDecl(func, result);
11201
+ }
11202
+ }));
11203
+ }
11204
+ function recordModifiedName(func, name) {
11205
+ if (!func.next_info) {
11206
+ func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
11207
+ }
11208
+ if (!func.next_info.modifiedNames) {
11209
+ func.next_info.modifiedNames = new Set();
11210
+ }
11211
+ func.next_info.modifiedNames.add(name);
11212
+ }
11213
+ function recordModifiedUnknown(func) {
11214
+ if (!func.next_info) {
11215
+ func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
11216
+ }
11217
+ func.next_info.modifiedUnknown = true;
11218
+ }
11219
+ function recordCalledFunc(func, callee) {
11220
+ if (!func.next_info) {
11221
+ func.next_info = { modifiedDecls: new Set(), calledFuncs: new Set() };
11222
+ }
11223
+ func.next_info.calledFuncs.add(callee);
11224
+ return null;
11225
+ }
11226
+ function recordCalledFuncs(func, callees) {
11227
+ callees.forEach((callee) => {
11228
+ recordCalledFunc(func, callee);
11229
+ });
11230
+ }
11231
+ function functionMayModify(state, func, decl) {
11232
+ const info = func.info;
11233
+ if (!info || info.modifiedUnknown)
11234
+ return true;
11235
+ if (info.resolvedDecls) {
11236
+ return info.resolvedDecls.has(decl);
11237
+ }
11238
+ if (info.modifiedNames?.has(decl.name))
11239
+ return true;
11240
+ if (info.modifiedDecls.has(decl))
11241
+ return true;
11242
+ const visited = new Set();
11243
+ const resolved = new Set();
11244
+ const resolveDecls = (f) => {
11245
+ if (visited.has(f))
11246
+ return true;
11247
+ if (!f.info)
11248
+ return false;
11249
+ if (f.info.modifiedUnknown) {
11250
+ info.modifiedUnknown = true;
11251
+ return false;
11252
+ }
11253
+ if (f.info.modifiedNames) {
11254
+ if (info.modifiedNames) {
11255
+ mergeSet(info.modifiedNames, f.info.modifiedNames);
11256
+ }
11257
+ else {
11258
+ info.modifiedNames = cloneSet(f.info.modifiedNames);
11259
+ }
11260
+ }
11261
+ mergeSet(resolved, f.info.modifiedDecls);
11262
+ visited.add(f);
11263
+ const q = true;
11264
+ if (q &&
11265
+ f.info.callsExposed &&
11266
+ state.exposed &&
11267
+ !Object.keys(state.exposed).every((key) => !state.allFunctions[key] ||
11268
+ state.allFunctions[key].every(resolveDecls))) {
11269
+ return false;
11270
+ }
11271
+ return Array.from(f.info.calledFuncs).every(resolveDecls);
11272
+ };
11273
+ if (resolveDecls(func)) {
11274
+ info.resolvedDecls = resolved;
11275
+ return resolved.has(decl);
11276
+ }
11277
+ return true;
11278
+ }
11279
+ function findCallees(lookupDefs) {
11280
+ const decls = lookupDefs.reduce((decls, r) => (decls ? decls.concat(r.results) : r.results), null);
11281
+ return (decls &&
11282
+ decls.filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
11283
+ }
11284
+ function findCalleesForNew(lookupDefs) {
11285
+ const initializer = (decl) => {
11286
+ if (hasProperty(decl.decls, "initialize")) {
11287
+ return decl.decls["initialize"];
11288
+ }
11289
+ if (decl.superClass && decl.superClass !== true) {
11290
+ return decl.superClass.reduce((cur, cls) => {
11291
+ const init = initializer(cls);
11292
+ if (init) {
11293
+ if (!cur)
11294
+ return init;
11295
+ return cur.concat(init);
11296
+ }
11297
+ return cur;
11298
+ }, null);
11299
+ }
11300
+ return null;
11301
+ };
11302
+ return lookupDefs.flatMap((r) => r.results
11303
+ .filter((decl) => decl.type === "ClassDeclaration")
11304
+ .flatMap(initializer)
11305
+ .filter((decl) => decl ? decl.type === "FunctionDeclaration" : false));
11306
+ }
11178
11307
 
11179
11308
  ;// CONCATENATED MODULE: ./src/variable-renamer.ts
11180
11309
 
@@ -11236,6 +11365,7 @@ function renameVariable(state, locals, declName) {
11236
11365
 
11237
11366
 
11238
11367
 
11368
+
11239
11369
  function getArgSafety(state, func, args, requireAll) {
11240
11370
  // determine whether decl might be changed by a function call
11241
11371
  // or assignment during the evaluation of FunctionStateNode.
@@ -11268,8 +11398,9 @@ function getArgSafety(state, func, args, requireAll) {
11268
11398
  }
11269
11399
  };
11270
11400
  const safeArgs = [];
11401
+ const argDecls = [];
11271
11402
  let allSafe = true;
11272
- if (!args.every((arg) => {
11403
+ if (!args.every((arg, i) => {
11273
11404
  switch (arg.type) {
11274
11405
  case "Literal":
11275
11406
  safeArgs.push(true);
@@ -11283,13 +11414,17 @@ function getArgSafety(state, func, args, requireAll) {
11283
11414
  safeArgs.push(null);
11284
11415
  return !requireAll;
11285
11416
  }
11286
- const safety = getSafety(results[0].results[0]);
11417
+ const decl = results[0].results[0];
11418
+ const safety = getSafety(decl);
11287
11419
  safeArgs.push(safety);
11288
11420
  if (!safety) {
11289
11421
  allSafe = false;
11290
11422
  if (safety === null) {
11291
11423
  return !requireAll;
11292
11424
  }
11425
+ else if (decl.type === "VariableDeclarator") {
11426
+ argDecls[i] = decl;
11427
+ }
11293
11428
  }
11294
11429
  return true;
11295
11430
  }
@@ -11302,34 +11437,91 @@ function getArgSafety(state, func, args, requireAll) {
11302
11437
  }
11303
11438
  if (allSafe && requireAll)
11304
11439
  return true;
11305
- let callSeen = false;
11440
+ const callsSeen = new Set();
11441
+ const modifiedDecls = new Set();
11442
+ let modifiedUnknown = false;
11306
11443
  const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
11307
11444
  // look for uses of "unsafe" args that occur after a call.
11308
11445
  // use post to do the checking, because arguments are evaluated
11309
11446
  // prior to the call, so eg "return f(x.y);" is fine, but
11310
11447
  // "return f()+x.y" is not.
11311
- traverseAst(func.node.body, null, (node) => {
11312
- switch (node.type) {
11313
- case "AssignmentExpression":
11314
- case "UpdateExpression": {
11315
- const v = node.type == "UpdateExpression" ? node.argument : node.left;
11316
- if (v.type === "Identifier" && (0,external_api_cjs_namespaceObject.hasProperty)(params, v.name)) {
11317
- safeArgs[params[v.name]] = null;
11448
+ const { pre, post, stack } = state;
11449
+ try {
11450
+ delete state.pre;
11451
+ state.post = (node) => {
11452
+ switch (node.type) {
11453
+ case "AssignmentExpression":
11454
+ case "UpdateExpression": {
11455
+ const v = node.type == "UpdateExpression" ? node.argument : node.left;
11456
+ if (v.type === "Identifier" && (0,external_api_cjs_namespaceObject.hasProperty)(params, v.name)) {
11457
+ // If a parameter is modified, we can't just substitute the
11458
+ // argument wherever the parameter is used.
11459
+ safeArgs[params[v.name]] = null;
11460
+ break;
11461
+ }
11462
+ if (modifiedUnknown)
11463
+ break;
11464
+ const [, results] = state.lookup(v);
11465
+ if (results) {
11466
+ results.forEach((r) => r.results.forEach((decl) => decl.type === "VariableDeclarator" && modifiedDecls.add(decl)));
11467
+ }
11468
+ else {
11469
+ modifiedUnknown = true;
11470
+ }
11471
+ break;
11318
11472
  }
11473
+ case "CallExpression":
11474
+ case "NewExpression":
11475
+ if (!modifiedUnknown) {
11476
+ const [, results] = state.lookup(node.callee, null,
11477
+ // calls are looked up as non-locals, but new is not
11478
+ node.type === "CallExpression" ? func.stack : state.stack);
11479
+ if (!results) {
11480
+ const callee_name = node.callee.type === "Identifier"
11481
+ ? node.callee
11482
+ : node.callee.type === "MemberExpression"
11483
+ ? (0,external_api_cjs_namespaceObject.isLookupCandidate)(node.callee)
11484
+ : null;
11485
+ if (callee_name) {
11486
+ const callees = state.allFunctions[callee_name.name];
11487
+ if (callees) {
11488
+ callees.forEach((callee) => callsSeen.add(callee));
11489
+ }
11490
+ }
11491
+ else {
11492
+ modifiedUnknown = true;
11493
+ }
11494
+ }
11495
+ else {
11496
+ const callees = node.type === "CallExpression"
11497
+ ? findCallees(results)
11498
+ : findCalleesForNew(results);
11499
+ if (callees) {
11500
+ callees.forEach((callee) => callsSeen.add(callee));
11501
+ }
11502
+ }
11503
+ }
11504
+ break;
11505
+ case "Identifier":
11506
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name) &&
11507
+ !safeArgs[params[node.name]] &&
11508
+ (modifiedUnknown ||
11509
+ !argDecls[params[node.name]] ||
11510
+ modifiedDecls.has(argDecls[params[node.name]]) ||
11511
+ Array.from(callsSeen).some((callee) => functionMayModify(state, callee, argDecls[params[node.name]])))) {
11512
+ safeArgs[params[node.name]] = null;
11513
+ }
11319
11514
  }
11320
- // fall through
11321
- case "CallExpression":
11322
- case "NewExpression":
11323
- callSeen = true;
11324
- break;
11325
- case "Identifier":
11326
- if (callSeen &&
11327
- (0,external_api_cjs_namespaceObject.hasProperty)(params, node.name) &&
11328
- !safeArgs[params[node.name]]) {
11329
- safeArgs[params[node.name]] = null;
11330
- }
11331
- }
11332
- });
11515
+ return null;
11516
+ };
11517
+ state.stack = func.stack;
11518
+ state.traverse(func.node.body);
11519
+ }
11520
+ finally {
11521
+ state.pre = pre;
11522
+ state.post = post;
11523
+ state.stack = stack;
11524
+ }
11333
11525
  return safeArgs;
11334
11526
  }
11335
11527
  function canInline(state, func, args) {
@@ -11434,9 +11626,6 @@ function processInlineBody(state, func, call, root, params) {
11434
11626
  state.pre = (node) => {
11435
11627
  if (failed)
11436
11628
  return [];
11437
- node.start = call.start;
11438
- node.end = call.end;
11439
- node.loc = call.loc;
11440
11629
  if (replacements.has(node))
11441
11630
  return false;
11442
11631
  const result = pre(node, state);
@@ -11451,6 +11640,7 @@ function processInlineBody(state, func, call, root, params) {
11451
11640
  if (params[paramName] >= 0)
11452
11641
  return null;
11453
11642
  const name = renameVariable(state, locals, paramName) || paramName;
11643
+ locals.map[name] = true;
11454
11644
  return {
11455
11645
  type: "VariableDeclarator",
11456
11646
  id: { type: "Identifier", name },
@@ -11469,31 +11659,49 @@ function processInlineBody(state, func, call, root, params) {
11469
11659
  }
11470
11660
  return result;
11471
11661
  };
11662
+ const fixId = (node) => {
11663
+ if (state.inType)
11664
+ return null;
11665
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name)) {
11666
+ const ix = params[node.name];
11667
+ if (ix >= 0) {
11668
+ const replacement = { ...call.arguments[ix] };
11669
+ replacements.add(replacement);
11670
+ return replacement;
11671
+ }
11672
+ return null;
11673
+ }
11674
+ const replacement = fixNodeScope(state, node, func.stack);
11675
+ if (!replacement) {
11676
+ failed = true;
11677
+ inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
11678
+ }
11679
+ return replacement;
11680
+ };
11472
11681
  state.post = (node) => {
11473
11682
  if (failed)
11474
11683
  return post(node, state);
11475
11684
  let replacement = null;
11476
11685
  switch (node.type) {
11477
- case "Identifier": {
11478
- if (state.inType)
11479
- break;
11480
- if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name)) {
11481
- const ix = params[node.name];
11482
- if (ix >= 0) {
11483
- replacement = { ...call.arguments[ix] };
11484
- replacements.add(replacement);
11485
- return replacement;
11686
+ case "AssignmentExpression":
11687
+ if (node.left.type === "Identifier") {
11688
+ const rep = fixId(node.left);
11689
+ if (rep) {
11690
+ node.left = rep;
11486
11691
  }
11487
- break;
11488
11692
  }
11489
- replacement = fixNodeScope(state, node, func.stack);
11490
- if (!replacement) {
11491
- failed = true;
11492
- inlineDiagnostic(state, func, call, `Failed to resolve '${node.name}'`);
11493
- return post(node, state);
11693
+ break;
11694
+ case "UpdateExpression":
11695
+ if (node.argument.type === "Identifier") {
11696
+ const rep = fixId(node.argument);
11697
+ if (rep) {
11698
+ node.argument = rep;
11699
+ }
11494
11700
  }
11495
11701
  break;
11496
- }
11702
+ case "Identifier":
11703
+ replacement = fixId(node);
11704
+ break;
11497
11705
  }
11498
11706
  const ret = post(replacement || node, state);
11499
11707
  return ret === false || ret ? ret : replacement;
@@ -11662,7 +11870,7 @@ function inlineWithArgs(state, func, call, context) {
11662
11870
  }
11663
11871
  }
11664
11872
  }
11665
- const body = JSON.parse(JSON.stringify(func.node.body));
11873
+ const body = cloneDeep(func.node.body);
11666
11874
  const safeArgs = getArgSafety(state, func, call.arguments, false);
11667
11875
  const params = Object.fromEntries(func.node.params.map((param, i) => {
11668
11876
  const argnum = safeArgs === true || (safeArgs !== false && safeArgs[i] !== null)
@@ -11711,18 +11919,19 @@ function inlineWithArgs(state, func, call, context) {
11711
11919
  --block.body.length;
11712
11920
  }
11713
11921
  }
11922
+ withLocDeep(body, context, context, true);
11714
11923
  return body;
11715
11924
  }
11716
11925
  function inlineFunction(state, func, call, context) {
11717
11926
  if (context) {
11718
11927
  return inlineWithArgs(state, func, call, context);
11719
11928
  }
11720
- const retArg = JSON.parse(JSON.stringify(func.node.body.body[0].argument));
11929
+ const retArg = cloneDeep(func.node.body.body[0].argument);
11721
11930
  const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
11722
11931
  const map = fixupLocalsMap(state);
11723
11932
  const ret = processInlineBody(state, func, call, retArg, params);
11724
11933
  state.localsStack[state.localsStack.length - 1].map = map;
11725
- return ret;
11934
+ return ret && withLocDeep(ret, call, call, true);
11726
11935
  }
11727
11936
  function applyTypeIfNeeded(node) {
11728
11937
  if ("enumType" in node && node.enumType) {
@@ -11827,6 +12036,121 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11827
12036
  return null;
11828
12037
  }
11829
12038
 
12039
+ ;// CONCATENATED MODULE: ./src/pragma-checker.ts
12040
+
12041
+
12042
+
12043
+ function pragmaChecker(state, ast, diagnostics) {
12044
+ const comments = ast.comments;
12045
+ if (!comments)
12046
+ return;
12047
+ diagnostics = diagnostics
12048
+ ?.slice()
12049
+ .sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
12050
+ let diagIndex = 0;
12051
+ let index = -1;
12052
+ let comment;
12053
+ let matchers;
12054
+ const next = () => {
12055
+ while (++index < comments.length) {
12056
+ comment = comments[index];
12057
+ let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
12058
+ if (!match)
12059
+ continue;
12060
+ const kind = match[1];
12061
+ let str = match[2];
12062
+ matchers = [];
12063
+ while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
12064
+ matchers.push({ kind, quote: match[1], needle: match[2] });
12065
+ str = str.substring(match[0].length);
12066
+ if (!str.length)
12067
+ break;
12068
+ }
12069
+ if (!str.length)
12070
+ break;
12071
+ if (!matchers.length) {
12072
+ match = str.match(/^(\S+)\s+$/);
12073
+ if (match) {
12074
+ matchers.push({ kind, quote: '"', needle: match[1] });
12075
+ break;
12076
+ }
12077
+ }
12078
+ diagnostic(state, comment.loc, `Build pragma '${comment.value}' is invalid`, "ERROR");
12079
+ }
12080
+ };
12081
+ const matcher = (quote, needle, haystack) => {
12082
+ if (quote == '"') {
12083
+ return haystack.includes(needle);
12084
+ }
12085
+ const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
12086
+ return re.test(haystack);
12087
+ };
12088
+ next();
12089
+ traverseAst(ast, (node) => {
12090
+ if (index >= comments.length)
12091
+ return false;
12092
+ if (node.start && node.start >= (comment.end || Infinity)) {
12093
+ const { kind, quote, needle } = matchers.shift();
12094
+ if (kind === "match") {
12095
+ const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " ");
12096
+ if (!matcher(quote, needle, haystack)) {
12097
+ matcher(quote, needle, haystack);
12098
+ diagnostic(state, comment.loc, `Didn't find '${needle}' in '${haystack}'`, "ERROR");
12099
+ }
12100
+ }
12101
+ else if (kind === "expect") {
12102
+ const locCmp = (a, b) => {
12103
+ if (!b)
12104
+ return -1;
12105
+ if (a.start.line < b.start.line)
12106
+ return -1;
12107
+ if (a.start.line === b.start.line &&
12108
+ a.start.column < b.start.column) {
12109
+ return -1;
12110
+ }
12111
+ if (a.end.line > b.end.line)
12112
+ return 1;
12113
+ if (a.end.line === b.end.line && a.end.column >= b.end.column) {
12114
+ return 1;
12115
+ }
12116
+ return 0;
12117
+ };
12118
+ let found = false;
12119
+ if (diagnostics) {
12120
+ while (true) {
12121
+ if (diagIndex >= diagnostics.length) {
12122
+ diagnostics = null;
12123
+ break;
12124
+ }
12125
+ const diag = diagnostics[diagIndex];
12126
+ const cmp = locCmp(diag.loc, node.loc);
12127
+ if (cmp > 0) {
12128
+ break;
12129
+ }
12130
+ diagIndex++;
12131
+ if (cmp < 0)
12132
+ continue;
12133
+ if (matcher(quote, needle, diag.message)) {
12134
+ found = true;
12135
+ diag.type = "INFO";
12136
+ }
12137
+ }
12138
+ }
12139
+ if (!found) {
12140
+ diagnostic(state, comment.loc, `Missing error message '${needle}`, "ERROR");
12141
+ }
12142
+ }
12143
+ if (matchers.length) {
12144
+ // if we're checking a series of nodes, we need
12145
+ // to skip over this one.
12146
+ return false;
12147
+ }
12148
+ next();
12149
+ }
12150
+ return null;
12151
+ });
12152
+ }
12153
+
11830
12154
  ;// CONCATENATED MODULE: ./src/control-flow.ts
11831
12155
 
11832
12156
 
@@ -12347,6 +12671,7 @@ var priorityqueuejs = __webpack_require__(2789);
12347
12671
 
12348
12672
 
12349
12673
 
12674
+
12350
12675
  /**
12351
12676
  * This implements a pseudo Partial Redundancy Elimination
12352
12677
  * pass. It isn't quite like traditional PRE because we're
@@ -12416,7 +12741,7 @@ function sizeBasedPRE(state, func) {
12416
12741
  return;
12417
12742
  }
12418
12743
  const { graph: head, identifiers } = buildPREGraph(state, func);
12419
- const candidates = computeAttributes(head);
12744
+ const candidates = computeAttributes(state, head);
12420
12745
  if (candidates) {
12421
12746
  if (logging) {
12422
12747
  console.log(`Found ${candidates.size} candidates in ${func.fullName}`);
@@ -12436,8 +12761,10 @@ function sizeBasedPRE(state, func) {
12436
12761
  let i = 0;
12437
12762
  do {
12438
12763
  name = `pre_${declName(decl)}${i ? "_" + i : ""}`;
12439
- if (!identifiers.has(name))
12764
+ if (!identifiers.has(name)) {
12765
+ identifiers.add(name);
12440
12766
  break;
12767
+ }
12441
12768
  i++;
12442
12769
  } while (true);
12443
12770
  declMap.set(decl, name);
@@ -12528,7 +12855,7 @@ function buildPREGraph(state, func) {
12528
12855
  case "ParenthesizedExpression":
12529
12856
  break;
12530
12857
  case "Literal":
12531
- if (!node.value && refCost(node) > LocalRefCost) {
12858
+ if (refCost(node) > LocalRefCost) {
12532
12859
  let decl = literals.get(node.value);
12533
12860
  if (!decl) {
12534
12861
  decl = node;
@@ -12612,10 +12939,18 @@ function buildPREGraph(state, func) {
12612
12939
  }
12613
12940
  break;
12614
12941
  }
12615
- case "NewExpression":
12616
- case "CallExpression":
12942
+ case "NewExpression": {
12943
+ const [, results] = state.lookup(node.callee);
12944
+ const callees = results ? findCalleesForNew(results) : null;
12945
+ liveDef(null, stmt);
12946
+ return { type: "mod", node, mayThrow, callees };
12947
+ }
12948
+ case "CallExpression": {
12617
12949
  liveDef(null, stmt);
12618
- return { type: "mod", node, mayThrow };
12950
+ const [, results] = state.lookup(node.callee);
12951
+ const callees = results ? findCallees(results) : null;
12952
+ return { type: "mod", node, mayThrow, callees };
12953
+ }
12619
12954
  default:
12620
12955
  if (!isExpression(node))
12621
12956
  break;
@@ -12631,12 +12966,6 @@ function buildPREGraph(state, func) {
12631
12966
  function anticipatedDecls() {
12632
12967
  return new Map();
12633
12968
  }
12634
- function cloneSet(ae) {
12635
- return new Set(ae);
12636
- }
12637
- function mergeSet(a, b) {
12638
- b.forEach((event) => a.add(event));
12639
- }
12640
12969
  function equalSet(a, b) {
12641
12970
  if (a.size != b.size)
12642
12971
  return false;
@@ -12715,6 +13044,7 @@ function refCost(node) {
12715
13044
  switch (typeof node.value) {
12716
13045
  case "string":
12717
13046
  return 5;
13047
+ case "bigint":
12718
13048
  case "number":
12719
13049
  return 5;
12720
13050
  case "boolean":
@@ -12776,7 +13106,7 @@ function candidateCost(candState) {
12776
13106
  cost += defCost(candState.node) * boundarySize;
12777
13107
  return cost;
12778
13108
  }
12779
- function computeAttributes(head) {
13109
+ function computeAttributes(state, head) {
12780
13110
  const order = getPostOrder(head);
12781
13111
  order.forEach((block, i) => {
12782
13112
  block.order = i;
@@ -12885,7 +13215,9 @@ function computeAttributes(head) {
12885
13215
  curState.forEach((candidates, decl) => {
12886
13216
  if (decl.type === "VariableDeclarator" &&
12887
13217
  decl.node.kind === "var" &&
12888
- candidates.live) {
13218
+ candidates.live &&
13219
+ (!event.callees ||
13220
+ event.callees.some((callee) => functionMayModify(state, callee, decl)))) {
12889
13221
  candidates.ant.add(getMod(event, decl, candidates.node));
12890
13222
  candidates.live = false;
12891
13223
  }
@@ -13074,20 +13406,26 @@ function applyReplacements(func, nodeMap, declMap) {
13074
13406
  stmtStack.pop();
13075
13407
  const events = nodeMap.get(node);
13076
13408
  if (events) {
13077
- if (events.length === 1) {
13078
- if (events[0].type === "ref") {
13409
+ const ret = events.reduce((ret, event) => {
13410
+ if (event.type === "ref") {
13411
+ if (ret) {
13412
+ throw new Error(`ref found when there was already a replacement for this node`);
13413
+ }
13079
13414
  if (node.type !== "Identifier" &&
13080
13415
  node.type !== "MemberExpression" &&
13081
13416
  node.type !== "Literal") {
13082
13417
  throw new Error(`Ref found, but wrong type of node: ${node.type}`);
13083
13418
  }
13084
- const name = declMap.get(events[0].decl);
13419
+ const name = declMap.get(event.decl);
13085
13420
  if (!name) {
13086
13421
  throw new Error(`No replacement found for "${(0,external_api_cjs_namespaceObject.formatAst)(node)}"`);
13087
13422
  }
13088
13423
  return ident(name, node);
13089
13424
  }
13090
- else if (events[0].type === "def") {
13425
+ if (event.type === "def") {
13426
+ if (ret) {
13427
+ throw new Error(`def found when there was already a replacement for this node`);
13428
+ }
13091
13429
  if (node.type !== "AssignmentExpression" &&
13092
13430
  node.type !== "UpdateExpression") {
13093
13431
  throw new Error(`Def found, but wrong type of node: ${node.type}`);
@@ -13095,7 +13433,7 @@ function applyReplacements(func, nodeMap, declMap) {
13095
13433
  const target = node.type === "AssignmentExpression"
13096
13434
  ? node.left
13097
13435
  : node.argument;
13098
- const name = declMap.get(events[0].decl);
13436
+ const name = declMap.get(event.decl);
13099
13437
  if (!name) {
13100
13438
  throw new Error(`No replacement found for "${(0,external_api_cjs_namespaceObject.formatAst)(target)}"`);
13101
13439
  }
@@ -13114,20 +13452,24 @@ function applyReplacements(func, nodeMap, declMap) {
13114
13452
  }
13115
13453
  return withLoc({ type: "SequenceExpression", expressions: [node, assign] }, node);
13116
13454
  }
13117
- }
13118
- events.forEach((event) => {
13119
- if (event.type !== "mod") {
13120
- throw new Error(`Unexpected ${event.type} found amongst multiple events`);
13121
- }
13122
- if (!event.decl) {
13123
- throw new Error(`Unexpected null decl on mod event`);
13455
+ if (event.type === "mod") {
13456
+ if (!event.decl) {
13457
+ throw new Error(`Unexpected null decl on mod event`);
13458
+ }
13459
+ let pending = pendingMap.get(stmt);
13460
+ if (!pending) {
13461
+ pendingMap.set(stmt, (pending = new Set()));
13462
+ }
13463
+ pending.add(event);
13124
13464
  }
13125
- let pending = pendingMap.get(stmt);
13126
- if (!pending) {
13127
- pendingMap.set(stmt, (pending = new Set()));
13465
+ else {
13466
+ throw new Error(`Unexpected ${event.type} found`);
13128
13467
  }
13129
- pending.add(event);
13130
- });
13468
+ return ret;
13469
+ }, null);
13470
+ if (ret) {
13471
+ return ret;
13472
+ }
13131
13473
  }
13132
13474
  const pending = pendingMap.get(node);
13133
13475
  if (node.type === "SequenceExpression") {
@@ -13201,10 +13543,152 @@ function applyReplacements(func, nodeMap, declMap) {
13201
13543
  });
13202
13544
  }
13203
13545
 
13204
- ;// CONCATENATED MODULE: ./src/visitor.ts
13546
+ ;// CONCATENATED MODULE: ./src/unused-exprs.ts
13205
13547
 
13206
- function visitReferences(state, ast, name, defn, callback) {
13207
- const checkResults = ([name, results], node) => {
13548
+
13549
+
13550
+ function cleanupUnusedVars(state, node) {
13551
+ const [parent] = state.stack.slice(-1);
13552
+ if (parent.node !== node) {
13553
+ return;
13554
+ }
13555
+ if (parent.type != "BlockStatement") {
13556
+ throw new Error(`Unexpected parent type '${parent.type}' for local declaration`);
13557
+ }
13558
+ if (parent.decls) {
13559
+ let toRemove = null;
13560
+ Object.values(parent.decls).forEach((decls) => {
13561
+ if (decls.length === 1 &&
13562
+ decls[0].type === "VariableDeclarator" &&
13563
+ !decls[0].used) {
13564
+ if (!toRemove)
13565
+ toRemove = {};
13566
+ toRemove[decls[0].name] = decls[0];
13567
+ }
13568
+ });
13569
+ if (toRemove) {
13570
+ const varDeclarations = new Map();
13571
+ traverseAst(node, null, (node) => {
13572
+ switch (node.type) {
13573
+ case "VariableDeclaration": {
13574
+ node.declarations.forEach((decl, i) => {
13575
+ const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(decl.id);
13576
+ if (hasProperty(toRemove, name)) {
13577
+ const indices = varDeclarations.get(node);
13578
+ if (indices) {
13579
+ indices.push(i);
13580
+ }
13581
+ else {
13582
+ varDeclarations.set(node, [i]);
13583
+ }
13584
+ }
13585
+ });
13586
+ break;
13587
+ }
13588
+ case "ExpressionStatement":
13589
+ if (node.expression.type === "AssignmentExpression") {
13590
+ if (node.expression.left.type === "Identifier" &&
13591
+ hasProperty(toRemove, node.expression.left.name)) {
13592
+ return unused(node.expression.right);
13593
+ }
13594
+ }
13595
+ else if (node.expression.type === "UpdateExpression" &&
13596
+ node.expression.argument.type === "Identifier" &&
13597
+ hasProperty(toRemove, node.expression.argument.name)) {
13598
+ return false;
13599
+ }
13600
+ break;
13601
+ case "SequenceExpression": {
13602
+ for (let i = node.expressions.length; i--;) {
13603
+ const expr = node.expressions[i];
13604
+ if (expr.type === "AssignmentExpression") {
13605
+ if (expr.left.type === "Identifier" &&
13606
+ hasProperty(toRemove, expr.left.name)) {
13607
+ const rep = unused(expr.right);
13608
+ if (!rep.length) {
13609
+ node.expressions.splice(i, 1);
13610
+ }
13611
+ else {
13612
+ // Sequence expressions can only be assignments
13613
+ // or update expressions. Even calls aren't allowed
13614
+ toRemove[expr.left.name] = null;
13615
+ expr.operator = "=";
13616
+ }
13617
+ }
13618
+ }
13619
+ else if (expr.type === "UpdateExpression" &&
13620
+ expr.argument.type === "Identifier" &&
13621
+ hasProperty(toRemove, expr.argument.name)) {
13622
+ node.expressions.splice(i, 1);
13623
+ }
13624
+ }
13625
+ break;
13626
+ }
13627
+ }
13628
+ return null;
13629
+ });
13630
+ varDeclarations.forEach((indices, decl) => {
13631
+ let index = -1;
13632
+ for (let ii = indices.length, j = decl.declarations.length; ii--;) {
13633
+ const i = indices[ii];
13634
+ const vdecl = decl.declarations[i];
13635
+ const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id);
13636
+ if (hasProperty(toRemove, name)) {
13637
+ const rep = vdecl.init ? unused(vdecl.init) : [];
13638
+ if (rep.length) {
13639
+ if (parent.node.type === "ForStatement") {
13640
+ // declarations whose inits have side effects
13641
+ // can't be deleted from for statements.
13642
+ continue;
13643
+ }
13644
+ if (index < 0) {
13645
+ index = parent.node.body.findIndex((s) => s === decl);
13646
+ if (index < 0) {
13647
+ throw new Error(`Failed to find variable declaration for ${(0,external_api_cjs_namespaceObject.variableDeclarationName)(vdecl.id)}`);
13648
+ }
13649
+ }
13650
+ if (j > i + 1) {
13651
+ const tail = {
13652
+ ...decl,
13653
+ declarations: decl.declarations.slice(i + 1, j),
13654
+ };
13655
+ if (decl.loc && vdecl.loc) {
13656
+ tail.loc = { ...decl.loc, start: vdecl.loc.end };
13657
+ tail.start = vdecl.end;
13658
+ }
13659
+ rep.push(tail);
13660
+ }
13661
+ if (decl.loc && vdecl.loc) {
13662
+ decl.loc = { ...decl.loc, end: vdecl.loc.start };
13663
+ decl.end = vdecl.start;
13664
+ }
13665
+ decl.declarations.splice(i);
13666
+ parent.node.body.splice(index + 1, 0, ...rep);
13667
+ j = i;
13668
+ continue;
13669
+ }
13670
+ if (toRemove[name]) {
13671
+ j--;
13672
+ decl.declarations.splice(i, 1);
13673
+ if (i === j && decl.loc && vdecl.loc) {
13674
+ decl.loc = { ...decl.loc, end: vdecl.loc.start };
13675
+ decl.end = vdecl.start;
13676
+ }
13677
+ }
13678
+ else {
13679
+ delete vdecl.init;
13680
+ }
13681
+ }
13682
+ }
13683
+ });
13684
+ }
13685
+ }
13686
+ }
13687
+
13688
+ ;// CONCATENATED MODULE: ./src/visitor.ts
13689
+
13690
+ function visitReferences(state, ast, name, defn, callback) {
13691
+ const checkResults = ([name, results], node) => {
13208
13692
  if (name && results) {
13209
13693
  if (!defn || (0,external_api_cjs_namespaceObject.sameLookupResult)(results, defn)) {
13210
13694
  if (callback(node, results, false) === false) {
@@ -13265,14 +13749,16 @@ function visitReferences(state, ast, name, defn, callback) {
13265
13749
  return checkResults(state.lookup(node), node);
13266
13750
  }
13267
13751
  break;
13268
- case "MemberExpression":
13269
- if (!node.computed && node.property.type === "Identifier") {
13270
- if (!name || node.property.name === name) {
13752
+ case "MemberExpression": {
13753
+ const property = (0,external_api_cjs_namespaceObject.isLookupCandidate)(node);
13754
+ if (property) {
13755
+ if (!name || property.name === name) {
13271
13756
  return checkResults(state.lookup(node), node) || ["object"];
13272
13757
  }
13273
13758
  return ["object"];
13274
13759
  }
13275
13760
  break;
13761
+ }
13276
13762
  case "MethodDefinition": {
13277
13763
  if (!state.inType) {
13278
13764
  throw new Error("Method definition outside of type!");
@@ -13281,7 +13767,6 @@ function visitReferences(state, ast, name, defn, callback) {
13281
13767
  node.params.forEach((param) => {
13282
13768
  if (param.type == "BinaryExpression") {
13283
13769
  state.traverse(param.right);
13284
- state.inType = true;
13285
13770
  }
13286
13771
  });
13287
13772
  }
@@ -13304,6 +13789,9 @@ function visitReferences(state, ast, name, defn, callback) {
13304
13789
 
13305
13790
 
13306
13791
 
13792
+
13793
+
13794
+
13307
13795
  function collectClassInfo(state) {
13308
13796
  const toybox = state.stack[0].decls["Toybox"][0];
13309
13797
  const lang = toybox.decls["Lang"][0];
@@ -13363,8 +13851,7 @@ function collectClassInfo(state) {
13363
13851
  c.decls &&
13364
13852
  Object.values(c.decls).forEach((funcs) => {
13365
13853
  funcs.forEach((f) => {
13366
- if ((0,external_api_cjs_namespaceObject.isStateNode)(f) &&
13367
- f.type === "FunctionDeclaration" &&
13854
+ if (f.type === "FunctionDeclaration" &&
13368
13855
  (0,external_api_cjs_namespaceObject.hasProperty)(cls.decls, f.name)) {
13369
13856
  f.node.hasOverride = true;
13370
13857
  }
@@ -13377,6 +13864,15 @@ function collectClassInfo(state) {
13377
13864
  state.allClasses.forEach((elm) => {
13378
13865
  if (elm.superClass)
13379
13866
  markOverrides(elm, elm.superClass);
13867
+ if (elm.hasInvoke && elm.decls) {
13868
+ Object.values(elm.decls).forEach((funcs) => {
13869
+ funcs.forEach((f) => {
13870
+ if (f.type === "FunctionDeclaration" && !f.isStatic) {
13871
+ (0,external_api_cjs_namespaceObject.markInvokeClassMethod)(f);
13872
+ }
13873
+ });
13874
+ });
13875
+ }
13380
13876
  });
13381
13877
  }
13382
13878
  function getFileSources(fnMap) {
@@ -13415,7 +13911,7 @@ async function analyze(fnMap, barrelList, config) {
13415
13911
  const preState = {
13416
13912
  fnMap,
13417
13913
  config,
13418
- allFunctions: [],
13914
+ allFunctions: {},
13419
13915
  allClasses: [],
13420
13916
  shouldExclude(node) {
13421
13917
  if ("attrs" in node &&
@@ -13445,11 +13941,6 @@ async function analyze(fnMap, barrelList, config) {
13445
13941
  pre(node, state) {
13446
13942
  switch (node.type) {
13447
13943
  case "FunctionDeclaration":
13448
- if (markApi) {
13449
- node.body = null;
13450
- break;
13451
- }
13452
- // falls through
13453
13944
  case "ModuleDeclaration":
13454
13945
  case "ClassDeclaration": {
13455
13946
  const [scope] = state.stack.slice(-1);
@@ -13460,7 +13951,18 @@ async function analyze(fnMap, barrelList, config) {
13460
13951
  (scope.node.attrs &&
13461
13952
  scope.node.attrs.access &&
13462
13953
  scope.node.attrs.access.includes("static"));
13463
- state.allFunctions.push(scope);
13954
+ if (markApi) {
13955
+ node.body = null;
13956
+ scope.info = (0,external_api_cjs_namespaceObject.getApiFunctionInfo)(scope);
13957
+ delete scope.stack;
13958
+ }
13959
+ const allFuncs = state.allFunctions;
13960
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(allFuncs, scope.name)) {
13961
+ allFuncs[scope.name] = [scope];
13962
+ }
13963
+ else {
13964
+ allFuncs[scope.name].push(scope);
13965
+ }
13464
13966
  }
13465
13967
  else if (scope.type === "ClassDeclaration") {
13466
13968
  state.allClasses.push(scope);
@@ -13485,7 +13987,7 @@ async function analyze(fnMap, barrelList, config) {
13485
13987
  value.hasTests = hasTests;
13486
13988
  });
13487
13989
  delete state.shouldExclude;
13488
- delete state.post;
13990
+ delete state.pre;
13489
13991
  collectClassInfo(state);
13490
13992
  const diagnosticType = config?.checkInvalidSymbols !== "OFF"
13491
13993
  ? config?.checkInvalidSymbols || "WARNING"
@@ -13508,6 +14010,8 @@ async function analyze(fnMap, barrelList, config) {
13508
14010
  });
13509
14011
  });
13510
14012
  }
14013
+ state.exposed = state.nextExposed;
14014
+ state.nextExposed = {};
13511
14015
  return state;
13512
14016
  }
13513
14017
  function compareLiteralLike(a, b) {
@@ -13553,15 +14057,12 @@ function getLiteralNode(node) {
13553
14057
  if (node.argument.type != "Literal")
13554
14058
  return null;
13555
14059
  switch (node.operator) {
13556
- case "-":
13557
- if (typeof node.argument.value == "number") {
13558
- return {
13559
- ...node.argument,
13560
- value: -node.argument.value,
13561
- raw: "-" + node.argument.value,
13562
- enumType: node.enumType,
13563
- };
14060
+ case "-": {
14061
+ const [arg, type] = getNodeValue(node.argument);
14062
+ if (type === "Number" || type === "Long") {
14063
+ return replacementLiteral(arg, -arg.value, type);
13564
14064
  }
14065
+ }
13565
14066
  }
13566
14067
  }
13567
14068
  return null;
@@ -13580,29 +14081,29 @@ function getNodeValue(node) {
13580
14081
  if (node.type != "Literal") {
13581
14082
  return [null, null];
13582
14083
  }
13583
- let type = node.value === null ? "Null" : typeof node.value;
14084
+ if (node.value === null) {
14085
+ return [node, "Null"];
14086
+ }
14087
+ const type = typeof node.value;
13584
14088
  if (type === "number") {
13585
- const match = node.raw && prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
14089
+ const match = prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.exec(node.raw);
13586
14090
  if (match) {
13587
- type = match[2] == "l" ? "Long" : "Number";
13588
- }
13589
- else if (node.raw && node.raw.endsWith("d")) {
13590
- type = "Double";
13591
- }
13592
- else {
13593
- type = "Float";
14091
+ return match[2] === "l" || match[2] === "L"
14092
+ ? [node, "Long"]
14093
+ : [node, "Number"];
13594
14094
  }
14095
+ return [node, node.raw.endsWith("d") ? "Double" : "Float"];
13595
14096
  }
13596
- else if (type === "string") {
13597
- type = "String";
14097
+ if (type === "bigint") {
14098
+ return [node, "Long"];
13598
14099
  }
13599
- else if (type === "boolean") {
13600
- type = "Boolean";
14100
+ if (type === "string") {
14101
+ return [node, "String"];
13601
14102
  }
13602
- else {
13603
- type = "Unknown";
14103
+ if (type === "boolean") {
14104
+ return [node, "Boolean"];
13604
14105
  }
13605
- return [node, type];
14106
+ throw new Error(`Literal has unknown type '${type}'`);
13606
14107
  }
13607
14108
  function fullTypeName(state, tsp) {
13608
14109
  if (typeof tsp.name === "string") {
@@ -13647,6 +14148,46 @@ function isBooleanExpression(state, node) {
13647
14148
  }
13648
14149
  return false;
13649
14150
  }
14151
+ function replacementLiteral(arg, value, type) {
14152
+ if (typeof value === "boolean") {
14153
+ type = "Boolean";
14154
+ }
14155
+ else if (type === "Number") {
14156
+ value = Number(BigInt.asIntN(32, BigInt(value)));
14157
+ }
14158
+ else if (type === "Long") {
14159
+ value = BigInt.asIntN(64, BigInt(value));
14160
+ }
14161
+ return {
14162
+ ...arg,
14163
+ value,
14164
+ raw: value.toString() + (type === "Long" ? "l" : ""),
14165
+ };
14166
+ }
14167
+ const operators = {
14168
+ "+": (left, right) => left + right,
14169
+ "-": (left, right) => left - right,
14170
+ "*": (left, right) => left * right,
14171
+ "/": (left, right) => left / right,
14172
+ "%": (left, right) => left % right,
14173
+ "&": (left, right) => left & right,
14174
+ "|": (left, right) => left | right,
14175
+ "^": (left, right) => left ^ right,
14176
+ "<<": (left, right) => left << (right & 127n),
14177
+ ">>": (left, right) => left >> (right & 127n),
14178
+ "==": (left, right) =>
14179
+ // two string literals will compare unequal, becuase string
14180
+ // equality is object equality.
14181
+ typeof left === "string" ? false : left === right,
14182
+ "!=": (left, right) => typeof left === "string" ? true : left !== right,
14183
+ "<=": (left, right) => left <= right,
14184
+ ">=": (left, right) => left >= right,
14185
+ "<": (left, right) => left < right,
14186
+ ">": (left, right) => left > right,
14187
+ as: null,
14188
+ instanceof: null,
14189
+ has: null,
14190
+ };
13650
14191
  function optimizeNode(state, node) {
13651
14192
  switch (node.type) {
13652
14193
  case "UnaryExpression": {
@@ -13661,29 +14202,17 @@ function optimizeNode(state, node) {
13661
14202
  break;
13662
14203
  case "-":
13663
14204
  if (type === "Number" || type === "Long") {
13664
- return {
13665
- ...arg,
13666
- value: -arg.value,
13667
- raw: (-arg.value).toString() + (type === "Long" ? "l" : ""),
13668
- };
14205
+ return replacementLiteral(arg, -arg.value, type);
13669
14206
  }
13670
14207
  break;
13671
14208
  case "!":
13672
14209
  case "~":
13673
14210
  {
13674
- let value;
13675
14211
  if (type === "Number" || type === "Long") {
13676
- value = -arg.value - 1;
14212
+ return replacementLiteral(arg, ~BigInt(arg.value), type);
13677
14213
  }
13678
- else if (type === "Boolean" && node.operator == "!") {
13679
- value = !arg.value;
13680
- }
13681
- if (value !== undefined) {
13682
- return {
13683
- ...arg,
13684
- value,
13685
- raw: value.toString() + (type === "Long" ? "l" : ""),
13686
- };
14214
+ if (type === "Boolean" && node.operator == "!") {
14215
+ return replacementLiteral(arg, !arg.value, type);
13687
14216
  }
13688
14217
  }
13689
14218
  break;
@@ -13691,27 +14220,6 @@ function optimizeNode(state, node) {
13691
14220
  break;
13692
14221
  }
13693
14222
  case "BinaryExpression": {
13694
- const operators = {
13695
- "+": (left, right) => left + right,
13696
- "-": (left, right) => left - right,
13697
- "*": (left, right) => left * right,
13698
- "/": (left, right) => Math.trunc(left / right),
13699
- "%": (left, right) => left % right,
13700
- "&": (left, right, type) => type === "Number" ? left & right : null,
13701
- "|": (left, right, type) => type === "Number" ? left | right : null,
13702
- "^": (left, right, type) => type === "Number" ? left ^ right : null,
13703
- "<<": (left, right, type) => type === "Number" ? left << right : null,
13704
- ">>": (left, right, type) => type === "Number" ? left >> right : null,
13705
- "==": (left, right) => left == right,
13706
- "!=": (left, right) => left != right,
13707
- "<=": (left, right) => left <= right,
13708
- ">=": (left, right) => left >= right,
13709
- "<": (left, right) => left < right,
13710
- ">": (left, right) => left > right,
13711
- as: null,
13712
- instanceof: null,
13713
- has: null,
13714
- };
13715
14223
  const op = operators[node.operator];
13716
14224
  if (op) {
13717
14225
  const [left, left_type] = getNodeValue(node.left);
@@ -13719,23 +14227,22 @@ function optimizeNode(state, node) {
13719
14227
  if (!left || !right)
13720
14228
  break;
13721
14229
  let value = null;
13722
- if (left_type != right_type ||
13723
- (left_type != "Number" && left_type != "Long")) {
14230
+ let type;
14231
+ if ((left_type != "Number" && left_type != "Long") ||
14232
+ left_type != right_type) {
13724
14233
  if (node.operator !== "==" && node.operator !== "!=") {
13725
14234
  break;
13726
14235
  }
13727
14236
  value = operators[node.operator](left.value, right.value);
14237
+ type = "Boolean";
13728
14238
  }
13729
14239
  else {
13730
- value = op(left.value, right.value, left_type);
14240
+ type = left_type;
14241
+ value = op(BigInt(left.value), BigInt(right.value));
13731
14242
  }
13732
14243
  if (value === null)
13733
14244
  break;
13734
- return {
13735
- ...left,
13736
- value,
13737
- raw: value.toString() + (left_type === "Long" ? "l" : ""),
13738
- };
14245
+ return replacementLiteral(left, value, type);
13739
14246
  }
13740
14247
  break;
13741
14248
  }
@@ -13745,7 +14252,8 @@ function optimizeNode(state, node) {
13745
14252
  break;
13746
14253
  const falsy = left.value === false ||
13747
14254
  left.value === null ||
13748
- (left.value === 0 && (left_type === "Number" || left_type === "Long"));
14255
+ ((left_type === "Number" || left_type === "Long") &&
14256
+ (left.value === 0 || left.value === 0n));
13749
14257
  if (falsy === (node.operator === "&&")) {
13750
14258
  return left;
13751
14259
  }
@@ -13786,9 +14294,7 @@ function evaluateFunction(state, func, args) {
13786
14294
  const paramValues = args &&
13787
14295
  Object.fromEntries(func.params.map((p, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(p), args[i]]));
13788
14296
  let ret = null;
13789
- const body = args
13790
- ? JSON.parse(JSON.stringify(func.body))
13791
- : func.body;
14297
+ const body = args ? cloneDeep(func.body) : func.body;
13792
14298
  try {
13793
14299
  traverseAst(body, (node) => {
13794
14300
  switch (node.type) {
@@ -13839,12 +14345,10 @@ function markFunctionCalled(state, func) {
13839
14345
  (0,external_util_cjs_namespaceObject.pushUnique)(state.calledFunctions[func.id.name], func);
13840
14346
  }
13841
14347
  async function optimizeMonkeyC(fnMap, barrelList, config) {
13842
- const state = {
13843
- ...(await analyze(fnMap, barrelList, config)),
13844
- localsStack: [{}],
13845
- exposed: {},
13846
- calledFunctions: {},
13847
- };
14348
+ const state = (await analyze(fnMap, barrelList, config));
14349
+ state.localsStack = [{}];
14350
+ state.calledFunctions = {};
14351
+ state.usedByName = {};
13848
14352
  const replace = (node, old) => {
13849
14353
  if (node === false || node === null)
13850
14354
  return node;
@@ -13933,6 +14437,58 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
13933
14437
  f.type == "FunctionDeclaration" &&
13934
14438
  maybeCalled(f.node))) ||
13935
14439
  (sc.superClass && checkInherited(sc, name))));
14440
+ const renamer = (idnode) => {
14441
+ const ident = idnode.type === "Identifier" ? idnode : idnode.left;
14442
+ const locals = topLocals();
14443
+ const { map } = locals;
14444
+ if (map) {
14445
+ const declName = ident.name;
14446
+ const name = renameVariable(state, locals, declName);
14447
+ if (name) {
14448
+ const [, results] = state.lookupValue(ident);
14449
+ if (!results) {
14450
+ throw new Error(`Didn't find local ${declName} which needed renaming`);
14451
+ }
14452
+ if (results.length !== 1) {
14453
+ throw new Error(`Lookup of local ${declName} found more than one result`);
14454
+ }
14455
+ const parent = results[0].parent;
14456
+ if (!parent) {
14457
+ throw new Error(`No parent in lookup of local ${declName}`);
14458
+ }
14459
+ const decls = parent.decls;
14460
+ if (!decls || !(0,external_api_cjs_namespaceObject.hasProperty)(decls, declName)) {
14461
+ throw new Error(`Missing decls in lookup of local ${declName}`);
14462
+ }
14463
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(decls, name)) {
14464
+ throw new Error(`While renaming ${declName} to ${name}, there was already a variable ${name}`);
14465
+ }
14466
+ if (decls[declName].length === 1) {
14467
+ decls[name] = decls[declName];
14468
+ delete decls[declName];
14469
+ }
14470
+ else {
14471
+ let i = decls[declName].length;
14472
+ while (i--) {
14473
+ const decl = decls[declName][i];
14474
+ if (decl === idnode ||
14475
+ (decl.type === "VariableDeclarator" && decl.node.id === idnode)) {
14476
+ decls[declName].splice(i, 1);
14477
+ decls[name] = [decl];
14478
+ break;
14479
+ }
14480
+ }
14481
+ if (i < 0) {
14482
+ throw new Error(`While renaming ${declName} to ${name}: Didn't find original declaration`);
14483
+ }
14484
+ }
14485
+ ident.name = name;
14486
+ }
14487
+ else {
14488
+ map[declName] = true;
14489
+ }
14490
+ }
14491
+ };
13936
14492
  state.pre = (node) => {
13937
14493
  switch (node.type) {
13938
14494
  case "ConditionalExpression":
@@ -13953,7 +14509,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
13953
14509
  result = !!value.value;
13954
14510
  }
13955
14511
  if (result !== null) {
13956
- node.test = { type: "Literal", value: result };
14512
+ node.test = {
14513
+ type: "Literal",
14514
+ value: result,
14515
+ raw: result.toString(),
14516
+ };
13957
14517
  if (node.type === "IfStatement" ||
13958
14518
  node.type === "ConditionalExpression") {
13959
14519
  return [result ? "consequent" : "alternate"];
@@ -13972,7 +14532,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
13972
14532
  return null;
13973
14533
  }
13974
14534
  case "EnumDeclaration":
13975
- return false;
14535
+ return [];
13976
14536
  case "ForStatement": {
13977
14537
  const map = topLocals().map;
13978
14538
  if (map) {
@@ -13981,43 +14541,13 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
13981
14541
  break;
13982
14542
  }
13983
14543
  case "VariableDeclarator": {
13984
- const locals = topLocals();
13985
- const { map } = locals;
13986
- if (map) {
13987
- const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id);
13988
- const name = renameVariable(state, locals, declName);
13989
- if (name) {
13990
- if (node.id.type === "Identifier") {
13991
- node.id.name = name;
13992
- }
13993
- else {
13994
- node.id.left.name = name;
13995
- }
13996
- }
13997
- else {
13998
- map[declName] = true;
13999
- }
14000
- }
14544
+ renamer(node.id);
14001
14545
  return ["init"];
14002
14546
  }
14003
14547
  case "CatchClause":
14004
14548
  if (node.param) {
14005
14549
  state.localsStack.push({ node, map: { ...(topLocals().map || {}) } });
14006
- const locals = topLocals();
14007
- const map = locals.map;
14008
- const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.param);
14009
- const name = renameVariable(state, locals, declName);
14010
- if (name) {
14011
- if (node.param.type === "Identifier") {
14012
- node.param.name = name;
14013
- }
14014
- else {
14015
- node.param.left.name = name;
14016
- }
14017
- }
14018
- else {
14019
- map[declName] = true;
14020
- }
14550
+ renamer(node.param);
14021
14551
  return ["body"];
14022
14552
  }
14023
14553
  break;
@@ -14033,14 +14563,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14033
14563
  break;
14034
14564
  case "UnaryExpression":
14035
14565
  if (node.operator == ":") {
14036
- // If we produce a Symbol, for a given name,
14037
- // its possible that someone uses that symbol
14038
- // indirectly, so we can't remove any enums or
14039
- // constants with that name (we can still replace
14040
- // uses of those constants though).
14041
- state.exposed[node.argument.name] = true;
14042
- // In any case, we can't replace *this* use of the
14043
- // symbol with its value...
14566
+ // node.argument is not a normal identifier.
14567
+ // don't visit it.
14044
14568
  return [];
14045
14569
  }
14046
14570
  break;
@@ -14052,29 +14576,73 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14052
14576
  if (typeof name === "string") {
14053
14577
  node.name = name;
14054
14578
  }
14579
+ const [, results] = state.lookupValue(node);
14580
+ if (results) {
14581
+ if (results.length !== 1 || results[0].results.length !== 1) {
14582
+ throw new Error(`Local ${node.name} had multiple lookup results`);
14583
+ }
14584
+ const parent = results[0].parent;
14585
+ if (!parent) {
14586
+ throw new Error(`Local ${node.name} had no parent`);
14587
+ }
14588
+ const decl = results[0].results[0];
14589
+ if (parent.type === "FunctionDeclaration" ||
14590
+ decl.type !== "VariableDeclarator") {
14591
+ // we can't optimize away function or catch parameters
14592
+ return [];
14593
+ }
14594
+ if (parent.type !== "BlockStatement") {
14595
+ throw new Error(`Local ${node.name} was not declared at block scope(??)`);
14596
+ }
14597
+ decl.used = true;
14598
+ }
14055
14599
  }
14056
14600
  }
14057
14601
  if ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, node.name)) {
14058
14602
  if (!lookupAndReplace(node)) {
14059
- state.exposed[node.name] = true;
14603
+ state.usedByName[node.name] = true;
14060
14604
  }
14061
14605
  }
14062
14606
  return [];
14063
14607
  }
14064
- case "MemberExpression":
14065
- if (node.property.type === "Identifier" && !node.computed) {
14066
- if ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, node.property.name)) {
14608
+ case "MemberExpression": {
14609
+ const property = (0,external_api_cjs_namespaceObject.isLookupCandidate)(node);
14610
+ if (property) {
14611
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, property.name)) {
14067
14612
  if (lookupAndReplace(node)) {
14068
14613
  return false;
14069
14614
  }
14070
14615
  else {
14071
- state.exposed[node.property.name] = true;
14616
+ state.usedByName[property.name] = true;
14072
14617
  }
14073
14618
  }
14074
14619
  // Don't optimize the property.
14075
14620
  return ["object"];
14076
14621
  }
14077
14622
  break;
14623
+ }
14624
+ case "AssignmentExpression":
14625
+ case "UpdateExpression": {
14626
+ const lhs = node.type === "AssignmentExpression" ? node.left : node.argument;
14627
+ if (lhs.type === "Identifier") {
14628
+ const map = topLocals().map;
14629
+ if (map) {
14630
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(map, lhs.name)) {
14631
+ const name = map[lhs.name];
14632
+ if (typeof name === "string") {
14633
+ lhs.name = name;
14634
+ }
14635
+ }
14636
+ }
14637
+ }
14638
+ else if (lhs.type === "MemberExpression") {
14639
+ state.traverse(lhs.object);
14640
+ if (lhs.computed) {
14641
+ state.traverse(lhs.property);
14642
+ }
14643
+ }
14644
+ return node.type === "AssignmentExpression" ? ["right"] : [];
14645
+ }
14078
14646
  case "BlockStatement": {
14079
14647
  const map = topLocals().map;
14080
14648
  if (map) {
@@ -14090,7 +14658,11 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14090
14658
  node.params &&
14091
14659
  node.params.forEach((p) => (map[(0,external_api_cjs_namespaceObject.variableDeclarationName)(p)] = true));
14092
14660
  state.localsStack.push({ node, map });
14093
- const [parent] = state.stack.slice(-2);
14661
+ const [parent, self] = state.stack.slice(-2);
14662
+ if (state.currentFunction) {
14663
+ throw new Error(`Nested functions: ${self.fullName} was activated during processing of ${state.currentFunction.fullName}`);
14664
+ }
14665
+ state.currentFunction = self;
14094
14666
  if (parent.type == "ClassDeclaration" && !maybeCalled(node)) {
14095
14667
  let used = false;
14096
14668
  if (node.id.name == "initialize") {
@@ -14117,10 +14689,23 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14117
14689
  return replace(opt, node);
14118
14690
  }
14119
14691
  switch (node.type) {
14692
+ case "FunctionDeclaration":
14693
+ if (!state.currentFunction) {
14694
+ throw new Error(`Finished function ${state.stack.slice(-1)[0].fullName}, but it was not marked current`);
14695
+ }
14696
+ state.currentFunction.info = state.currentFunction.next_info;
14697
+ delete state.currentFunction.next_info;
14698
+ delete state.currentFunction;
14699
+ break;
14120
14700
  case "BlockStatement":
14121
14701
  if (node.body.length === 1 && node.body[0].type === "BlockStatement") {
14122
14702
  node.body.splice(0, 1, ...node.body[0].body);
14123
14703
  }
14704
+ // fall through
14705
+ case "ForStatement":
14706
+ if (locals.map) {
14707
+ cleanupUnusedVars(state, node);
14708
+ }
14124
14709
  break;
14125
14710
  case "ConditionalExpression":
14126
14711
  case "IfStatement":
@@ -14153,17 +14738,20 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14153
14738
  return replace(optimizeCall(state, node.argument, node), node.argument);
14154
14739
  }
14155
14740
  break;
14741
+ case "NewExpression":
14742
+ if (state.currentFunction) {
14743
+ const [, results] = state.lookup(node.callee);
14744
+ if (results) {
14745
+ recordCalledFuncs(state.currentFunction, findCalleesForNew(results));
14746
+ }
14747
+ else {
14748
+ recordModifiedUnknown(state.currentFunction);
14749
+ }
14750
+ }
14751
+ break;
14156
14752
  case "CallExpression": {
14157
14753
  return replace(optimizeCall(state, node, null), node);
14158
14754
  }
14159
- case "AssignmentExpression":
14160
- if (node.operator === "=" &&
14161
- node.left.type === "Identifier" &&
14162
- node.right.type === "Identifier" &&
14163
- node.left.name === node.right.name) {
14164
- return { type: "Literal", value: null, raw: "null" };
14165
- }
14166
- break;
14167
14755
  case "VariableDeclaration": {
14168
14756
  const locals = topLocals();
14169
14757
  if (locals.map &&
@@ -14237,6 +14825,32 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14237
14825
  }
14238
14826
  }
14239
14827
  break;
14828
+ case "AssignmentExpression":
14829
+ if (node.operator === "=" &&
14830
+ node.left.type === "Identifier" &&
14831
+ node.right.type === "Identifier" &&
14832
+ node.left.name === node.right.name) {
14833
+ return { type: "Literal", value: null, raw: "null" };
14834
+ }
14835
+ // fall through;
14836
+ case "UpdateExpression":
14837
+ if (state.currentFunction) {
14838
+ const lhs = node.type === "AssignmentExpression" ? node.left : node.argument;
14839
+ const [, results] = state.lookup(lhs);
14840
+ if (results) {
14841
+ recordModifiedDecls(state.currentFunction, results);
14842
+ }
14843
+ else {
14844
+ const id = lhs.type === "Identifier" ? lhs : (0,external_api_cjs_namespaceObject.isLookupCandidate)(lhs);
14845
+ if (id) {
14846
+ recordModifiedName(state.currentFunction, id.name);
14847
+ }
14848
+ else {
14849
+ recordModifiedUnknown(state.currentFunction);
14850
+ }
14851
+ }
14852
+ }
14853
+ break;
14240
14854
  }
14241
14855
  return null;
14242
14856
  };
@@ -14244,13 +14858,16 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14244
14858
  (0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
14245
14859
  });
14246
14860
  state.calledFunctions = {};
14247
- state.exposed = {};
14861
+ state.exposed = state.nextExposed;
14862
+ state.nextExposed = {};
14248
14863
  Object.values(fnMap).forEach((f) => {
14249
14864
  (0,external_api_cjs_namespaceObject.collectNamespaces)(f.ast, state);
14250
14865
  });
14866
+ state.exposed = state.nextExposed;
14867
+ state.nextExposed = {};
14251
14868
  delete state.pre;
14252
14869
  delete state.post;
14253
- state.allFunctions.forEach((fn) => sizeBasedPRE(state, fn));
14870
+ Object.values(state.allFunctions).forEach((fns) => fns.forEach((fn) => sizeBasedPRE(state, fn)));
14254
14871
  const cleanup = (node) => {
14255
14872
  switch (node.type) {
14256
14873
  case "ThisExpression":
@@ -14260,7 +14877,8 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14260
14877
  if (node.members.every((m) => {
14261
14878
  const name = "name" in m ? m.name : m.id.name;
14262
14879
  return ((0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) &&
14263
- !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
14880
+ !(0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name) &&
14881
+ !(0,external_api_cjs_namespaceObject.hasProperty)(state.usedByName, name));
14264
14882
  })) {
14265
14883
  node.enumType = [
14266
14884
  ...new Set(node.members.map((m) => {
@@ -14303,7 +14921,9 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14303
14921
  case "VariableDeclaration": {
14304
14922
  node.declarations = node.declarations.filter((d) => {
14305
14923
  const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(d.id);
14306
- return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) || (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name));
14924
+ return (!(0,external_api_cjs_namespaceObject.hasProperty)(state.index, name) ||
14925
+ (0,external_api_cjs_namespaceObject.hasProperty)(state.exposed, name) ||
14926
+ (0,external_api_cjs_namespaceObject.hasProperty)(state.usedByName, name));
14307
14927
  });
14308
14928
  if (!node.declarations.length) {
14309
14929
  return false;
@@ -14336,7 +14956,7 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14336
14956
  }
14337
14957
  return null;
14338
14958
  };
14339
- Object.values(fnMap).forEach((f) => {
14959
+ Object.entries(fnMap).forEach(([name, f]) => {
14340
14960
  traverseAst(f.ast, undefined, (node) => {
14341
14961
  const ret = cleanup(node);
14342
14962
  if (ret === false) {
@@ -14344,16 +14964,15 @@ async function optimizeMonkeyC(fnMap, barrelList, config) {
14344
14964
  }
14345
14965
  return ret;
14346
14966
  });
14967
+ if (state.config && state.config.checkBuildPragmas) {
14968
+ pragmaChecker(state, f.ast, state.diagnostics?.[name]);
14969
+ }
14347
14970
  });
14348
14971
  return state.diagnostics;
14349
14972
  }
14350
14973
  function optimizeCall(state, node, context) {
14351
14974
  const [name, results] = state.lookupNonlocal(node.callee);
14352
- const callees = results &&
14353
- results
14354
- .map((r) => r.results)
14355
- .flat()
14356
- .filter((c) => c.type === "FunctionDeclaration");
14975
+ const callees = results ? findCallees(results) : null;
14357
14976
  if (!callees || !callees.length) {
14358
14977
  const n = name ||
14359
14978
  ("name" in node.callee && node.callee.name) ||
@@ -14362,14 +14981,24 @@ function optimizeCall(state, node, context) {
14362
14981
  "name" in node.callee.property &&
14363
14982
  node.callee.property.name);
14364
14983
  if (n) {
14365
- state.exposed[n] = true;
14984
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(state.allFunctions, n)) {
14985
+ if (state.currentFunction) {
14986
+ recordCalledFuncs(state.currentFunction, state.allFunctions[n]);
14987
+ }
14988
+ state.allFunctions[n].forEach((fn) => markFunctionCalled(state, fn.node));
14989
+ }
14366
14990
  }
14367
- else {
14368
- // There are unnamed CallExpressions, such as new [size]
14369
- // So there's nothing to do here.
14991
+ else if (state.currentFunction) {
14992
+ // I don't think this can happen: foo[x](args)
14993
+ // doesn't parse, so you can't even do things like
14994
+ // $.Toybox.Lang[:format]("fmt", [])
14995
+ recordModifiedUnknown(state.currentFunction);
14370
14996
  }
14371
14997
  return null;
14372
14998
  }
14999
+ if (state.currentFunction) {
15000
+ recordCalledFuncs(state.currentFunction, callees);
15001
+ }
14373
15002
  if (callees.length == 1 && callees[0].type === "FunctionDeclaration") {
14374
15003
  const callee = callees[0].node;
14375
15004
  if (!context &&
@@ -14392,120 +15021,6 @@ function optimizeCall(state, node, context) {
14392
15021
  return null;
14393
15022
  }
14394
15023
 
14395
- ;// CONCATENATED MODULE: ./src/pragma-checker.ts
14396
-
14397
-
14398
- function pragmaChecker(ast, diagnostics) {
14399
- const comments = ast.comments;
14400
- if (!comments)
14401
- return;
14402
- diagnostics = diagnostics
14403
- ?.slice()
14404
- .sort((d1, d2) => d1.loc.start < d2.loc.start ? -1 : d1.loc.start == d2.loc.start ? 0 : 1);
14405
- let diagIndex = 0;
14406
- let index = -1;
14407
- let comment;
14408
- let matchers;
14409
- const next = () => {
14410
- while (++index < comments.length) {
14411
- comment = comments[index];
14412
- let match = comment.value.match(/^\s*@(match|expect)\s+(.+)/);
14413
- if (!match)
14414
- continue;
14415
- const kind = match[1];
14416
- let str = match[2];
14417
- matchers = [];
14418
- while ((match = str.match(/^([/%&#@"])(.+?(?<!\\)(?:\\{2})*)\1(\s+|$)/))) {
14419
- matchers.push({ kind, quote: match[1], needle: match[2] });
14420
- str = str.substring(match[0].length);
14421
- if (!str.length)
14422
- break;
14423
- }
14424
- if (!str.length)
14425
- break;
14426
- if (!matchers.length) {
14427
- match = str.match(/^(\S+)\s+$/);
14428
- if (match) {
14429
- matchers.push({ kind, quote: '"', needle: match[1] });
14430
- break;
14431
- }
14432
- }
14433
- throw new Error(`Build pragma '${comment.value}' is invalid. In ${comment.loc.source}:${comment.loc.start.line}`);
14434
- }
14435
- };
14436
- const matcher = (quote, needle, haystack) => {
14437
- if (quote == '"') {
14438
- return haystack.includes(needle);
14439
- }
14440
- const re = new RegExp(needle.replace(/@(\d+)/g, "(pre_)?$1(_\\d+)?"));
14441
- return re.test(haystack);
14442
- };
14443
- next();
14444
- traverseAst(ast, (node) => {
14445
- if (index >= comments.length)
14446
- return false;
14447
- if (node.start && node.start >= (comment.end || Infinity)) {
14448
- const { kind, quote, needle } = matchers.shift();
14449
- if (kind === "match") {
14450
- const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/([\r\n]|\s)+/g, " ");
14451
- if (!matcher(quote, needle, haystack)) {
14452
- matcher(quote, needle, haystack);
14453
- throw new Error(`Didn't find '${needle}' in '${haystack}' at ${comment.loc.source}:${comment.loc.start.line}`);
14454
- }
14455
- }
14456
- else if (kind === "expect") {
14457
- const locCmp = (a, b) => {
14458
- if (!b)
14459
- return -1;
14460
- if (a.start.line < b.start.line)
14461
- return -1;
14462
- if (a.start.line === b.start.line &&
14463
- a.start.column < b.start.column) {
14464
- return -1;
14465
- }
14466
- if (a.end.line > b.end.line)
14467
- return 1;
14468
- if (a.end.line === b.end.line && a.end.column >= b.end.column) {
14469
- return 1;
14470
- }
14471
- return 0;
14472
- };
14473
- let found = false;
14474
- if (diagnostics) {
14475
- while (true) {
14476
- if (diagIndex >= diagnostics.length) {
14477
- diagnostics = null;
14478
- break;
14479
- }
14480
- const diag = diagnostics[diagIndex];
14481
- const cmp = locCmp(diag.loc, node.loc);
14482
- if (cmp > 0) {
14483
- break;
14484
- }
14485
- diagIndex++;
14486
- if (cmp < 0)
14487
- continue;
14488
- if (matcher(quote, needle, diag.message)) {
14489
- found = true;
14490
- diag.type = "INFO";
14491
- }
14492
- }
14493
- }
14494
- if (!found) {
14495
- throw new Error(`Missing error message '${needle} at ${comment.loc.source}:${comment.loc.start.line}`);
14496
- }
14497
- }
14498
- if (matchers.length) {
14499
- // if we're checking a series of nodes, we need
14500
- // to skip over this one.
14501
- return false;
14502
- }
14503
- next();
14504
- }
14505
- return null;
14506
- });
14507
- }
14508
-
14509
15024
  ;// CONCATENATED MODULE: ./src/optimizer.ts
14510
15025
 
14511
15026
 
@@ -14943,22 +15458,19 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
14943
15458
  // the oldest optimized file, we don't need to regenerate
14944
15459
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
14945
15460
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
14946
- if (source_time < opt_time && 1656860602542 < opt_time) {
15461
+ if (source_time < opt_time && 1657670997056 < opt_time) {
14947
15462
  return { hasTests, diagnostics: prevDiagnostics };
14948
15463
  }
14949
15464
  }
14950
15465
  await promises_namespaceObject.rm(output, { recursive: true, force: true });
14951
15466
  await promises_namespaceObject.mkdir(output, { recursive: true });
14952
15467
  const diagnostics = await optimizeMonkeyC(fnMap, Object.keys(buildConfig.barrelMap || {}), config);
14953
- return Promise.all(Object.entries(fnMap).map(async ([inFile, info]) => {
15468
+ return Promise.all(Object.values(fnMap).map(async (info) => {
14954
15469
  const name = info.output;
14955
15470
  const dir = external_path_.dirname(name);
14956
15471
  await promises_namespaceObject.mkdir(dir, { recursive: true });
14957
15472
  const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
14958
15473
  await promises_namespaceObject.writeFile(name, opt_source);
14959
- if (config.checkBuildPragmas) {
14960
- pragmaChecker(info.ast, diagnostics?.[inFile]);
14961
- }
14962
15474
  return info.hasTests;
14963
15475
  })).then((results) => {
14964
15476
  const hasTests = results.some((v) => v);