Skip to content

Commit ac7e60f

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

File tree

14 files changed

+1035
-15
lines changed

14 files changed

+1035
-15
lines changed

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: 82 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",
@@ -45,6 +53,7 @@ java_library(
4553
"//:auto_value",
4654
"//runtime:activation",
4755
"//runtime:evaluation_exception",
56+
"//runtime:evaluation_exception_builder",
4857
"//runtime:function_resolver",
4958
"//runtime:interpretable",
5059
"//runtime:program",
@@ -95,6 +104,70 @@ java_library(
95104
],
96105
)
97106

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