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.
255 lines
8.3 KiB
255 lines
8.3 KiB
"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; |