diff --git a/bundle/src/main/java/dev/cel/bundle/CelBuilder.java b/bundle/src/main/java/dev/cel/bundle/CelBuilder.java
index 1dadaeb39..9c0b5d3b2 100644
--- a/bundle/src/main/java/dev/cel/bundle/CelBuilder.java
+++ b/bundle/src/main/java/dev/cel/bundle/CelBuilder.java
@@ -197,8 +197,7 @@ public interface CelBuilder {
* provider will be used first before falling back to the built-in {@link
* dev.cel.common.values.ProtoMessageValueProvider} for resolving protobuf messages.
*
- *
Note that {@link CelOptions#enableCelValue()} must be enabled or this method will be a
- * no-op.
+ *
Note that this option is only supported for planner-based runtime.
*/
@CanIgnoreReturnValue
CelBuilder setValueProvider(CelValueProvider celValueProvider);
diff --git a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java
index 0708b37c3..1b887ff60 100644
--- a/bundle/src/test/java/dev/cel/bundle/CelImplTest.java
+++ b/bundle/src/test/java/dev/cel/bundle/CelImplTest.java
@@ -560,24 +560,6 @@ public void program_withVars() throws Exception {
assertThat(program.eval(ImmutableMap.of("variable", "hello"))).isEqualTo(true);
}
- @Test
- public void program_withCelValue() throws Exception {
- Cel cel =
- standardCelBuilderWithMacros()
- .setOptions(CelOptions.current().enableCelValue(true).build())
- .addDeclarations(
- Decl.newBuilder()
- .setName("variable")
- .setIdent(IdentDecl.newBuilder().setType(CelProtoTypes.STRING))
- .build())
- .setResultType(SimpleType.BOOL)
- .build();
-
- CelRuntime.Program program = cel.createProgram(cel.compile("variable == 'hello'").getAst());
-
- assertThat(program.eval(ImmutableMap.of("variable", "hello"))).isEqualTo(true);
- }
-
@Test
public void program_withProtoVars() throws Exception {
Cel cel =
@@ -1426,26 +1408,6 @@ public void programAdvanceEvaluation_nestedSelect() throws Exception {
.isEqualTo(CelUnknownSet.create(CelAttribute.fromQualifiedIdentifier("com.google.a")));
}
- @Test
- public void programAdvanceEvaluation_nestedSelect_withCelValue() throws Exception {
- Cel cel =
- standardCelBuilderWithMacros()
- .setOptions(
- CelOptions.current().enableUnknownTracking(true).enableCelValue(true).build())
- .addVar("com", MapType.create(SimpleType.STRING, SimpleType.DYN))
- .addFunctionBindings()
- .setResultType(SimpleType.BOOL)
- .build();
- CelRuntime.Program program = cel.createProgram(cel.compile("com.google.a || false").getAst());
-
- assertThat(
- program.advanceEvaluation(
- UnknownContext.create(
- fromMap(ImmutableMap.of()),
- ImmutableList.of(CelAttributePattern.fromQualifiedIdentifier("com.google.a")))))
- .isEqualTo(CelUnknownSet.create(CelAttribute.fromQualifiedIdentifier("com.google.a")));
- }
-
@Test
public void programAdvanceEvaluation_argumentMergeErrorPriority() throws Exception {
Cel cel =
diff --git a/checker/src/main/java/dev/cel/checker/DescriptorTypeProvider.java b/checker/src/main/java/dev/cel/checker/DescriptorTypeProvider.java
index b5f849d50..47e180b0f 100644
--- a/checker/src/main/java/dev/cel/checker/DescriptorTypeProvider.java
+++ b/checker/src/main/java/dev/cel/checker/DescriptorTypeProvider.java
@@ -67,7 +67,10 @@ public DescriptorTypeProvider() {
/**
* Constructs a provider based on the given file descriptor set proto, as it is emitted by the
* protocol compiler.
+ *
+ * @deprecated Do not use. Migrate to CEL-Java fluent APIs.
*/
+ @Deprecated
public DescriptorTypeProvider(FileDescriptorSet descriptorSet) {
this(FileDescriptorSetConverter.convert(descriptorSet));
}
diff --git a/common/BUILD.bazel b/common/BUILD.bazel
index 21a124565..bffc1af37 100644
--- a/common/BUILD.bazel
+++ b/common/BUILD.bazel
@@ -22,6 +22,11 @@ java_library(
exports = ["//common/src/main/java/dev/cel/common:container"],
)
+cel_android_library(
+ name = "container_android",
+ exports = ["//common/src/main/java/dev/cel/common:container_android"],
+)
+
java_library(
name = "proto_ast",
exports = ["//common/src/main/java/dev/cel/common:proto_ast"],
diff --git a/common/src/main/java/dev/cel/common/BUILD.bazel b/common/src/main/java/dev/cel/common/BUILD.bazel
index 62ba8db78..821922fc2 100644
--- a/common/src/main/java/dev/cel/common/BUILD.bazel
+++ b/common/src/main/java/dev/cel/common/BUILD.bazel
@@ -342,6 +342,18 @@ java_library(
],
)
+cel_android_library(
+ name = "container_android",
+ srcs = ["CelContainer.java"],
+ tags = [
+ ],
+ deps = [
+ "//:auto_value",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "operator",
srcs = ["Operator.java"],
diff --git a/common/src/main/java/dev/cel/common/CelOptions.java b/common/src/main/java/dev/cel/common/CelOptions.java
index d0b020697..498391598 100644
--- a/common/src/main/java/dev/cel/common/CelOptions.java
+++ b/common/src/main/java/dev/cel/common/CelOptions.java
@@ -17,7 +17,6 @@
import com.google.auto.value.AutoValue;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.Immutable;
-import dev.cel.common.annotations.Beta;
/**
* Options to configure how the CEL parser, type-checker, and evaluator behave.
@@ -107,8 +106,6 @@ public enum ProtoUnsetFieldOptions {
public abstract boolean enableUnknownTracking();
- public abstract boolean enableCelValue();
-
public abstract int comprehensionMaxIterations();
public abstract boolean evaluateCanonicalTypesToNativeValues();
@@ -165,7 +162,6 @@ public static Builder newBuilder() {
.errorOnDuplicateMapKeys(false)
.resolveTypeDependencies(true)
.enableUnknownTracking(false)
- .enableCelValue(false)
.comprehensionMaxIterations(-1)
.unwrapWellKnownTypesOnFunctionDispatch(true)
.fromProtoUnsetFieldOption(ProtoUnsetFieldOptions.BIND_DEFAULT)
@@ -435,16 +431,6 @@ public abstract static class Builder {
*/
public abstract Builder enableUnknownTracking(boolean value);
- /**
- * Enables the usage of {@code CelValue} for the runtime. It is a native value representation of
- * CEL that wraps Java native objects, and comes with extended capabilities, such as allowing
- * value constructs not understood by CEL (ex: POJOs).
- *
- *
Warning: This option is experimental.
- */
- @Beta
- public abstract Builder enableCelValue(boolean value);
-
/**
* Limit the total number of iterations permitted within comprehension loops.
*
diff --git a/common/src/main/java/dev/cel/common/types/BUILD.bazel b/common/src/main/java/dev/cel/common/types/BUILD.bazel
index a35a897b8..23ec63e62 100644
--- a/common/src/main/java/dev/cel/common/types/BUILD.bazel
+++ b/common/src/main/java/dev/cel/common/types/BUILD.bazel
@@ -183,6 +183,32 @@ java_library(
],
)
+java_library(
+ name = "message_lite_type_provider",
+ srcs = [
+ "ProtoMessageLiteTypeProvider.java",
+ ],
+ tags = [
+ ],
+ deps = [
+ "//common/types",
+ "//common/types:type_providers",
+ "//protobuf:cel_lite_descriptor",
+ "@maven//:com_google_guava_guava",
+ ],
+)
+
+cel_android_library(
+ name = "message_lite_type_provider_android",
+ srcs = [
+ "ProtoMessageLiteTypeProvider.java",
+ ],
+ tags = [
+ ],
+ deps = [
+ ],
+)
+
java_library(
name = "default_type_provider",
srcs = [
@@ -193,10 +219,26 @@ java_library(
deps = [
":type_providers",
":types",
+ "@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
],
)
+cel_android_library(
+ name = "default_type_provider_android",
+ srcs = [
+ "DefaultTypeProvider.java",
+ ],
+ tags = [
+ ],
+ deps = [
+ ":type_providers_android",
+ ":types_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
cel_android_library(
name = "cel_types_android",
srcs = ["CelTypes.java"],
diff --git a/common/src/main/java/dev/cel/common/types/DefaultTypeProvider.java b/common/src/main/java/dev/cel/common/types/DefaultTypeProvider.java
index 84e6c9ede..372a50e73 100644
--- a/common/src/main/java/dev/cel/common/types/DefaultTypeProvider.java
+++ b/common/src/main/java/dev/cel/common/types/DefaultTypeProvider.java
@@ -16,9 +16,11 @@
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.Immutable;
import java.util.Optional;
/** {@code DefaultTypeProvider} is a registry of common CEL types. */
+@Immutable
public class DefaultTypeProvider implements CelTypeProvider {
private static final DefaultTypeProvider INSTANCE = new DefaultTypeProvider();
@@ -43,6 +45,7 @@ private DefaultTypeProvider() {
typeMapBuilder.putAll(SimpleType.TYPE_MAP);
typeMapBuilder.put("list", ListType.create(SimpleType.DYN));
typeMapBuilder.put("map", MapType.create(SimpleType.DYN, SimpleType.DYN));
+ typeMapBuilder.put("type", TypeType.create(SimpleType.DYN));
typeMapBuilder.put(
"optional_type",
// TODO: Move to CelOptionalLibrary and register it on demand
diff --git a/common/src/main/java/dev/cel/common/types/ProtoMessageLiteTypeProvider.java b/common/src/main/java/dev/cel/common/types/ProtoMessageLiteTypeProvider.java
new file mode 100644
index 000000000..9de3fc322
--- /dev/null
+++ b/common/src/main/java/dev/cel/common/types/ProtoMessageLiteTypeProvider.java
@@ -0,0 +1,123 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dev.cel.common.types;
+
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
+
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import dev.cel.protobuf.CelLiteDescriptor;
+import dev.cel.protobuf.CelLiteDescriptor.FieldLiteDescriptor;
+import dev.cel.protobuf.CelLiteDescriptor.MessageLiteDescriptor;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
+/** TODO: Add */
+public final class ProtoMessageLiteTypeProvider implements CelTypeProvider {
+ private static final ImmutableMap PROTO_TYPE_TO_CEL_TYPE =
+ ImmutableMap.builder()
+ .put(FieldLiteDescriptor.Type.DOUBLE, SimpleType.DOUBLE)
+ .put(FieldLiteDescriptor.Type.FLOAT, SimpleType.DOUBLE)
+ .put(FieldLiteDescriptor.Type.INT64, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.INT32, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.SFIXED32, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.SFIXED64, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.SINT32, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.SINT64, SimpleType.INT)
+ .put(FieldLiteDescriptor.Type.BOOL, SimpleType.BOOL)
+ .put(FieldLiteDescriptor.Type.STRING, SimpleType.STRING)
+ .put(FieldLiteDescriptor.Type.BYTES, SimpleType.BYTES)
+ .put(FieldLiteDescriptor.Type.FIXED32, SimpleType.UINT)
+ .put(FieldLiteDescriptor.Type.FIXED64, SimpleType.UINT)
+ .put(FieldLiteDescriptor.Type.UINT32, SimpleType.UINT)
+ .put(FieldLiteDescriptor.Type.UINT64, SimpleType.UINT)
+ .buildOrThrow();
+
+ private final ImmutableMap allTypes;
+
+ @Override
+ public ImmutableCollection types() {
+ return allTypes.values();
+ }
+
+ @Override
+ public Optional findType(String typeName) {
+ return Optional.empty();
+ }
+
+ public static ProtoMessageLiteTypeProvider newInstance(CelLiteDescriptor... celLiteDescriptors) {
+ return newInstance(ImmutableSet.copyOf(celLiteDescriptors));
+ }
+
+ public static ProtoMessageLiteTypeProvider newInstance(
+ Set celLiteDescriptors) {
+ return new ProtoMessageLiteTypeProvider(celLiteDescriptors);
+ }
+
+ private ProtoMessageLiteTypeProvider(Set celLiteDescriptors) {
+ ImmutableMap.Builder builder = ImmutableMap.builder();
+ for (CelLiteDescriptor descriptor : celLiteDescriptors) {
+ for (Entry entry :
+ descriptor.getProtoTypeNamesToDescriptors().entrySet()) {
+ builder.put(entry.getKey(), createMessageType(entry.getValue()));
+ }
+ }
+
+ this.allTypes = builder.buildOrThrow();
+ }
+
+ private static ProtoMessageType createMessageType(MessageLiteDescriptor messageLiteDescriptor) {
+ ImmutableMap fields =
+ messageLiteDescriptor.getFieldDescriptors().stream()
+ .collect(toImmutableMap(FieldLiteDescriptor::getFieldName, Function.identity()));
+
+ return new ProtoMessageType(
+ messageLiteDescriptor.getProtoTypeName(),
+ fields.keySet(),
+ new FieldResolver(fields),
+ extensionFieldName -> {
+ throw new UnsupportedOperationException(
+ "Proto extensions are not yet supported in MessageLite.");
+ },
+ jsonFieldName -> {
+ throw new UnsupportedOperationException("JSON name is not yet supported in MessageLite.");
+ });
+ }
+
+ private static class FieldResolver implements StructType.FieldResolver {
+ private final ImmutableMap fields;
+
+ @Override
+ public Optional findField(String fieldName) {
+ FieldLiteDescriptor fieldDescriptor = fields.get(fieldName);
+ if (fieldDescriptor == null) {
+ return Optional.empty();
+ }
+
+ FieldLiteDescriptor.Type fieldType = fieldDescriptor.getProtoFieldType();
+ switch (fieldDescriptor.getProtoFieldType()) {
+ default:
+ return Optional.of(PROTO_TYPE_TO_CEL_TYPE.get(fieldType));
+ }
+ }
+
+ private FieldResolver(ImmutableMap fields) {
+ this.fields = fields;
+ }
+ }
+}
diff --git a/common/src/main/java/dev/cel/common/values/BUILD.bazel b/common/src/main/java/dev/cel/common/values/BUILD.bazel
index 3a78091bf..8e7bc2ee3 100644
--- a/common/src/main/java/dev/cel/common/values/BUILD.bazel
+++ b/common/src/main/java/dev/cel/common/values/BUILD.bazel
@@ -57,6 +57,7 @@ java_library(
tags = [
],
deps = [
+ ":values",
"//common/values",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
@@ -81,6 +82,7 @@ java_library(
tags = [
],
deps = [
+ "//common/values",
"//common/values:cel_value_provider",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
@@ -94,6 +96,7 @@ cel_android_library(
],
deps = [
"//common/values:cel_value_provider_android",
+ "//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
],
@@ -286,7 +289,9 @@ java_library(
"//common/annotations",
"//common/internal:cel_lite_descriptor_pool",
"//common/internal:default_lite_descriptor_pool",
+ "//common/values",
"//common/values:base_proto_cel_value_converter",
+ "//common/values:cel_value_provider",
"//protobuf:cel_lite_descriptor",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
@@ -306,6 +311,8 @@ cel_android_library(
"//common/internal:cel_lite_descriptor_pool_android",
"//common/internal:default_lite_descriptor_pool_android",
"//common/values:base_proto_cel_value_converter_android",
+ "//common/values:cel_value_provider_android",
+ "//common/values:values_android",
"//protobuf:cel_lite_descriptor",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
diff --git a/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java b/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java
index f42a16179..f9b7a6ce4 100644
--- a/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java
+++ b/common/src/main/java/dev/cel/common/values/BaseProtoMessageValueProvider.java
@@ -25,7 +25,4 @@
*/
@Internal
@Immutable
-public abstract class BaseProtoMessageValueProvider implements CelValueProvider {
-
- public abstract BaseProtoCelValueConverter protoCelValueConverter();
-}
+public abstract class BaseProtoMessageValueProvider implements CelValueProvider {}
diff --git a/common/src/main/java/dev/cel/common/values/CombinedCelValueProvider.java b/common/src/main/java/dev/cel/common/values/CombinedCelValueProvider.java
index 8fe62cb7b..6aff39a45 100644
--- a/common/src/main/java/dev/cel/common/values/CombinedCelValueProvider.java
+++ b/common/src/main/java/dev/cel/common/values/CombinedCelValueProvider.java
@@ -30,6 +30,7 @@
@Immutable
public final class CombinedCelValueProvider implements CelValueProvider {
private final ImmutableList celValueProviders;
+ private final CelValueConverter celValueConverter;
/** Combines the provided first and second {@link CelValueProvider}. */
public static CombinedCelValueProvider combine(CelValueProvider... providers) {
@@ -49,12 +50,18 @@ public Optional newValue(String structType, Map fields)
return Optional.empty();
}
+ @Override
+ public CelValueConverter celValueConverter() {
+ return celValueConverter;
+ }
+
/** Returns the underlying {@link CelValueProvider}s in order. */
public ImmutableList valueProviders() {
return celValueProviders;
}
private CombinedCelValueProvider(ImmutableList providers) {
- celValueProviders = checkNotNull(providers);
+ this.celValueProviders = checkNotNull(providers);
+ this.celValueConverter = providers.get(0).celValueConverter();
}
}
diff --git a/common/src/main/java/dev/cel/common/values/ProtoLiteCelValueConverter.java b/common/src/main/java/dev/cel/common/values/ProtoLiteCelValueConverter.java
index 3fbb0ad75..e064e1f48 100644
--- a/common/src/main/java/dev/cel/common/values/ProtoLiteCelValueConverter.java
+++ b/common/src/main/java/dev/cel/common/values/ProtoLiteCelValueConverter.java
@@ -28,6 +28,7 @@
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.MessageLite;
+import com.google.protobuf.MessageLiteOrBuilder;
import com.google.protobuf.WireFormat;
import dev.cel.common.annotations.Internal;
import dev.cel.common.internal.CelLiteDescriptorPool;
@@ -163,8 +164,13 @@ Object getDefaultCelValue(String protoTypeName, String fieldName) {
@SuppressWarnings("LiteProtoToString") // No alternative identifier to use. Debug only info is OK.
public Object toRuntimeValue(Object value) {
checkNotNull(value);
- if (value instanceof MessageLite) {
- MessageLite msg = (MessageLite) value;
+ if (value instanceof MessageLiteOrBuilder) {
+ MessageLite msg;
+ if (value instanceof MessageLite.Builder) {
+ msg = ((MessageLite.Builder) value).build();
+ } else {
+ msg = (MessageLite) value;
+ }
MessageLiteDescriptor descriptor =
descriptorPool
diff --git a/common/src/main/java/dev/cel/common/values/ProtoMessageLiteValueProvider.java b/common/src/main/java/dev/cel/common/values/ProtoMessageLiteValueProvider.java
index 041d850a6..b3ee2ef04 100644
--- a/common/src/main/java/dev/cel/common/values/ProtoMessageLiteValueProvider.java
+++ b/common/src/main/java/dev/cel/common/values/ProtoMessageLiteValueProvider.java
@@ -32,12 +32,12 @@
*/
@Immutable
@Beta
-public class ProtoMessageLiteValueProvider extends BaseProtoMessageValueProvider {
+public class ProtoMessageLiteValueProvider implements CelValueProvider {
private final CelLiteDescriptorPool descriptorPool;
private final ProtoLiteCelValueConverter protoLiteCelValueConverter;
@Override
- public BaseProtoCelValueConverter protoCelValueConverter() {
+ public CelValueConverter celValueConverter() {
return protoLiteCelValueConverter;
}
diff --git a/common/src/test/java/dev/cel/common/values/BUILD.bazel b/common/src/test/java/dev/cel/common/values/BUILD.bazel
index ab7eae8dd..d1651379a 100644
--- a/common/src/test/java/dev/cel/common/values/BUILD.bazel
+++ b/common/src/test/java/dev/cel/common/values/BUILD.bazel
@@ -9,7 +9,6 @@ java_library(
srcs = glob(["*.java"]),
deps = [
"//:java_truth",
- "//bundle:cel",
"//common:cel_ast",
"//common:cel_descriptor_util",
"//common:options",
@@ -29,6 +28,9 @@ java_library(
"//common/values:proto_message_lite_value_provider",
"//common/values:proto_message_value",
"//common/values:proto_message_value_provider",
+ "//compiler",
+ "//compiler:compiler_builder",
+ "//runtime",
"//testing/protos:test_all_types_cel_java_proto3",
"@cel_spec//proto/cel/expr/conformance/proto2:test_all_types_java_proto",
"@cel_spec//proto/cel/expr/conformance/proto3:test_all_types_java_proto",
diff --git a/common/src/test/java/dev/cel/common/values/ProtoMessageLiteValueProviderTest.java b/common/src/test/java/dev/cel/common/values/ProtoMessageLiteValueProviderTest.java
index bbe116c80..95e0e031c 100644
--- a/common/src/test/java/dev/cel/common/values/ProtoMessageLiteValueProviderTest.java
+++ b/common/src/test/java/dev/cel/common/values/ProtoMessageLiteValueProviderTest.java
@@ -49,6 +49,6 @@ public void newValue_emptyFields_success() {
@Test
public void getProtoLiteCelValueConverter() {
- assertThat(VALUE_PROVIDER.protoCelValueConverter()).isNotNull();
+ assertThat(VALUE_PROVIDER.celValueConverter()).isNotNull();
}
}
diff --git a/common/src/test/java/dev/cel/common/values/StructValueTest.java b/common/src/test/java/dev/cel/common/values/StructValueTest.java
index b8d6371a8..65bf7cd72 100644
--- a/common/src/test/java/dev/cel/common/values/StructValueTest.java
+++ b/common/src/test/java/dev/cel/common/values/StructValueTest.java
@@ -22,8 +22,6 @@
import com.google.common.collect.ImmutableSet;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import com.google.testing.junit.testparameterinjector.TestParameters;
-import dev.cel.bundle.Cel;
-import dev.cel.bundle.CelFactory;
import dev.cel.common.CelAbstractSyntaxTree;
import dev.cel.common.CelOptions;
import dev.cel.common.internal.DynamicProto;
@@ -31,6 +29,11 @@
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructType;
+import dev.cel.compiler.CelCompiler;
+import dev.cel.compiler.CelCompilerFactory;
+import dev.cel.expr.conformance.proto3.TestAllTypes;
+import dev.cel.runtime.CelRuntime;
+import dev.cel.runtime.CelRuntimeFactory;
import java.util.Map;
import java.util.Optional;
import org.junit.Test;
@@ -114,72 +117,92 @@ public void celTypeTest() {
@Test
public void evaluate_usingCustomClass_createNewStruct() throws Exception {
- Cel cel =
- CelFactory.standardCelBuilder()
- .setOptions(CelOptions.current().enableCelValue(true).build())
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
.setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
.setValueProvider(CUSTOM_STRUCT_VALUE_PROVIDER)
.build();
- CelAbstractSyntaxTree ast = cel.compile("custom_struct{data: 50}").getAst();
+ CelAbstractSyntaxTree ast = compiler.compile("custom_struct{data: 50}").getAst();
- CelCustomStructValue result = (CelCustomStructValue) cel.createProgram(ast).eval();
+ CelCustomStructValue result = (CelCustomStructValue) plannerRuntime.createProgram(ast).eval();
assertThat(result.data).isEqualTo(50);
}
@Test
public void evaluate_usingCustomClass_asVariable() throws Exception {
- Cel cel =
- CelFactory.standardCelBuilder()
- .setOptions(CelOptions.current().enableCelValue(true).build())
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
.addVar("a", CUSTOM_STRUCT_TYPE)
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
.setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
.setValueProvider(CUSTOM_STRUCT_VALUE_PROVIDER)
.build();
- CelAbstractSyntaxTree ast = cel.compile("a").getAst();
+ CelAbstractSyntaxTree ast = compiler.compile("a").getAst();
CelCustomStructValue result =
(CelCustomStructValue)
- cel.createProgram(ast).eval(ImmutableMap.of("a", new CelCustomStructValue(10)));
+ plannerRuntime
+ .createProgram(ast)
+ .eval(ImmutableMap.of("a", new CelCustomStructValue(10)));
assertThat(result.data).isEqualTo(10);
}
@Test
public void evaluate_usingCustomClass_asVariableSelectField() throws Exception {
- Cel cel =
- CelFactory.standardCelBuilder()
- .setOptions(CelOptions.current().enableCelValue(true).build())
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
.addVar("a", CUSTOM_STRUCT_TYPE)
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
.setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
.setValueProvider(CUSTOM_STRUCT_VALUE_PROVIDER)
.build();
- CelAbstractSyntaxTree ast = cel.compile("a.data").getAst();
+ CelAbstractSyntaxTree ast = compiler.compile("a.data").getAst();
- assertThat(cel.createProgram(ast).eval(ImmutableMap.of("a", new CelCustomStructValue(20))))
+ assertThat(
+ plannerRuntime
+ .createProgram(ast)
+ .eval(ImmutableMap.of("a", new CelCustomStructValue(20))))
.isEqualTo(20L);
}
@Test
public void evaluate_usingCustomClass_selectField() throws Exception {
- Cel cel =
- CelFactory.standardCelBuilder()
- .setOptions(CelOptions.current().enableCelValue(true).build())
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
.setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
.setValueProvider(CUSTOM_STRUCT_VALUE_PROVIDER)
.build();
- CelAbstractSyntaxTree ast = cel.compile("custom_struct{data: 5}.data").getAst();
+ CelAbstractSyntaxTree ast = compiler.compile("custom_struct{data: 5}.data").getAst();
- Object result = cel.createProgram(ast).eval();
+ Object result = plannerRuntime.createProgram(ast).eval();
assertThat(result).isEqualTo(5L);
}
@Test
public void evaluate_usingMultipleProviders_selectFieldFromCustomClass() throws Exception {
- Cel cel =
- CelFactory.standardCelBuilder()
- .setOptions(CelOptions.current().enableCelValue(true).build())
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
.setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
.setValueProvider(
CombinedCelValueProvider.combine(
@@ -187,15 +210,48 @@ public void evaluate_usingMultipleProviders_selectFieldFromCustomClass() throws
CelOptions.DEFAULT, DynamicProto.create(unused -> Optional.empty())),
CUSTOM_STRUCT_VALUE_PROVIDER))
.build();
- CelAbstractSyntaxTree ast = cel.compile("custom_struct{data: 5}.data").getAst();
+ CelAbstractSyntaxTree ast = compiler.compile("custom_struct{data: 5}.data").getAst();
- Object result = cel.createProgram(ast).eval();
+ Object result = plannerRuntime.createProgram(ast).eval();
assertThat(result).isEqualTo(5L);
}
- // TODO: Bring back evaluate_usingMultipleProviders_selectFieldFromProtobufMessage
- // once planner is exposed from factory
+ @Test
+ public void evaluate_usingMultipleProviders_selectFieldFromProtobufMessage() throws Exception {
+ CelCompiler compiler =
+ CelCompilerFactory.standardCelCompilerBuilder()
+ .addMessageTypes(TestAllTypes.getDescriptor())
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .build();
+ CelRuntime plannerRuntime =
+ CelRuntimeFactory.plannerCelRuntimeBuilder()
+ .addMessageTypes(TestAllTypes.getDescriptor())
+ .setTypeProvider(CUSTOM_STRUCT_TYPE_PROVIDER)
+ .setValueProvider(
+ CombinedCelValueProvider.combine(
+ ProtoMessageValueProvider.newInstance(
+ CelOptions.DEFAULT,
+ // Note: this is unideal. Future iterations should make DynamicProto
+ // completely an internal concern, and not expose it at all.
+ DynamicProto.create(
+ typeName -> {
+ if (typeName.equals(TestAllTypes.getDescriptor().getFullName())) {
+ return Optional.of(TestAllTypes.newBuilder());
+ }
+ return Optional.empty();
+ })),
+ CUSTOM_STRUCT_VALUE_PROVIDER))
+ .build();
+ CelAbstractSyntaxTree ast =
+ compiler
+ .compile("cel.expr.conformance.proto3.TestAllTypes{single_string: 'foo'}.single_string")
+ .getAst();
+
+ String result = (String) plannerRuntime.createProgram(ast).eval();
+
+ assertThat(result).isEqualTo("foo");
+ }
@SuppressWarnings("Immutable") // Test only
private static class CelCustomStructValue extends StructValue {
diff --git a/common/types/BUILD.bazel b/common/types/BUILD.bazel
index 41d3d59b2..7d00c8307 100644
--- a/common/types/BUILD.bazel
+++ b/common/types/BUILD.bazel
@@ -35,6 +35,18 @@ java_library(
exports = ["//common/src/main/java/dev/cel/common/types:message_type_provider"],
)
+java_library(
+ name = "message_lite_type_provider",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/types:message_lite_type_provider"],
+)
+
+cel_android_library(
+ name = "message_lite_type_provider_android",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/types:message_lite_type_provider_android"],
+)
+
java_library(
name = "cel_types",
exports = ["//common/src/main/java/dev/cel/common/types:cel_types"],
@@ -56,6 +68,12 @@ java_library(
exports = ["//common/src/main/java/dev/cel/common/types:default_type_provider"],
)
+cel_android_library(
+ name = "default_type_provider_android",
+ visibility = ["//:internal"],
+ exports = ["//common/src/main/java/dev/cel/common/types:default_type_provider_android"],
+)
+
java_library(
name = "cel_v1alpha1_types",
visibility = ["//:internal"],
diff --git a/runtime/BUILD.bazel b/runtime/BUILD.bazel
index a42ee7fb4..074ef2059 100644
--- a/runtime/BUILD.bazel
+++ b/runtime/BUILD.bazel
@@ -9,14 +9,31 @@ package(
java_library(
name = "runtime",
exports = [
+ ":descriptor_message_provider",
":evaluation_exception",
+ ":function_overload",
":late_function_binding",
":metadata",
+ ":runtime_factory",
+ ":runtime_legacy_impl",
+ ":variable_resolver",
"//runtime/src/main/java/dev/cel/runtime",
- "//runtime/src/main/java/dev/cel/runtime:descriptor_message_provider",
- "//runtime/src/main/java/dev/cel/runtime:function_overload",
"//runtime/src/main/java/dev/cel/runtime:runtime_type_provider",
- "//runtime/src/main/java/dev/cel/runtime:variable_resolver",
+ ],
+)
+
+java_library(
+ name = "runtime_factory",
+ exports = [
+ "//runtime/src/main/java/dev/cel/runtime:runtime_factory",
+ ],
+)
+
+java_library(
+ name = "runtime_legacy_impl",
+ visibility = ["//:internal"],
+ exports = [
+ "//runtime/src/main/java/dev/cel/runtime:runtime_legacy_impl",
],
)
@@ -28,6 +45,14 @@ java_library(
],
)
+cel_android_library(
+ name = "dispatcher_android",
+ visibility = ["//:internal"],
+ exports = [
+ "//runtime/src/main/java/dev/cel/runtime:dispatcher_android",
+ ],
+)
+
java_library(
name = "standard_functions",
exports = [
@@ -43,6 +68,14 @@ java_library(
],
)
+cel_android_library(
+ name = "activation_android",
+ visibility = ["//:internal"],
+ exports = [
+ "//runtime/src/main/java/dev/cel/runtime:activation_android",
+ ],
+)
+
java_library(
name = "proto_message_activation_factory",
visibility = ["//:internal"],
@@ -79,6 +112,7 @@ cel_android_library(
java_library(
name = "evaluation_exception_builder",
+ # used_by_android
exports = ["//runtime/src/main/java/dev/cel/runtime:evaluation_exception_builder"],
)
@@ -112,6 +146,12 @@ java_library(
exports = ["//runtime/src/main/java/dev/cel/runtime:interpretable"],
)
+cel_android_library(
+ name = "interpretable_android",
+ visibility = ["//:internal"],
+ exports = ["//runtime/src/main/java/dev/cel/runtime:interpretable_android"],
+)
+
java_library(
name = "runtime_helpers",
visibility = ["//:internal"],
@@ -154,6 +194,18 @@ java_library(
exports = ["//runtime/src/main/java/dev/cel/runtime:type_resolver"],
)
+cel_android_library(
+ name = "type_resolver_android",
+ visibility = ["//:internal"],
+ exports = ["//runtime/src/main/java/dev/cel/runtime:type_resolver_android"],
+)
+
+java_library(
+ name = "descriptor_type_resolver",
+ visibility = ["//:internal"],
+ exports = ["//runtime/src/main/java/dev/cel/runtime:descriptor_type_resolver"],
+)
+
java_library(
name = "unknown_attributes",
exports = ["//runtime/src/main/java/dev/cel/runtime:unknown_attributes"],
@@ -253,12 +305,20 @@ cel_android_library(
java_library(
name = "metadata",
+ # used_by_android
visibility = ["//:internal"],
exports = ["//runtime/src/main/java/dev/cel/runtime:metadata"],
)
+java_library(
+ name = "variable_resolver",
+ # used_by_android
+ exports = ["//runtime/src/main/java/dev/cel/runtime:variable_resolver"],
+)
+
java_library(
name = "concatenated_list_view",
+ # used_by_android
visibility = ["//:internal"],
exports = [
"//runtime/src/main/java/dev/cel/runtime:concatenated_list_view",
@@ -266,10 +326,14 @@ java_library(
)
java_library(
- name = "variable_resolver",
- exports = [
- "//runtime/src/main/java/dev/cel/runtime:variable_resolver",
- ],
+ name = "function_overload",
+ exports = ["//runtime/src/main/java/dev/cel/runtime:function_overload"],
+)
+
+java_library(
+ name = "descriptor_message_provider",
+ visibility = ["//:internal"],
+ exports = ["//runtime/src/main/java/dev/cel/runtime:descriptor_message_provider"],
)
java_library(
diff --git a/runtime/planner/BUILD.bazel b/runtime/planner/BUILD.bazel
index 8da29f270..b76391b54 100644
--- a/runtime/planner/BUILD.bazel
+++ b/runtime/planner/BUILD.bazel
@@ -1,4 +1,5 @@
load("@rules_java//java:defs.bzl", "java_library")
+load("//:cel_android_rules.bzl", "cel_android_library")
package(
default_applicable_licenses = ["//:license"],
@@ -9,3 +10,8 @@ java_library(
name = "program_planner",
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:program_planner"],
)
+
+cel_android_library(
+ name = "program_planner_android",
+ exports = ["//runtime/src/main/java/dev/cel/runtime/planner:program_planner_android"],
+)
diff --git a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
index f77c48d96..ae9bdc082 100644
--- a/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
+++ b/runtime/src/main/java/dev/cel/runtime/BUILD.bazel
@@ -44,11 +44,6 @@ LITE_RUNTIME_IMPL_SOURCES = [
"LiteRuntimeImpl.java",
]
-# keep sorted
-LITE_PROGRAM_IMPL_SOURCES = [
- "LiteProgramImpl.java",
-]
-
# keep sorted
FUNCTION_BINDING_SOURCES = [
"CelFunctionBinding.java",
@@ -139,7 +134,8 @@ java_library(
cel_android_library(
name = "dispatcher_android",
srcs = DISPATCHER_SOURCES,
- visibility = ["//visibility:private"],
+ tags = [
+ ],
deps = [
":evaluation_exception",
":evaluation_exception_builder",
@@ -175,7 +171,8 @@ java_library(
cel_android_library(
name = "activation_android",
srcs = ["Activation.java"],
- visibility = ["//visibility:private"],
+ tags = [
+ ],
deps = [
":interpretable_android",
":runtime_helpers_android",
@@ -207,8 +204,10 @@ java_library(
tags = [
],
deps = [
+ "//common/annotations",
"//common/types",
"//common/types:type_providers",
+ "//common/values",
"//common/values:cel_byte_string",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
@@ -219,11 +218,14 @@ java_library(
cel_android_library(
name = "type_resolver_android",
srcs = ["TypeResolver.java"],
- visibility = ["//visibility:private"],
+ tags = [
+ ],
deps = [
+ "//common/annotations",
"//common/types:type_providers_android",
"//common/types:types_android",
"//common/values:cel_byte_string",
+ "//common/values:values_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven_android//:com_google_guava_guava",
@@ -234,14 +236,17 @@ cel_android_library(
java_library(
name = "descriptor_type_resolver",
srcs = ["DescriptorTypeResolver.java"],
- visibility = ["//visibility:private"],
+ tags = [
+ ],
deps = [
":type_resolver",
+ "//common/annotations",
"//common/types",
"//common/types:type_providers",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
+ "@maven//:org_jspecify_jspecify",
],
)
@@ -476,8 +481,6 @@ RUNTIME_SOURCES = [
"CelInternalRuntimeLibrary.java",
"CelRuntime.java",
"CelRuntimeBuilder.java",
- "CelRuntimeFactory.java",
- "CelRuntimeLegacyImpl.java",
"CelRuntimeLibrary.java",
"ProgramImpl.java",
"UnknownContext.java",
@@ -570,6 +573,8 @@ java_library(
name = "metadata",
srcs = ["Metadata.java"],
# used_by_android
+ tags = [
+ ],
deps = [
"//common/annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
@@ -579,6 +584,8 @@ java_library(
java_library(
name = "interpretable",
srcs = INTERPRABLE_SOURCES,
+ tags = [
+ ],
deps = [
":evaluation_exception",
":evaluation_listener",
@@ -592,7 +599,8 @@ java_library(
cel_android_library(
name = "interpretable_android",
srcs = INTERPRABLE_SOURCES,
- visibility = ["//visibility:private"],
+ tags = [
+ ],
deps = [
":evaluation_exception",
":evaluation_listener_android",
@@ -782,7 +790,7 @@ java_library(
],
deps = [
":evaluation_exception",
- "//runtime:unknown_attributes",
+ ":unknown_attributes",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
],
@@ -795,7 +803,7 @@ cel_android_library(
],
deps = [
":evaluation_exception",
- "//runtime:unknown_attributes_android",
+ ":unknown_attributes_android",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven_android//:com_google_guava_guava",
],
@@ -803,11 +811,22 @@ cel_android_library(
java_library(
name = "runtime_planner_impl",
- testonly = 1,
srcs = ["CelRuntimeImpl.java"],
tags = [
],
deps = [
+ ":descriptor_type_resolver",
+ ":dispatcher",
+ ":evaluation_exception",
+ ":evaluation_listener",
+ ":function_binding",
+ ":function_resolver",
+ ":program",
+ ":proto_message_runtime_helpers",
+ ":runtime",
+ ":runtime_equality",
+ ":standard_functions",
+ ":variable_resolver",
"//:auto_value",
"//common:cel_ast",
"//common:cel_descriptor_util",
@@ -825,17 +844,8 @@ java_library(
"//common/values:cel_value_provider",
"//common/values:combined_cel_value_provider",
"//common/values:proto_message_value_provider",
- "//runtime",
- "//runtime:dispatcher",
- "//runtime:evaluation_listener",
- "//runtime:function_binding",
- "//runtime:function_resolver",
- "//runtime:program",
- "//runtime:proto_message_runtime_helpers",
- "//runtime:runtime_equality",
- "//runtime:standard_functions",
- "//runtime:variable_resolver",
"//runtime/planner:program_planner",
+ "//runtime/standard:type",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
@@ -844,30 +854,21 @@ java_library(
)
java_library(
- name = "runtime",
- srcs = RUNTIME_SOURCES,
+ name = "runtime_legacy_impl",
+ srcs = ["CelRuntimeLegacyImpl.java"],
tags = [
],
deps = [
- ":activation",
- ":cel_value_runtime_type_provider",
":descriptor_message_provider",
":descriptor_type_resolver",
":dispatcher",
- ":evaluation_exception",
- ":evaluation_listener",
":function_binding",
- ":function_resolver",
- ":interpretable",
":interpreter",
- ":program",
- ":proto_message_activation_factory",
":proto_message_runtime_equality",
+ ":runtime",
":runtime_equality",
":runtime_type_provider",
":standard_functions",
- ":unknown_attributes",
- "//:auto_value",
"//common:cel_ast",
"//common:cel_descriptor_util",
"//common:cel_descriptors",
@@ -881,8 +882,6 @@ java_library(
"//common/types:cel_types",
"//common/types:type_providers",
"//common/values:cel_value_provider",
- "//common/values:proto_message_value_provider",
- "//runtime:variable_resolver",
"//runtime/standard:add",
"//runtime/standard:int",
"//runtime/standard:timestamp",
@@ -895,79 +894,104 @@ java_library(
)
java_library(
- name = "lite_runtime",
- srcs = LITE_RUNTIME_SOURCES,
+ name = "runtime_factory",
+ srcs = ["CelRuntimeFactory.java"],
+ tags = [
+ ],
+ deps = [
+ ":runtime",
+ ":runtime_legacy_impl",
+ ":runtime_planner_impl",
+ ":standard_functions",
+ "//common:options",
+ "//common/annotations",
+ ],
+)
+
+java_library(
+ name = "runtime",
+ srcs = RUNTIME_SOURCES,
tags = [
],
deps = [
+ ":activation",
":evaluation_exception",
+ ":evaluation_listener",
":function_binding",
+ ":function_resolver",
+ ":interpretable",
+ ":interpreter",
":program",
+ ":proto_message_activation_factory",
+ ":runtime_equality",
+ ":standard_functions",
+ ":unknown_attributes",
+ ":variable_resolver",
"//:auto_value",
"//common:cel_ast",
+ "//common:container",
"//common:options",
"//common/annotations",
+ "//common/types:type_providers",
"//common/values:cel_value_provider",
- "//runtime/standard:standard_function",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
+ "@maven//:com_google_protobuf_protobuf_java",
+ "@maven//:org_jspecify_jspecify",
],
)
java_library(
- name = "lite_runtime_impl",
- srcs = LITE_RUNTIME_IMPL_SOURCES,
+ name = "lite_runtime",
+ srcs = LITE_RUNTIME_SOURCES,
tags = [
],
deps = [
- ":cel_value_runtime_type_provider",
- ":dispatcher",
+ ":evaluation_exception",
":function_binding",
- ":interpreter",
- ":lite_program_impl",
- ":lite_runtime",
":program",
- ":runtime_equality",
- ":runtime_helpers",
- ":type_resolver",
"//:auto_value",
"//common:cel_ast",
+ "//common:container",
"//common:options",
+ "//common/annotations",
+ "//common/types:type_providers",
"//common/values:cel_value_provider",
"//runtime/standard:standard_function",
"@maven//:com_google_code_findbugs_annotations",
+ "@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
],
)
java_library(
- name = "lite_program_impl",
- srcs = LITE_PROGRAM_IMPL_SOURCES,
- deps = [
- ":activation",
- ":evaluation_exception",
- ":function_resolver",
- ":interpretable",
- ":program",
- "//:auto_value",
- "//runtime:variable_resolver",
- "@maven//:com_google_errorprone_error_prone_annotations",
+ name = "lite_runtime_impl",
+ srcs = LITE_RUNTIME_IMPL_SOURCES,
+ tags = [
],
-)
-
-cel_android_library(
- name = "lite_program_impl_android",
- srcs = LITE_PROGRAM_IMPL_SOURCES,
deps = [
- ":activation_android",
+ ":dispatcher",
":evaluation_exception",
- ":function_resolver_android",
- ":interpretable_android",
- ":program_android",
- ":variable_resolver",
+ ":function_binding",
+ ":lite_runtime",
+ ":program",
+ ":runtime_equality",
+ ":runtime_helpers",
"//:auto_value",
+ "//common:cel_ast",
+ "//common:container",
+ "//common:options",
+ "//common/types:default_type_provider",
+ "//common/types:type_providers",
+ "//common/values",
+ "//common/values:cel_value",
+ "//common/values:cel_value_provider",
+ "//runtime/planner:program_planner",
+ "//runtime/standard:standard_function",
+ "@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:com_google_guava_guava",
],
)
@@ -977,20 +1001,23 @@ cel_android_library(
tags = [
],
deps = [
- ":cel_value_runtime_type_provider_android",
":dispatcher_android",
+ ":evaluation_exception",
":function_binding_android",
- ":interpreter_android",
- ":lite_program_impl_android",
":lite_runtime_android",
":program_android",
":runtime_equality_android",
":runtime_helpers_android",
- ":type_resolver_android",
"//:auto_value",
"//common:cel_ast_android",
+ "//common:container_android",
"//common:options",
+ "//common/types:default_type_provider_android",
+ "//common/types:type_providers_android",
+ "//common/values:cel_value_android",
"//common/values:cel_value_provider_android",
+ "//common/values:values_android",
+ "//runtime/planner:program_planner_android",
"//runtime/standard:standard_function_android",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
@@ -1083,46 +1110,6 @@ cel_android_library(
],
)
-java_library(
- name = "cel_value_runtime_type_provider",
- srcs = ["CelValueRuntimeTypeProvider.java"],
- deps = [
- ":runtime_type_provider",
- ":unknown_attributes",
- "//common/annotations",
- "//common/exceptions:attribute_not_found",
- "//common/values",
- "//common/values:base_proto_cel_value_converter",
- "//common/values:base_proto_message_value_provider",
- "//common/values:cel_value",
- "//common/values:cel_value_provider",
- "//common/values:combined_cel_value_provider",
- "@maven//:com_google_errorprone_error_prone_annotations",
- "@maven//:com_google_guava_guava",
- "@maven//:com_google_protobuf_protobuf_java",
- ],
-)
-
-cel_android_library(
- name = "cel_value_runtime_type_provider_android",
- srcs = ["CelValueRuntimeTypeProvider.java"],
- deps = [
- ":runtime_type_provider_android",
- ":unknown_attributes_android",
- "//common/annotations",
- "//common/exceptions:attribute_not_found",
- "//common/values:base_proto_cel_value_converter_android",
- "//common/values:base_proto_message_value_provider_android",
- "//common/values:cel_value_android",
- "//common/values:cel_value_provider_android",
- "//common/values:combined_cel_value_provider_android",
- "//common/values:values_android",
- "@maven//:com_google_errorprone_error_prone_annotations",
- "@maven_android//:com_google_guava_guava",
- "@maven_android//:com_google_protobuf_protobuf_javalite",
- ],
-)
-
java_library(
name = "interpreter_util",
srcs = ["InterpreterUtil.java"],
@@ -1186,8 +1173,10 @@ cel_android_library(
":program_android",
"//:auto_value",
"//common:cel_ast_android",
+ "//common:container_android",
"//common:options",
"//common/annotations",
+ "//common/types:type_providers_android",
"//common/values:cel_value_provider_android",
"//runtime/standard:standard_function_android",
"@maven//:com_google_code_findbugs_annotations",
@@ -1253,19 +1242,6 @@ cel_android_library(
],
)
-java_library(
- name = "variable_resolver",
- srcs = [
- "CelVariableResolver.java",
- "HierarchicalVariableResolver.java",
- ],
- # used_by_android
- tags = [
- ],
- deps = [
- ],
-)
-
java_library(
name = "program",
srcs = ["Program.java"],
@@ -1318,3 +1294,14 @@ cel_android_library(
"@maven_android//:com_google_guava_guava",
],
)
+
+java_library(
+ name = "variable_resolver",
+ srcs = [
+ "CelVariableResolver.java",
+ "HierarchicalVariableResolver.java",
+ ],
+ # used_by_android
+ tags = [
+ ],
+)
diff --git a/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java b/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java
index 48b51274d..c7b1e63a4 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelLiteRuntimeBuilder.java
@@ -16,7 +16,9 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
+import dev.cel.common.CelContainer;
import dev.cel.common.CelOptions;
+import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.values.CelValueProvider;
import dev.cel.runtime.standard.CelStandardFunction;
@@ -47,6 +49,25 @@ CelLiteRuntimeBuilder setStandardFunctions(
@CanIgnoreReturnValue
CelLiteRuntimeBuilder addFunctionBindings(Iterable bindings);
+ /**
+ * Adds bindings for functions that are allowed to be late-bound (resolved at execution time).
+ */
+ @CanIgnoreReturnValue
+ CelLiteRuntimeBuilder addLateBoundFunctions(String... lateBoundFunctionNames);
+
+ /**
+ * Adds bindings for functions that are allowed to be late-bound (resolved at execution time).
+ */
+ @CanIgnoreReturnValue
+ CelLiteRuntimeBuilder addLateBoundFunctions(Iterable lateBoundFunctionNames);
+
+ /**
+ * Sets the {@link CelTypeProvider} for resolving CEL types during evaluation, such as a fully
+ * qualified type name to a struct or an enum value.
+ */
+ @CanIgnoreReturnValue
+ CelLiteRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider);
+
/**
* Sets the {@link CelValueProvider} for resolving struct values during evaluation. Multiple
* providers can be combined using {@code CombinedCelValueProvider}. Note that if you intend to
@@ -62,6 +83,13 @@ CelLiteRuntimeBuilder setStandardFunctions(
@CanIgnoreReturnValue
CelLiteRuntimeBuilder addLibraries(Iterable extends CelLiteRuntimeLibrary> libraries);
+ /**
+ * Set the {@link CelContainer} to use as the namespace for resolving CEL expression variables and
+ * functions.
+ */
+ @CanIgnoreReturnValue
+ CelLiteRuntimeBuilder setContainer(CelContainer container);
+
@CheckReturnValue
CelLiteRuntime build();
}
diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeFactory.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeFactory.java
index 322985b22..b613e4ae5 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeFactory.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeFactory.java
@@ -15,6 +15,7 @@
package dev.cel.runtime;
import dev.cel.common.CelOptions;
+import dev.cel.common.annotations.Beta;
/** Helper class to construct new {@code CelRuntime} instances. */
public final class CelRuntimeFactory {
@@ -32,5 +33,16 @@ public static CelRuntimeBuilder standardCelRuntimeBuilder() {
.setStandardEnvironmentEnabled(true);
}
+ @Beta
+ public static CelRuntimeBuilder plannerCelRuntimeBuilder() {
+ return CelRuntimeImpl.newBuilder()
+ .setStandardFunctions(CelStandardFunctions.newBuilder().build())
+ .setOptions(
+ CelOptions.current()
+ .enableTimestampEpoch(true)
+ .enableHeterogeneousNumericComparisons(true)
+ .build());
+ }
+
private CelRuntimeFactory() {}
}
diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
index 3f3245c84..27bd1b3fc 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeImpl.java
@@ -46,6 +46,7 @@
import dev.cel.common.values.CombinedCelValueProvider;
import dev.cel.common.values.ProtoMessageValueProvider;
import dev.cel.runtime.planner.ProgramPlanner;
+import dev.cel.runtime.standard.TypeFunction;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -446,12 +447,20 @@ public CelRuntime build() {
CelTypeProvider combinedTypeProvider =
new CelTypeProvider.CombinedCelTypeProvider(
- messageTypeProvider, DefaultTypeProvider.getInstance());
+ DefaultTypeProvider.getInstance(), messageTypeProvider);
if (typeProvider() != null) {
combinedTypeProvider =
new CelTypeProvider.CombinedCelTypeProvider(combinedTypeProvider, typeProvider());
}
+ DescriptorTypeResolver descriptorTypeResolver =
+ DescriptorTypeResolver.create(combinedTypeProvider);
+ TypeFunction typeFunction = TypeFunction.create(descriptorTypeResolver);
+ for (CelFunctionBinding binding :
+ typeFunction.newFunctionBindings(options(), runtimeEquality)) {
+ mutableFunctionBindings.put(binding.getOverloadId(), binding);
+ }
+
DefaultDispatcher dispatcher =
newDispatcher(
standardFunctions(), mutableFunctionBindings.values(), runtimeEquality, options());
diff --git a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
index 60c2642d7..7c0bb8a1c 100644
--- a/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
@@ -44,7 +44,7 @@
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.CelTypes;
import dev.cel.common.values.CelValueProvider;
-import dev.cel.common.values.ProtoMessageValueProvider;
+import dev.cel.runtime.FunctionBindingImpl.DynamicDispatchBinding;
import dev.cel.runtime.standard.AddOperator.AddOverload;
import dev.cel.runtime.standard.IntFunction.IntOverload;
import dev.cel.runtime.standard.TimestampFunction.TimestampOverload;
@@ -79,7 +79,6 @@ public final class CelRuntimeLegacyImpl implements CelRuntime {
private final Function customTypeFactory;
private final CelStandardFunctions overriddenStandardFunctions;
- private final CelValueProvider celValueProvider;
private final ImmutableSet fileDescriptors;
// This does not affect the evaluation behavior in any manner.
@@ -114,10 +113,6 @@ public CelRuntimeBuilder toRuntimeBuilder() {
builder.setStandardFunctions(overriddenStandardFunctions);
}
- if (celValueProvider != null) {
- builder.setValueProvider(celValueProvider);
- }
-
return builder;
}
@@ -137,7 +132,6 @@ public static final class Builder implements CelRuntimeBuilder {
@VisibleForTesting final ImmutableSet.Builder celRuntimeLibraries;
@VisibleForTesting Function customTypeFactory;
- @VisibleForTesting CelValueProvider celValueProvider;
@VisibleForTesting CelStandardFunctions overriddenStandardFunctions;
private CelOptions options;
@@ -210,8 +204,8 @@ public CelRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider) {
@Override
public CelRuntimeBuilder setValueProvider(CelValueProvider celValueProvider) {
- this.celValueProvider = celValueProvider;
- return this;
+ throw new UnsupportedOperationException(
+ "setValueProvider is not supported for legacy runtime");
}
@Override
@@ -308,6 +302,10 @@ public CelRuntimeLegacyImpl build() {
ImmutableMap.builder();
for (CelFunctionBinding standardFunctionBinding :
newStandardFunctionBindings(runtimeEquality)) {
+ if (standardFunctionBinding instanceof DynamicDispatchBinding) {
+ continue;
+ }
+
functionBindingsBuilder.put(
standardFunctionBinding.getOverloadId(), standardFunctionBinding);
}
@@ -322,19 +320,8 @@ public CelRuntimeLegacyImpl build() {
dispatcherBuilder.addOverload(
overloadId, func.getArgTypes(), func.isStrict(), func.getDefinition()));
- RuntimeTypeProvider runtimeTypeProvider;
-
- if (options.enableCelValue()) {
- CelValueProvider messageValueProvider = celValueProvider;
-
- if (messageValueProvider == null) {
- messageValueProvider = ProtoMessageValueProvider.newInstance(options, dynamicProto);
- }
-
- runtimeTypeProvider = CelValueRuntimeTypeProvider.newInstance(messageValueProvider);
- } else {
- runtimeTypeProvider = new DescriptorMessageProvider(runtimeTypeFactory, options);
- }
+ RuntimeTypeProvider runtimeTypeProvider =
+ new DescriptorMessageProvider(runtimeTypeFactory, options);
DefaultInterpreter interpreter =
new DefaultInterpreter(
@@ -350,7 +337,6 @@ public CelRuntimeLegacyImpl build() {
extensionRegistry,
customTypeFactory,
overriddenStandardFunctions,
- celValueProvider,
fileDescriptors,
runtimeLibraries,
ImmutableList.copyOf(customFunctionBindings.values()));
@@ -448,7 +434,6 @@ private CelRuntimeLegacyImpl(
ExtensionRegistry extensionRegistry,
@Nullable Function customTypeFactory,
@Nullable CelStandardFunctions overriddenStandardFunctions,
- @Nullable CelValueProvider celValueProvider,
ImmutableSet fileDescriptors,
ImmutableSet celRuntimeLibraries,
ImmutableList celFunctionBindings) {
@@ -458,7 +443,6 @@ private CelRuntimeLegacyImpl(
this.extensionRegistry = extensionRegistry;
this.customTypeFactory = customTypeFactory;
this.overriddenStandardFunctions = overriddenStandardFunctions;
- this.celValueProvider = celValueProvider;
this.fileDescriptors = fileDescriptors;
this.celRuntimeLibraries = celRuntimeLibraries;
this.celFunctionBindings = celFunctionBindings;
diff --git a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java b/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java
deleted file mode 100644
index e071289ca..000000000
--- a/runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2023 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dev.cel.runtime;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.errorprone.annotations.Immutable;
-import com.google.protobuf.MessageLite;
-import dev.cel.common.annotations.Internal;
-import dev.cel.common.exceptions.CelAttributeNotFoundException;
-import dev.cel.common.values.BaseProtoCelValueConverter;
-import dev.cel.common.values.BaseProtoMessageValueProvider;
-import dev.cel.common.values.CelValue;
-import dev.cel.common.values.CelValueProvider;
-import dev.cel.common.values.CombinedCelValueProvider;
-import dev.cel.common.values.SelectableValue;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-/** Bridge between the old RuntimeTypeProvider and CelValueProvider APIs. */
-@Internal
-@Immutable
-final class CelValueRuntimeTypeProvider implements RuntimeTypeProvider {
-
- private final CelValueProvider valueProvider;
- private final BaseProtoCelValueConverter protoCelValueConverter;
- private static final BaseProtoCelValueConverter DEFAULT_CEL_VALUE_CONVERTER =
- new BaseProtoCelValueConverter() {};
-
- static CelValueRuntimeTypeProvider newInstance(CelValueProvider valueProvider) {
- BaseProtoCelValueConverter converter = DEFAULT_CEL_VALUE_CONVERTER;
-
- // Find the underlying ProtoCelValueConverter.
- // This is required because DefaultInterpreter works with a resolved protobuf messages directly
- // in evaluation flow.
- // A new runtime should not directly depend on protobuf, thus this will not be needed in the
- // future.
- if (valueProvider instanceof BaseProtoMessageValueProvider) {
- converter = ((BaseProtoMessageValueProvider) valueProvider).protoCelValueConverter();
- } else if (valueProvider instanceof CombinedCelValueProvider) {
- converter =
- ((CombinedCelValueProvider) valueProvider)
- .valueProviders().stream()
- .filter(p -> p instanceof BaseProtoMessageValueProvider)
- .map(p -> ((BaseProtoMessageValueProvider) p).protoCelValueConverter())
- .findFirst()
- .orElse(DEFAULT_CEL_VALUE_CONVERTER);
- }
-
- return new CelValueRuntimeTypeProvider(valueProvider, converter);
- }
-
- @Override
- public Object createMessage(String messageName, Map values) {
- return maybeUnwrapCelValue(
- valueProvider
- .newValue(messageName, values)
- .orElseThrow(
- () ->
- new NoSuchElementException(
- String.format("cannot resolve '%s' as a message", messageName))));
- }
-
- @Override
- public Object selectField(Object message, String fieldName) {
- if (message instanceof Map) {
- Map, ?> map = (Map, ?>) message;
- if (map.containsKey(fieldName)) {
- return map.get(fieldName);
- }
-
- throw CelAttributeNotFoundException.forMissingMapKey(fieldName);
- }
-
- SelectableValue selectableValue = getSelectableValueOrThrow(message, fieldName);
- Object value = selectableValue.select(fieldName);
-
- return maybeUnwrapCelValue(value);
- }
-
- @Override
- public Object hasField(Object message, String fieldName) {
- SelectableValue selectableValue = getSelectableValueOrThrow(message, fieldName);
-
- return selectableValue.find(fieldName).isPresent();
- }
-
- @SuppressWarnings("unchecked")
- private SelectableValue getSelectableValueOrThrow(Object obj, String fieldName) {
- Object convertedCelValue = protoCelValueConverter.toRuntimeValue(obj);
-
- if (!(convertedCelValue instanceof SelectableValue)) {
- throwInvalidFieldSelection(fieldName);
- }
-
- return (SelectableValue) convertedCelValue;
- }
-
- @Override
- public Object adapt(String messageName, Object message) {
- if (message instanceof CelUnknownSet) {
- return message; // CelUnknownSet is handled specially for iterative evaluation. No need to
- // adapt to CelValue.
- }
-
- if (message instanceof MessageLite.Builder) {
- message = ((MessageLite.Builder) message).build();
- }
-
- if (message instanceof MessageLite) {
- return maybeUnwrapCelValue(protoCelValueConverter.toRuntimeValue(message));
- }
-
- return message;
- }
-
- /**
- * DefaultInterpreter cannot handle CelValue and instead expects plain Java objects.
- *
- * This will become unnecessary once we introduce a rewrite of a Cel runtime.
- */
- private Object maybeUnwrapCelValue(Object object) {
- if (object instanceof CelValue) {
- return protoCelValueConverter.unwrap((CelValue) object);
- }
- return object;
- }
-
- private static void throwInvalidFieldSelection(String fieldName) {
- throw CelAttributeNotFoundException.forFieldResolution(fieldName);
- }
-
- private CelValueRuntimeTypeProvider(
- CelValueProvider valueProvider, BaseProtoCelValueConverter protoCelValueConverter) {
- this.valueProvider = checkNotNull(valueProvider);
- this.protoCelValueConverter = checkNotNull(protoCelValueConverter);
- }
-}
diff --git a/runtime/src/main/java/dev/cel/runtime/DescriptorTypeResolver.java b/runtime/src/main/java/dev/cel/runtime/DescriptorTypeResolver.java
index 46ad0d231..63fcb87b6 100644
--- a/runtime/src/main/java/dev/cel/runtime/DescriptorTypeResolver.java
+++ b/runtime/src/main/java/dev/cel/runtime/DescriptorTypeResolver.java
@@ -18,24 +18,46 @@
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.MessageOrBuilder;
+import dev.cel.common.annotations.Internal;
import dev.cel.common.types.CelType;
+import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.types.TypeType;
+import java.util.NoSuchElementException;
import java.util.Optional;
+import org.jspecify.annotations.Nullable;
/**
* {@code DescriptorTypeResolver} extends {@link TypeResolver} and additionally resolves incoming
* protobuf message types using descriptors.
+ *
+ *
CEL Library Internals. Do Not Use.
*/
@Immutable
-final class DescriptorTypeResolver extends TypeResolver {
+@Internal
+public final class DescriptorTypeResolver extends TypeResolver {
- static DescriptorTypeResolver create() {
+ private final @Nullable CelTypeProvider typeProvider;
+
+ /**
+ * Creates a {@code DescriptorTypeResolver}. All protobuf messages are resolved as a type of
+ * {@link StructTypeReference}.
+ */
+ public static DescriptorTypeResolver create() {
return new DescriptorTypeResolver();
}
+ /**
+ * Creates a {@code DescriptorTypeResolver}. If the protobuf message to be resolved can be found
+ * in the provided {@link CelTypeProvider}, the message is resolved as a concrete {@code
+ * ProtoMessageType} instead of a {@link StructTypeReference}.
+ */
+ public static DescriptorTypeResolver create(CelTypeProvider typeProvider) {
+ return new DescriptorTypeResolver(typeProvider);
+ }
+
@Override
- TypeType resolveObjectType(Object obj, CelType typeCheckedType) {
+ public TypeType resolveObjectType(Object obj, CelType typeCheckedType) {
checkNotNull(obj);
Optional wellKnownTypeType = resolveWellKnownObjectType(obj);
@@ -45,11 +67,25 @@ TypeType resolveObjectType(Object obj, CelType typeCheckedType) {
if (obj instanceof MessageOrBuilder) {
MessageOrBuilder msg = (MessageOrBuilder) obj;
- return TypeType.create(StructTypeReference.create(msg.getDescriptorForType().getFullName()));
+ String typeName = msg.getDescriptorForType().getFullName();
+ if (typeProvider != null) {
+ return typeProvider
+ .findType(typeName)
+ .map(TypeType::create)
+ .orElseThrow(() -> new NoSuchElementException("Could not find type: " + typeName));
+ } else {
+ return TypeType.create(StructTypeReference.create(typeName));
+ }
}
return super.resolveObjectType(obj, typeCheckedType);
}
- private DescriptorTypeResolver() {}
+ private DescriptorTypeResolver() {
+ this(null);
+ }
+
+ private DescriptorTypeResolver(@Nullable CelTypeProvider typeProvider) {
+ this.typeProvider = typeProvider;
+ }
}
diff --git a/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java b/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java
deleted file mode 100644
index 5e57f497b..000000000
--- a/runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package dev.cel.runtime;
-
-import com.google.auto.value.AutoValue;
-import com.google.errorprone.annotations.Immutable;
-import java.util.Map;
-
-@Immutable
-@AutoValue
-abstract class LiteProgramImpl implements Program {
-
- abstract Interpretable interpretable();
-
- @Override
- public Object eval() throws CelEvaluationException {
- return interpretable().eval(GlobalResolver.EMPTY);
- }
-
- @Override
- public Object eval(Map mapValue) throws CelEvaluationException {
- return interpretable().eval(Activation.copyOf(mapValue));
- }
-
- @Override
- public Object eval(Map mapValue, CelFunctionResolver lateBoundFunctionResolver)
- throws CelEvaluationException {
- return interpretable().eval(Activation.copyOf(mapValue), lateBoundFunctionResolver);
- }
-
- @Override
- public Object eval(CelVariableResolver resolver, CelFunctionResolver lateBoundFunctionResolver) {
- // TODO: Wire in program planner
- throw new UnsupportedOperationException("To be implemented");
- }
-
- @Override
- public Object eval(CelVariableResolver resolver) throws CelEvaluationException {
- // TODO: Wire in program planner
- throw new UnsupportedOperationException("To be implemented");
- }
-
- static Program plan(Interpretable interpretable) {
- return new AutoValue_LiteProgramImpl(interpretable);
- }
-}
diff --git a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
index 45c322da9..9141b2419 100644
--- a/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
+++ b/runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java
@@ -15,7 +15,6 @@
package dev.cel.runtime;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -23,29 +22,36 @@
import com.google.common.collect.ImmutableSet;
import javax.annotation.concurrent.ThreadSafe;
import dev.cel.common.CelAbstractSyntaxTree;
+import dev.cel.common.CelContainer;
import dev.cel.common.CelOptions;
+import dev.cel.common.types.CelTypeProvider;
+import dev.cel.common.types.DefaultTypeProvider;
+import dev.cel.common.values.CelValue;
+import dev.cel.common.values.CelValueConverter;
import dev.cel.common.values.CelValueProvider;
+import dev.cel.runtime.planner.ProgramPlanner;
import dev.cel.runtime.standard.CelStandardFunction;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Map;
import java.util.Optional;
@ThreadSafe
final class LiteRuntimeImpl implements CelLiteRuntime {
- private final Interpreter interpreter;
+ private final ProgramPlanner planner;
private final CelOptions celOptions;
private final ImmutableList customFunctionBindings;
private final ImmutableSet celStandardFunctions;
+ private final CelTypeProvider celTypeProvider;
private final CelValueProvider celValueProvider;
+ private final CelContainer celContainer;
- // This does not affect the evaluation behavior in any manner.
// CEL-Internal-4
private final ImmutableSet runtimeLibraries;
@Override
- public Program createProgram(CelAbstractSyntaxTree ast) {
- checkState(ast.isChecked(), "programs must be created from checked expressions");
- return LiteProgramImpl.plan(interpreter.createInterpretable(ast));
+ public Program createProgram(CelAbstractSyntaxTree ast) throws CelEvaluationException {
+ return planner.plan(ast);
}
@Override
@@ -55,22 +61,30 @@ public CelLiteRuntimeBuilder toRuntimeBuilder() {
.setOptions(celOptions)
.setStandardFunctions(celStandardFunctions)
.addFunctionBindings(customFunctionBindings)
- .addLibraries(runtimeLibraries);
+ .addLibraries(runtimeLibraries)
+ .setContainer(celContainer);
if (celValueProvider != null) {
builder.setValueProvider(celValueProvider);
}
+ if (celTypeProvider != null) {
+ builder.setTypeProvider(celTypeProvider);
+ }
+
return builder;
}
static final class Builder implements CelLiteRuntimeBuilder {
+ private CelContainer container;
// Following is visible to test `toBuilder`.
@VisibleForTesting CelOptions celOptions;
@VisibleForTesting final HashMap customFunctionBindings;
+ @VisibleForTesting final ImmutableSet.Builder lateBoundFunctionNamesBuilder;
@VisibleForTesting final ImmutableSet.Builder runtimeLibrariesBuilder;
@VisibleForTesting final ImmutableSet.Builder standardFunctionBuilder;
+ @VisibleForTesting CelTypeProvider celTypeProvider;
@VisibleForTesting CelValueProvider celValueProvider;
@Override
@@ -102,6 +116,23 @@ public CelLiteRuntimeBuilder addFunctionBindings(Iterable bi
return this;
}
+ @Override
+ public CelLiteRuntimeBuilder addLateBoundFunctions(String... lateBoundFunctionNames) {
+ return addLateBoundFunctions(Arrays.asList(lateBoundFunctionNames));
+ }
+
+ @Override
+ public CelLiteRuntimeBuilder addLateBoundFunctions(Iterable lateBoundFunctionNames) {
+ lateBoundFunctionNamesBuilder.addAll(lateBoundFunctionNames);
+ return this;
+ }
+
+ @Override
+ public CelLiteRuntimeBuilder setTypeProvider(CelTypeProvider celTypeProvider) {
+ this.celTypeProvider = celTypeProvider;
+ return this;
+ }
+
@Override
public CelLiteRuntimeBuilder setValueProvider(CelValueProvider celValueProvider) {
this.celValueProvider = celValueProvider;
@@ -119,12 +150,15 @@ public CelLiteRuntimeBuilder addLibraries(Iterable extends CelLiteRuntimeLibra
return this;
}
+ @Override
+ public CelLiteRuntimeBuilder setContainer(CelContainer container) {
+ this.container = checkNotNull(container);
+ return this;
+ }
+
/** Throws if an unsupported flag in CelOptions is toggled. */
private static void assertAllowedCelOptions(CelOptions celOptions) {
String prefix = "Misconfigured CelOptions: ";
- if (!celOptions.enableCelValue()) {
- throw new IllegalArgumentException(prefix + "enableCelValue must be enabled.");
- }
if (!celOptions.enableUnsignedLongs()) {
throw new IllegalArgumentException(prefix + "enableUnsignedLongs cannot be disabled.");
}
@@ -184,31 +218,57 @@ public CelLiteRuntime build() {
dispatcherBuilder.addOverload(
overloadId, func.getArgTypes(), func.isStrict(), func.getDefinition()));
- Interpreter interpreter =
- new DefaultInterpreter(
- TypeResolver.create(),
- CelValueRuntimeTypeProvider.newInstance(celValueProvider),
+ CelTypeProvider celTypeProvider = DefaultTypeProvider.getInstance();
+ if (this.celTypeProvider != null) {
+ celTypeProvider =
+ new CelTypeProvider.CombinedCelTypeProvider(celTypeProvider, this.celTypeProvider);
+ }
+
+ ProgramPlanner planner =
+ ProgramPlanner.newPlanner(
+ celTypeProvider,
+ celValueProvider,
dispatcherBuilder.build(),
- celOptions);
+ celValueProvider.celValueConverter(),
+ CelContainer.newBuilder().build(),
+ celOptions,
+ lateBoundFunctionNamesBuilder.build());
return new LiteRuntimeImpl(
- interpreter,
celOptions,
customFunctionBindings.values(),
standardFunctions,
runtimeLibs,
- celValueProvider);
+ celValueProvider,
+ celTypeProvider,
+ container,
+ planner);
}
private Builder() {
- this.celOptions =
- CelOptions.current()
- .enableCelValue(true)
- .build();
- this.celValueProvider = (structType, fields) -> Optional.empty();
+ this.celOptions = CelOptions.DEFAULT;
+ this.celValueProvider =
+ new CelValueProvider() {
+ @Override
+ public Optional newValue(String structType, Map fields) {
+ return Optional.empty();
+ }
+
+ @Override
+ public CelValueConverter celValueConverter() {
+ return new CelValueConverter() {
+ @Override
+ public Object unwrap(CelValue celValue) {
+ return super.unwrap(celValue);
+ }
+ };
+ }
+ };
this.customFunctionBindings = new HashMap<>();
this.standardFunctionBuilder = ImmutableSet.builder();
this.runtimeLibrariesBuilder = ImmutableSet.builder();
+ this.lateBoundFunctionNamesBuilder = ImmutableSet.builder();
+ this.container = CelContainer.newBuilder().build();
}
}
@@ -217,17 +277,21 @@ static CelLiteRuntimeBuilder newBuilder() {
}
private LiteRuntimeImpl(
- Interpreter interpreter,
CelOptions celOptions,
Iterable customFunctionBindings,
ImmutableSet celStandardFunctions,
ImmutableSet runtimeLibraries,
- CelValueProvider celValueProvider) {
- this.interpreter = interpreter;
+ CelValueProvider celValueProvider,
+ CelTypeProvider celTypeProvider,
+ CelContainer celContainer,
+ ProgramPlanner planner) {
this.celOptions = celOptions;
this.customFunctionBindings = ImmutableList.copyOf(customFunctionBindings);
this.celStandardFunctions = celStandardFunctions;
this.runtimeLibraries = runtimeLibraries;
this.celValueProvider = celValueProvider;
+ this.celTypeProvider = celTypeProvider;
+ this.celContainer = celContainer;
+ this.planner = planner;
}
}
diff --git a/runtime/src/main/java/dev/cel/runtime/TypeResolver.java b/runtime/src/main/java/dev/cel/runtime/TypeResolver.java
index 905120988..c2ebf521c 100644
--- a/runtime/src/main/java/dev/cel/runtime/TypeResolver.java
+++ b/runtime/src/main/java/dev/cel/runtime/TypeResolver.java
@@ -26,6 +26,7 @@
import com.google.protobuf.MessageLiteOrBuilder;
import com.google.protobuf.NullValue;
import com.google.protobuf.Timestamp;
+import dev.cel.common.annotations.Internal;
import dev.cel.common.types.CelType;
import dev.cel.common.types.ListType;
import dev.cel.common.types.MapType;
@@ -45,9 +46,12 @@
/**
* {@code TypeResolver} resolves incoming {@link CelType} into {@link TypeType}., either as part of
* a type call (type('foo'), type(1), etc.) or as a type literal (type, int, string, etc.)
+ *
+ * CEL Library Internals. Do Not Use.
*/
@Immutable
-class TypeResolver {
+@Internal
+public class TypeResolver {
static TypeResolver create() {
return new TypeResolver();
@@ -65,6 +69,7 @@ static TypeResolver create() {
.put(UnsignedLong.class, TypeType.create(SimpleType.UINT))
.put(String.class, TypeType.create(SimpleType.STRING))
.put(NullValue.class, TypeType.create(SimpleType.NULL_TYPE))
+ .put(dev.cel.common.values.NullValue.class, TypeType.create(SimpleType.NULL_TYPE))
.put(java.time.Duration.class, TypeType.create(SimpleType.DURATION))
.put(Instant.class, TypeType.create(SimpleType.TIMESTAMP))
.put(
@@ -135,7 +140,7 @@ Optional resolveWellKnownObjectType(Object obj) {
}
/** Resolve the CEL type of the {@code obj}. */
- TypeType resolveObjectType(Object obj, CelType typeCheckedType) {
+ public TypeType resolveObjectType(Object obj, CelType typeCheckedType) {
checkNotNull(obj);
Optional wellKnownTypeType = resolveWellKnownObjectType(obj);
if (wellKnownTypeType.isPresent()) {
@@ -188,5 +193,5 @@ private static CelType adaptStructType(StructType typeOfType) {
return newTypeOfType;
}
- TypeResolver() {}
+ protected TypeResolver() {}
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/ActivationWrapper.java b/runtime/src/main/java/dev/cel/runtime/planner/ActivationWrapper.java
index f844ab232..506541868 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/ActivationWrapper.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/ActivationWrapper.java
@@ -17,6 +17,6 @@
import dev.cel.runtime.GlobalResolver;
/** Identifies a resolver that can be unwrapped to bypass local variable state. */
-public interface ActivationWrapper extends GlobalResolver {
+interface ActivationWrapper extends GlobalResolver {
GlobalResolver unwrap();
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel
index 59f39fc91..63487ed65 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel
+++ b/runtime/src/main/java/dev/cel/runtime/planner/BUILD.bazel
@@ -1,4 +1,5 @@
load("@rules_java//java:defs.bzl", "java_library")
+load("//:cel_android_rules.bzl", "cel_android_library")
package(
default_applicable_licenses = ["//:license"],
@@ -57,6 +58,55 @@ java_library(
],
)
+cel_android_library(
+ name = "program_planner_android",
+ srcs = ["ProgramPlanner.java"],
+ tags = [
+ ],
+ deps = [
+ ":attribute_android",
+ ":error_metadata_android",
+ ":eval_and_android",
+ ":eval_attribute_android",
+ ":eval_conditional_android",
+ ":eval_const_android",
+ ":eval_create_list_android",
+ ":eval_create_map_android",
+ ":eval_create_struct_android",
+ ":eval_fold_android",
+ ":eval_late_bound_call_android",
+ ":eval_or_android",
+ ":eval_test_only_android",
+ ":eval_unary_android",
+ ":eval_var_args_call_android",
+ ":eval_zero_arity_android",
+ ":interpretable_attribute_android",
+ ":planned_interpretable_android",
+ ":planned_program_android",
+ ":qualifier_android",
+ ":string_qualifier_android",
+ "//:auto_value",
+ "//common:cel_ast_android",
+ "//common:container_android",
+ "//common:operator_android",
+ "//common:options",
+ "//common/annotations",
+ "//common/ast:ast_android",
+ "//common/exceptions:overload_not_found",
+ "//common/types:type_providers_android",
+ "//common/types:types_android",
+ "//common/values:cel_value_provider_android",
+ "//common/values:values_android",
+ "//runtime:dispatcher_android",
+ "//runtime:evaluation_exception",
+ "//runtime:evaluation_exception_builder",
+ "//runtime:program_android",
+ "//runtime:resolved_overload_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "planned_program",
srcs = ["PlannedProgram.java"],
@@ -69,7 +119,6 @@ java_library(
"//common:options",
"//common/exceptions:runtime_exception",
"//common/values",
- "//runtime",
"//runtime:activation",
"//runtime:evaluation_exception",
"//runtime:evaluation_exception_builder",
@@ -77,6 +126,31 @@ java_library(
"//runtime:interpretable",
"//runtime:program",
"//runtime:resolved_overload",
+ "//runtime:variable_resolver",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+cel_android_library(
+ name = "planned_program_android",
+ srcs = ["PlannedProgram.java"],
+ deps = [
+ ":error_metadata_android",
+ ":execution_frame_android",
+ ":localized_evaluation_exception",
+ ":planned_interpretable_android",
+ "//:auto_value",
+ "//common:options",
+ "//common/exceptions:runtime_exception",
+ "//common/values:values_android",
+ "//runtime:activation_android",
+ "//runtime:evaluation_exception",
+ "//runtime:evaluation_exception_builder",
+ "//runtime:interpretable_android",
+ "//runtime:program_android",
+ "//runtime:resolved_overload_android",
+ "//runtime:variable_resolver",
+ "//runtime/src/main/java/dev/cel/runtime:function_resolver_android",
"@maven//:com_google_errorprone_error_prone_annotations",
],
)
@@ -93,6 +167,18 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_const_android",
+ srcs = ["EvalConstant.java"],
+ deps = [
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "interpretable_attribute",
srcs = ["InterpretableAttribute.java"],
@@ -103,16 +189,28 @@ java_library(
],
)
+cel_android_library(
+ name = "interpretable_attribute_android",
+ srcs = ["InterpretableAttribute.java"],
+ deps = [
+ ":planned_interpretable_android",
+ ":qualifier_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+ATTRIBUTE_SOURCES = [
+ "Attribute.java",
+ "AttributeFactory.java",
+ "MaybeAttribute.java",
+ "MissingAttribute.java",
+ "NamespacedAttribute.java",
+ "RelativeAttribute.java",
+]
+
java_library(
name = "attribute",
- srcs = [
- "Attribute.java",
- "AttributeFactory.java",
- "MaybeAttribute.java",
- "MissingAttribute.java",
- "NamespacedAttribute.java",
- "RelativeAttribute.java",
- ],
+ srcs = ATTRIBUTE_SOURCES,
deps = [
":activation_wrapper",
":eval_helpers",
@@ -131,6 +229,27 @@ java_library(
],
)
+cel_android_library(
+ name = "attribute_android",
+ srcs = ATTRIBUTE_SOURCES,
+ deps = [
+ ":activation_wrapper_android",
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ ":qualifier_android",
+ "//common/exceptions:attribute_not_found",
+ "//common/src/main/java/dev/cel/common:container_android",
+ "//common/types:type_providers_android",
+ "//common/types:types_android",
+ "//common/values:cel_value_android",
+ "//common/values:values_android",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "activation_wrapper",
srcs = ["ActivationWrapper.java"],
@@ -139,6 +258,14 @@ java_library(
],
)
+cel_android_library(
+ name = "activation_wrapper_android",
+ srcs = ["ActivationWrapper.java"],
+ deps = [
+ "//runtime:interpretable_android",
+ ],
+)
+
java_library(
name = "qualifier",
srcs = ["Qualifier.java"],
@@ -147,6 +274,14 @@ java_library(
],
)
+cel_android_library(
+ name = "qualifier_android",
+ srcs = ["Qualifier.java"],
+ deps = [
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
java_library(
name = "presence_test_qualifier",
srcs = ["PresenceTestQualifier.java"],
@@ -154,6 +289,18 @@ java_library(
":attribute",
":qualifier",
"//common/values",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+cel_android_library(
+ name = "presence_test_qualifier_android",
+ srcs = ["PresenceTestQualifier.java"],
+ deps = [
+ ":attribute_android",
+ ":qualifier_android",
+ "//common/values:values_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
],
)
@@ -164,6 +311,18 @@ java_library(
":qualifier",
"//common/exceptions:attribute_not_found",
"//common/values",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
+cel_android_library(
+ name = "string_qualifier_android",
+ srcs = ["StringQualifier.java"],
+ deps = [
+ ":qualifier_android",
+ "//common/exceptions:attribute_not_found",
+ "//common/values:values_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
],
)
@@ -181,6 +340,19 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_attribute_android",
+ srcs = ["EvalAttribute.java"],
+ deps = [
+ ":attribute_android",
+ ":execution_frame_android",
+ ":interpretable_attribute_android",
+ ":qualifier_android",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
java_library(
name = "eval_test_only",
srcs = ["EvalTestOnly.java"],
@@ -195,20 +367,48 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_test_only_android",
+ srcs = ["EvalTestOnly.java"],
+ deps = [
+ ":execution_frame_android",
+ ":interpretable_attribute_android",
+ ":presence_test_qualifier_android",
+ ":qualifier_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
java_library(
name = "eval_zero_arity",
srcs = ["EvalZeroArity.java"],
deps = [
+ ":eval_helpers",
":execution_frame",
":planned_interpretable",
"//common/values",
- "//common/values:cel_value",
"//runtime:evaluation_exception",
"//runtime:interpretable",
"//runtime:resolved_overload",
],
)
+cel_android_library(
+ name = "eval_zero_arity_android",
+ srcs = ["EvalZeroArity.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "//runtime:resolved_overload_android",
+ ],
+)
+
java_library(
name = "eval_unary",
srcs = ["EvalUnary.java"],
@@ -217,13 +417,26 @@ java_library(
":execution_frame",
":planned_interpretable",
"//common/values",
- "//common/values:cel_value",
"//runtime:evaluation_exception",
"//runtime:interpretable",
"//runtime:resolved_overload",
],
)
+cel_android_library(
+ name = "eval_unary_android",
+ srcs = ["EvalUnary.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "//runtime:resolved_overload_android",
+ ],
+)
+
java_library(
name = "eval_var_args_call",
srcs = ["EvalVarArgsCall.java"],
@@ -232,13 +445,26 @@ java_library(
":execution_frame",
":planned_interpretable",
"//common/values",
- "//common/values:cel_value",
"//runtime:evaluation_exception",
"//runtime:interpretable",
"//runtime:resolved_overload",
],
)
+cel_android_library(
+ name = "eval_var_args_call_android",
+ srcs = ["EvalVarArgsCall.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "//runtime:resolved_overload_android",
+ ],
+)
+
java_library(
name = "eval_late_bound_call",
srcs = ["EvalLateBoundCall.java"],
@@ -248,7 +474,6 @@ java_library(
":planned_interpretable",
"//common/exceptions:overload_not_found",
"//common/values",
- "//common/values:cel_value",
"//runtime:evaluation_exception",
"//runtime:interpretable",
"//runtime:resolved_overload",
@@ -256,6 +481,22 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_late_bound_call_android",
+ srcs = ["EvalLateBoundCall.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/exceptions:overload_not_found",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "//runtime:resolved_overload_android",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_or",
srcs = ["EvalOr.java"],
@@ -269,6 +510,19 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_or_android",
+ srcs = ["EvalOr.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/values:values_android",
+ "//runtime:interpretable_android",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_and",
srcs = ["EvalAnd.java"],
@@ -282,6 +536,19 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_and_android",
+ srcs = ["EvalAnd.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/values:values_android",
+ "//runtime:interpretable_android",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_conditional",
srcs = ["EvalConditional.java"],
@@ -294,6 +561,18 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_conditional_android",
+ srcs = ["EvalConditional.java"],
+ deps = [
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_create_struct",
srcs = ["EvalCreateStruct.java"],
@@ -310,6 +589,21 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_create_struct_android",
+ srcs = ["EvalCreateStruct.java"],
+ deps = [
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//common/types:types_android",
+ "//common/values:cel_value_provider_android",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
+
java_library(
name = "eval_create_list",
srcs = ["EvalCreateList.java"],
@@ -324,6 +618,20 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_create_list_android",
+ srcs = ["EvalCreateList.java"],
+ deps = [
+ ":eval_helpers_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_create_map",
srcs = ["EvalCreateMap.java"],
@@ -339,6 +647,21 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_create_map_android",
+ srcs = ["EvalCreateMap.java"],
+ deps = [
+ ":execution_frame_android",
+ ":localized_evaluation_exception",
+ ":planned_interpretable_android",
+ "//common/exceptions:duplicate_key",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "eval_fold",
srcs = ["EvalFold.java"],
@@ -355,6 +678,22 @@ java_library(
],
)
+cel_android_library(
+ name = "eval_fold_android",
+ srcs = ["EvalFold.java"],
+ deps = [
+ ":activation_wrapper_android",
+ ":execution_frame_android",
+ ":planned_interpretable_android",
+ "//runtime:concatenated_list_view",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven//:org_jspecify_jspecify",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "execution_frame",
srcs = ["ExecutionFrame.java"],
@@ -367,6 +706,18 @@ java_library(
],
)
+cel_android_library(
+ name = "execution_frame_android",
+ srcs = ["ExecutionFrame.java"],
+ deps = [
+ "//common:options",
+ "//common/exceptions:iteration_budget_exceeded",
+ "//runtime:evaluation_exception",
+ "//runtime:resolved_overload_android",
+ "//runtime/src/main/java/dev/cel/runtime:function_resolver_android",
+ ],
+)
+
java_library(
name = "eval_helpers",
srcs = ["EvalHelpers.java"],
@@ -377,13 +728,36 @@ java_library(
"//common:error_codes",
"//common/exceptions:runtime_exception",
"//common/values",
+ "//common/values:cel_value",
+ "//runtime:evaluation_exception",
"//runtime:interpretable",
+ "//runtime:resolved_overload",
+ "@maven//:com_google_guava_guava",
+ ],
+)
+
+cel_android_library(
+ name = "eval_helpers_android",
+ srcs = ["EvalHelpers.java"],
+ deps = [
+ ":execution_frame_android",
+ ":localized_evaluation_exception",
+ ":planned_interpretable_android",
+ "//common:error_codes",
+ "//common/exceptions:runtime_exception",
+ "//common/values:cel_value_android",
+ "//common/values:values_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "//runtime:resolved_overload_android",
+ "@maven_android//:com_google_guava_guava",
],
)
java_library(
name = "localized_evaluation_exception",
srcs = ["LocalizedEvaluationException.java"],
+ # used_by_android
deps = [
"//common:error_codes",
"//common/exceptions:runtime_exception",
@@ -400,6 +774,16 @@ java_library(
],
)
+cel_android_library(
+ name = "error_metadata_android",
+ srcs = ["ErrorMetadata.java"],
+ deps = [
+ "//runtime:metadata",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "planned_interpretable",
srcs = ["PlannedInterpretable.java"],
@@ -410,3 +794,14 @@ java_library(
"@maven//:com_google_errorprone_error_prone_annotations",
],
)
+
+cel_android_library(
+ name = "planned_interpretable_android",
+ srcs = ["PlannedInterpretable.java"],
+ deps = [
+ ":execution_frame_android",
+ "//runtime:evaluation_exception",
+ "//runtime:interpretable_android",
+ "@maven//:com_google_errorprone_error_prone_annotations",
+ ],
+)
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
index 7923682ee..08f4fa8a8 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalHelpers.java
@@ -14,9 +14,14 @@
package dev.cel.runtime.planner;
+import com.google.common.base.Joiner;
import dev.cel.common.CelErrorCode;
import dev.cel.common.exceptions.CelRuntimeException;
+import dev.cel.common.values.CelValue;
+import dev.cel.common.values.CelValueConverter;
import dev.cel.common.values.ErrorValue;
+import dev.cel.runtime.CelEvaluationException;
+import dev.cel.runtime.CelResolvedOverload;
import dev.cel.runtime.GlobalResolver;
final class EvalHelpers {
@@ -51,5 +56,26 @@ static Object evalStrictly(
}
}
+ static Object dispatch(CelResolvedOverload overload, CelValueConverter valueConverter, Object[] args) throws CelEvaluationException {
+ try {
+ Object result = overload.getDefinition().apply(args);
+ Object runtimeValue = valueConverter.toRuntimeValue(result);
+ if (runtimeValue instanceof CelValue) {
+ return valueConverter.unwrap((CelValue) runtimeValue);
+ }
+
+ return runtimeValue;
+ } catch (CelRuntimeException e) {
+ // Function dispatch failure that's already been handled -- just propagate.
+ throw e;
+ } catch (RuntimeException e) {
+ // Unexpected function dispatch failure.
+ throw new IllegalArgumentException(String.format(
+ "Function '%s' failed with arg(s) '%s'",
+ overload.getOverloadId(), Joiner.on(", ").join(args)),
+ e);
+ }
+ }
+
private EvalHelpers() {}
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
index dedef58ca..a22ba8e94 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalLateBoundCall.java
@@ -18,7 +18,6 @@
import com.google.common.collect.ImmutableList;
import dev.cel.common.exceptions.CelOverloadNotFoundException;
-import dev.cel.common.values.CelValue;
import dev.cel.common.values.CelValueConverter;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelResolvedOverload;
@@ -48,12 +47,7 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
.findOverload(functionName, overloadIds, argVals)
.orElseThrow(() -> new CelOverloadNotFoundException(functionName, overloadIds));
- Object result = resolvedOverload.getDefinition().apply(argVals);
- Object runtimeValue = celValueConverter.toRuntimeValue(result);
- if (runtimeValue instanceof CelValue) {
- return celValueConverter.unwrap((CelValue) runtimeValue);
- }
- return runtimeValue;
+ return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVals);
}
static EvalLateBoundCall create(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
index e936c511b..c715ff032 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalUnary.java
@@ -17,7 +17,6 @@
import static dev.cel.runtime.planner.EvalHelpers.evalNonstrictly;
import static dev.cel.runtime.planner.EvalHelpers.evalStrictly;
-import dev.cel.common.values.CelValue;
import dev.cel.common.values.CelValueConverter;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelResolvedOverload;
@@ -37,12 +36,7 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
: evalNonstrictly(arg, resolver, frame);
Object[] arguments = new Object[] {argVal};
- Object result = resolvedOverload.getDefinition().apply(arguments);
- Object runtimeValue = celValueConverter.toRuntimeValue(result);
- if (runtimeValue instanceof CelValue) {
- return celValueConverter.unwrap((CelValue) runtimeValue);
- }
- return runtimeValue;
+ return EvalHelpers.dispatch(resolvedOverload, celValueConverter, arguments);
}
static EvalUnary create(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
index a7f2b643d..9f14f8bf9 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalVarArgsCall.java
@@ -17,7 +17,6 @@
import static dev.cel.runtime.planner.EvalHelpers.evalNonstrictly;
import static dev.cel.runtime.planner.EvalHelpers.evalStrictly;
-import dev.cel.common.values.CelValue;
import dev.cel.common.values.CelValueConverter;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelResolvedOverload;
@@ -43,12 +42,7 @@ public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEval
: evalNonstrictly(arg, resolver, frame);
}
- Object result = resolvedOverload.getDefinition().apply(argVals);
- Object runtimeValue = celValueConverter.toRuntimeValue(result);
- if (runtimeValue instanceof CelValue) {
- return celValueConverter.unwrap((CelValue) runtimeValue);
- }
- return runtimeValue;
+ return EvalHelpers.dispatch(resolvedOverload, celValueConverter, argVals);
}
static EvalVarArgsCall create(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java b/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
index 1a4218860..5b3138207 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/EvalZeroArity.java
@@ -14,7 +14,6 @@
package dev.cel.runtime.planner;
-import dev.cel.common.values.CelValue;
import dev.cel.common.values.CelValueConverter;
import dev.cel.runtime.CelEvaluationException;
import dev.cel.runtime.CelResolvedOverload;
@@ -28,12 +27,7 @@ final class EvalZeroArity extends PlannedInterpretable {
@Override
public Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEvaluationException {
- Object result = resolvedOverload.getDefinition().apply(EMPTY_ARRAY);
- Object runtimeValue = celValueConverter.toRuntimeValue(result);
- if (runtimeValue instanceof CelValue) {
- return celValueConverter.unwrap((CelValue) runtimeValue);
- }
- return runtimeValue;
+ return EvalHelpers.dispatch(resolvedOverload, celValueConverter, EMPTY_ARRAY);
}
static EvalZeroArity create(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java b/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java
index 596d1bae4..b64c3282c 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/MissingAttribute.java
@@ -15,10 +15,12 @@
package dev.cel.runtime.planner;
import com.google.common.collect.ImmutableSet;
+import com.google.errorprone.annotations.Immutable;
import dev.cel.common.exceptions.CelAttributeNotFoundException;
import dev.cel.runtime.GlobalResolver;
/** Represents a missing attribute that is surfaced while resolving a struct field or a map key. */
+@Immutable
final class MissingAttribute implements Attribute {
private final ImmutableSet missingAttributes;
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/PlannedInterpretable.java b/runtime/src/main/java/dev/cel/runtime/planner/PlannedInterpretable.java
index 5ce3208f8..6f3a9d7ff 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/PlannedInterpretable.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/PlannedInterpretable.java
@@ -25,8 +25,6 @@ abstract class PlannedInterpretable {
/** Runs interpretation with the given activation which supplies name/value bindings. */
abstract Object eval(GlobalResolver resolver, ExecutionFrame frame) throws CelEvaluationException;
- // TODO: Implement support for late-bound functions and evaluation listener
-
long exprId() {
return exprId;
}
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java b/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java
index 22aff43c8..9fcd05447 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/PlannedProgram.java
@@ -115,7 +115,11 @@ private CelEvaluationException newCelEvaluationException(long exprId, Exception
} else if (e instanceof CelRuntimeException) {
builder = CelEvaluationExceptionBuilder.newBuilder((CelRuntimeException) e);
} else {
- builder = CelEvaluationExceptionBuilder.newBuilder(e.getMessage()).setCause(e);
+ // Unhandled function dispatch failures wraps the original exception with a descriptive message
+ // (e.g: "Function foo failed with...")
+ // We need to unwrap the cause here to preserve the original exception message and its cause.
+ Throwable cause = e.getCause() != null ? e.getCause() : e;
+ builder = CelEvaluationExceptionBuilder.newBuilder(e.getMessage()).setCause(cause);
}
return builder.setMetadata(metadata(), exprId).build();
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java b/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java
index 973182b9b..b527719f7 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/PresenceTestQualifier.java
@@ -16,10 +16,12 @@
import static dev.cel.runtime.planner.MissingAttribute.newMissingAttribute;
+import com.google.errorprone.annotations.Immutable;
import dev.cel.common.values.SelectableValue;
import java.util.Map;
/** A qualifier for presence testing a field or a map key. */
+@Immutable
final class PresenceTestQualifier implements Qualifier {
@SuppressWarnings("Immutable")
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java b/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
index b5d43728b..7f8b8a0e0 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java
@@ -40,6 +40,7 @@
import dev.cel.common.types.CelKind;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
+import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructType;
import dev.cel.common.types.TypeType;
import dev.cel.common.values.CelValueConverter;
@@ -60,7 +61,6 @@
@Immutable
@Internal
public final class ProgramPlanner {
-
private final CelTypeProvider typeProvider;
private final CelValueProvider valueProvider;
private final DefaultDispatcher dispatcher;
@@ -182,7 +182,13 @@ private PlannedInterpretable planCheckedIdent(
TypeType identType =
typeProvider
.findType(identRef.name())
- .map(TypeType::create)
+ .map(
+ t ->
+ (t instanceof TypeType)
+ // Coalesce all type(foo) "type" into a sentinel runtime type to allow for
+ // erasure based type comparisons
+ ? TypeType.create(SimpleType.DYN)
+ : TypeType.create(t))
.orElseThrow(
() ->
new NoSuchElementException(
diff --git a/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java b/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java
index 4ceaa0e51..25503e65b 100644
--- a/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java
+++ b/runtime/src/main/java/dev/cel/runtime/planner/StringQualifier.java
@@ -14,11 +14,13 @@
package dev.cel.runtime.planner;
+import com.google.errorprone.annotations.Immutable;
import dev.cel.common.exceptions.CelAttributeNotFoundException;
import dev.cel.common.values.SelectableValue;
import java.util.Map;
/** A qualifier that accesses fields or map keys using a string identifier. */
+@Immutable
final class StringQualifier implements Qualifier {
private final String value;
diff --git a/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel b/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel
index 5853220ae..0a76b6135 100644
--- a/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel
+++ b/runtime/src/main/java/dev/cel/runtime/standard/BUILD.bazel
@@ -1389,6 +1389,40 @@ cel_android_library(
],
)
+java_library(
+ name = "type",
+ srcs = ["TypeFunction.java"],
+ tags = [
+ ],
+ deps = [
+ ":standard_function",
+ ":standard_overload",
+ "//common:options",
+ "//common/types",
+ "//runtime:function_binding",
+ "//runtime:runtime_equality",
+ "//runtime:type_resolver",
+ "@maven//:com_google_guava_guava",
+ ],
+)
+
+cel_android_library(
+ name = "type_android",
+ srcs = ["TypeFunction.java"],
+ tags = [
+ ],
+ deps = [
+ ":standard_function_android",
+ ":standard_overload_android",
+ "//common:options",
+ "//common/types:types_android",
+ "//runtime:function_binding_android",
+ "//runtime:runtime_equality_android",
+ "//runtime:type_resolver_android",
+ "@maven_android//:com_google_guava_guava",
+ ],
+)
+
java_library(
name = "uint",
srcs = ["UintFunction.java"],
diff --git a/runtime/src/main/java/dev/cel/runtime/standard/TypeFunction.java b/runtime/src/main/java/dev/cel/runtime/standard/TypeFunction.java
new file mode 100644
index 000000000..b325c0e9c
--- /dev/null
+++ b/runtime/src/main/java/dev/cel/runtime/standard/TypeFunction.java
@@ -0,0 +1,71 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dev.cel.runtime.standard;
+
+import com.google.common.collect.ImmutableSet;
+import dev.cel.common.CelOptions;
+import dev.cel.common.types.SimpleType;
+import dev.cel.common.types.TypeType;
+import dev.cel.runtime.CelFunctionBinding;
+import dev.cel.runtime.RuntimeEquality;
+import dev.cel.runtime.TypeResolver;
+
+/**
+ * Standard function for the {@code type} function.
+ *
+ * The {@code type} function returns the CEL type of its argument. It accepts a
+ * {@link TypeResolver} so that different runtimes can supply the appropriate resolver (e.g. a
+ * descriptor-based resolver for full proto, or a base resolver for lite proto).
+ */
+public final class TypeFunction extends CelStandardFunction {
+
+ private final TypeResolver typeResolver;
+
+ public static TypeFunction create(TypeResolver typeResolver) {
+ return new TypeFunction(typeResolver);
+ }
+
+ /** Overloads for the standard {@code type} function. */
+ public enum TypeOverload implements CelStandardOverload {
+ TYPE;
+
+ @Override
+ public CelFunctionBinding newFunctionBinding(
+ CelOptions celOptions, RuntimeEquality runtimeEquality) {
+ // This overload is not used directly. The binding is created in TypeFunction via the
+ // TypeResolver instance.
+ // TODO: Instantiate from CelStandardFunctions.
+ throw new UnsupportedOperationException(
+ "TypeOverload bindings must be created through TypeFunction.create(TypeResolver)");
+ }
+ }
+
+ @Override
+ public ImmutableSet newFunctionBindings(
+ CelOptions celOptions, RuntimeEquality runtimeEquality) {
+ CelFunctionBinding binding =
+ CelFunctionBinding.from(
+ "type",
+ Object.class,
+ arg -> typeResolver.resolveObjectType(arg, TypeType.create(SimpleType.DYN)));
+
+ return CelFunctionBinding.fromOverloads("type", ImmutableSet.of(binding));
+ }
+
+ private TypeFunction(TypeResolver typeResolver) {
+ super("type", ImmutableSet.copyOf(TypeOverload.values()));
+ this.typeResolver = typeResolver;
+ }
+}
\ No newline at end of file
diff --git a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
index 097282f6b..a95f62c79 100644
--- a/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
+++ b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel
@@ -51,6 +51,7 @@ java_library(
"//common/internal:well_known_proto",
"//common/types",
"//common/types:cel_v1alpha1_types",
+ "//common/types:message_lite_type_provider",
"//common/types:message_type_provider",
"//common/values",
"//common/values:cel_byte_string",
@@ -134,7 +135,6 @@ java_library(
"//common:options",
"//extensions",
"//runtime",
- "//runtime:runtime_planner_impl",
"//testing:base_interpreter_test",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
"@maven//:junit_junit",
@@ -161,6 +161,7 @@ cel_android_local_test(
"//runtime:lite_runtime_android",
"//runtime:lite_runtime_factory_android",
"//runtime:lite_runtime_impl_android",
+ "//runtime:program_android",
"//runtime:standard_functions_android",
"//runtime:unknown_attributes_android",
"//runtime/src/main/java/dev/cel/runtime:program_android",
diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java
index b3a1f2efa..798cf3ac9 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java
@@ -31,13 +31,14 @@ public class CelLiteInterpreterTest extends BaseInterpreterTest {
@Override
protected CelRuntimeBuilder newBaseRuntimeBuilder(CelOptions celOptions) {
- return CelRuntimeFactory.standardCelRuntimeBuilder()
+ return CelRuntimeFactory.plannerCelRuntimeBuilder()
.setValueProvider(
ProtoMessageLiteValueProvider.newInstance(
dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(),
TestAllTypesCelDescriptor.getDescriptor()))
+ .addLateBoundFunctions("record")
.addLibraries(CelOptionalLibrary.INSTANCE)
- .setOptions(celOptions.toBuilder().enableCelValue(true).build());
+ .setOptions(celOptions);
}
@Override
@@ -52,6 +53,12 @@ public void dynamicMessage_dynamicDescriptor() throws Exception {
skipBaselineVerification();
}
+ @Override
+ public void typeComparisons() {
+ // TODO: Implement DescriptorLiteTypeResolver
+ skipBaselineVerification();
+ }
+
// All the tests below rely on message creation with fields populated. They are excluded for time
// being until this support is added.
@Override
diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
index 638782c2e..fc4c3762e 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeAndroidTest.java
@@ -124,7 +124,7 @@ public void toRuntimeBuilder_isNewInstance() {
@Test
public void toRuntimeBuilder_propertiesCopied() {
- CelOptions celOptions = CelOptions.current().enableCelValue(true).build();
+ CelOptions celOptions = CelOptions.current().build();
CelLiteRuntimeLibrary runtimeExtension =
CelLiteExtensions.sets(celOptions, SetsFunction.INTERSECTS);
CelValueProvider celValueProvider = ProtoMessageLiteValueProvider.newInstance();
@@ -284,6 +284,7 @@ public void eval_customFunctions() throws Exception {
public void eval_customFunctions_asLateBoundFunctions() throws Exception {
CelLiteRuntime runtime =
CelLiteRuntimeFactory.newLiteRuntimeBuilder()
+ .addLateBoundFunctions("isEmpty")
.addFunctionBindings(CelFunctionBinding.from("list_isEmpty", List.class, List::isEmpty))
.setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS)
.build();
@@ -712,7 +713,6 @@ public void eval_protoMessage_mapFields(String checkedExpr) throws Exception {
}
private enum CelOptionsTestCase {
- CEL_VALUE_DISABLED(newBaseTestOptions().enableCelValue(false).build()),
UNSIGNED_LONG_DISABLED(newBaseTestOptions().enableUnsignedLongs(false).build()),
UNWRAP_WKT_DISABLED(newBaseTestOptions().unwrapWellKnownTypesOnFunctionDispatch(false).build()),
STRING_CONCAT_DISABLED(newBaseTestOptions().enableStringConcatenation(false).build()),
@@ -723,7 +723,7 @@ private enum CelOptionsTestCase {
private final CelOptions celOptions;
private static CelOptions.Builder newBaseTestOptions() {
- return CelOptions.current().enableCelValue(true);
+ return CelOptions.current();
}
CelOptionsTestCase(CelOptions celOptions) {
diff --git a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java
index 4ffe0941c..52570b0a3 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelLiteRuntimeTest.java
@@ -42,6 +42,7 @@
import dev.cel.common.CelFunctionDecl;
import dev.cel.common.CelOverloadDecl;
import dev.cel.common.internal.ProtoTimeUtils;
+import dev.cel.common.types.ProtoMessageLiteTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.StructTypeReference;
import dev.cel.common.values.CelByteString;
@@ -74,22 +75,29 @@
/** Exercises tests for CelLiteRuntime using full version of protobuf messages . */
@RunWith(TestParameterInjector.class)
public class CelLiteRuntimeTest {
+ private static final CelContainer CEL_CONTAINER =
+ CelContainer.ofName("cel.expr.conformance.proto3");
private static final CelCompiler CEL_COMPILER =
CelCompilerFactory.standardCelCompilerBuilder()
.setStandardMacros(CelStandardMacro.STANDARD_MACROS)
.addVar("msg", StructTypeReference.create(TestAllTypes.getDescriptor().getFullName()))
.addVar("content", SimpleType.DYN)
.addMessageTypes(TestAllTypes.getDescriptor())
- .setContainer(CelContainer.ofName("cel.expr.conformance.proto3"))
+ .setContainer(CEL_CONTAINER)
.build();
private static final CelLiteRuntime CEL_RUNTIME =
CelLiteRuntimeFactory.newLiteRuntimeBuilder()
.setStandardFunctions(CelStandardFunctions.ALL_STANDARD_FUNCTIONS)
+ .setTypeProvider(
+ ProtoMessageLiteTypeProvider.newInstance(
+ dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(),
+ TestAllTypesCelDescriptor.getDescriptor()))
.setValueProvider(
ProtoMessageLiteValueProvider.newInstance(
dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(),
TestAllTypesCelDescriptor.getDescriptor()))
+ .setContainer(CEL_CONTAINER)
.build();
@Test
@@ -623,7 +631,10 @@ public void eval_withLateBoundFunction() throws Exception {
CelOverloadDecl.newGlobalOverload(
"lateBoundFunc_string", SimpleType.STRING, SimpleType.STRING)))
.build();
- CelLiteRuntime celRuntime = CelLiteRuntimeFactory.newLiteRuntimeBuilder().build();
+ CelLiteRuntime celRuntime =
+ CelLiteRuntimeFactory.newLiteRuntimeBuilder()
+ .addLateBoundFunctions("lateBoundFunc")
+ .build();
CelAbstractSyntaxTree ast = celCompiler.compile("lateBoundFunc('hello')").getAst();
String result =
diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeFactoryTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeFactoryTest.java
index 28676ebcb..3abf90f7e 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeFactoryTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeFactoryTest.java
@@ -27,4 +27,10 @@ public final class CelRuntimeFactoryTest {
public void standardCelRuntimeBuilder() {
assertThat(CelRuntimeFactory.standardCelRuntimeBuilder().build()).isNotNull();
}
+
+ @Test
+ public void plannerCelRuntimeBuilder() {
+ CelRuntime runtime = CelRuntimeFactory.plannerCelRuntimeBuilder().build();
+ assertThat(runtime).isNotNull();
+ }
}
diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java
index fa3b5f4ae..fec5fab41 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeLegacyImplTest.java
@@ -19,12 +19,10 @@
import com.google.protobuf.Message;
import dev.cel.common.CelException;
import dev.cel.common.exceptions.CelDivideByZeroException;
-import dev.cel.common.values.CelValueProvider;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.expr.conformance.proto3.TestAllTypes;
import dev.cel.runtime.CelStandardFunctions.StandardFunction;
-import java.util.Optional;
import java.util.function.Function;
import org.junit.Assert;
import org.junit.Test;
@@ -108,13 +106,11 @@ public void toRuntimeBuilder_optionalProperties() {
Function customTypeFactory = (typeName) -> TestAllTypes.newBuilder();
CelStandardFunctions overriddenStandardFunctions =
CelStandardFunctions.newBuilder().includeFunctions(StandardFunction.ADD).build();
- CelValueProvider noOpValueProvider = (structType, fields) -> Optional.empty();
CelRuntimeBuilder celRuntimeBuilder =
CelRuntimeFactory.standardCelRuntimeBuilder()
.setStandardEnvironmentEnabled(false)
.setTypeFactory(customTypeFactory)
- .setStandardFunctions(overriddenStandardFunctions)
- .setValueProvider(noOpValueProvider);
+ .setStandardFunctions(overriddenStandardFunctions);
CelRuntime celRuntime = celRuntimeBuilder.build();
CelRuntimeLegacyImpl.Builder newRuntimeBuilder =
@@ -123,6 +119,5 @@ public void toRuntimeBuilder_optionalProperties() {
assertThat(newRuntimeBuilder.customTypeFactory).isEqualTo(customTypeFactory);
assertThat(newRuntimeBuilder.overriddenStandardFunctions)
.isEqualTo(overriddenStandardFunctions);
- assertThat(newRuntimeBuilder.celValueProvider).isEqualTo(noOpValueProvider);
}
}
diff --git a/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java b/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java
index c7f142602..efae51712 100644
--- a/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/CelRuntimeTest.java
@@ -22,6 +22,7 @@
import com.google.api.expr.v1alpha1.Type.PrimitiveType;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.primitives.UnsignedLong;
import com.google.protobuf.Any;
import com.google.protobuf.BoolValue;
import com.google.protobuf.ByteString;
@@ -739,4 +740,15 @@ public void standardEnvironmentDisabledForRuntime_throws() throws Exception {
.hasMessageThat()
.contains("No matching overload for function 'size'. Overload candidates: size_string");
}
+
+ @Test
+ public void uintConversion_dynamicDispatch() throws Exception {
+ CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder().build();
+ CelRuntime celRuntime = CelRuntimeFactory.plannerCelRuntimeBuilder().build();
+ CelAbstractSyntaxTree ast = celCompiler.compile("uint(dyn(1u))").getAst();
+
+ Object result = celRuntime.createProgram(ast).eval();
+
+ assertThat(result).isEqualTo(UnsignedLong.valueOf(1L));
+ }
}
diff --git a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
index 205fb2bed..e0e450460 100644
--- a/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/PlannerInterpreterTest.java
@@ -26,7 +26,7 @@ public class PlannerInterpreterTest extends BaseInterpreterTest {
@Override
protected CelRuntimeBuilder newBaseRuntimeBuilder(CelOptions celOptions) {
- return CelRuntimeImpl.newBuilder()
+ return CelRuntimeFactory.plannerCelRuntimeBuilder()
.addLateBoundFunctions("record")
// CEL-Internal-2
.setOptions(celOptions)
@@ -46,18 +46,6 @@ public void unknownResultSet() {
skipBaselineVerification();
}
- @Override
- public void typeComparisons() {
- // TODO: type() standard function needs to be implemented first.
- skipBaselineVerification();
- }
-
- @Override
- public void optional_errors() {
- // TODO: Fix error message for function dispatch failures
- skipBaselineVerification();
- }
-
@Override
public void jsonFieldNames() throws Exception {
// TODO: Support JSON field names for planner
diff --git a/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel
index 6749be24f..83014259b 100644
--- a/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel
+++ b/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel
@@ -38,8 +38,10 @@ java_library(
"//compiler",
"//compiler:compiler_builder",
"//extensions",
+ "//extensions:optional_library",
"//parser:macro",
"//runtime",
+ "//runtime:descriptor_type_resolver",
"//runtime:dispatcher",
"//runtime:function_binding",
"//runtime:program",
@@ -47,6 +49,7 @@ java_library(
"//runtime:runtime_helpers",
"//runtime:standard_functions",
"//runtime/planner:program_planner",
+ "//runtime/standard:type",
"@cel_spec//proto/cel/expr/conformance/proto3:test_all_types_java_proto",
"@maven//:com_google_guava_guava",
"@maven//:com_google_testparameterinjector_test_parameter_injector",
diff --git a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
index ca862ed27..e8f5c6662 100644
--- a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
+++ b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java
@@ -71,9 +71,11 @@
import dev.cel.runtime.CelStandardFunctions;
import dev.cel.runtime.CelStandardFunctions.StandardFunction;
import dev.cel.runtime.DefaultDispatcher;
+import dev.cel.runtime.DescriptorTypeResolver;
import dev.cel.runtime.Program;
import dev.cel.runtime.RuntimeEquality;
import dev.cel.runtime.RuntimeHelpers;
+import dev.cel.runtime.standard.TypeFunction;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -173,6 +175,10 @@ private static DefaultDispatcher newDispatcher() {
addBindingsToDispatcher(
builder, stdFunctions.newFunctionBindings(RUNTIME_EQUALITY, CEL_OPTIONS));
+ TypeFunction typeFunction = TypeFunction.create(DescriptorTypeResolver.create(TYPE_PROVIDER));
+ addBindingsToDispatcher(
+ builder, typeFunction.newFunctionBindings(CEL_OPTIONS, RUNTIME_EQUALITY));
+
// Custom functions
addBindingsToDispatcher(
builder,
@@ -397,10 +403,17 @@ public void plan_call_zeroArgs() throws Exception {
public void plan_call_throws() throws Exception {
CelAbstractSyntaxTree ast = compile("error()");
Program program = PLANNER.plan(ast);
+ String expectedOverloadId = isParseOnly ? "error" : "error_overload";
CelEvaluationException e = assertThrows(CelEvaluationException.class, program::eval);
- assertThat(e).hasMessageThat().contains("evaluation error at :5: Intentional error");
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "evaluation error at :5: Function '"
+ + expectedOverloadId
+ + "' failed with arg(s) ''");
assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+ assertThat(e.getCause()).hasMessageThat().contains("Intentional error");
}
@Test
@@ -601,6 +614,17 @@ public void plan_call_lateBoundFunction() throws Exception {
assertThat(result).isEqualTo("test_resolved");
}
+ @Test
+ public void plan_call_typeResolution(@TestParameter TypeObjectTestCase testCase)
+ throws Exception {
+ CelAbstractSyntaxTree ast = compile(testCase.expression);
+ Program program = PLANNER.plan(ast);
+
+ TypeType result = (TypeType) program.eval();
+
+ assertThat(result).isEqualTo(testCase.type);
+ }
+
@Test
public void plan_select_protoMessageField() throws Exception {
CelAbstractSyntaxTree ast = compile("msg.single_string");
@@ -1005,6 +1029,23 @@ private enum TypeLiteralTestCase {
}
}
+ private enum TypeObjectTestCase {
+ BOOL("type(true)", SimpleType.BOOL),
+ INT("type(1)", SimpleType.INT),
+ DOUBLE("type(1.5)", SimpleType.DOUBLE),
+ PROTO_MESSAGE_TYPE(
+ "type(cel.expr.conformance.proto3.TestAllTypes{})",
+ TYPE_PROVIDER.findType("cel.expr.conformance.proto3.TestAllTypes").get());
+
+ private final String expression;
+ private final TypeType type;
+
+ TypeObjectTestCase(String expression, CelType type) {
+ this.expression = expression;
+ this.type = TypeType.create(type);
+ }
+ }
+
@SuppressWarnings("Immutable") // Test only
private enum PresenceTestCase {
PROTO_FIELD_PRESENT(
diff --git a/runtime/standard/BUILD.bazel b/runtime/standard/BUILD.bazel
index bc6ab9ed3..4ca87e5e0 100644
--- a/runtime/standard/BUILD.bazel
+++ b/runtime/standard/BUILD.bazel
@@ -406,6 +406,16 @@ cel_android_library(
exports = ["//runtime/src/main/java/dev/cel/runtime/standard:uint_android"],
)
+java_library(
+ name = "type",
+ exports = ["//runtime/src/main/java/dev/cel/runtime/standard:type"],
+)
+
+cel_android_library(
+ name = "type_android",
+ exports = ["//runtime/src/main/java/dev/cel/runtime/standard:type_android"],
+)
+
java_library(
name = "not_strictly_false",
exports = ["//runtime/src/main/java/dev/cel/runtime/standard:not_strictly_false"],