Call node handler group. We provide finer granularity for Call node callbacks to allow special handling for short-circuiting PreVisitCall is invoked before child nodes are processed.
| 990 | // handling for short-circuiting |
| 991 | // PreVisitCall is invoked before child nodes are processed. |
| 992 | void PreVisitCall(const cel::Expr& expr, |
| 993 | const cel::CallExpr& call_expr) override { |
| 994 | if (!progress_status_.ok()) { |
| 995 | return; |
| 996 | } |
| 997 | |
| 998 | std::unique_ptr<CondVisitor> cond_visitor; |
| 999 | if (call_expr.function() == cel::builtin::kAnd) { |
| 1000 | cond_visitor = std::make_unique<BinaryCondVisitor>( |
| 1001 | this, BinaryCond::kAnd, options_.short_circuiting); |
| 1002 | } else if (call_expr.function() == cel::builtin::kOr) { |
| 1003 | cond_visitor = std::make_unique<BinaryCondVisitor>( |
| 1004 | this, BinaryCond::kOr, options_.short_circuiting); |
| 1005 | } else if (call_expr.function() == cel::builtin::kTernary) { |
| 1006 | if (options_.short_circuiting) { |
| 1007 | cond_visitor = std::make_unique<TernaryCondVisitor>(this); |
| 1008 | } else { |
| 1009 | cond_visitor = std::make_unique<ExhaustiveTernaryCondVisitor>(this); |
| 1010 | } |
| 1011 | } else if (enable_optional_types_ && |
| 1012 | call_expr.function() == kOptionalOrFn && |
| 1013 | call_expr.has_target() && call_expr.args().size() == 1) { |
| 1014 | cond_visitor = std::make_unique<BinaryCondVisitor>( |
| 1015 | this, BinaryCond::kOptionalOr, options_.short_circuiting); |
| 1016 | } else if (enable_optional_types_ && |
| 1017 | call_expr.function() == kOptionalOrValueFn && |
| 1018 | call_expr.has_target() && call_expr.args().size() == 1) { |
| 1019 | cond_visitor = std::make_unique<BinaryCondVisitor>( |
| 1020 | this, BinaryCond::kOptionalOrValue, options_.short_circuiting); |
| 1021 | } else if (IsBlock(&call_expr)) { |
| 1022 | // cel.@block |
| 1023 | if (block_.has_value()) { |
| 1024 | // There can only be one for now. |
| 1025 | SetProgressStatusError( |
| 1026 | absl::InvalidArgumentError("multiple cel.@block are not allowed")); |
| 1027 | return; |
| 1028 | } |
| 1029 | block_ = BlockInfo(); |
| 1030 | BlockInfo& block = *block_; |
| 1031 | block.in = true; |
| 1032 | if (call_expr.args().empty()) { |
| 1033 | SetProgressStatusError(absl::InvalidArgumentError( |
| 1034 | "malformed cel.@block: missing list of bound expressions")); |
| 1035 | return; |
| 1036 | } |
| 1037 | if (call_expr.args().size() != 2) { |
| 1038 | SetProgressStatusError(absl::InvalidArgumentError( |
| 1039 | "malformed cel.@block: missing bound expression")); |
| 1040 | return; |
| 1041 | } |
| 1042 | if (!call_expr.args()[0].has_list_expr()) { |
| 1043 | SetProgressStatusError( |
| 1044 | absl::InvalidArgumentError("malformed cel.@block: first argument " |
| 1045 | "is not a list of bound expressions")); |
| 1046 | return; |
| 1047 | } |
| 1048 | const auto& list_expr = call_expr.args().front().list_expr(); |
| 1049 | block.size = list_expr.elements().size(); |
nothing calls this directly
no test coverage detected