Skip to content

Commit 69a6d54

Browse files
l46kokcopybara-github
authored andcommitted
Add isStrict flag to denote function overloads as strict
PiperOrigin-RevId: 824731652
1 parent 741e5d0 commit 69a6d54

13 files changed

+87
-48
lines changed

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ java_library(
118118
tags = [
119119
],
120120
deps = [
121-
":base",
122121
":evaluation_exception",
123122
":evaluation_exception_builder",
123+
":function_overload",
124124
":resolved_overload",
125125
":resolved_overload_internal",
126126
"//:auto_value",
@@ -138,9 +138,9 @@ cel_android_library(
138138
srcs = DISPATCHER_SOURCES,
139139
visibility = ["//visibility:private"],
140140
deps = [
141-
":base_android",
142141
":evaluation_exception",
143142
":evaluation_exception_builder",
143+
":function_overload_android",
144144
":function_resolver_android",
145145
":resolved_overload_android",
146146
":resolved_overload_internal_android",
@@ -725,7 +725,6 @@ java_library(
725725
],
726726
deps = [
727727
":function_overload",
728-
"//common/annotations",
729728
"@maven//:com_google_errorprone_error_prone_annotations",
730729
"@maven//:com_google_guava_guava",
731730
],
@@ -738,7 +737,6 @@ cel_android_library(
738737
],
739738
deps = [
740739
":function_overload_android",
741-
"//common/annotations",
742740
"@maven//:com_google_errorprone_error_prone_annotations",
743741
"@maven_android//:com_google_guava_guava",
744742
],

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import com.google.common.collect.ImmutableList;
1818
import com.google.errorprone.annotations.Immutable;
19-
import dev.cel.common.annotations.Internal;
2019

2120
/**
2221
* Binding consisting of an overload id, a Java-native argument signature, and an overload
@@ -36,7 +35,7 @@
3635
*
3736
* <p>Examples: string_startsWith_string, mathMax_list, lessThan_money_money
3837
*/
39-
@Internal
38+
4039
@Immutable
4140
public interface CelFunctionBinding {
4241
String getOverloadId();
@@ -45,6 +44,8 @@ public interface CelFunctionBinding {
4544

4645
CelFunctionOverload getDefinition();
4746

47+
boolean isStrict();
48+
4849
/** Create a unary function binding from the {@code overloadId}, {@code arg}, and {@code impl}. */
4950
@SuppressWarnings("unchecked")
5051
static <T> CelFunctionBinding from(
@@ -66,6 +67,7 @@ static <T1, T2> CelFunctionBinding from(
6667
/** Create a function binding from the {@code overloadId}, {@code argTypes}, and {@code impl}. */
6768
static CelFunctionBinding from(
6869
String overloadId, Iterable<Class<?>> argTypes, CelFunctionOverload impl) {
69-
return new FunctionBindingImpl(overloadId, ImmutableList.copyOf(argTypes), impl);
70+
return new FunctionBindingImpl(
71+
overloadId, ImmutableList.copyOf(argTypes), impl, /* isStrict= */ true);
7072
}
7173
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ private static ResolvedOverload createResolvedOverload(CelFunctionBinding bindin
5858
return CelResolvedOverload.of(
5959
binding.getOverloadId(),
6060
(args) -> binding.getDefinition().apply(args),
61+
binding.isStrict(),
6162
binding.getArgTypes());
6263
}
6364
}

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ abstract class CelResolvedOverload implements ResolvedOverload {
3535
@Override
3636
public abstract ImmutableList<Class<?>> getParameterTypes();
3737

38+
/* Denotes whether an overload is strict.
39+
*
40+
* <p>A strict function will not be invoked if any of its arguments are an error or unknown value.
41+
* The runtime automatically propagates the error or unknown instead.
42+
*
43+
* <p>A non-strict function will be invoked even if its arguments contain errors or unknowns. The
44+
* function's implementation is then responsible for handling these values. This is primarily used
45+
* for short-circuiting logical operators (e.g., `||`, `&&`) and comprehension's
46+
* internal @not_strictly_false function.
47+
*
48+
* <p>In a vast majority of cases, this should be set to true.
49+
*/
50+
@Override
51+
public abstract boolean isStrict();
52+
3853
/** The function definition. */
3954
@Override
4055
public abstract CelFunctionOverload getDefinition();
@@ -43,16 +58,22 @@ abstract class CelResolvedOverload implements ResolvedOverload {
4358
* Creates a new resolved overload from the given overload id, parameter types, and definition.
4459
*/
4560
public static CelResolvedOverload of(
46-
String overloadId, CelFunctionOverload definition, Class<?>... parameterTypes) {
47-
return of(overloadId, definition, ImmutableList.copyOf(parameterTypes));
61+
String overloadId,
62+
CelFunctionOverload definition,
63+
boolean isStrict,
64+
Class<?>... parameterTypes) {
65+
return of(overloadId, definition, isStrict, ImmutableList.copyOf(parameterTypes));
4866
}
4967

5068
/**
5169
* Creates a new resolved overload from the given overload id, parameter types, and definition.
5270
*/
5371
public static CelResolvedOverload of(
54-
String overloadId, CelFunctionOverload definition, List<Class<?>> parameterTypes) {
72+
String overloadId,
73+
CelFunctionOverload definition,
74+
boolean isStrict,
75+
List<Class<?>> parameterTypes) {
5576
return new AutoValue_CelResolvedOverload(
56-
overloadId, ImmutableList.copyOf(parameterTypes), definition);
77+
overloadId, ImmutableList.copyOf(parameterTypes), isStrict, definition);
5778
}
5879
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public CelRuntimeLegacyImpl build() {
293293
.forEach(
294294
(String overloadId, CelFunctionBinding func) ->
295295
dispatcher.add(
296-
overloadId, func.getArgTypes(), (args) -> func.getDefinition().apply(args)));
296+
overloadId, func.getArgTypes(), func.isStrict(), func.getDefinition()));
297297

298298
RuntimeTypeProvider runtimeTypeProvider;
299299

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

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,17 @@
3232
* <p>Should be final, do not mock; mocking {@link Dispatcher} instead.
3333
*/
3434
@ThreadSafe
35-
final class DefaultDispatcher implements Dispatcher, Registrar {
35+
final class DefaultDispatcher implements Dispatcher {
3636
public static DefaultDispatcher create() {
3737
return new DefaultDispatcher();
3838
}
3939

4040
@GuardedBy("this")
4141
private final Map<String, ResolvedOverload> overloads = new HashMap<>();
4242

43-
@Override
44-
@SuppressWarnings("unchecked")
45-
public synchronized <T> void add(
46-
String overloadId, Class<T> argType, final Registrar.UnaryFunction<T> function) {
47-
overloads.put(
48-
overloadId,
49-
CelResolvedOverload.of(overloadId, args -> function.apply((T) args[0]), argType));
50-
}
51-
52-
@Override
53-
@SuppressWarnings("unchecked")
54-
public synchronized <T1, T2> void add(
55-
String overloadId,
56-
Class<T1> argType1,
57-
Class<T2> argType2,
58-
final Registrar.BinaryFunction<T1, T2> function) {
59-
overloads.put(
60-
overloadId,
61-
CelResolvedOverload.of(
62-
overloadId, args -> function.apply((T1) args[0], (T2) args[1]), argType1, argType2));
63-
}
64-
65-
@Override
6643
public synchronized void add(
67-
String overloadId, List<Class<?>> argTypes, Registrar.Function function) {
68-
overloads.put(overloadId, CelResolvedOverload.of(overloadId, function, argTypes));
44+
String overloadId, List<Class<?>> argTypes, boolean isStrict, CelFunctionOverload overload) {
45+
overloads.put(overloadId, CelResolvedOverload.of(overloadId, overload, isStrict, argTypes));
6946
}
7047

7148
@Override

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ final class FunctionBindingImpl implements CelFunctionBinding {
2626

2727
private final CelFunctionOverload definition;
2828

29+
private final boolean isStrict;
30+
2931
@Override
3032
public String getOverloadId() {
3133
return overloadId;
@@ -41,10 +43,19 @@ public CelFunctionOverload getDefinition() {
4143
return definition;
4244
}
4345

46+
@Override
47+
public boolean isStrict() {
48+
return isStrict;
49+
}
50+
4451
FunctionBindingImpl(
45-
String overloadId, ImmutableList<Class<?>> argTypes, CelFunctionOverload definition) {
52+
String overloadId,
53+
ImmutableList<Class<?>> argTypes,
54+
CelFunctionOverload definition,
55+
boolean isStrict) {
4656
this.overloadId = overloadId;
4757
this.argTypes = argTypes;
4858
this.definition = definition;
59+
this.isStrict = isStrict;
4960
}
5061
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ public CelLiteRuntime build() {
182182
.forEach(
183183
(String overloadId, CelFunctionBinding func) ->
184184
dispatcher.add(
185-
overloadId, func.getArgTypes(), (args) -> func.getDefinition().apply(args)));
185+
overloadId,
186+
func.getArgTypes(),
187+
func.isStrict(),
188+
(args) -> func.getDefinition().apply(args)));
186189

187190
Interpreter interpreter =
188191
new DefaultInterpreter(

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
package dev.cel.runtime;
1616

1717
import com.google.errorprone.annotations.Immutable;
18-
import dev.cel.common.annotations.Internal;
1918
import java.util.List;
2019

2120
/**
2221
* An object which registers the functions that a {@link Dispatcher} calls.
2322
*
24-
* <p>CEL Library Internals. Do Not Use.
23+
* @deprecated Do not use. This interface exists solely for legacy async stack compatibility
24+
* reasons.
2525
*/
26-
@Internal
26+
@Deprecated
2727
public interface Registrar {
2828

2929
/** Interface describing the general signature of all CEL custom function implementations. */

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ interface ResolvedOverload {
3535
/** The function definition. */
3636
CelFunctionOverload getDefinition();
3737

38+
/**
39+
* Denotes whether an overload is strict.
40+
*
41+
* <p>A strict function will not be invoked if any of its arguments are an error or unknown value.
42+
* The runtime automatically propagates the error or unknown instead.
43+
*
44+
* <p>A non-strict function will be invoked even if its arguments contain errors or unknowns. The
45+
* function's implementation is then responsible for handling these values. This is primarily used
46+
* for short-circuiting logical operators (e.g., `||`, `&&`) and comprehension's
47+
* internal @not_strictly_false function.
48+
*
49+
* <p>In a vast majority of cases, a function should be kept strict.
50+
*/
51+
boolean isStrict();
52+
3853
/**
3954
* Returns true if the overload's expected argument types match the types of the given arguments.
4055
*/

0 commit comments

Comments
 (0)