souffle  2.0.2-371-g6315b36
BinaryConstraintOps.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file BinaryConstraintOps.h
12  *
13  * Defines binary constraint operators for AST & RAM
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "souffle/TypeAttribute.h"
21 #include <iostream>
22 #include <string>
23 #include <vector>
24 
25 namespace souffle {
26 
27 /**
28  * Binary Constraint Operators
29  */
30 
31 // TODO (darth_tytus): Some of the constraints are repeated because of float and unsigned.
32 // This is inelegant solution, but Ram execution demands this distinction.
33 // Investigate a better way.
34 
35 enum class BinaryConstraintOp {
36  EQ, // equivalence of two values
37  FEQ, // float equiv; b/c NaNs are never equiv
38  NE, // whether two values are different
39  FNE, // float diff; b/c NaNs are always different
40  LT, // signed <
41  ULT, // Unsigned <
42  FLT, // Float <
43  SLT, // Symbol <
44  LE, // signed ≤
45  ULE, // Unsigned ≤
46  FLE, // Float ≤
47  SLE, // Symbol ≤
48  GT, // signed >
49  UGT, // unsigned >
50  FGT, // float >
51  SGT, // Symbol >
52  GE, // signed ≥
53  UGE, // Unsigned ≥
54  FGE, // Float ≥
55  SGE, // Symbol ≥
56  MATCH, // matching string
57  CONTAINS, // whether a sub-string is contained in a string
58  NOT_MATCH, // not matching string
59  NOT_CONTAINS // whether a sub-string is not contained in a string
60 };
61 
62 char const* toBinaryConstraintSymbol(const BinaryConstraintOp op);
63 
64 inline std::ostream& operator<<(std::ostream& os, BinaryConstraintOp x) {
65  return os << toBinaryConstraintSymbol(x);
66 }
67 
68 inline BinaryConstraintOp getEqConstraint(const std::string& type) {
69  switch (type[0]) {
70  case 'f': return BinaryConstraintOp::FEQ;
71  case 'u': return BinaryConstraintOp::EQ;
72  case 'i': return BinaryConstraintOp::EQ;
73 
74  default: return BinaryConstraintOp::EQ;
75  }
76 }
77 
78 inline BinaryConstraintOp getLessEqualConstraint(const std::string& type) {
79  switch (type[0]) {
80  case 'f': return BinaryConstraintOp::FLE;
81  case 'u': return BinaryConstraintOp::ULE;
82  case 'i': return BinaryConstraintOp::LE;
83 
84  default: return BinaryConstraintOp::LE;
85  }
86 }
87 
88 inline BinaryConstraintOp getGreaterEqualConstraint(const std::string& type) {
89  switch (type[0]) {
90  case 'f': return BinaryConstraintOp::FGE;
91  case 'u': return BinaryConstraintOp::UGE;
92  case 'i': return BinaryConstraintOp::GE;
93 
94  default: return BinaryConstraintOp::GE;
95  }
96 }
97 
98 inline BinaryConstraintOp getLessThanConstraint(const std::string& type) {
99  switch (type[0]) {
100  case 'f': return BinaryConstraintOp::FLT;
101  case 'u': return BinaryConstraintOp::ULT;
102  case 'i': return BinaryConstraintOp::LT;
103 
104  default: return BinaryConstraintOp::LT;
105  }
106 }
107 
108 inline BinaryConstraintOp getGreaterThanConstraint(const std::string& type) {
109  switch (type[0]) {
110  case 'f': return BinaryConstraintOp::FGT;
111  case 'u': return BinaryConstraintOp::UGT;
112  case 'i': return BinaryConstraintOp::GT;
113 
114  default: return BinaryConstraintOp::GT;
115  }
116 }
117 
118 inline bool isEqConstraint(const BinaryConstraintOp constraintOp) {
119  switch (constraintOp) {
121  case BinaryConstraintOp::FEQ: return true;
122  default: break;
123  }
124  return false;
125 }
126 
127 inline bool isStrictIneqConstraint(const BinaryConstraintOp constraintOp) {
128  switch (constraintOp) {
134  case BinaryConstraintOp::FGT: return true;
135  default: break;
136  }
137  return false;
138 }
139 
140 inline bool isWeakIneqConstraint(const BinaryConstraintOp constraintOp) {
141  switch (constraintOp) {
147  case BinaryConstraintOp::FGE: return true;
148  default: break;
149  }
150  return false;
151 }
152 
154  assert(isStrictIneqConstraint(constraintOp));
155  switch (constraintOp) {
162  default: break;
163  }
164  return constraintOp;
165 }
166 
168  assert(isStrictIneqConstraint(constraintOp));
169  switch (constraintOp) {
176  default: break;
177  }
178  return constraintOp;
179 }
180 
181 inline bool isLessThan(const BinaryConstraintOp constraintOp) {
182  switch (constraintOp) {
185  case BinaryConstraintOp::FLT: return true;
186  default: break;
187  }
188  return false;
189 }
190 
191 inline bool isGreaterThan(const BinaryConstraintOp constraintOp) {
192  switch (constraintOp) {
195  case BinaryConstraintOp::FGT: return true;
196  default: break;
197  }
198  return false;
199 }
200 
201 inline bool isLessEqual(const BinaryConstraintOp constraintOp) {
202  switch (constraintOp) {
205  case BinaryConstraintOp::FLE: return true;
206  default: break;
207  }
208  return false;
209 }
210 
211 inline bool isGreaterEqual(const BinaryConstraintOp constraintOp) {
212  switch (constraintOp) {
215  case BinaryConstraintOp::FGE: return true;
216  default: break;
217  }
218  return false;
219 }
220 
221 /**
222  * Utility function, informing whether constraint is overloaded.
223  * Only the signed version's are treated as overloaded (as they are returned by the parser).
224  */
225 inline bool isOverloaded(const BinaryConstraintOp constraintOp) {
226  switch (constraintOp) {
232  case BinaryConstraintOp::GE: return true;
233  default: break;
234  }
235  return false;
236 }
237 
238 /**
239  * Convert Constraint to work with requested type.
240  * Example: constraintOp = LT, toType = Float -> FLT (less-than working on floats).
241  */
243  const BinaryConstraintOp constraintOp, const TypeAttribute toType) {
244  auto FAIL = [&]() -> BinaryConstraintOp {
245  fatal("invalid binary constraint overload: op = %s; type = %s", constraintOp, toType);
246  };
247 
248  // clang-format off
249 #define COMPARE_CONSTRAINT_FLOAT_OR_RAW(op) \
250  case BinaryConstraintOp::op: \
251  switch (toType) { \
252  default : return BinaryConstraintOp:: op; \
253  case TypeAttribute::Float : return BinaryConstraintOp::F##op; \
254  }
255 #define COMPARE_CONSTRAINT(op) \
256  case BinaryConstraintOp::op: \
257  switch (toType) { \
258  case TypeAttribute::Signed : return BinaryConstraintOp:: op; \
259  case TypeAttribute::Unsigned: return BinaryConstraintOp::U##op; \
260  case TypeAttribute::Float : return BinaryConstraintOp::F##op; \
261  case TypeAttribute::Symbol : return BinaryConstraintOp::S##op; \
262  case TypeAttribute::ADT : \
263  case TypeAttribute::Record : return FAIL(); \
264  } \
265  break; /* HACK: GCC-9 is incorrectly reporting a case fallthru */
266  // clang-format on
267 
268  switch (constraintOp) {
271 
276 
277  default: fatal("invalid constraint conversion: constraint = %s", constraintOp);
278  }
279 
281 
282 #undef COMPARE_CONSTRAINT_FLOAT_OR_RAW
283 #undef COMPARE_CONSTRAINT
284 }
285 
286 /**
287  * Negated Constraint Operator
288  * Each operator requires a negated operator which is
289  * necessary for the expansion of complex rule bodies with disjunction and negation.
290  */
292  switch (op) {
297 
302 
307 
312 
317 
322  }
323 
325 }
326 
327 /**
328  * Converts operator to its symbolic representation
329  */
330 inline char const* toBinaryConstraintSymbol(const BinaryConstraintOp op) {
331  switch (op) {
333  case BinaryConstraintOp::EQ: return "=";
335  case BinaryConstraintOp::NE: return "!=";
339  case BinaryConstraintOp::LT: return "<";
343  case BinaryConstraintOp::LE: return "<=";
347  case BinaryConstraintOp::GT: return ">";
351  case BinaryConstraintOp::GE: return ">=";
352  case BinaryConstraintOp::MATCH: return "match";
353  case BinaryConstraintOp::CONTAINS: return "contains";
354  case BinaryConstraintOp::NOT_MATCH: return "not_match";
355  case BinaryConstraintOp::NOT_CONTAINS: return "not_contains";
356  }
357 
359 }
360 
361 /**
362  * Converts symbolic representation of an operator to the operator.
363  * Note that this won't tell you which polymorphic overload is actually used.
364  */
365 inline BinaryConstraintOp toBinaryConstraintOp(const std::string& symbol) {
366  if (symbol == "=") return BinaryConstraintOp::EQ;
367  if (symbol == "!=") return BinaryConstraintOp::NE;
368  if (symbol == "<") return BinaryConstraintOp::LT;
369  if (symbol == "<=") return BinaryConstraintOp::LE;
370  if (symbol == ">=") return BinaryConstraintOp::GE;
371  if (symbol == ">") return BinaryConstraintOp::GT;
372  if (symbol == "match") return BinaryConstraintOp::MATCH;
373  if (symbol == "contains") return BinaryConstraintOp::CONTAINS;
374  if (symbol == "not_match") return BinaryConstraintOp::NOT_MATCH;
375  if (symbol == "not_contains") return BinaryConstraintOp::NOT_CONTAINS;
376 
377  fatal("unrecognised binary operator: symbol = `%s`", symbol);
378 }
379 
380 /**
381  * Determines whether arguments of constraint are orderable
382  */
383 inline bool isOrderedBinaryConstraintOp(const BinaryConstraintOp op) {
384  switch (op) {
404  case BinaryConstraintOp::SGT: return true;
405 
409  case BinaryConstraintOp::NOT_CONTAINS: return false;
410  }
411 
413 }
414 
415 /**
416  * Determines whether a functor should be written using infix notation (e.g. `a + b + c`)
417  * or prefix notation (e.g. `+(a,b,c)`)
418  */
419 inline bool isInfixFunctorOp(const BinaryConstraintOp op) {
420  switch (op) {
424  case BinaryConstraintOp::NOT_CONTAINS: return false;
425 
426  default: return true;
427  }
428 }
429 
430 /**
431  * Get type binary constraint operates on.
432  **/
433 inline std::vector<TypeAttribute> getBinaryConstraintTypes(const BinaryConstraintOp op) {
434  // clang-format off
435 #define COMPARE_EQUALS(op) \
436  case BinaryConstraintOp::F##op: return { TypeAttribute::Float }; \
437  case BinaryConstraintOp:: op: \
438  return { TypeAttribute::Signed, TypeAttribute::Unsigned, TypeAttribute::Float, \
439  TypeAttribute::Symbol, TypeAttribute::Record, TypeAttribute::ADT};
440 #define COMPARE_OP(op) \
441  case BinaryConstraintOp:: op: return { TypeAttribute::Signed }; \
442  case BinaryConstraintOp::U##op: return { TypeAttribute::Unsigned }; \
443  case BinaryConstraintOp::F##op: return { TypeAttribute::Float }; \
444  case BinaryConstraintOp::S##op: return { TypeAttribute::Symbol };
445  // clang-format on
446 
447  switch (op) {
450  COMPARE_OP(LT)
451  COMPARE_OP(LE)
452  COMPARE_OP(GT)
453  COMPARE_OP(GE)
454 
459  }
460 
462 
463 #undef COMPARE_EQUALS
464 #undef COMPARE_OP
465 }
466 
467 } // end of namespace souffle
souffle::BinaryConstraintOp::ULT
@ ULT
UNREACHABLE_BAD_CASE_ANALYSIS
#define UNREACHABLE_BAD_CASE_ANALYSIS
Definition: MiscUtil.h:206
souffle::isGreaterEqual
bool isGreaterEqual(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:217
souffle::BinaryConstraintOp::UGE
@ UGE
TypeAttribute
Type attribute class.
souffle::BinaryConstraintOp::MATCH
@ MATCH
souffle::isGreaterThan
bool isGreaterThan(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:197
souffle::BinaryConstraintOp::FGE
@ FGE
souffle::BinaryConstraintOp::FNE
@ FNE
souffle::getLessThanConstraint
BinaryConstraintOp getLessThanConstraint(const std::string &type)
Definition: BinaryConstraintOps.h:104
souffle::getGreaterEqualConstraint
BinaryConstraintOp getGreaterEqualConstraint(const std::string &type)
Definition: BinaryConstraintOps.h:94
souffle::BinaryConstraintOp::LE
@ LE
souffle::TypeAttribute::Symbol
@ Symbol
souffle::BinaryConstraintOp::EQ
@ EQ
souffle::BinaryConstraintOp::GT
@ GT
MiscUtil.h
souffle::BinaryConstraintOp::SLT
@ SLT
souffle::BinaryConstraintOp::NE
@ NE
souffle::toBinaryConstraintSymbol
char const * toBinaryConstraintSymbol(const BinaryConstraintOp op)
Converts operator to its symbolic representation.
Definition: BinaryConstraintOps.h:336
souffle::isWeakIneqConstraint
bool isWeakIneqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:146
souffle::getLessEqualConstraint
BinaryConstraintOp getLessEqualConstraint(const std::string &type)
Definition: BinaryConstraintOps.h:84
souffle::isOverloaded
bool isOverloaded(const BinaryConstraintOp constraintOp)
Utility function, informing whether constraint is overloaded.
Definition: BinaryConstraintOps.h:231
souffle::BinaryConstraintOp::FEQ
@ FEQ
souffle::BinaryConstraintOp::FLT
@ FLT
souffle::BinaryConstraintOp::FLE
@ FLE
souffle::negatedConstraintOp
BinaryConstraintOp negatedConstraintOp(const BinaryConstraintOp op)
Negated Constraint Operator Each operator requires a negated operator which is necessary for the expa...
Definition: BinaryConstraintOps.h:297
souffle::convertStrictToNotEqualConstraint
BinaryConstraintOp convertStrictToNotEqualConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:173
souffle::BinaryConstraintOp::GE
@ GE
souffle::isLessEqual
bool isLessEqual(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:207
souffle::convertOverloadedConstraint
BinaryConstraintOp convertOverloadedConstraint(const BinaryConstraintOp constraintOp, const TypeAttribute toType)
Convert Constraint to work with requested type.
Definition: BinaryConstraintOps.h:248
souffle::toBinaryConstraintOp
BinaryConstraintOp toBinaryConstraintOp(const std::string &symbol)
Converts symbolic representation of an operator to the operator.
Definition: BinaryConstraintOps.h:371
souffle::BinaryConstraintOp::SGE
@ SGE
souffle::BinaryConstraintOp::ULE
@ ULE
souffle::BinaryConstraintOp
BinaryConstraintOp
Binary Constraint Operators.
Definition: BinaryConstraintOps.h:41
souffle::BinaryConstraintOp::SGT
@ SGT
souffle::BinaryConstraintOp::LT
@ LT
souffle::getBinaryConstraintTypes
std::vector< TypeAttribute > getBinaryConstraintTypes(const BinaryConstraintOp op)
Get type binary constraint operates on.
Definition: BinaryConstraintOps.h:439
souffle::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
souffle::operator<<
std::ostream & operator<<(std::ostream &os, AggregateOp op)
Definition: AggregateOp.h:51
souffle::BinaryConstraintOp::UGT
@ UGT
souffle::isStrictIneqConstraint
bool isStrictIneqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:133
souffle::BinaryConstraintOp::CONTAINS
@ CONTAINS
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
COMPARE_OP
#define COMPARE_OP(op)
souffle
Definition: AggregateOp.h:25
souffle::getEqConstraint
BinaryConstraintOp getEqConstraint(const std::string &type)
Definition: BinaryConstraintOps.h:74
COMPARE_EQUALS
#define COMPARE_EQUALS(op)
souffle::isInfixFunctorOp
bool isInfixFunctorOp(std::string_view symbol)
Determines whether a functor should be written using infix notation (e.g.
Definition: FunctorOps.cpp:252
souffle::BinaryConstraintOp::SLE
@ SLE
souffle::BinaryConstraintOp::FGT
@ FGT
COMPARE_CONSTRAINT_FLOAT_OR_RAW
#define COMPARE_CONSTRAINT_FLOAT_OR_RAW(op)
souffle::getGreaterThanConstraint
BinaryConstraintOp getGreaterThanConstraint(const std::string &type)
Definition: BinaryConstraintOps.h:114
souffle::isLessThan
bool isLessThan(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:187
souffle::BinaryConstraintOp::NOT_MATCH
@ NOT_MATCH
souffle::isOrderedBinaryConstraintOp
bool isOrderedBinaryConstraintOp(const BinaryConstraintOp op)
Determines whether arguments of constraint are orderable.
Definition: BinaryConstraintOps.h:389
COMPARE_CONSTRAINT
#define COMPARE_CONSTRAINT(op)
std::type
ElementType type
Definition: span.h:640
souffle::convertStrictToWeakIneqConstraint
BinaryConstraintOp convertStrictToWeakIneqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:159
TypeAttribute.h
souffle::BinaryConstraintOp::NOT_CONTAINS
@ NOT_CONTAINS