| 2532 | } // namespace |
| 2533 | |
| 2534 | absl::StatusOr<FlatExpression> FlatExprBuilder::CreateExpressionImpl( |
| 2535 | std::unique_ptr<Ast> ast, std::vector<RuntimeIssue>* issues) const { |
| 2536 | if (absl::StartsWith(container_, ".") || absl::EndsWith(container_, ".")) { |
| 2537 | return absl::InvalidArgumentError( |
| 2538 | absl::StrCat("Invalid expression container: '", container_, "'")); |
| 2539 | } |
| 2540 | |
| 2541 | RuntimeIssue::Severity max_severity = options_.fail_on_warnings |
| 2542 | ? RuntimeIssue::Severity::kWarning |
| 2543 | : RuntimeIssue::Severity::kError; |
| 2544 | IssueCollector issue_collector(max_severity); |
| 2545 | |
| 2546 | absl::StatusOr<std::vector<cel::ExtensionSpec>> runtime_extensions = |
| 2547 | ExtractAndValidateRuntimeExtensions(*ast); |
| 2548 | |
| 2549 | if (!runtime_extensions.ok()) { |
| 2550 | CEL_RETURN_IF_ERROR(issue_collector.AddIssue( |
| 2551 | RuntimeIssue::CreateError(runtime_extensions.status()))); |
| 2552 | } |
| 2553 | |
| 2554 | auto status = CheckAstExtensions(*runtime_extensions); |
| 2555 | if (!status.ok()) { |
| 2556 | CEL_RETURN_IF_ERROR( |
| 2557 | issue_collector.AddIssue(RuntimeIssue::CreateError(status))); |
| 2558 | } |
| 2559 | |
| 2560 | Resolver resolver(container_, function_registry_, type_registry_, |
| 2561 | GetTypeProvider(), |
| 2562 | options_.enable_qualified_type_identifiers); |
| 2563 | |
| 2564 | std::shared_ptr<google::protobuf::Arena> arena; |
| 2565 | ProgramBuilder program_builder; |
| 2566 | PlannerContext extension_context(env_, resolver, options_, GetTypeProvider(), |
| 2567 | issue_collector, program_builder, arena); |
| 2568 | |
| 2569 | for (const std::unique_ptr<AstTransform>& transform : ast_transforms_) { |
| 2570 | CEL_RETURN_IF_ERROR(transform->UpdateAst(extension_context, *ast)); |
| 2571 | } |
| 2572 | |
| 2573 | std::vector<std::unique_ptr<ProgramOptimizer>> optimizers; |
| 2574 | for (const ProgramOptimizerFactory& optimizer_factory : program_optimizers_) { |
| 2575 | CEL_ASSIGN_OR_RETURN(auto optimizer, |
| 2576 | optimizer_factory(extension_context, *ast)); |
| 2577 | if (optimizer != nullptr) { |
| 2578 | optimizers.push_back(std::move(optimizer)); |
| 2579 | } |
| 2580 | } |
| 2581 | |
| 2582 | // These objects are expected to remain scoped to one build call -- references |
| 2583 | // to them shouldn't be persisted in any part of the result expression. |
| 2584 | FlatExprVisitor visitor(resolver, options_, std::move(optimizers), |
| 2585 | ast->reference_map(), GetTypeProvider(), |
| 2586 | issue_collector, program_builder, extension_context, |
| 2587 | enable_optional_types_); |
| 2588 | |
| 2589 | if (options_.max_recursion_depth == -1 || options_.max_recursion_depth > 0) { |
| 2590 | int depth_limit = options_.max_recursion_depth == -1 |
| 2591 | ? std::numeric_limits<int>::max() |