|
28 | 28 | #include "iceberg/iceberg_export.h" |
29 | 29 | #include "iceberg/result.h" |
30 | 30 | #include "iceberg/util/formattable.h" |
| 31 | +#include "iceberg/util/macros.h" |
31 | 32 |
|
32 | 33 | namespace iceberg { |
33 | 34 |
|
@@ -80,6 +81,11 @@ class ICEBERG_EXPORT Expression : public util::Formattable { |
80 | 81 | } |
81 | 82 |
|
82 | 83 | std::string ToString() const override { return "Expression"; } |
| 84 | + |
| 85 | + virtual bool is_unbound_predicate() const { return false; } |
| 86 | + virtual bool is_bound_predicate() const { return false; } |
| 87 | + virtual bool is_unbound_aggregate() const { return false; } |
| 88 | + virtual bool is_bound_aggregate() const { return false; } |
83 | 89 | }; |
84 | 90 |
|
85 | 91 | /// \brief An Expression that is always true. |
@@ -137,6 +143,45 @@ class ICEBERG_EXPORT And : public Expression { |
137 | 143 | static Result<std::unique_ptr<And>> Make(std::shared_ptr<Expression> left, |
138 | 144 | std::shared_ptr<Expression> right); |
139 | 145 |
|
| 146 | + /// \brief Creates a folded And expression from two sub-expressions. |
| 147 | + /// |
| 148 | + /// \param left The left operand of the AND expression |
| 149 | + /// \param right The right operand of the AND expression |
| 150 | + /// \param args Additional operands of the AND expression |
| 151 | + /// \return A Result containing a shared pointer to the folded And expression, or an |
| 152 | + /// error if left or right is nullptr |
| 153 | + /// \note A folded And expression is an expression that is equivalent to the original |
| 154 | + /// that is equivalent to the original expression, but with the And operation removed. |
| 155 | + /// For example, (true and x) = x. |
| 156 | + template <typename... Args> |
| 157 | + static Result<std::shared_ptr<Expression>> MakeFolded(std::shared_ptr<Expression> left, |
| 158 | + std::shared_ptr<Expression> right, |
| 159 | + Args&&... args) |
| 160 | + requires std::conjunction_v<std::is_same<Args, std::shared_ptr<Expression>>...> |
| 161 | + { |
| 162 | + if constexpr (sizeof...(args) == 0) { |
| 163 | + if (left->op() == Expression::Operation::kFalse || |
| 164 | + right->op() == Expression::Operation::kFalse) { |
| 165 | + return False::Instance(); |
| 166 | + } |
| 167 | + |
| 168 | + if (left->op() == Expression::Operation::kTrue) { |
| 169 | + return right; |
| 170 | + } |
| 171 | + |
| 172 | + if (right->op() == Expression::Operation::kTrue) { |
| 173 | + return left; |
| 174 | + } |
| 175 | + |
| 176 | + return And::Make(std::move(left), std::move(right)); |
| 177 | + } else { |
| 178 | + ICEBERG_ASSIGN_OR_THROW(auto and_expr, |
| 179 | + And::Make(std::move(left), std::move(right))); |
| 180 | + |
| 181 | + return And::MakeFolded(std::move(and_expr), std::forward<Args>(args)...); |
| 182 | + } |
| 183 | + } |
| 184 | + |
140 | 185 | /// \brief Returns the left operand of the AND expression. |
141 | 186 | /// |
142 | 187 | /// \return The left operand of the AND expression |
@@ -175,6 +220,44 @@ class ICEBERG_EXPORT Or : public Expression { |
175 | 220 | static Result<std::unique_ptr<Or>> Make(std::shared_ptr<Expression> left, |
176 | 221 | std::shared_ptr<Expression> right); |
177 | 222 |
|
| 223 | + /// \brief Creates a folded Or expression from two sub-expressions. |
| 224 | + /// |
| 225 | + /// \param left The left operand of the OR expression |
| 226 | + /// \param right The right operand of the OR expression |
| 227 | + /// \param args Additional operands of the OR expression |
| 228 | + /// \return A Result containing a shared pointer to the folded Or expression, or an |
| 229 | + /// error if left or right is nullptr |
| 230 | + /// \note A folded Or expression is an expression that is equivalent to the original |
| 231 | + /// that is equivalent to the original expression, but with the Or operation removed. |
| 232 | + /// For example, (false or x) = x. |
| 233 | + template <typename... Args> |
| 234 | + static Result<std::shared_ptr<Expression>> MakeFolded(std::shared_ptr<Expression> left, |
| 235 | + std::shared_ptr<Expression> right, |
| 236 | + Args&&... args) |
| 237 | + requires std::conjunction_v<std::is_same<Args, std::shared_ptr<Expression>>...> |
| 238 | + { |
| 239 | + if constexpr (sizeof...(args) == 0) { |
| 240 | + if (left->op() == Expression::Operation::kTrue || |
| 241 | + right->op() == Expression::Operation::kTrue) { |
| 242 | + return True::Instance(); |
| 243 | + } |
| 244 | + |
| 245 | + if (left->op() == Expression::Operation::kFalse) { |
| 246 | + return right; |
| 247 | + } |
| 248 | + |
| 249 | + if (right->op() == Expression::Operation::kFalse) { |
| 250 | + return left; |
| 251 | + } |
| 252 | + |
| 253 | + return Or::Make(std::move(left), std::move(right)); |
| 254 | + } else { |
| 255 | + ICEBERG_ASSIGN_OR_THROW(auto or_expr, Or::Make(std::move(left), std::move(right))); |
| 256 | + |
| 257 | + return Or::MakeFolded(std::move(or_expr), std::forward<Args>(args)...); |
| 258 | + } |
| 259 | + } |
| 260 | + |
178 | 261 | /// \brief Returns the left operand of the OR expression. |
179 | 262 | /// |
180 | 263 | /// \return The left operand of the OR expression |
@@ -211,6 +294,16 @@ class ICEBERG_EXPORT Not : public Expression { |
211 | 294 | /// \return A Result containing a unique pointer to Not, or an error if child is nullptr |
212 | 295 | static Result<std::unique_ptr<Not>> Make(std::shared_ptr<Expression> child); |
213 | 296 |
|
| 297 | + /// \brief Creates a folded Not expression from a child expression. |
| 298 | + /// |
| 299 | + /// \param child The expression to negate |
| 300 | + /// \return A Result containing a shared pointer to the folded Not expression, or an |
| 301 | + /// error if child is nullptr \note A folded Not expression is an expression that is |
| 302 | + /// equivalent to the original expression, but with the Not operation removed. For |
| 303 | + /// example, not(not(x)) = x. |
| 304 | + static Result<std::shared_ptr<Expression>> MakeFolded( |
| 305 | + std::shared_ptr<Expression> child); |
| 306 | + |
214 | 307 | /// \brief Returns the child expression. |
215 | 308 | /// |
216 | 309 | /// \return The child expression being negated |
|
0 commit comments