| 125 | } |
| 126 | |
| 127 | absl::StatusOr<std::unique_ptr<TraceableProgram>> |
| 128 | RuntimeImpl::CreateTraceableProgram( |
| 129 | std::unique_ptr<Ast> ast, |
| 130 | const Runtime::CreateProgramOptions& options) const { |
| 131 | CEL_ASSIGN_OR_RETURN(auto flat_expr, expr_builder_.CreateExpressionImpl( |
| 132 | std::move(ast), options.issues)); |
| 133 | |
| 134 | // Special case if the program is fully recursive. |
| 135 | // |
| 136 | // This implementation avoids unnecessary allocs at evaluation time which |
| 137 | // improves performance notably for small expressions. |
| 138 | if (expr_builder_.options().max_recursion_depth != 0 && |
| 139 | !flat_expr.subexpressions().empty() && |
| 140 | // mainline expression is exactly one recursive step. |
| 141 | flat_expr.subexpressions().front().size() == 1 && |
| 142 | flat_expr.subexpressions().front().front()->GetNativeTypeId() == |
| 143 | NativeTypeId::For<WrappedDirectStep>()) { |
| 144 | const DirectExpressionStep* root = |
| 145 | internal::down_cast<const WrappedDirectStep*>( |
| 146 | flat_expr.subexpressions().front().front().get()) |
| 147 | ->wrapped(); |
| 148 | return std::make_unique<RecursiveProgramImpl>(environment_, |
| 149 | std::move(flat_expr), root); |
| 150 | } |
| 151 | |
| 152 | return std::make_unique<ProgramImpl>(environment_, std::move(flat_expr)); |
| 153 | } |
| 154 | |
| 155 | bool TestOnly_IsRecursiveImpl(const Program* program) { |
| 156 | return dynamic_cast<const RecursiveProgramImpl*>(program) != nullptr; |
nothing calls this directly
no test coverage detected