83 lines
2.4 KiB
JavaScript
83 lines
2.4 KiB
JavaScript
"use strict";
|
|
|
|
var h = require("./helpers");
|
|
var PatternMatch = require("./pattern-match");
|
|
|
|
module.exports = function (t) {
|
|
var OP_AND = function OP_AND(input) {
|
|
return input === "&&";
|
|
};
|
|
var OP_OR = function OP_OR(input) {
|
|
return input === "||";
|
|
};
|
|
|
|
function simplifyPatterns(path) {
|
|
// cache of path.evaluate()
|
|
var evaluateMemo = new Map();
|
|
|
|
var TRUTHY = function TRUTHY(input) {
|
|
// !NaN and !undefined are truthy
|
|
// separate check here as they are considered impure by babel
|
|
if (input.isUnaryExpression() && input.get("argument").isIdentifier()) {
|
|
if (input.node.argument.name === "NaN" || input.node.argument.name === "undefined") {
|
|
return true;
|
|
}
|
|
}
|
|
var evalResult = input.evaluate();
|
|
evaluateMemo.set(input, evalResult);
|
|
return evalResult.confident && input.isPure() && evalResult.value;
|
|
};
|
|
|
|
var FALSY = function FALSY(input) {
|
|
// NaN and undefined are falsy
|
|
// separate check here as they are considered impure by babel
|
|
if (input.isIdentifier()) {
|
|
if (input.node.name === "NaN" || input.node.name === "undefined") {
|
|
return true;
|
|
}
|
|
}
|
|
var evalResult = input.evaluate();
|
|
evaluateMemo.set(input, evalResult);
|
|
return evalResult.confident && input.isPure() && !evalResult.value;
|
|
};
|
|
|
|
var _h$typeSymbols = h.typeSymbols(t),
|
|
EX = _h$typeSymbols.Expression;
|
|
|
|
// Convention:
|
|
// [left, operator, right, handler(leftNode, rightNode)]
|
|
|
|
|
|
var matcher = new PatternMatch([[TRUTHY, OP_AND, EX, function (l, r) {
|
|
return r;
|
|
}], [FALSY, OP_AND, EX, function (l) {
|
|
return l;
|
|
}], [TRUTHY, OP_OR, EX, function (l) {
|
|
return l;
|
|
}], [FALSY, OP_OR, EX, function (l, r) {
|
|
return r;
|
|
}]]);
|
|
|
|
var left = path.get("left");
|
|
var right = path.get("right");
|
|
var operator = path.node.operator;
|
|
|
|
var result = matcher.match([left, operator, right], h.isPatternMatchesPath(t));
|
|
|
|
if (result.match) {
|
|
// here we are sure that left.evaluate is always confident becuase
|
|
// it satisfied one of TRUTHY/FALSY paths
|
|
var value = void 0;
|
|
if (evaluateMemo.has(left)) {
|
|
value = evaluateMemo.get(left).value;
|
|
} else {
|
|
value = left.evaluate().value;
|
|
}
|
|
path.replaceWith(result.value(t.valueToNode(value), right.node));
|
|
}
|
|
}
|
|
|
|
return {
|
|
simplifyPatterns
|
|
};
|
|
}; |