@markw65/monkeyc-optimizer 1.0.43 → 1.0.44

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.
@@ -4789,7 +4789,9 @@ function getNodeValue(node) {
4789
4789
  return [node, "Long"];
4790
4790
  }
4791
4791
  if (type === "string") {
4792
- return [node, "String"];
4792
+ return node.raw.startsWith("'")
4793
+ ? [node, "Char"]
4794
+ : [node, "String"];
4793
4795
  }
4794
4796
  if (type === "boolean") {
4795
4797
  return [node, "Boolean"];
@@ -5885,7 +5887,7 @@ function pragmaChecker(state, ast, diagnostics) {
5885
5887
  if (quote == '"') {
5886
5888
  return haystack.includes(needle);
5887
5889
  }
5888
- const re = new RegExp(needle.replace(/@([\d\w]+)/g, "(pre_)?$1(_\\d+)?"));
5890
+ const re = new RegExp(needle.replace(/@([-\d.\w]+|"[^"]*")/g, (_match, pat) => `(?:${pat}|pre_${pat.replace(/[".]/g, "_")}(?:_\\d+)?)`));
5889
5891
  return re.test(haystack);
5890
5892
  };
5891
5893
  next();
@@ -7832,7 +7834,7 @@ function getLiteralNode(node) {
7832
7834
  case "-": {
7833
7835
  const [arg, type] = getNodeValue(node.argument);
7834
7836
  if (type === "Number" || type === "Long") {
7835
- return replacementLiteral(arg, -arg.value, type);
7837
+ return replacementLiteral(node, -arg.value, type);
7836
7838
  }
7837
7839
  }
7838
7840
  }
@@ -7882,8 +7884,14 @@ function isBooleanExpression(state, node) {
7882
7884
  }
7883
7885
  return false;
7884
7886
  }
7887
+ function roundToFloat(value) {
7888
+ return new Float32Array([value])[0];
7889
+ }
7885
7890
  function replacementLiteral(arg, value, type) {
7886
- if (typeof value === "boolean") {
7891
+ if (value === null) {
7892
+ type = "Null";
7893
+ }
7894
+ else if (typeof value === "boolean") {
7887
7895
  type = "Boolean";
7888
7896
  }
7889
7897
  else if (type === "Number") {
@@ -7892,32 +7900,189 @@ function replacementLiteral(arg, value, type) {
7892
7900
  else if (type === "Long") {
7893
7901
  value = BigInt.asIntN(64, BigInt(value));
7894
7902
  }
7903
+ else if (type === "Float") {
7904
+ value = roundToFloat(Number(value));
7905
+ }
7906
+ let raw = type === "String"
7907
+ ? JSON.stringify(value)
7908
+ : type === "Char"
7909
+ ? value === "'"
7910
+ ? "'\\''"
7911
+ : "'" + JSON.stringify(value).slice(1, -1) + "'"
7912
+ : value == null
7913
+ ? "null"
7914
+ : value.toString();
7915
+ if (type === "Long") {
7916
+ raw += "l";
7917
+ }
7918
+ else if (type === "Double") {
7919
+ raw += "d";
7920
+ }
7921
+ else if (type === "Float" && prettier_plugin_monkeyc_namespaceObject.LiteralIntegerRe.test(raw)) {
7922
+ raw += "f";
7923
+ }
7924
+ const { start, end, loc } = arg;
7895
7925
  return {
7896
- ...arg,
7926
+ type: "Literal",
7897
7927
  value,
7898
- raw: value.toString() + (type === "Long" ? "l" : ""),
7928
+ raw,
7929
+ start,
7930
+ end,
7931
+ loc,
7899
7932
  };
7900
7933
  }
7934
+ function classify(arg) {
7935
+ switch (arg) {
7936
+ case "Number":
7937
+ return { big: false, int: true };
7938
+ case "Long":
7939
+ return { big: true, int: true };
7940
+ case "Float":
7941
+ return { big: false, int: false };
7942
+ case "Double":
7943
+ return { big: true, int: false };
7944
+ }
7945
+ return null;
7946
+ }
7947
+ function common_arith_types(left, right) {
7948
+ const l = classify(left);
7949
+ if (!l)
7950
+ return null;
7951
+ const r = classify(right);
7952
+ if (!r)
7953
+ return null;
7954
+ if (l.big || r.big) {
7955
+ return l.int && r.int
7956
+ ? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
7957
+ : ["Double", (v) => Number(v)];
7958
+ }
7959
+ else {
7960
+ return l.int && r.int
7961
+ ? ["Number", (v) => BigInt.asIntN(32, BigInt(v))]
7962
+ : ["Float", (v) => roundToFloat(Number(v))];
7963
+ }
7964
+ }
7965
+ function common_bitwise_types(left, right) {
7966
+ if (left === "Boolean" && right === "Boolean") {
7967
+ return ["Boolean", (v) => (v ? true : false)];
7968
+ }
7969
+ const l = classify(left);
7970
+ if (!l)
7971
+ return null;
7972
+ const r = classify(right);
7973
+ if (!r)
7974
+ return null;
7975
+ if (!l.int || !r.int)
7976
+ return null;
7977
+ return l.big || r.big
7978
+ ? ["Long", (v) => BigInt.asIntN(64, BigInt(v))]
7979
+ : ["Number", (v) => Number(BigInt.asIntN(32, BigInt(v)))];
7980
+ }
7981
+ function plus_types(left, right) {
7982
+ if (left === "String" || right === "String") {
7983
+ // Boolean + String is an error, and
7984
+ // Float/Double + String is legal, but its hard to predict
7985
+ // the way the float will be formatted (and it won't match
7986
+ // what javascript would do by default)
7987
+ if (/Float|Double|Boolean/.test(left + right)) {
7988
+ return null;
7989
+ }
7990
+ return ["String", String];
7991
+ }
7992
+ if (left === "Char" || right === "Char") {
7993
+ if (left === right) {
7994
+ // adding two chars produces a string
7995
+ return ["String", String];
7996
+ }
7997
+ if (/Number|Long/.test(left + right)) {
7998
+ return ["Char", (v) => v];
7999
+ }
8000
+ }
8001
+ return common_arith_types(left, right);
8002
+ }
8003
+ function shift_mod_types(left, right) {
8004
+ const result = common_bitwise_types(left, right);
8005
+ if (result && result[0] === "Boolean") {
8006
+ return null;
8007
+ }
8008
+ return result;
8009
+ }
7901
8010
  const operators = {
7902
- "+": (left, right) => left + right,
7903
- "-": (left, right) => left - right,
7904
- "*": (left, right) => left * right,
7905
- "/": (left, right) => left / right,
7906
- "%": (left, right) => left % right,
7907
- "&": (left, right) => left & right,
7908
- "|": (left, right) => left | right,
7909
- "^": (left, right) => left ^ right,
7910
- "<<": (left, right) => left << (right & 127n),
7911
- ">>": (left, right) => left >> (right & 127n),
7912
- "==": (left, right) =>
7913
- // two string literals will compare unequal, becuase string
7914
- // equality is object equality.
7915
- typeof left === "string" ? false : left === right,
7916
- "!=": (left, right) => typeof left === "string" ? true : left !== right,
7917
- "<=": (left, right) => left <= right,
7918
- ">=": (left, right) => left >= right,
7919
- "<": (left, right) => left < right,
7920
- ">": (left, right) => left > right,
8011
+ "+": {
8012
+ typeFn: plus_types,
8013
+ valueFn: (left, right) => typeof left === "string" && typeof right !== "string"
8014
+ ? String.fromCharCode(left.charCodeAt(0) + Number(right))
8015
+ : typeof left !== "string" && typeof right === "string"
8016
+ ? String.fromCharCode(right.charCodeAt(0) + Number(left))
8017
+ : left + right,
8018
+ },
8019
+ "-": {
8020
+ typeFn: common_arith_types,
8021
+ valueFn: (left, right) => left - right,
8022
+ },
8023
+ "*": {
8024
+ typeFn: common_arith_types,
8025
+ valueFn: (left, right) => left * right,
8026
+ },
8027
+ "/": {
8028
+ typeFn: common_arith_types,
8029
+ valueFn: (left, right) => left / right,
8030
+ },
8031
+ "%": {
8032
+ typeFn: shift_mod_types,
8033
+ valueFn: (left, right) => left % right,
8034
+ },
8035
+ "&": {
8036
+ typeFn: common_bitwise_types,
8037
+ valueFn: (left, right) => left & right,
8038
+ },
8039
+ "|": {
8040
+ typeFn: common_bitwise_types,
8041
+ valueFn: (left, right) => left | right,
8042
+ },
8043
+ "^": {
8044
+ typeFn: common_bitwise_types,
8045
+ valueFn: (left, right) => left ^ right,
8046
+ },
8047
+ "<<": {
8048
+ typeFn: shift_mod_types,
8049
+ valueFn: (left, right) => typeof right === "bigint"
8050
+ ? left << right
8051
+ : left << right,
8052
+ },
8053
+ ">>": {
8054
+ typeFn: shift_mod_types,
8055
+ valueFn: (left, right) => typeof right === "bigint"
8056
+ ? left >> right
8057
+ : left >> right,
8058
+ },
8059
+ "==": {
8060
+ typeFn: () => ["Boolean", (v) => v],
8061
+ valueFn: (left, right) =>
8062
+ // two string literals will compare unequal, becuase string
8063
+ // equality is object equality.
8064
+ typeof left === "string" ? false : left === right,
8065
+ },
8066
+ "!=": {
8067
+ typeFn: () => ["Boolean", (v) => v],
8068
+ valueFn: (left, right) => typeof left === "string" ? true : left !== right,
8069
+ },
8070
+ "<=": {
8071
+ typeFn: common_arith_types,
8072
+ valueFn: (left, right) => left <= right,
8073
+ },
8074
+ ">=": {
8075
+ typeFn: common_arith_types,
8076
+ valueFn: (left, right) => left >= right,
8077
+ },
8078
+ "<": {
8079
+ typeFn: common_arith_types,
8080
+ valueFn: (left, right) => left < right,
8081
+ },
8082
+ ">": {
8083
+ typeFn: common_arith_types,
8084
+ valueFn: (left, right) => left > right,
8085
+ },
7921
8086
  as: null,
7922
8087
  instanceof: null,
7923
8088
  has: null,
@@ -7930,23 +8095,31 @@ function optimizeNode(state, node) {
7930
8095
  break;
7931
8096
  switch (node.operator) {
7932
8097
  case "+":
7933
- if (type === "Number" || type === "Long") {
8098
+ if (type === "Number" ||
8099
+ type === "Long" ||
8100
+ type === "Float" ||
8101
+ type === "Double" ||
8102
+ type === "Char" ||
8103
+ type === "String") {
7934
8104
  return arg;
7935
8105
  }
7936
8106
  break;
7937
8107
  case "-":
7938
- if (type === "Number" || type === "Long") {
7939
- return replacementLiteral(arg, -arg.value, type);
8108
+ if (type === "Number" ||
8109
+ type === "Long" ||
8110
+ type === "Float" ||
8111
+ type === "Double") {
8112
+ return replacementLiteral(node, -arg.value, type);
7940
8113
  }
7941
8114
  break;
7942
8115
  case "!":
7943
8116
  case "~":
7944
8117
  {
7945
8118
  if (type === "Number" || type === "Long") {
7946
- return replacementLiteral(arg, ~BigInt(arg.value), type);
8119
+ return replacementLiteral(node, ~BigInt(arg.value), type);
7947
8120
  }
7948
8121
  if (type === "Boolean" && node.operator == "!") {
7949
- return replacementLiteral(arg, !arg.value, type);
8122
+ return replacementLiteral(node, !arg.value, type);
7950
8123
  }
7951
8124
  }
7952
8125
  break;
@@ -7960,23 +8133,13 @@ function optimizeNode(state, node) {
7960
8133
  const [right, right_type] = getNodeValue(node.right);
7961
8134
  if (!left || !right)
7962
8135
  break;
7963
- let value = null;
7964
- let type;
7965
- if ((left_type != "Number" && left_type != "Long") ||
7966
- left_type != right_type) {
7967
- if (node.operator !== "==" && node.operator !== "!=") {
7968
- break;
7969
- }
7970
- value = operators[node.operator](left.value, right.value);
7971
- type = "Boolean";
7972
- }
7973
- else {
7974
- type = left_type;
7975
- value = op(BigInt(left.value), BigInt(right.value));
7976
- }
8136
+ const type = op.typeFn(left_type, right_type);
8137
+ if (!type)
8138
+ break;
8139
+ const value = op.valueFn(type[1](left.value), type[1](right.value));
7977
8140
  if (value === null)
7978
8141
  break;
7979
- return replacementLiteral(left, value, type);
8142
+ return replacementLiteral(node, value, type[0]);
7980
8143
  }
7981
8144
  break;
7982
8145
  }
@@ -9266,7 +9429,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
9266
9429
  // the oldest optimized file, we don't need to regenerate
9267
9430
  const source_time = await (0,external_util_cjs_namespaceObject.last_modified)(Object.keys(fnMap).concat(dependencyFiles));
9268
9431
  const opt_time = await (0,external_util_cjs_namespaceObject.first_modified)(Object.values(fnMap).map((v) => v.output));
9269
- if (source_time < opt_time && 1670458646779 < opt_time) {
9432
+ if (source_time < opt_time && 1670782882733 < opt_time) {
9270
9433
  return { hasTests, diagnostics: prevDiagnostics };
9271
9434
  }
9272
9435
  }
@@ -9293,7 +9456,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
9293
9456
  return promises_namespaceObject.writeFile(external_path_.join(output, "build-info.json"), JSON.stringify({
9294
9457
  hasTests,
9295
9458
  diagnostics,
9296
- optimizerVersion: "1.0.43",
9459
+ optimizerVersion: "1.0.44",
9297
9460
  ...Object.fromEntries(configOptionsToCheck.map((option) => [option, config[option]])),
9298
9461
  }))
9299
9462
  .then(() => ({ hasTests, diagnostics }));