| 342 | } // namespace |
| 343 | |
| 344 | bool Expression::IsSatisfiable() const { |
| 345 | if (type() == nullptr) return true; |
| 346 | if (type()->id() != Type::BOOL) return true; |
| 347 | |
| 348 | if (auto lit = literal()) { |
| 349 | if (lit->null_count() == lit->length()) { |
| 350 | return false; |
| 351 | } |
| 352 | |
| 353 | if (lit->is_scalar()) { |
| 354 | return lit->scalar_as<BooleanScalar>().value; |
| 355 | } |
| 356 | |
| 357 | return true; |
| 358 | } |
| 359 | |
| 360 | if (field_ref()) return true; |
| 361 | |
| 362 | auto call = CallNotNull(*this); |
| 363 | |
| 364 | // invert(true_unless_null(x)) is always false or null by definition |
| 365 | // true_unless_null arises in simplification of inequalities below |
| 366 | if (call->function_name == "invert") { |
| 367 | if (auto nested_call = call->arguments[0].call()) { |
| 368 | if (nested_call->function_name == "true_unless_null") return false; |
| 369 | } |
| 370 | } |
| 371 | |
| 372 | if (call->function_name == "and_kleene" || call->function_name == "and") { |
| 373 | return std::all_of(call->arguments.begin(), call->arguments.end(), |
| 374 | [](const Expression& arg) { return arg.IsSatisfiable(); }); |
| 375 | } |
| 376 | if (call->function_name == "or_kleene" || call->function_name == "or") { |
| 377 | return std::any_of(call->arguments.begin(), call->arguments.end(), |
| 378 | [](const Expression& arg) { return arg.IsSatisfiable(); }); |
| 379 | } |
| 380 | |
| 381 | return true; |
| 382 | } |
| 383 | |
| 384 | namespace { |
| 385 | |