| "use strict"; |
| |
| Object.defineProperty(exports, "__esModule", { |
| value: true |
| }); |
| exports.default = void 0; |
| |
| var _convert = _interopRequireDefault(require("./convert")); |
| |
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
| |
| function reduce(node, precision) { |
| if (node.type === "MathExpression") return reduceMathExpression(node, precision); |
| return node; |
| } |
| |
| function isEqual(left, right) { |
| return left.type === right.type && left.value === right.value; |
| } |
| |
| function isValueType(type) { |
| switch (type) { |
| case 'LengthValue': |
| case 'AngleValue': |
| case 'TimeValue': |
| case 'FrequencyValue': |
| case 'ResolutionValue': |
| case 'EmValue': |
| case 'ExValue': |
| case 'ChValue': |
| case 'RemValue': |
| case 'VhValue': |
| case 'VwValue': |
| case 'VminValue': |
| case 'VmaxValue': |
| case 'PercentageValue': |
| case 'Value': |
| return true; |
| } |
| |
| return false; |
| } |
| |
| function convertMathExpression(node, precision) { |
| var nodes = (0, _convert.default)(node.left, node.right, precision); |
| var left = reduce(nodes.left, precision); |
| var right = reduce(nodes.right, precision); |
| |
| if (left.type === "MathExpression" && right.type === "MathExpression") { |
| if (left.operator === '/' && right.operator === '*' || left.operator === '-' && right.operator === '+' || left.operator === '*' && right.operator === '/' || left.operator === '+' && right.operator === '-') { |
| 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); |
| left = reduce(nodes.left, precision); |
| right = reduce(nodes.right, precision); |
| } |
| } |
| |
| node.left = left; |
| node.right = right; |
| return node; |
| } |
| |
| function flip(operator) { |
| return operator === '+' ? '-' : '+'; |
| } |
| |
| function flipValue(node) { |
| if (isValueType(node.type)) node.value = -node.value;else if (node.type == 'MathExpression') { |
| node.left = flipValue(node.left); |
| node.right = flipValue(node.right); |
| } |
| return node; |
| } |
| |
| function reduceAddSubExpression(node, precision) { |
| var _node = node, |
| left = _node.left, |
| right = _node.right, |
| op = _node.operator; |
| if (left.type === 'Function' || right.type === 'Function') return node; // something + 0 => something |
| // something - 0 => something |
| |
| if (right.value === 0) return left; // 0 + something => something |
| |
| if (left.value === 0 && op === "+") return right; // 0 - something => -something |
| |
| if (left.value === 0 && op === "-") return flipValue(right); // value + value |
| // value - value |
| |
| if (left.type === right.type && isValueType(left.type)) { |
| node = Object.assign({}, left); |
| if (op === "+") node.value = left.value + right.value;else node.value = left.value - right.value; |
| } // value <op> (expr) |
| |
| |
| if (isValueType(left.type) && (right.operator === '+' || right.operator === '-') && right.type === 'MathExpression') { |
| // value + (value + something) => (value + value) + something |
| // value + (value - something) => (value + value) - something |
| // value - (value + something) => (value - value) - something |
| // value - (value - something) => (value - value) + something |
| if (left.type === right.left.type) { |
| node = Object.assign({}, node); |
| node.left = reduce({ |
| type: 'MathExpression', |
| operator: op, |
| left: left, |
| right: right.left |
| }, precision); |
| node.right = right.right; |
| node.operator = op === '-' ? flip(right.operator) : right.operator; |
| return reduce(node, precision); |
| } // value + (something + value) => (value + value) + something |
| // value + (something - value) => (value - value) + something |
| // value - (something + value) => (value - value) - something |
| // value - (something - value) => (value + value) - something |
| else if (left.type === right.right.type) { |
| node = Object.assign({}, node); |
| node.left = reduce({ |
| type: 'MathExpression', |
| operator: op === '-' ? flip(right.operator) : right.operator, |
| left: left, |
| right: right.right |
| }, precision); |
| node.right = right.left; |
| return reduce(node, precision); |
| } // value - (something + something) => value - something - something |
| else if (op === '-' && right.operator === '+') { |
| node = Object.assign({}, node); |
| node.right.operator = '-'; |
| return reduce(node, precision); |
| } |
| } // (expr) <op> value |
| |
| |
| if (left.type === 'MathExpression' && (left.operator === '+' || left.operator === '-') && isValueType(right.type)) { |
| // (value + something) + value => (value + value) + something |
| // (value - something) + value => (value + value) - something |
| // (value + something) - value => (value - value) + something |
| // (value - something) - value => (value - value) - something |
| if (right.type === left.left.type) { |
| node = Object.assign({}, left); |
| node.left = reduce({ |
| type: 'MathExpression', |
| operator: op, |
| left: left.left, |
| right: right |
| }, precision); |
| return reduce(node, precision); |
| } // (something + value) + value => something + (value + value) |
| // (something - value1) + value2 => something - (value2 - value1) |
| // (something + value) - value => something + (value - value) |
| // (something - value) - value => something - (value + value) |
| else if (right.type === left.right.type) { |
| node = Object.assign({}, left); |
| |
| if (left.operator === '-') { |
| node.right = reduce({ |
| type: 'MathExpression', |
| operator: flip(op), |
| left: left.right, |
| right: right |
| }, precision); |
| |
| if (node.right.value && node.right.value < 0) { |
| node.right.value = Math.abs(node.right.value); |
| node.operator = '+'; |
| } else { |
| node.operator = left.operator; |
| } |
| } else { |
| node.right = reduce({ |
| type: 'MathExpression', |
| operator: op, |
| left: left.right, |
| right: right |
| }, precision); |
| } |
| |
| if (node.right.value < 0) { |
| node.right.value *= -1; |
| node.operator = node.operator === '-' ? '+' : '-'; |
| } |
| |
| return reduce(node, precision); |
| } |
| } |
| |
| if (left.type === 'MathExpression' && right.type === 'MathExpression' && op === '-' && right.operator === '-') { |
| node.right.operator = flip(node.right.operator); |
| } |
| |
| return node; |
| } |
| |
| function reduceDivisionExpression(node) { |
| if (!isValueType(node.right.type)) return node; |
| if (node.right.type !== 'Value') throw new Error(`Cannot divide by "${node.right.unit}", number expected`); |
| if (node.right.value === 0) throw new Error('Cannot divide by zero'); // something / value |
| |
| if (isValueType(node.left.type)) { |
| node.left.value /= node.right.value; |
| return node.left; |
| } |
| |
| return node; |
| } |
| |
| function reduceMultiplicationExpression(node) { |
| // (expr) * value |
| if (node.left.type === 'MathExpression' && node.right.type === 'Value') { |
| if (isValueType(node.left.left.type) && isValueType(node.left.right.type)) { |
| node.left.left.value *= node.right.value; |
| node.left.right.value *= node.right.value; |
| return node.left; |
| } |
| } // something * value |
| else if (isValueType(node.left.type) && node.right.type === 'Value') { |
| node.left.value *= node.right.value; |
| return node.left; |
| } // value * (expr) |
| else if (node.left.type === 'Value' && node.right.type === 'MathExpression') { |
| if (isValueType(node.right.left.type) && isValueType(node.right.right.type)) { |
| node.right.left.value *= node.left.value; |
| node.right.right.value *= node.left.value; |
| return node.right; |
| } |
| } // value * something |
| else if (node.left.type === 'Value' && isValueType(node.right.type)) { |
| node.right.value *= node.left.value; |
| return node.right; |
| } |
| |
| return node; |
| } |
| |
| function reduceMathExpression(node, precision) { |
| node = convertMathExpression(node, precision); |
| |
| switch (node.operator) { |
| case "+": |
| case "-": |
| return reduceAddSubExpression(node, precision); |
| |
| case "/": |
| return reduceDivisionExpression(node, precision); |
| |
| case "*": |
| return reduceMultiplicationExpression(node); |
| } |
| |
| return node; |
| } |
| |
| var _default = reduce; |
| exports.default = _default; |
| module.exports = exports.default; |