You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
8.3 KiB

4 years ago
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _convert = _interopRequireDefault(require("./convert"));
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. function reduce(node, precision) {
  9. if (node.type === "MathExpression") return reduceMathExpression(node, precision);
  10. return node;
  11. }
  12. function isEqual(left, right) {
  13. return left.type === right.type && left.value === right.value;
  14. }
  15. function isValueType(type) {
  16. switch (type) {
  17. case 'LengthValue':
  18. case 'AngleValue':
  19. case 'TimeValue':
  20. case 'FrequencyValue':
  21. case 'ResolutionValue':
  22. case 'EmValue':
  23. case 'ExValue':
  24. case 'ChValue':
  25. case 'RemValue':
  26. case 'VhValue':
  27. case 'VwValue':
  28. case 'VminValue':
  29. case 'VmaxValue':
  30. case 'PercentageValue':
  31. case 'Value':
  32. return true;
  33. }
  34. return false;
  35. }
  36. function convertMathExpression(node, precision) {
  37. var nodes = (0, _convert.default)(node.left, node.right, precision);
  38. var left = reduce(nodes.left, precision);
  39. var right = reduce(nodes.right, precision);
  40. if (left.type === "MathExpression" && right.type === "MathExpression") {
  41. if (left.operator === '/' && right.operator === '*' || left.operator === '-' && right.operator === '+' || left.operator === '*' && right.operator === '/' || left.operator === '+' && right.operator === '-') {
  42. if (isEqual(left.right, right.right)) nodes = (0, _convert.default)(left.left, right.left, precision);else if (isEqual(left.right, right.left)) nodes = (0, _convert.default)(left.left, right.right, precision);
  43. left = reduce(nodes.left, precision);
  44. right = reduce(nodes.right, precision);
  45. }
  46. }
  47. node.left = left;
  48. node.right = right;
  49. return node;
  50. }
  51. function flip(operator) {
  52. return operator === '+' ? '-' : '+';
  53. }
  54. function flipValue(node) {
  55. if (isValueType(node.type)) node.value = -node.value;else if (node.type == 'MathExpression') {
  56. node.left = flipValue(node.left);
  57. node.right = flipValue(node.right);
  58. }
  59. return node;
  60. }
  61. function reduceAddSubExpression(node, precision) {
  62. var _node = node,
  63. left = _node.left,
  64. right = _node.right,
  65. op = _node.operator;
  66. if (left.type === 'Function' || right.type === 'Function') return node; // something + 0 => something
  67. // something - 0 => something
  68. if (right.value === 0) return left; // 0 + something => something
  69. if (left.value === 0 && op === "+") return right; // 0 - something => -something
  70. if (left.value === 0 && op === "-") return flipValue(right); // value + value
  71. // value - value
  72. if (left.type === right.type && isValueType(left.type)) {
  73. node = Object.assign({}, left);
  74. if (op === "+") node.value = left.value + right.value;else node.value = left.value - right.value;
  75. } // value <op> (expr)
  76. if (isValueType(left.type) && (right.operator === '+' || right.operator === '-') && right.type === 'MathExpression') {
  77. // value + (value + something) => (value + value) + something
  78. // value + (value - something) => (value + value) - something
  79. // value - (value + something) => (value - value) - something
  80. // value - (value - something) => (value - value) + something
  81. if (left.type === right.left.type) {
  82. node = Object.assign({}, node);
  83. node.left = reduce({
  84. type: 'MathExpression',
  85. operator: op,
  86. left: left,
  87. right: right.left
  88. }, precision);
  89. node.right = right.right;
  90. node.operator = op === '-' ? flip(right.operator) : right.operator;
  91. return reduce(node, precision);
  92. } // value + (something + value) => (value + value) + something
  93. // value + (something - value) => (value - value) + something
  94. // value - (something + value) => (value - value) - something
  95. // value - (something - value) => (value + value) - something
  96. else if (left.type === right.right.type) {
  97. node = Object.assign({}, node);
  98. node.left = reduce({
  99. type: 'MathExpression',
  100. operator: op === '-' ? flip(right.operator) : right.operator,
  101. left: left,
  102. right: right.right
  103. }, precision);
  104. node.right = right.left;
  105. return reduce(node, precision);
  106. } // value - (something + something) => value - something - something
  107. else if (op === '-' && right.operator === '+') {
  108. node = Object.assign({}, node);
  109. node.right.operator = '-';
  110. return reduce(node, precision);
  111. }
  112. } // (expr) <op> value
  113. if (left.type === 'MathExpression' && (left.operator === '+' || left.operator === '-') && isValueType(right.type)) {
  114. // (value + something) + value => (value + value) + something
  115. // (value - something) + value => (value + value) - something
  116. // (value + something) - value => (value - value) + something
  117. // (value - something) - value => (value - value) - something
  118. if (right.type === left.left.type) {
  119. node = Object.assign({}, left);
  120. node.left = reduce({
  121. type: 'MathExpression',
  122. operator: op,
  123. left: left.left,
  124. right: right
  125. }, precision);
  126. return reduce(node, precision);
  127. } // (something + value) + value => something + (value + value)
  128. // (something - value1) + value2 => something - (value2 - value1)
  129. // (something + value) - value => something + (value - value)
  130. // (something - value) - value => something - (value + value)
  131. else if (right.type === left.right.type) {
  132. node = Object.assign({}, left);
  133. if (left.operator === '-') {
  134. node.right = reduce({
  135. type: 'MathExpression',
  136. operator: flip(op),
  137. left: left.right,
  138. right: right
  139. }, precision);
  140. if (node.right.value && node.right.value < 0) {
  141. node.right.value = Math.abs(node.right.value);
  142. node.operator = '+';
  143. } else {
  144. node.operator = left.operator;
  145. }
  146. } else {
  147. node.right = reduce({
  148. type: 'MathExpression',
  149. operator: op,
  150. left: left.right,
  151. right: right
  152. }, precision);
  153. }
  154. if (node.right.value < 0) {
  155. node.right.value *= -1;
  156. node.operator = node.operator === '-' ? '+' : '-';
  157. }
  158. return reduce(node, precision);
  159. }
  160. }
  161. if (left.type === 'MathExpression' && right.type === 'MathExpression' && op === '-' && right.operator === '-') {
  162. node.right.operator = flip(node.right.operator);
  163. }
  164. return node;
  165. }
  166. function reduceDivisionExpression(node) {
  167. if (!isValueType(node.right.type)) return node;
  168. if (node.right.type !== 'Value') throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
  169. if (node.right.value === 0) throw new Error('Cannot divide by zero'); // something / value
  170. if (isValueType(node.left.type)) {
  171. node.left.value /= node.right.value;
  172. return node.left;
  173. }
  174. return node;
  175. }
  176. function reduceMultiplicationExpression(node) {
  177. // (expr) * value
  178. if (node.left.type === 'MathExpression' && node.right.type === 'Value') {
  179. if (isValueType(node.left.left.type) && isValueType(node.left.right.type)) {
  180. node.left.left.value *= node.right.value;
  181. node.left.right.value *= node.right.value;
  182. return node.left;
  183. }
  184. } // something * value
  185. else if (isValueType(node.left.type) && node.right.type === 'Value') {
  186. node.left.value *= node.right.value;
  187. return node.left;
  188. } // value * (expr)
  189. else if (node.left.type === 'Value' && node.right.type === 'MathExpression') {
  190. if (isValueType(node.right.left.type) && isValueType(node.right.right.type)) {
  191. node.right.left.value *= node.left.value;
  192. node.right.right.value *= node.left.value;
  193. return node.right;
  194. }
  195. } // value * something
  196. else if (node.left.type === 'Value' && isValueType(node.right.type)) {
  197. node.right.value *= node.left.value;
  198. return node.right;
  199. }
  200. return node;
  201. }
  202. function reduceMathExpression(node, precision) {
  203. node = convertMathExpression(node, precision);
  204. switch (node.operator) {
  205. case "+":
  206. case "-":
  207. return reduceAddSubExpression(node, precision);
  208. case "/":
  209. return reduceDivisionExpression(node, precision);
  210. case "*":
  211. return reduceMultiplicationExpression(node);
  212. }
  213. return node;
  214. }
  215. var _default = reduce;
  216. exports.default = _default;
  217. module.exports = exports.default;