@markw65/monkeyc-optimizer 1.0.16 → 1.0.17

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.
@@ -1,4 +1,4 @@
1
- 0 && (module.exports = {copyRecursiveAsNeeded,get_jungle,launchSimulator,manifestProducts,mctree,simulateProgram,defaultConfig,isErrorWithLocation,buildOptimizedProject,generateOptimizedProject,getProjectAnalysis,generateApiMirTests});
1
+ 0 && (module.exports = {buildOptimizedProject,copyRecursiveAsNeeded,defaultConfig,generateApiMirTests,generateOptimizedProject,getProjectAnalysis,get_jungle,isErrorWithLocation,launchSimulator,manifestProducts,mctree,simulateProgram});
2
2
  /******/ (() => { // webpackBootstrap
3
3
  /******/ var __webpack_modules__ = ({
4
4
 
@@ -10791,11 +10791,67 @@ function simulateProgram(prg, device, test) {
10791
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(() => { }));
10792
10792
  }
10793
10793
 
10794
+ ;// CONCATENATED MODULE: ./src/variable-renamer.ts
10795
+
10796
+ function renameVariable(state, locals, declName) {
10797
+ const map = locals.map;
10798
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(map, declName))
10799
+ return null;
10800
+ let suffix = 0;
10801
+ let node_name = declName;
10802
+ const match = node_name.match(/^pmcr_(.*)_(\d+)$/);
10803
+ if (match) {
10804
+ node_name = match[1];
10805
+ suffix = parseInt(match[2], 10) + 1;
10806
+ }
10807
+ if (!locals.inners) {
10808
+ // find all the names declared in this scope, to avoid
10809
+ // more conflicts
10810
+ locals.inners = {};
10811
+ const inners = locals.inners;
10812
+ (0,external_api_cjs_namespaceObject.traverseAst)(locals.node, (node) => {
10813
+ if (node.type === "VariableDeclarator") {
10814
+ inners[(0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id)] = true;
10815
+ }
10816
+ });
10817
+ }
10818
+ let name;
10819
+ while (true) {
10820
+ name = `pmcr_${node_name}_${suffix}`;
10821
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(map, name) && !(0,external_api_cjs_namespaceObject.hasProperty)(locals.inners, name)) {
10822
+ // we also need to ensure that we don't hide the name of
10823
+ // an outer module, class, function, enum or variable,
10824
+ // since someone might want to access it from this scope.
10825
+ let ok = false;
10826
+ let i;
10827
+ for (i = state.stack.length; i--;) {
10828
+ const elm = state.stack[i];
10829
+ if (ok) {
10830
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(elm.decls, name)) {
10831
+ break;
10832
+ }
10833
+ }
10834
+ else if (elm.node && elm.node.type === "FunctionDeclaration") {
10835
+ ok = true;
10836
+ }
10837
+ }
10838
+ if (i < 0) {
10839
+ break;
10840
+ }
10841
+ }
10842
+ suffix++;
10843
+ }
10844
+ map[declName] = name;
10845
+ map[name] = true;
10846
+ return name;
10847
+ }
10848
+
10794
10849
  ;// CONCATENATED MODULE: ./src/inliner.ts
10795
10850
 
10796
- function canInline(state, func, args) {
10851
+
10852
+ function getArgSafety(state, func, args, requireAll) {
10797
10853
  // determine whether decl might be changed by a function call
10798
- // during the evaluation of FunctionStateNode.
10854
+ // or assignment during the evaluation of FunctionStateNode.
10799
10855
  const getSafety = (decl) => {
10800
10856
  // enums are constant, they cant change
10801
10857
  if (decl.type === "EnumStringMember")
@@ -10825,18 +10881,24 @@ function canInline(state, func, args) {
10825
10881
  case "Identifier":
10826
10882
  case "MemberExpression": {
10827
10883
  const [, results] = state.lookup(arg);
10828
- if (!results || results.length !== 1)
10829
- return false;
10884
+ if (!results || results.length !== 1) {
10885
+ safeArgs.push(null);
10886
+ return !requireAll;
10887
+ }
10830
10888
  const safety = getSafety(results[0]);
10831
- if (safety === null)
10832
- return false;
10833
- if (!safety)
10834
- allSafe = false;
10835
10889
  safeArgs.push(safety);
10890
+ if (!safety) {
10891
+ allSafe = false;
10892
+ if (safety === null) {
10893
+ return !requireAll;
10894
+ }
10895
+ }
10836
10896
  return true;
10837
10897
  }
10838
10898
  }
10839
- return false;
10899
+ allSafe = false;
10900
+ safeArgs.push(null);
10901
+ return !requireAll;
10840
10902
  })) {
10841
10903
  return false;
10842
10904
  }
@@ -10865,17 +10927,26 @@ function canInline(state, func, args) {
10865
10927
  switch (node.type) {
10866
10928
  case "CallExpression":
10867
10929
  case "NewExpression":
10930
+ case "AssignmentExpression":
10931
+ case "UpdateExpression":
10868
10932
  callSeen = true;
10869
10933
  break;
10870
10934
  case "Identifier":
10871
10935
  if (callSeen &&
10872
10936
  (0,external_api_cjs_namespaceObject.hasProperty)(params, node.name) &&
10873
10937
  !safeArgs[params[node.name]]) {
10874
- ok = false;
10938
+ safeArgs[params[node.name]] = null;
10875
10939
  }
10876
10940
  }
10877
10941
  });
10878
- return ok;
10942
+ return safeArgs;
10943
+ }
10944
+ function canInline(state, func, args) {
10945
+ const safeArgs = getArgSafety(state, func, args, true);
10946
+ if (safeArgs === true || safeArgs === false) {
10947
+ return safeArgs;
10948
+ }
10949
+ return safeArgs.every((arg) => arg !== null);
10879
10950
  }
10880
10951
  function inliningLooksUseful(func, node) {
10881
10952
  while (true) {
@@ -10900,68 +10971,114 @@ function inliningLooksUseful(func, node) {
10900
10971
  }
10901
10972
  return false;
10902
10973
  }
10974
+ var InlineStatus;
10975
+ (function (InlineStatus) {
10976
+ InlineStatus[InlineStatus["Never"] = 0] = "Never";
10977
+ InlineStatus[InlineStatus["AsExpression"] = 1] = "AsExpression";
10978
+ InlineStatus[InlineStatus["AsStatement"] = 2] = "AsStatement";
10979
+ })(InlineStatus || (InlineStatus = {}));
10903
10980
  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;
10981
+ let autoInline = false;
10982
+ let inlineAsExpression = false;
10983
+ if (func.node.body &&
10984
+ func.node.body.body.length === 1 &&
10985
+ func.node.body.body[0].type === "ReturnStatement" &&
10986
+ func.node.body.body[0].argument &&
10987
+ func.node.params.length === args.length) {
10988
+ inlineAsExpression = true;
10989
+ autoInline = inliningLooksUseful(func.node, func.node.body.body[0].argument);
10990
+ }
10991
+ if (autoInline === 1) {
10992
+ return InlineStatus.AsExpression;
10910
10993
  }
10911
- const autoInline = inliningLooksUseful(func.node, func.node.body.body[0].argument);
10912
10994
  const excludeAnnotations = (func.node.loc?.source &&
10913
- state.fnMap[func.node.loc?.source].excludeAnnotations) ||
10995
+ state.fnMap[func.node.loc?.source]?.excludeAnnotations) ||
10914
10996
  {};
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]));
10997
+ const inlineRequested = func.node.attrs &&
10998
+ func.node.attrs.attrs &&
10999
+ func.node.attrs.attrs.some((attr) => attr.type === "UnaryExpression" &&
11000
+ (attr.argument.name === "inline" ||
11001
+ (attr.argument.name.startsWith("inline_") &&
11002
+ (0,external_api_cjs_namespaceObject.hasProperty)(excludeAnnotations, attr.argument.name.substring(7)))));
11003
+ if (autoInline || inlineRequested) {
11004
+ return inlineAsExpression && canInline(state, func, args)
11005
+ ? InlineStatus.AsExpression
11006
+ : InlineStatus.AsStatement;
11007
+ }
11008
+ return InlineStatus.Never;
11009
+ }
11010
+ function processInlineBody(state, func, call, root, insertedVariableDecls, params) {
11011
+ if (!params) {
11012
+ const safeArgs = getArgSafety(state, func, call.arguments, false);
11013
+ params = Object.fromEntries(func.node.params.map((param, i) => {
11014
+ const argnum = safeArgs === true || (safeArgs !== false && safeArgs[i] !== null)
11015
+ ? i
11016
+ : -1;
11017
+ const name = (0,external_api_cjs_namespaceObject.variableDeclarationName)(param);
11018
+ return [name, argnum];
11019
+ }));
11020
+ }
11021
+ const pre = state.pre;
11022
+ const post = state.post;
10927
11023
  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
- }
11024
+ state.pre = (node) => {
11025
+ node.start = call.start;
11026
+ node.end = call.end;
11027
+ node.loc = call.loc;
11028
+ if (node === insertedVariableDecls)
11029
+ return false;
11030
+ const result = pre(node, state);
11031
+ if (!insertedVariableDecls && node.type === "BlockStatement") {
11032
+ const locals = state.localsStack[state.localsStack.length - 1];
11033
+ const { map } = locals;
11034
+ if (!map)
11035
+ throw new Error("No local variable map!");
11036
+ const declarations = func.node.params
11037
+ .map((param, i) => {
11038
+ const paramName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(param);
11039
+ if (params[paramName] >= 0)
11040
+ return null;
11041
+ const name = renameVariable(state, locals, paramName) || paramName;
11042
+ return {
11043
+ type: "VariableDeclarator",
11044
+ id: { type: "Identifier", name },
11045
+ kind: "var",
11046
+ init: call.arguments[i],
11047
+ };
11048
+ })
11049
+ .filter((n) => n != null);
11050
+ insertedVariableDecls = {
11051
+ type: "VariableDeclaration",
11052
+ declarations,
11053
+ kind: "var",
11054
+ };
11055
+ node.body.unshift(insertedVariableDecls);
10944
11056
  }
10945
- return null;
10946
- }, (node) => {
11057
+ return result;
11058
+ };
11059
+ state.post = (node) => {
11060
+ let replacement = null;
10947
11061
  switch (node.type) {
10948
11062
  case "Identifier": {
11063
+ if (state.inType)
11064
+ break;
10949
11065
  if ((0,external_api_cjs_namespaceObject.hasProperty)(params, node.name)) {
10950
- return call.arguments[params[node.name]];
11066
+ const ix = params[node.name];
11067
+ if (ix >= 0) {
11068
+ replacement = call.arguments[ix];
11069
+ }
11070
+ break;
10951
11071
  }
10952
- const rep = fixNodeScope(state, node, func.stack);
10953
- if (!rep) {
11072
+ replacement = fixNodeScope(state, node, func.stack);
11073
+ if (!replacement) {
10954
11074
  throw new Error(`Inliner: Couldn't fix the scope of '${node.name}`);
10955
11075
  }
10956
- return rep;
11076
+ break;
10957
11077
  }
10958
11078
  }
10959
- return null;
10960
- }) || retArg;
10961
- result.loc = call.loc;
10962
- result.start = call.start;
10963
- result.end = call.end;
10964
- return result;
11079
+ return post(replacement || node, state) || replacement;
11080
+ };
11081
+ return state.traverse(root) || null;
10965
11082
  }
10966
11083
  catch (ex) {
10967
11084
  if (ex instanceof Error) {
@@ -10971,6 +11088,75 @@ function inlineFunction(state, func, call) {
10971
11088
  }
10972
11089
  throw ex;
10973
11090
  }
11091
+ finally {
11092
+ state.pre = pre;
11093
+ state.post = post;
11094
+ }
11095
+ }
11096
+ function unused(expression, top) {
11097
+ switch (expression.type) {
11098
+ case "Literal":
11099
+ return [];
11100
+ case "Identifier":
11101
+ return [];
11102
+ case "BinaryExpression":
11103
+ if (expression.operator === "as") {
11104
+ return unused(expression.left);
11105
+ }
11106
+ // fall through
11107
+ case "LogicalExpression":
11108
+ return unused(expression.left).concat(unused(expression.right));
11109
+ case "UnaryExpression":
11110
+ return unused(expression.argument);
11111
+ case "MemberExpression":
11112
+ return unused(expression.object).concat(unused(expression.property));
11113
+ }
11114
+ return top
11115
+ ? null
11116
+ : [
11117
+ {
11118
+ type: "ExpressionStatement",
11119
+ expression,
11120
+ },
11121
+ ];
11122
+ }
11123
+ function inlineWithArgs(state, func, call) {
11124
+ if (!func.node || !func.node.body) {
11125
+ return null;
11126
+ }
11127
+ let retStmtCount = 0;
11128
+ (0,external_api_cjs_namespaceObject.traverseAst)(func.node.body, (node) => {
11129
+ node.type === "ReturnStatement" && retStmtCount++;
11130
+ });
11131
+ if (retStmtCount > 1 ||
11132
+ (retStmtCount === 1 &&
11133
+ func.node.body.body.slice(-1)[0].type !== "ReturnStatement")) {
11134
+ return null;
11135
+ }
11136
+ const body = JSON.parse(JSON.stringify(func.node.body));
11137
+ processInlineBody(state, func, call, body, func.node.params.length ? false : true);
11138
+ if (retStmtCount) {
11139
+ const last = body.body[body.body.length - 1];
11140
+ if (last.type != "ReturnStatement") {
11141
+ throw new Error("ReturnStatement got lost!");
11142
+ }
11143
+ if (last.argument) {
11144
+ const side_exprs = unused(last.argument);
11145
+ body.body.splice(body.body.length - 1, 1, ...side_exprs);
11146
+ }
11147
+ else {
11148
+ --body.body.length;
11149
+ }
11150
+ }
11151
+ return body;
11152
+ }
11153
+ function inlineFunction(state, func, call, inlineStatus) {
11154
+ if (inlineStatus == InlineStatus.AsStatement) {
11155
+ return inlineWithArgs(state, func, call);
11156
+ }
11157
+ const retArg = JSON.parse(JSON.stringify(func.node.body.body[0].argument));
11158
+ const params = Object.fromEntries(func.node.params.map((param, i) => [(0,external_api_cjs_namespaceObject.variableDeclarationName)(param), i]));
11159
+ return processInlineBody(state, func, call, retArg, true, params) || retArg;
10974
11160
  }
10975
11161
  function applyTypeIfNeeded(node) {
10976
11162
  if ("enumType" in node && node.enumType) {
@@ -10984,6 +11170,16 @@ function applyTypeIfNeeded(node) {
10984
11170
  return node;
10985
11171
  }
10986
11172
  function fixNodeScope(state, lookupNode, nodeStack) {
11173
+ if (lookupNode.type === "Identifier") {
11174
+ for (let i = state.stack.length; --i > nodeStack.length;) {
11175
+ const si = state.stack[i];
11176
+ if ((0,external_api_cjs_namespaceObject.hasProperty)(si.decls, lookupNode.name)) {
11177
+ // its a local from the inlined function.
11178
+ // Nothing to do.
11179
+ return lookupNode;
11180
+ }
11181
+ }
11182
+ }
10987
11183
  const [, original] = state.lookup(lookupNode, null, nodeStack);
10988
11184
  if (!original) {
10989
11185
  return null;
@@ -11067,6 +11263,7 @@ function fixNodeScope(state, lookupNode, nodeStack) {
11067
11263
 
11068
11264
 
11069
11265
 
11266
+
11070
11267
  function processImports(allImports, lookup) {
11071
11268
  allImports.forEach(({ node, stack }) => {
11072
11269
  const [name, module] = lookup(node.id, ("as" in node && node.as && node.as.name) || null, stack);
@@ -11080,10 +11277,13 @@ function processImports(allImports, lookup) {
11080
11277
  module.forEach((m) => {
11081
11278
  if ((0,external_api_cjs_namespaceObject.isStateNode)(m) && m.type == "ModuleDeclaration") {
11082
11279
  (0,external_util_cjs_namespaceObject.pushUnique)(decls[name], m);
11280
+ if (!parent.type_decls)
11281
+ parent.type_decls = {};
11282
+ const tdecls = parent.type_decls;
11283
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
11284
+ tdecls[name] = [];
11285
+ (0,external_util_cjs_namespaceObject.pushUnique)(tdecls[name], m);
11083
11286
  if (node.type == "ImportModule" && m.type_decls) {
11084
- if (!parent.type_decls)
11085
- parent.type_decls = {};
11086
- const tdecls = parent.type_decls;
11087
11287
  Object.entries(m.type_decls).forEach(([name, decls]) => {
11088
11288
  if (!(0,external_api_cjs_namespaceObject.hasProperty)(tdecls, name))
11089
11289
  tdecls[name] = [];
@@ -11624,57 +11824,8 @@ async function optimizeMonkeyC(fnMap) {
11624
11824
  const { map } = locals;
11625
11825
  if (map) {
11626
11826
  const declName = (0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id);
11627
- if ((0,external_api_cjs_namespaceObject.hasProperty)(map, declName)) {
11628
- // We already have a variable with this name in scope
11629
- // Recent monkeyc compilers complain, so rename it
11630
- let suffix = 0;
11631
- let node_name = declName;
11632
- const match = node_name.match(/^pmcr_(.*)_(\d+)$/);
11633
- if (match) {
11634
- node_name = match[1];
11635
- suffix = parseInt(match[2], 10) + 1;
11636
- }
11637
- if (!locals.inners) {
11638
- // find all the names declared in this scope, to avoid
11639
- // more conflicts
11640
- locals.inners = {};
11641
- const inners = locals.inners;
11642
- (0,external_api_cjs_namespaceObject.traverseAst)(locals.node, (node) => {
11643
- if (node.type === "VariableDeclarator") {
11644
- inners[(0,external_api_cjs_namespaceObject.variableDeclarationName)(node.id)] = true;
11645
- }
11646
- });
11647
- }
11648
- let name;
11649
- while (true) {
11650
- name = `pmcr_${node_name}_${suffix}`;
11651
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(map, name) &&
11652
- !(0,external_api_cjs_namespaceObject.hasProperty)(locals.inners, name)) {
11653
- // we also need to ensure that we don't hide the name of
11654
- // an outer module, class, function, enum or variable,
11655
- // since someone might want to access it from this scope.
11656
- let ok = false;
11657
- let i;
11658
- for (i = state.stack.length; i--;) {
11659
- const elm = state.stack[i];
11660
- if (ok) {
11661
- if ((0,external_api_cjs_namespaceObject.hasProperty)(elm.decls, name)) {
11662
- break;
11663
- }
11664
- }
11665
- else if (elm.node &&
11666
- elm.node.type === "FunctionDeclaration") {
11667
- ok = true;
11668
- }
11669
- }
11670
- if (i < 0) {
11671
- break;
11672
- }
11673
- }
11674
- suffix++;
11675
- }
11676
- map[declName] = name;
11677
- map[name] = true;
11827
+ const name = renameVariable(state, locals, declName);
11828
+ if (name) {
11678
11829
  if (node.id.type === "Identifier") {
11679
11830
  node.id.name = name;
11680
11831
  }
@@ -11698,7 +11849,7 @@ async function optimizeMonkeyC(fnMap) {
11698
11849
  state.exposed[node.argument.name] = true;
11699
11850
  // In any case, we can't replace *this* use of the
11700
11851
  // symbol with its value...
11701
- return false;
11852
+ return [];
11702
11853
  }
11703
11854
  break;
11704
11855
  case "Identifier": {
@@ -11716,7 +11867,7 @@ async function optimizeMonkeyC(fnMap) {
11716
11867
  state.exposed[node.name] = true;
11717
11868
  }
11718
11869
  }
11719
- return false;
11870
+ return [];
11720
11871
  }
11721
11872
  case "MemberExpression":
11722
11873
  if (node.property.type === "Identifier" && !node.computed) {
@@ -11798,48 +11949,29 @@ async function optimizeMonkeyC(fnMap) {
11798
11949
  }
11799
11950
  break;
11800
11951
  case "CallExpression": {
11801
- const [name, callees] = state.lookup(node.callee);
11802
- if (!callees || !callees.length) {
11803
- const n = name ||
11804
- ("name" in node.callee && node.callee.name) ||
11805
- ("property" in node.callee &&
11806
- node.callee.property &&
11807
- "name" in node.callee.property &&
11808
- node.callee.property.name);
11809
- if (n) {
11810
- state.exposed[n] = true;
11811
- }
11812
- else {
11813
- // There are unnamed CallExpressions, such as new [size]
11814
- // So there's nothing to do here.
11815
- }
11816
- return null;
11952
+ const ret = optimizeCall(state, node, false);
11953
+ if (ret) {
11954
+ replace(node, ret);
11817
11955
  }
11818
- if (callees.length == 1 && callees[0].type === "FunctionDeclaration") {
11819
- const callee = callees[0].node;
11820
- if (callee.optimizable &&
11821
- !callee.hasOverride &&
11822
- node.arguments.every((n) => getNodeValue(n)[0] !== null)) {
11823
- const ret = evaluateFunction(callee, node.arguments);
11824
- if (ret) {
11825
- replace(node, ret);
11826
- return null;
11827
- }
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;
11956
+ break;
11957
+ }
11958
+ case "ExpressionStatement":
11959
+ if (node.expression.type === "CallExpression") {
11960
+ const ret = optimizeCall(state, node.expression, true);
11961
+ if (ret) {
11962
+ if (ret.type === "BlockStatement") {
11963
+ return ret;
11834
11964
  }
11965
+ node.expression = ret;
11835
11966
  }
11836
11967
  }
11837
- if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.calledFunctions, name)) {
11838
- state.calledFunctions[name] = [];
11968
+ else {
11969
+ const ret = unused(node.expression, true);
11970
+ if (ret) {
11971
+ return ret;
11972
+ }
11839
11973
  }
11840
- callees.forEach((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && state.calledFunctions[name].push(c.node));
11841
11974
  break;
11842
- }
11843
11975
  }
11844
11976
  return null;
11845
11977
  };
@@ -11922,6 +12054,98 @@ async function optimizeMonkeyC(fnMap) {
11922
12054
  });
11923
12055
  });
11924
12056
  }
12057
+ function optimizeCall(state, node, asStatement) {
12058
+ const [name, callees] = state.lookup(node.callee);
12059
+ if (!callees || !callees.length) {
12060
+ const n = name ||
12061
+ ("name" in node.callee && node.callee.name) ||
12062
+ ("property" in node.callee &&
12063
+ node.callee.property &&
12064
+ "name" in node.callee.property &&
12065
+ node.callee.property.name);
12066
+ if (n) {
12067
+ state.exposed[n] = true;
12068
+ }
12069
+ else {
12070
+ // There are unnamed CallExpressions, such as new [size]
12071
+ // So there's nothing to do here.
12072
+ }
12073
+ return null;
12074
+ }
12075
+ if (callees.length == 1 && callees[0].type === "FunctionDeclaration") {
12076
+ const callee = callees[0].node;
12077
+ if (callee.optimizable &&
12078
+ !callee.hasOverride &&
12079
+ node.arguments.every((n) => getNodeValue(n)[0] !== null)) {
12080
+ const ret = evaluateFunction(callee, node.arguments);
12081
+ if (ret) {
12082
+ return ret;
12083
+ }
12084
+ }
12085
+ const inlineStatus = shouldInline(state, callees[0], node.arguments);
12086
+ if (inlineStatus === InlineStatus.AsExpression ||
12087
+ (asStatement && inlineStatus === InlineStatus.AsStatement)) {
12088
+ const ret = inlineFunction(state, callees[0], node, inlineStatus);
12089
+ if (ret) {
12090
+ return ret;
12091
+ }
12092
+ }
12093
+ }
12094
+ if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.calledFunctions, name)) {
12095
+ state.calledFunctions[name] = [];
12096
+ }
12097
+ callees.forEach((c) => (0,external_api_cjs_namespaceObject.isStateNode)(c) && state.calledFunctions[name].push(c.node));
12098
+ return null;
12099
+ }
12100
+
12101
+ ;// CONCATENATED MODULE: ./src/pragma-checker.ts
12102
+
12103
+ function pragmaChecker(ast) {
12104
+ const comments = ast.comments;
12105
+ if (!comments)
12106
+ return;
12107
+ let index = -1;
12108
+ let comment;
12109
+ const next = () => {
12110
+ while (++index < comments.length) {
12111
+ comment = comments[index];
12112
+ if (comment.value.match(/^\s*@match\s+/)) {
12113
+ break;
12114
+ }
12115
+ }
12116
+ };
12117
+ next();
12118
+ (0,external_api_cjs_namespaceObject.traverseAst)(ast, (node) => {
12119
+ if (index >= comments.length)
12120
+ return false;
12121
+ if (node.start && node.start >= (comment.end || Infinity)) {
12122
+ let match = comment.value.match(/^\s*@match\s+([/%&#@"])(.+(?<!\\)(?:\\{2})*)\1\s+$/) || comment.value.match(/^\s*@match\s+(\S+)\s+$/);
12123
+ if (!match) {
12124
+ throw new Error(`Build pragma '${comment.value}' is invalid. In ${comment.loc.source}:${comment.loc.start.line}`);
12125
+ }
12126
+ const haystack = (0,external_api_cjs_namespaceObject.formatAst)(node).replace(/[\r\n]/g, " ");
12127
+ let found = false;
12128
+ let needle = match[1];
12129
+ if (match.length == 2) {
12130
+ found = haystack.includes(needle);
12131
+ }
12132
+ else {
12133
+ if (needle == '"') {
12134
+ found = haystack.includes((needle = match[2]));
12135
+ }
12136
+ else {
12137
+ const re = new RegExp((needle = match[2]));
12138
+ found = re.test(haystack);
12139
+ }
12140
+ }
12141
+ if (!found) {
12142
+ throw new Error(`Didn't find '${needle}' in ${comment.loc.source}:${comment.loc.start.line}`);
12143
+ }
12144
+ next();
12145
+ }
12146
+ return null;
12147
+ });
12148
+ }
11925
12149
 
11926
12150
  ;// CONCATENATED MODULE: ./src/optimizer.ts
11927
12151
 
@@ -11937,6 +12161,7 @@ async function optimizeMonkeyC(fnMap) {
11937
12161
 
11938
12162
 
11939
12163
 
12164
+
11940
12165
  function relative_path_no_dotdot(relative) {
11941
12166
  return relative.replace(/^(\.\.[\\\/])+/, (str) => `__${"dot".repeat(str.length / 3)}__${str.slice(-1)}`);
11942
12167
  }
@@ -12346,7 +12571,7 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12346
12571
  // the oldest optimized file, we don't need to regenerate
12347
12572
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
12348
12573
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
12349
- if (source_time < opt_time && 1654222986123 < opt_time) {
12574
+ if (source_time < opt_time && 1654384985724 < opt_time) {
12350
12575
  return hasTests;
12351
12576
  }
12352
12577
  }
@@ -12358,15 +12583,10 @@ async function generateOneConfig(buildConfig, dependencyFiles, config) {
12358
12583
  const dir = external_path_.dirname(name);
12359
12584
  await promises_namespaceObject.mkdir(dir, { recursive: true });
12360
12585
  const opt_source = (0,external_api_cjs_namespaceObject.formatAst)(info.ast, info.monkeyCSource);
12586
+ await promises_namespaceObject.writeFile(name, opt_source);
12361
12587
  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
- }
12588
+ pragmaChecker(info.ast);
12368
12589
  }
12369
- await promises_namespaceObject.writeFile(name, opt_source);
12370
12590
  return info.hasTests;
12371
12591
  })).then((results) => {
12372
12592
  const hasTests = results.some((v) => v);