Skip to content

Commit 463bee0

Browse files
l46kokcopybara-github
authored andcommitted
Add iteration limit control to planned comprehensions
PiperOrigin-RevId: 850043882
1 parent 11edd62 commit 463bee0

31 files changed

+292
-411
lines changed

common/exceptions/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,9 @@ java_library(
4040
# used_by_android
4141
exports = ["//common/src/main/java/dev/cel/common/exceptions:invalid_argument"],
4242
)
43+
44+
java_library(
45+
name = "iteration_budget_exceeded",
46+
# used_by_android
47+
exports = ["//common/src/main/java/dev/cel/common/exceptions:iteration_budget_exceeded"],
48+
)

common/src/main/java/dev/cel/common/exceptions/BUILD.bazel

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,16 @@ java_library(
8585
"//common/annotations",
8686
],
8787
)
88+
89+
java_library(
90+
name = "iteration_budget_exceeded",
91+
srcs = ["CelIterationLimitExceededException.java"],
92+
# used_by_android
93+
tags = [
94+
],
95+
deps = [
96+
"//common:error_codes",
97+
"//common:runtime_exception",
98+
"//common/annotations",
99+
],
100+
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.common.exceptions;
16+
17+
import dev.cel.common.CelErrorCode;
18+
import dev.cel.common.CelRuntimeException;
19+
import dev.cel.common.annotations.Internal;
20+
import java.util.Locale;
21+
22+
/** Indicates that the iteration budget for a comprehension has been exceeded. */
23+
@Internal
24+
public final class CelIterationLimitExceededException extends CelRuntimeException {
25+
26+
public CelIterationLimitExceededException(int budget) {
27+
super(
28+
String.format(Locale.US, "Iteration budget exceeded: %d", budget),
29+
CelErrorCode.ITERATION_BUDGET_EXCEEDED);
30+
}
31+
}

runtime/src/main/java/dev/cel/runtime/AccumulatedUnknowns.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
5-
// You may obtain a copy of the License aj
5+
// You may obtain a copy of the License at
66
//
77
// https://www.apache.org/licenses/LICENSE-2.0
88
//

runtime/src/main/java/dev/cel/runtime/planner/Attribute.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
/** Represents a resolvable symbol or path (such as a variable or a field selection). */
2121
@Immutable
2222
interface Attribute {
23-
Object resolve(GlobalResolver ctx);
23+
Object resolve(GlobalResolver ctx, ExecutionFrame frame);
2424

2525
Attribute addQualifier(Qualifier qualifier);
2626
}

runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ java_library(
3737
"//common:cel_ast",
3838
"//common:container",
3939
"//common:operator",
40+
"//common:options",
4041
"//common/annotations",
4142
"//common/ast",
4243
"//common/types",
@@ -59,11 +60,14 @@ java_library(
5960
srcs = ["PlannedProgram.java"],
6061
deps = [
6162
":error_metadata",
63+
":execution_frame",
6264
":planned_interpretable",
6365
":strict_error_exception",
6466
"//:auto_value",
67+
"//common:options",
6568
"//common:runtime_exception",
6669
"//common/values",
70+
"//runtime",
6771
"//runtime:activation",
6872
"//runtime:evaluation_exception",
6973
"//runtime:evaluation_exception_builder",
@@ -78,11 +82,10 @@ java_library(
7882
name = "eval_const",
7983
srcs = ["EvalConstant.java"],
8084
deps = [
85+
":execution_frame",
8186
":planned_interpretable",
8287
"//common/values",
8388
"//common/values:cel_byte_string",
84-
"//runtime:evaluation_listener",
85-
"//runtime:function_resolver",
8689
"//runtime:interpretable",
8790
"@maven//:com_google_errorprone_error_prone_annotations",
8891
"@maven//:com_google_guava_guava",
@@ -111,6 +114,7 @@ java_library(
111114
],
112115
deps = [
113116
":eval_helpers",
117+
":execution_frame",
114118
":planned_interpretable",
115119
":qualifier",
116120
"//common:container",
@@ -158,10 +162,9 @@ java_library(
158162
srcs = ["EvalAttribute.java"],
159163
deps = [
160164
":attribute",
165+
":execution_frame",
161166
":interpretable_attribute",
162167
":qualifier",
163-
"//runtime:evaluation_listener",
164-
"//runtime:function_resolver",
165168
"//runtime:interpretable",
166169
"@maven//:com_google_errorprone_error_prone_annotations",
167170
"@maven//:com_google_guava_guava",
@@ -172,12 +175,11 @@ java_library(
172175
name = "eval_test_only",
173176
srcs = ["EvalTestOnly.java"],
174177
deps = [
178+
":execution_frame",
175179
":interpretable_attribute",
176180
":presence_test_qualifier",
177181
":qualifier",
178182
"//runtime:evaluation_exception",
179-
"//runtime:evaluation_listener",
180-
"//runtime:function_resolver",
181183
"//runtime:interpretable",
182184
"@maven//:com_google_errorprone_error_prone_annotations",
183185
],
@@ -187,10 +189,9 @@ java_library(
187189
name = "eval_zero_arity",
188190
srcs = ["EvalZeroArity.java"],
189191
deps = [
192+
":execution_frame",
190193
":planned_interpretable",
191194
"//runtime:evaluation_exception",
192-
"//runtime:evaluation_listener",
193-
"//runtime:function_resolver",
194195
"//runtime:interpretable",
195196
"//runtime:resolved_overload",
196197
],
@@ -201,10 +202,9 @@ java_library(
201202
srcs = ["EvalUnary.java"],
202203
deps = [
203204
":eval_helpers",
205+
":execution_frame",
204206
":planned_interpretable",
205207
"//runtime:evaluation_exception",
206-
"//runtime:evaluation_listener",
207-
"//runtime:function_resolver",
208208
"//runtime:interpretable",
209209
"//runtime:resolved_overload",
210210
],
@@ -215,10 +215,9 @@ java_library(
215215
srcs = ["EvalVarArgsCall.java"],
216216
deps = [
217217
":eval_helpers",
218+
":execution_frame",
218219
":planned_interpretable",
219220
"//runtime:evaluation_exception",
220-
"//runtime:evaluation_listener",
221-
"//runtime:function_resolver",
222221
"//runtime:interpretable",
223222
"//runtime:resolved_overload",
224223
],
@@ -229,10 +228,9 @@ java_library(
229228
srcs = ["EvalOr.java"],
230229
deps = [
231230
":eval_helpers",
231+
":execution_frame",
232232
":planned_interpretable",
233233
"//common/values",
234-
"//runtime:evaluation_listener",
235-
"//runtime:function_resolver",
236234
"//runtime:interpretable",
237235
"@maven//:com_google_guava_guava",
238236
],
@@ -243,10 +241,9 @@ java_library(
243241
srcs = ["EvalAnd.java"],
244242
deps = [
245243
":eval_helpers",
244+
":execution_frame",
246245
":planned_interpretable",
247246
"//common/values",
248-
"//runtime:evaluation_listener",
249-
"//runtime:function_resolver",
250247
"//runtime:interpretable",
251248
"@maven//:com_google_guava_guava",
252249
],
@@ -256,10 +253,9 @@ java_library(
256253
name = "eval_conditional",
257254
srcs = ["EvalConditional.java"],
258255
deps = [
256+
":execution_frame",
259257
":planned_interpretable",
260258
"//runtime:evaluation_exception",
261-
"//runtime:evaluation_listener",
262-
"//runtime:function_resolver",
263259
"//runtime:interpretable",
264260
"@maven//:com_google_guava_guava",
265261
],
@@ -269,13 +265,12 @@ java_library(
269265
name = "eval_create_struct",
270266
srcs = ["EvalCreateStruct.java"],
271267
deps = [
268+
":execution_frame",
272269
":planned_interpretable",
273270
"//common/types",
274271
"//common/values",
275272
"//common/values:cel_value_provider",
276273
"//runtime:evaluation_exception",
277-
"//runtime:evaluation_listener",
278-
"//runtime:function_resolver",
279274
"//runtime:interpretable",
280275
"@maven//:com_google_errorprone_error_prone_annotations",
281276
"@maven//:com_google_guava_guava",
@@ -286,10 +281,9 @@ java_library(
286281
name = "eval_create_list",
287282
srcs = ["EvalCreateList.java"],
288283
deps = [
284+
":execution_frame",
289285
":planned_interpretable",
290286
"//runtime:evaluation_exception",
291-
"//runtime:evaluation_listener",
292-
"//runtime:function_resolver",
293287
"//runtime:interpretable",
294288
"@maven//:com_google_errorprone_error_prone_annotations",
295289
"@maven//:com_google_guava_guava",
@@ -300,10 +294,9 @@ java_library(
300294
name = "eval_create_map",
301295
srcs = ["EvalCreateMap.java"],
302296
deps = [
297+
":execution_frame",
303298
":planned_interpretable",
304299
"//runtime:evaluation_exception",
305-
"//runtime:evaluation_listener",
306-
"//runtime:function_resolver",
307300
"//runtime:interpretable",
308301
"@maven//:com_google_errorprone_error_prone_annotations",
309302
"@maven//:com_google_guava_guava",
@@ -314,22 +307,33 @@ java_library(
314307
name = "eval_fold",
315308
srcs = ["EvalFold.java"],
316309
deps = [
310+
":execution_frame",
317311
":planned_interpretable",
318312
"//runtime:concatenated_list_view",
319313
"//runtime:evaluation_exception",
320-
"//runtime:evaluation_listener",
321-
"//runtime:function_resolver",
322314
"//runtime:interpretable",
323315
"@maven//:com_google_errorprone_error_prone_annotations",
324316
"@maven//:com_google_guava_guava",
325317
"@maven//:org_jspecify_jspecify",
326318
],
327319
)
328320

321+
java_library(
322+
name = "execution_frame",
323+
srcs = ["ExecutionFrame.java"],
324+
deps = [
325+
"//common:options",
326+
"//common/exceptions:iteration_budget_exceeded",
327+
"//runtime:interpretable",
328+
"@maven//:org_jspecify_jspecify",
329+
],
330+
)
331+
329332
java_library(
330333
name = "eval_helpers",
331334
srcs = ["EvalHelpers.java"],
332335
deps = [
336+
":execution_frame",
333337
":planned_interpretable",
334338
":strict_error_exception",
335339
"//common:error_codes",
@@ -362,6 +366,8 @@ java_library(
362366
name = "planned_interpretable",
363367
srcs = ["PlannedInterpretable.java"],
364368
deps = [
369+
":execution_frame",
370+
"//runtime:evaluation_exception",
365371
"//runtime:interpretable",
366372
"@maven//:com_google_errorprone_error_prone_annotations",
367373
],

runtime/src/main/java/dev/cel/runtime/planner/EvalAnd.java

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import com.google.common.base.Preconditions;
2020
import dev.cel.common.values.ErrorValue;
21-
import dev.cel.runtime.CelEvaluationListener;
22-
import dev.cel.runtime.CelFunctionResolver;
2321
import dev.cel.runtime.GlobalResolver;
2422

2523
final class EvalAnd extends PlannedInterpretable {
@@ -28,10 +26,10 @@ final class EvalAnd extends PlannedInterpretable {
2826
private final PlannedInterpretable[] args;
2927

3028
@Override
31-
public Object eval(GlobalResolver resolver) {
29+
public Object eval(GlobalResolver resolver, ExecutionFrame frame) {
3230
ErrorValue errorValue = null;
3331
for (PlannedInterpretable arg : args) {
34-
Object argVal = evalNonstrictly(arg, resolver);
32+
Object argVal = evalNonstrictly(arg, resolver, frame);
3533
if (argVal instanceof Boolean) {
3634
// Short-circuit on false
3735
if (!((boolean) argVal)) {
@@ -53,27 +51,6 @@ public Object eval(GlobalResolver resolver) {
5351
return true;
5452
}
5553

56-
@Override
57-
public Object eval(GlobalResolver resolver, CelEvaluationListener listener) {
58-
// TODO: Implement support
59-
throw new UnsupportedOperationException("Not yet supported");
60-
}
61-
62-
@Override
63-
public Object eval(GlobalResolver resolver, CelFunctionResolver lateBoundFunctionResolver) {
64-
// TODO: Implement support
65-
throw new UnsupportedOperationException("Not yet supported");
66-
}
67-
68-
@Override
69-
public Object eval(
70-
GlobalResolver resolver,
71-
CelFunctionResolver lateBoundFunctionResolver,
72-
CelEvaluationListener listener) {
73-
// TODO: Implement support
74-
throw new UnsupportedOperationException("Not yet supported");
75-
}
76-
7754
static EvalAnd create(long exprId, PlannedInterpretable[] args) {
7855
return new EvalAnd(exprId, args);
7956
}

0 commit comments

Comments
 (0)