Skip to content

Commit 004c8a3

Browse files
l46kokcopybara-github
authored andcommitted
Plan specialized calls for Logical OR/AND
PiperOrigin-RevId: 836484895
1 parent aa9f794 commit 004c8a3

14 files changed

Lines changed: 1035 additions & 15 deletions

File tree

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ java_library(
128128
":resolved_overload",
129129
"//:auto_value",
130130
"//common:error_codes",
131+
"//common/annotations",
131132
"@maven//:com_google_code_findbugs_annotations",
132133
"@maven//:com_google_errorprone_error_prone_annotations",
133134
"@maven//:com_google_guava_guava",
@@ -146,6 +147,7 @@ cel_android_library(
146147
":resolved_overload_android",
147148
"//:auto_value",
148149
"//common:error_codes",
150+
"//common/annotations",
149151
"@maven//:com_google_code_findbugs_annotations",
150152
"@maven//:com_google_errorprone_error_prone_annotations",
151153
"@maven_android//:com_google_guava_guava",
@@ -1172,6 +1174,7 @@ java_library(
11721174
":function_overload",
11731175
":unknown_attributes",
11741176
"//:auto_value",
1177+
"//common/annotations",
11751178
"@maven//:com_google_errorprone_error_prone_annotations",
11761179
"@maven//:com_google_guava_guava",
11771180
"@maven//:com_google_protobuf_protobuf_java",
@@ -1187,6 +1190,7 @@ cel_android_library(
11871190
":function_overload_android",
11881191
":unknown_attributes_android",
11891192
"//:auto_value",
1193+
"//common/annotations",
11901194
"@maven//:com_google_errorprone_error_prone_annotations",
11911195
"@maven_android//:com_google_guava_guava",
11921196
"@maven_android//:com_google_protobuf_protobuf_javalite",

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.google.common.collect.ImmutableList;
1919
import com.google.errorprone.annotations.Immutable;
2020
import com.google.protobuf.MessageLite;
21+
import dev.cel.common.annotations.Internal;
2122
import java.util.List;
2223
import java.util.Map;
2324

@@ -27,7 +28,8 @@
2728
*/
2829
@AutoValue
2930
@Immutable
30-
abstract class CelResolvedOverload {
31+
@Internal
32+
public abstract class CelResolvedOverload {
3133

3234
/** The overload id of the function. */
3335
public abstract String getOverloadId();
@@ -79,7 +81,14 @@ public static CelResolvedOverload of(
7981
* Returns true if the overload's expected argument types match the types of the given arguments.
8082
*/
8183
boolean canHandle(Object[] arguments) {
82-
ImmutableList<Class<?>> parameterTypes = getParameterTypes();
84+
return canHandle(arguments, getParameterTypes(), isStrict());
85+
}
86+
87+
/**
88+
* Returns true if the overload's expected argument types match the types of the given arguments.
89+
*/
90+
public static boolean canHandle(
91+
Object[] arguments, ImmutableList<Class<?>> parameterTypes, boolean isStrict) {
8392
if (parameterTypes.size() != arguments.length) {
8493
return false;
8594
}
@@ -99,7 +108,7 @@ boolean canHandle(Object[] arguments) {
99108

100109
if (arg instanceof Exception || arg instanceof CelUnknownSet) {
101110
// Only non-strict functions can accept errors/unknowns as arguments to a function
102-
if (!isStrict()) {
111+
if (!isStrict) {
103112
// Skip assignability check below, but continue to validate remaining args
104113
continue;
105114
}

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package dev.cel.runtime;
1616

17+
import static com.google.common.base.Preconditions.checkArgument;
1718
import static com.google.common.base.Preconditions.checkNotNull;
1819

1920
import com.google.auto.value.AutoBuilder;
@@ -22,17 +23,27 @@
2223
import com.google.errorprone.annotations.CanIgnoreReturnValue;
2324
import com.google.errorprone.annotations.Immutable;
2425
import dev.cel.common.CelErrorCode;
26+
import dev.cel.common.annotations.Internal;
2527
import java.util.ArrayList;
2628
import java.util.List;
2729
import java.util.Map;
2830
import java.util.Optional;
2931

30-
/** Default implementation of dispatcher. */
32+
/**
33+
* Default implementation of dispatcher.
34+
*
35+
* <p>CEL Library Internals. Do Not Use.
36+
*/
3137
@Immutable
32-
final class DefaultDispatcher implements CelFunctionResolver {
38+
@Internal
39+
public final class DefaultDispatcher implements CelFunctionResolver {
3340

3441
private final ImmutableMap<String, CelResolvedOverload> overloads;
3542

43+
public Optional<CelResolvedOverload> findOverload(String functionName) {
44+
return Optional.ofNullable(overloads.get(functionName));
45+
}
46+
3647
@Override
3748
public Optional<CelResolvedOverload> findOverloadMatchingArgs(
3849
String functionName, List<String> overloadIds, Object[] args) throws CelEvaluationException {
@@ -101,24 +112,26 @@ Optional<CelResolvedOverload> findSingleNonStrictOverload(List<String> overloadI
101112
return Optional.empty();
102113
}
103114

104-
static Builder newBuilder() {
115+
public static Builder newBuilder() {
105116
return new AutoBuilder_DefaultDispatcher_Builder();
106117
}
107118

119+
/** Builder for {@link DefaultDispatcher}. */
108120
@AutoBuilder(ofClass = DefaultDispatcher.class)
109-
abstract static class Builder {
121+
public abstract static class Builder {
110122

111123
abstract ImmutableMap<String, CelResolvedOverload> overloads();
112124

113125
abstract ImmutableMap.Builder<String, CelResolvedOverload> overloadsBuilder();
114126

115127
@CanIgnoreReturnValue
116-
Builder addOverload(
128+
public Builder addOverload(
117129
String overloadId,
118130
List<Class<?>> argTypes,
119131
boolean isStrict,
120132
CelFunctionOverload overload) {
121133
checkNotNull(overloadId);
134+
checkArgument(!overloadId.isEmpty(), "Overload ID cannot be empty.");
122135
checkNotNull(argTypes);
123136
checkNotNull(overload);
124137

@@ -127,7 +140,7 @@ Builder addOverload(
127140
return this;
128141
}
129142

130-
abstract DefaultDispatcher build();
143+
public abstract DefaultDispatcher build();
131144
}
132145

133146
DefaultDispatcher(ImmutableMap<String, CelResolvedOverload> overloads) {

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,32 @@ java_library(
1414
],
1515
deps = [
1616
":attribute",
17+
":eval_and",
1718
":eval_attribute",
1819
":eval_const",
1920
":eval_create_list",
2021
":eval_create_map",
2122
":eval_create_struct",
23+
":eval_or",
24+
":eval_unary",
25+
":eval_var_args_call",
26+
":eval_zero_arity",
2227
":planned_program",
2328
"//:auto_value",
2429
"//common:cel_ast",
2530
"//common:container",
31+
"//common:operator",
2632
"//common/annotations",
2733
"//common/ast",
2834
"//common/types",
2935
"//common/types:type_providers",
3036
"//common/values:cel_value_provider",
37+
"//runtime:dispatcher",
3138
"//runtime:evaluation_exception",
3239
"//runtime:evaluation_exception_builder",
3340
"//runtime:interpretable",
3441
"//runtime:program",
42+
"//runtime:resolved_overload",
3543
"@maven//:com_google_code_findbugs_annotations",
3644
"@maven//:com_google_errorprone_error_prone_annotations",
3745
"@maven//:com_google_guava_guava",
@@ -43,8 +51,11 @@ java_library(
4351
srcs = ["PlannedProgram.java"],
4452
deps = [
4553
"//:auto_value",
54+
"//common:runtime_exception",
55+
"//common/values",
4656
"//runtime:activation",
4757
"//runtime:evaluation_exception",
58+
"//runtime:evaluation_exception_builder",
4859
"//runtime:function_resolver",
4960
"//runtime:interpretable",
5061
"//runtime:program",
@@ -95,6 +106,70 @@ java_library(
95106
],
96107
)
97108

109+
java_library(
110+
name = "eval_zero_arity",
111+
srcs = ["EvalZeroArity.java"],
112+
deps = [
113+
"//runtime:evaluation_exception",
114+
"//runtime:evaluation_listener",
115+
"//runtime:function_resolver",
116+
"//runtime:interpretable",
117+
"//runtime:resolved_overload",
118+
],
119+
)
120+
121+
java_library(
122+
name = "eval_unary",
123+
srcs = ["EvalUnary.java"],
124+
deps = [
125+
"//runtime:evaluation_exception",
126+
"//runtime:evaluation_listener",
127+
"//runtime:function_resolver",
128+
"//runtime:interpretable",
129+
"//runtime:resolved_overload",
130+
],
131+
)
132+
133+
java_library(
134+
name = "eval_var_args_call",
135+
srcs = ["EvalVarArgsCall.java"],
136+
deps = [
137+
"//runtime:evaluation_exception",
138+
"//runtime:evaluation_listener",
139+
"//runtime:function_resolver",
140+
"//runtime:interpretable",
141+
"//runtime:resolved_overload",
142+
],
143+
)
144+
145+
java_library(
146+
name = "eval_or",
147+
srcs = ["EvalOr.java"],
148+
deps = [
149+
":eval_helpers",
150+
"//common/values",
151+
"//runtime:evaluation_exception",
152+
"//runtime:evaluation_listener",
153+
"//runtime:function_resolver",
154+
"//runtime:interpretable",
155+
"@maven//:com_google_guava_guava",
156+
],
157+
)
158+
159+
java_library(
160+
name = "eval_and",
161+
srcs = ["EvalAnd.java"],
162+
deps = [
163+
":eval_helpers",
164+
"//common/values",
165+
"//runtime:evaluation_exception",
166+
"//runtime:evaluation_listener",
167+
"//runtime:function_resolver",
168+
"//runtime:interpretable",
169+
"@maven//:com_google_guava_guava",
170+
],
171+
)
172+
98173
java_library(
99174
name = "eval_create_struct",
100175
srcs = ["EvalCreateStruct.java"],
@@ -136,3 +211,12 @@ java_library(
136211
"@maven//:com_google_guava_guava",
137212
],
138213
)
214+
215+
java_library(
216+
name = "eval_helpers",
217+
srcs = ["EvalHelpers.java"],
218+
deps = [
219+
"//common/values",
220+
"//runtime:interpretable",
221+
],
222+
)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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.runtime.planner;
16+
17+
import static dev.cel.runtime.planner.EvalHelpers.evalNonstrictly;
18+
19+
import com.google.common.base.Preconditions;
20+
import dev.cel.common.values.ErrorValue;
21+
import dev.cel.runtime.CelEvaluationListener;
22+
import dev.cel.runtime.CelFunctionResolver;
23+
import dev.cel.runtime.GlobalResolver;
24+
import dev.cel.runtime.Interpretable;
25+
26+
final class EvalAnd implements Interpretable {
27+
28+
@SuppressWarnings("Immutable")
29+
private final Interpretable[] args;
30+
31+
@Override
32+
public Object eval(GlobalResolver resolver) {
33+
ErrorValue errorValue = null;
34+
for (Interpretable arg : args) {
35+
Object argVal = evalNonstrictly(arg, resolver);
36+
if (argVal instanceof Boolean) {
37+
// Short-circuit on false
38+
if (!((boolean) argVal)) {
39+
return false;
40+
}
41+
} else if (argVal instanceof ErrorValue) {
42+
errorValue = (ErrorValue) argVal;
43+
}
44+
}
45+
46+
if (errorValue != null) {
47+
return errorValue;
48+
}
49+
50+
return true;
51+
}
52+
53+
@Override
54+
public Object eval(GlobalResolver resolver, CelEvaluationListener listener) {
55+
// TODO: Implement support
56+
throw new UnsupportedOperationException("Not yet supported");
57+
}
58+
59+
@Override
60+
public Object eval(GlobalResolver resolver, CelFunctionResolver lateBoundFunctionResolver) {
61+
// TODO: Implement support
62+
throw new UnsupportedOperationException("Not yet supported");
63+
}
64+
65+
@Override
66+
public Object eval(
67+
GlobalResolver resolver,
68+
CelFunctionResolver lateBoundFunctionResolver,
69+
CelEvaluationListener listener) {
70+
// TODO: Implement support
71+
throw new UnsupportedOperationException("Not yet supported");
72+
}
73+
74+
static EvalAnd create(Interpretable[] args) {
75+
return new EvalAnd(args);
76+
}
77+
78+
private EvalAnd(Interpretable[] args) {
79+
Preconditions.checkArgument(args.length == 2);
80+
this.args = args;
81+
}
82+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.runtime.planner;
16+
17+
import dev.cel.common.values.ErrorValue;
18+
import dev.cel.runtime.GlobalResolver;
19+
import dev.cel.runtime.Interpretable;
20+
21+
final class EvalHelpers {
22+
23+
static Object evalNonstrictly(Interpretable interpretable, GlobalResolver resolver) {
24+
try {
25+
return interpretable.eval(resolver);
26+
} catch (Exception e) {
27+
return ErrorValue.create(e);
28+
}
29+
}
30+
31+
private EvalHelpers() {}
32+
}

0 commit comments

Comments
 (0)