| 115 | } |
| 116 | |
| 117 | absl::optional<Expr> ExpandExistsMacro(MacroExprFactory& factory, Expr& target, |
| 118 | absl::Span<Expr> args) { |
| 119 | if (args.size() != 2) { |
| 120 | return factory.ReportError("exists() requires 2 arguments"); |
| 121 | } |
| 122 | if (!args[0].has_ident_expr() || args[0].ident_expr().name().empty()) { |
| 123 | return factory.ReportErrorAt( |
| 124 | args[0], "exists() variable name must be a simple identifier"); |
| 125 | } |
| 126 | if (args[0].ident_expr().name() == kAccumulatorVariableName) { |
| 127 | return factory.ReportErrorAt( |
| 128 | args[1], absl::StrCat("exists() variable name cannot be ", |
| 129 | kAccumulatorVariableName)); |
| 130 | } |
| 131 | auto init = factory.NewBoolConst(false); |
| 132 | auto condition = factory.NewCall( |
| 133 | CelOperator::NOT_STRICTLY_FALSE, |
| 134 | factory.NewCall(CelOperator::LOGICAL_NOT, factory.NewAccuIdent())); |
| 135 | auto step = factory.NewCall(CelOperator::LOGICAL_OR, factory.NewAccuIdent(), |
| 136 | std::move(args[1])); |
| 137 | auto result = factory.NewAccuIdent(); |
| 138 | return factory.NewComprehension(args[0].ident_expr().name(), |
| 139 | std::move(target), factory.AccuVarName(), |
| 140 | std::move(init), std::move(condition), |
| 141 | std::move(step), std::move(result)); |
| 142 | } |
| 143 | |
| 144 | Macro MakeExistsMacro() { |
| 145 | auto status_or_macro = |
nothing calls this directly
no test coverage detected