Skip to content

Commit 6d065c7

Browse files
l46kokcopybara-github
authored andcommitted
Group overloads to a single function to facilitate dynamic dispatch
PiperOrigin-RevId: 850451906
1 parent ceb8db3 commit 6d065c7

10 files changed

Lines changed: 346 additions & 232 deletions

File tree

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ java_library(
123123
deps = [
124124
":evaluation_exception",
125125
":evaluation_exception_builder",
126+
":function_binding",
126127
":function_overload",
127128
":function_resolver",
128129
":resolved_overload",
@@ -142,6 +143,7 @@ cel_android_library(
142143
deps = [
143144
":evaluation_exception",
144145
":evaluation_exception_builder",
146+
":function_binding_android",
145147
":function_overload_android",
146148
":function_resolver_android",
147149
":resolved_overload_android",
@@ -611,6 +613,7 @@ java_library(
611613
deps = [
612614
":function_binding",
613615
":runtime_equality",
616+
"//common:operator",
614617
"//common:options",
615618
"//common/annotations",
616619
"//runtime/standard:add",
@@ -668,6 +671,7 @@ cel_android_library(
668671
deps = [
669672
":function_binding_android",
670673
":runtime_equality_android",
674+
"//common:operator_android",
671675
"//common:options",
672676
"//common/annotations",
673677
"//runtime/standard:add_android",
@@ -725,6 +729,7 @@ java_library(
725729
tags = [
726730
],
727731
deps = [
732+
":evaluation_exception",
728733
":function_overload",
729734
"@maven//:com_google_errorprone_error_prone_annotations",
730735
"@maven//:com_google_guava_guava",
@@ -737,6 +742,7 @@ cel_android_library(
737742
tags = [
738743
],
739744
deps = [
745+
":evaluation_exception",
740746
":function_overload_android",
741747
"@maven//:com_google_errorprone_error_prone_annotations",
742748
"@maven_android//:com_google_guava_guava",
@@ -776,7 +782,9 @@ java_library(
776782
],
777783
deps = [
778784
":evaluation_exception",
785+
"//runtime:unknown_attributes",
779786
"@maven//:com_google_errorprone_error_prone_annotations",
787+
"@maven//:com_google_guava_guava",
780788
],
781789
)
782790

@@ -787,7 +795,9 @@ cel_android_library(
787795
],
788796
deps = [
789797
":evaluation_exception",
798+
"//runtime:unknown_attributes_android",
790799
"@maven//:com_google_errorprone_error_prone_annotations",
800+
"@maven_android//:com_google_guava_guava",
791801
],
792802
)
793803

@@ -1177,7 +1187,6 @@ java_library(
11771187
],
11781188
deps = [
11791189
":function_overload",
1180-
":unknown_attributes",
11811190
"//:auto_value",
11821191
"//common/annotations",
11831192
"@maven//:com_google_errorprone_error_prone_annotations",
@@ -1192,7 +1201,6 @@ cel_android_library(
11921201
],
11931202
deps = [
11941203
":function_overload_android",
1195-
":unknown_attributes_android",
11961204
"//:auto_value",
11971205
"//common/annotations",
11981206
"@maven//:com_google_errorprone_error_prone_annotations",

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@
1414

1515
package dev.cel.runtime;
1616

17+
import static com.google.common.base.Preconditions.checkArgument;
18+
19+
import com.google.common.base.Strings;
1720
import com.google.common.collect.ImmutableList;
21+
import com.google.common.collect.ImmutableSet;
1822
import com.google.errorprone.annotations.Immutable;
23+
import java.util.Collection;
1924

2025
/**
2126
* Binding consisting of an overload id, a Java-native argument signature, and an overload
@@ -35,7 +40,6 @@
3540
*
3641
* <p>Examples: string_startsWith_string, mathMax_list, lessThan_money_money
3742
*/
38-
3943
@Immutable
4044
public interface CelFunctionBinding {
4145
String getOverloadId();
@@ -70,4 +74,23 @@ static CelFunctionBinding from(
7074
return new FunctionBindingImpl(
7175
overloadId, ImmutableList.copyOf(argTypes), impl, /* isStrict= */ true);
7276
}
77+
78+
/** See {@link #fromOverloads(String, Collection)}. */
79+
static ImmutableSet<CelFunctionBinding> fromOverloads(
80+
String functionName, CelFunctionBinding... overloadBindings) {
81+
return fromOverloads(functionName, ImmutableList.copyOf(overloadBindings));
82+
}
83+
84+
/**
85+
* Creates a set of bindings for a function, enabling dynamic dispatch logic to select the correct
86+
* overload at runtime based on argument types.
87+
*/
88+
static ImmutableSet<CelFunctionBinding> fromOverloads(
89+
String functionName, Collection<CelFunctionBinding> overloadBindings) {
90+
checkArgument(!Strings.isNullOrEmpty(functionName), "Function name cannot be null or empty");
91+
checkArgument(!overloadBindings.isEmpty(), "You must provide at least one binding.");
92+
93+
return FunctionBindingImpl.groupOverloadsToFunction(
94+
functionName, ImmutableSet.copyOf(overloadBindings));
95+
}
7396
}

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
package dev.cel.runtime;
1616

17+
import com.google.common.collect.ImmutableList;
1718
import com.google.errorprone.annotations.Immutable;
19+
import java.util.Map;
1820

1921
/** Interface describing the general signature of all CEL custom function implementations. */
2022
@Immutable
@@ -43,4 +45,39 @@ interface Unary<T> {
4345
interface Binary<T1, T2> {
4446
Object apply(T1 arg1, T2 arg2) throws CelEvaluationException;
4547
}
48+
49+
/**
50+
* Returns true if the overload's expected argument types match the types of the given arguments.
51+
*/
52+
static boolean canHandle(
53+
Object[] arguments, ImmutableList<Class<?>> parameterTypes, boolean isStrict) {
54+
if (parameterTypes.size() != arguments.length) {
55+
return false;
56+
}
57+
for (int i = 0; i < parameterTypes.size(); i++) {
58+
Class<?> paramType = parameterTypes.get(i);
59+
Object arg = arguments[i];
60+
if (arg == null) {
61+
// null can be assigned to messages, maps, and to objects.
62+
// TODO: Remove null special casing
63+
if (paramType != Object.class && !Map.class.isAssignableFrom(paramType)) {
64+
return false;
65+
}
66+
continue;
67+
}
68+
69+
if (arg instanceof Exception || arg instanceof CelUnknownSet) {
70+
// Only non-strict functions can accept errors/unknowns as arguments to a function
71+
if (!isStrict) {
72+
// Skip assignability check below, but continue to validate remaining args
73+
continue;
74+
}
75+
}
76+
77+
if (!paramType.isAssignableFrom(arg.getClass())) {
78+
return false;
79+
}
80+
}
81+
return true;
82+
}
4683
}

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

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.google.errorprone.annotations.Immutable;
2020
import dev.cel.common.annotations.Internal;
2121
import java.util.List;
22-
import java.util.Map;
2322

2423
/**
2524
* Representation of a function overload which has been resolved to a specific set of argument types
@@ -80,41 +79,6 @@ public static CelResolvedOverload of(
8079
* Returns true if the overload's expected argument types match the types of the given arguments.
8180
*/
8281
boolean canHandle(Object[] arguments) {
83-
return canHandle(arguments, getParameterTypes(), isStrict());
84-
}
85-
86-
/**
87-
* Returns true if the overload's expected argument types match the types of the given arguments.
88-
*/
89-
public static boolean canHandle(
90-
Object[] arguments, ImmutableList<Class<?>> parameterTypes, boolean isStrict) {
91-
if (parameterTypes.size() != arguments.length) {
92-
return false;
93-
}
94-
for (int i = 0; i < parameterTypes.size(); i++) {
95-
Class<?> paramType = parameterTypes.get(i);
96-
Object arg = arguments[i];
97-
if (arg == null) {
98-
// null can be assigned to messages, maps, and to objects.
99-
// TODO: Remove null special casing
100-
if (paramType != Object.class && !Map.class.isAssignableFrom(paramType)) {
101-
return false;
102-
}
103-
continue;
104-
}
105-
106-
if (arg instanceof Exception || arg instanceof CelUnknownSet) {
107-
// Only non-strict functions can accept errors/unknowns as arguments to a function
108-
if (!isStrict) {
109-
// Skip assignability check below, but continue to validate remaining args
110-
continue;
111-
}
112-
}
113-
114-
if (!paramType.isAssignableFrom(arg.getClass())) {
115-
return false;
116-
}
117-
}
118-
return true;
82+
return CelFunctionOverload.canHandle(arguments, getParameterTypes(), isStrict());
11983
}
12084
}

0 commit comments

Comments
 (0)