You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
raqb/src/optimizers/flatten-not-predicates.js

53 lines
1.3 KiB
JavaScript

"use strict";
const matchValue = require("match-value");
const operations = require("../operations");
const typeOf = require("../type-of");
const NoChange = require("./util/no-change");
// FIXME: Generalize to all predicate lists?
function createHandler(type) {
let subItemProperty = matchValue(type, {
notCondition: "condition",
notExpression: "expression"
});
return function flattenNotPredicates(expression) {
// Flattens multiple levels of like-typed not(...) wrappers, ending up with a logically equivalent subtree
// `notCondition(condition)` -> `notCondition(condition)`
// `notCondition(notCondition(condition))` -> `condition`
// `notCondition(notCondition(notCondition(condition)))` -> `notCondition(condition)`
// etc.
let notLevels = 0;
let currentItem = expression;
while(typeOf(currentItem) === type) {
notLevels += 1;
currentItem = currentItem[subItemProperty];
}
if (notLevels === 1) {
return NoChange;
} else {
let hasNot = (notLevels % 2) === 1;
if (hasNot) {
return operations.not(currentItem);
} else {
return currentItem;
}
}
};
}
module.exports = {
name: "flatten-not-predicates",
category: [ "readability" ],
visitors: {
notExpression: createHandler("notExpression"),
notCondition: createHandler("notCondition")
}
};