20 for (
auto pred : *
this) {
29 for (
auto clause : *
this) {
39 res.reserve(lhs.size() + rhs.size());
40 res.insert(res.end(), lhs.begin(), lhs.end());
41 res.insert(res.end(), rhs.begin(), rhs.end());
56 res.reserve(lhs.size() + rhs.size());
57 res.insert(res.end(), lhs.begin(), lhs.end());
58 res.insert(res.end(), rhs.begin(), rhs.end());
67 else if (rhs.size() == 0)
70 res.reserve(lhs.size() * rhs.size());
71 for (
auto &clause_left : lhs) {
72 for (
auto &clause_right : rhs)
73 res.push_back(clause_left or clause_right);
81 for (
auto &p : clause)
82 res.emplace_back(
Clause({not p}));
89 for (
auto &clause : cnf)
90 res = res or not clause;
102 out <<
"NOT (" <<
expr() <<
')';
119 for (
auto it = begin(); it != end(); ++it) {
120 if (it != begin()) out <<
" OR ";
121 out <<
'(' << *it <<
')';
139 for (
auto it = begin(); it != end(); ++it) {
140 if (it != begin()) out <<
" AND ";
148std::ostream & cnf::operator<<(std::ostream &out,
const Predicate &pred)
153 print.expand_nested_queries(
false);
158std::ostream & cnf::operator<<(std::ostream &out,
const cnf::Clause &clause)
160 for (
auto it = clause.begin(); it != clause.end(); ++it) {
161 if (it != clause.begin()) out <<
" v ";
167std::ostream & cnf::operator<<(std::ostream &out,
const CNF &cnf)
171 else if (cnf.size() == 1)
174 for (
auto it = cnf.begin(); it != cnf.end(); ++it) {
175 if (it != cnf.begin()) out <<
" ^ ";
176 out <<
'(' << *it <<
')';
184 out << *
this << std::endl;
190 out << *
this << std::endl;
196 out << *
this << std::endl;
210 bool is_negative_ =
false;
218 using ConstASTExprVisitor::operator();
219 void operator()(Const<ErrorExpr> &e);
220 void operator()(Const<Designator> &e);
221 void operator()(Const<Constant> &e);
222 void operator()(Const<FnApplicationExpr> &e);
223 void operator()(Const<UnaryExpr> &e);
224 void operator()(Const<BinaryExpr> &e);
225 void operator()(Const<QueryExpr> &e);
250 switch (e.op().type) {
252 is_negative_ = not is_negative_;
254 is_negative_ = not is_negative_;
266 if (e.lhs->type()->is_boolean()
and e.rhs->type()->is_boolean()) {
269 auto cnf_lhs = result_;
271 auto cnf_rhs = result_;
273 if ((not is_negative_
and e.op() == TK_And) or (is_negative_
and e.op() == TK_Or)) {
274 result_ = cnf_lhs
and cnf_rhs;
275 }
else if ((not is_negative_
and e.op() == TK_Or) or (is_negative_
and e.op() == TK_And)) {
276 result_ = cnf_lhs or cnf_rhs;
277 }
else if (e.op() == TK_EQUAL or e.op() == TK_BANG_EQUAL) {
279 auto equiv = ((not cnf_lhs) or cnf_rhs)
and ((not cnf_rhs) or cnf_lhs);
280 if ((not is_negative_
and e.op() == TK_BANG_EQUAL) or (is_negative_
and e.op() == TK_EQUAL))
#define M_unreachable(MSG)
CNF M_EXPORT operator&&(const Clause &lhs, const Clause &rhs)
Returns the logical and of two cnf::Clauses, i.e. a CNF with the two cnf::Clauses lhs and rhs.
CNF M_EXPORT operator!(const Clause &clause)
Returns the logical negation of a cnf::Clause.
Clause M_EXPORT operator||(const Clause &lhs, const Clause &rhs)
Returns the logical or of two cnf::Clauses, i.e. the disjunction of the Predicates of lhs and rhs.
CNF M_EXPORT to_CNF(const ast::Expr &e)
Converts the Boolean Expr e to a CNF.
bool M_EXPORT contains(const H &haystack, const N &needle)
Checks whether haystack contains needle.
Helper class to convert Expr and Clause to cnf::CNF.
void operator()(Const< ErrorExpr > &e)
Pretty-prints the AST in SQL.
A CNF represents a conjunction of cnf::Clauses.
bool operator<=(const CNF &other) const
void to_sql(std::ostream &out) const
Print as SQL expression.
A cnf::Clause represents a disjunction of Predicates.
void to_sql(std::ostream &out) const
Print as SQL expression.
bool operator<=(const Clause &other) const
A Predicate contains a Expr of Boolean type in either positive or negative form.
static Predicate Create(const ast::Expr *e, bool is_negative)
Creates a Predicate from e.
void to_sql(std::ostream &out) const
Print as SQL expression.
ast::Expr & expr()
Returns the Expr within this Predicate.
bool negative() const
Returns true iff this Predicate is negative.