From 1d8277eff7edb813b676f56d1078bf551b13464b Mon Sep 17 00:00:00 2001 From: Sokwhan Huh Date: Thu, 20 Nov 2025 17:31:48 -0800 Subject: [PATCH] Internal Changes PiperOrigin-RevId: 834975953 --- .../main/java/dev/cel/bundle/CelBuilder.java | 3 +- .../test/java/dev/cel/bundle/CelImplTest.java | 38 -- common/BUILD.bazel | 5 + .../src/main/java/dev/cel/common/BUILD.bazel | 12 + .../main/java/dev/cel/common/CelOptions.java | 14 - .../java/dev/cel/common/types/BUILD.bazel | 40 ++ .../cel/common/types/DefaultTypeProvider.java | 2 + .../types/ProtoMessageLiteTypeProvider.java | 123 ++++++ .../java/dev/cel/common/values/BUILD.bazel | 7 + .../values/BaseProtoMessageValueProvider.java | 5 +- .../values/CombinedCelValueProvider.java | 9 +- .../values/ProtoLiteCelValueConverter.java | 10 +- .../values/ProtoMessageLiteValueProvider.java | 4 +- .../java/dev/cel/common/values/BUILD.bazel | 4 +- .../ProtoMessageLiteValueProviderTest.java | 2 +- .../cel/common/values/StructValueTest.java | 114 +++-- common/types/BUILD.bazel | 18 + runtime/BUILD.bazel | 38 +- runtime/planner/BUILD.bazel | 6 + .../src/main/java/dev/cel/runtime/BUILD.bazel | 151 +++---- .../cel/runtime/CelLiteRuntimeBuilder.java | 28 ++ .../dev/cel/runtime/CelRuntimeFactory.java | 12 + .../dev/cel/runtime/CelRuntimeLegacyImpl.java | 34 +- .../runtime/CelValueRuntimeTypeProvider.java | 150 ------- .../java/dev/cel/runtime/LiteProgramImpl.java | 58 --- .../java/dev/cel/runtime/LiteRuntimeImpl.java | 114 +++-- .../runtime/planner/ActivationWrapper.java | 2 +- .../java/dev/cel/runtime/planner/BUILD.bazel | 414 +++++++++++++++++- .../cel/runtime/planner/MissingAttribute.java | 2 + .../runtime/planner/PlannedInterpretable.java | 2 - .../planner/PresenceTestQualifier.java | 2 + .../cel/runtime/planner/ProgramPlanner.java | 1 - .../cel/runtime/planner/StringQualifier.java | 2 + .../src/test/java/dev/cel/runtime/BUILD.bazel | 2 + .../cel/runtime/CelLiteInterpreterTest.java | 2 +- .../runtime/CelLiteRuntimeAndroidTest.java | 6 +- .../dev/cel/runtime/CelLiteRuntimeTest.java | 15 +- .../cel/runtime/CelRuntimeFactoryTest.java | 6 + .../cel/runtime/CelRuntimeLegacyImplTest.java | 7 +- .../java/dev/cel/runtime/CelRuntimeTest.java | 12 + .../cel/runtime/PlannerInterpreterTest.java | 2 +- .../java/dev/cel/runtime/planner/BUILD.bazel | 1 + .../runtime/planner/ProgramPlannerTest.java | 7 +- 43 files changed, 997 insertions(+), 489 deletions(-) create mode 100644 common/src/main/java/dev/cel/common/types/ProtoMessageLiteTypeProvider.java delete mode 100644 runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java delete mode 100644 runtime/src/main/java/dev/cel/runtime/LiteProgramImpl.java 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/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..b079b9612 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 = [ @@ -197,6 +223,20 @@ java_library( ], ) +cel_android_library( + name = "default_type_provider_android", + srcs = [ + "DefaultTypeProvider.java", + ], + tags = [ + ], + deps = [ + "//common/types:type_providers_android", + "//common/types:types_android", + "@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..f72191e4e 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(); 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..0ca4cb4a2 100644 --- a/runtime/BUILD.bazel +++ b/runtime/BUILD.bazel @@ -28,6 +28,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 +51,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 +95,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 +129,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"], @@ -253,22 +276,23 @@ cel_android_library( java_library( name = "metadata", + # used_by_android visibility = ["//:internal"], exports = ["//runtime/src/main/java/dev/cel/runtime:metadata"], ) java_library( - name = "concatenated_list_view", - visibility = ["//:internal"], - exports = [ - "//runtime/src/main/java/dev/cel/runtime:concatenated_list_view", - ], + name = "variable_resolver", + # used_by_android + exports = ["//runtime/src/main/java/dev/cel/runtime:variable_resolver"], ) java_library( - name = "variable_resolver", + name = "concatenated_list_view", + # used_by_android + visibility = ["//:internal"], exports = [ - "//runtime/src/main/java/dev/cel/runtime:variable_resolver", + "//runtime/src/main/java/dev/cel/runtime:concatenated_list_view", ], ) 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..a16fa7c1b 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", @@ -477,6 +474,7 @@ RUNTIME_SOURCES = [ "CelRuntime.java", "CelRuntimeBuilder.java", "CelRuntimeFactory.java", + "CelRuntimeImpl.java", "CelRuntimeLegacyImpl.java", "CelRuntimeLibrary.java", "ProgramImpl.java", @@ -570,6 +568,8 @@ java_library( name = "metadata", srcs = ["Metadata.java"], # used_by_android + tags = [ + ], deps = [ "//common/annotations", "@maven//:com_google_errorprone_error_prone_annotations", @@ -579,11 +579,13 @@ java_library( java_library( name = "interpretable", srcs = INTERPRABLE_SOURCES, + tags = [ + ], deps = [ ":evaluation_exception", - ":evaluation_listener", ":function_resolver", "//common/annotations", + "//runtime:evaluation_listener", "@maven//:com_google_errorprone_error_prone_annotations", "@maven//:org_jspecify_jspecify", ], @@ -592,7 +594,8 @@ java_library( cel_android_library( name = "interpretable_android", srcs = INTERPRABLE_SOURCES, - visibility = ["//visibility:private"], + tags = [ + ], deps = [ ":evaluation_exception", ":evaluation_listener_android", @@ -850,7 +853,6 @@ java_library( ], deps = [ ":activation", - ":cel_value_runtime_type_provider", ":descriptor_message_provider", ":descriptor_type_resolver", ":dispatcher", @@ -867,6 +869,7 @@ java_library( ":runtime_type_provider", ":standard_functions", ":unknown_attributes", + ":variable_resolver", "//:auto_value", "//common:cel_ast", "//common:cel_descriptor_util", @@ -879,10 +882,16 @@ java_library( "//common/internal:dynamic_proto", "//common/internal:proto_message_factory", "//common/types:cel_types", + "//common/types:default_type_provider", + "//common/types:message_type_provider", "//common/types:type_providers", + "//common/values", "//common/values:cel_value_provider", + "//common/values:combined_cel_value_provider", "//common/values:proto_message_value_provider", + "//runtime:proto_message_runtime_helpers", "//runtime:variable_resolver", + "//runtime/planner:program_planner", "//runtime/standard:add", "//runtime/standard:int", "//runtime/standard:timestamp", @@ -905,8 +914,10 @@ java_library( ":program", "//: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", @@ -921,53 +932,27 @@ java_library( tags = [ ], deps = [ - ":cel_value_runtime_type_provider", ":dispatcher", ":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/types:default_type_provider", + "//common/types:type_providers", + "//common/values", + "//common/values:cel_value", "//common/values:cel_value_provider", + "//runtime:evaluation_exception", + "//runtime/planner:program_planner", "//runtime/standard:standard_function", "@maven//:com_google_code_findbugs_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", - ], -) - -cel_android_library( - name = "lite_program_impl_android", - srcs = LITE_PROGRAM_IMPL_SOURCES, - deps = [ - ":activation_android", - ":evaluation_exception", - ":function_resolver_android", - ":interpretable_android", - ":program_android", - ":variable_resolver", - "//:auto_value", "@maven//:com_google_errorprone_error_prone_annotations", + "@maven//:com_google_guava_guava", ], ) @@ -977,20 +962,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 +1071,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 +1134,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 +1203,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"], @@ -1275,6 +1212,7 @@ java_library( ":evaluation_exception", ":function_resolver", ":variable_resolver", + "//runtime:variable_resolver", "@maven//:com_google_errorprone_error_prone_annotations", ], ) @@ -1318,3 +1256,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 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/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/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 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/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..e87ee7edf 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,56 @@ 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:late_function_binding_android", + "//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 +120,6 @@ java_library( "//common:options", "//common/exceptions:runtime_exception", "//common/values", - "//runtime", "//runtime:activation", "//runtime:evaluation_exception", "//runtime:evaluation_exception_builder", @@ -77,6 +127,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 +168,20 @@ java_library( ], ) +cel_android_library( + name = "eval_const_android", + srcs = ["EvalConstant.java"], + deps = [ + ":execution_frame_android", + ":planned_interpretable_android", + "//common/values:cel_byte_string", + "//common/values:values_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 +192,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 +232,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 +261,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 +277,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 +292,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 +314,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 +343,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,6 +370,20 @@ 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"], @@ -209,6 +398,20 @@ java_library( ], ) +cel_android_library( + name = "eval_zero_arity_android", + srcs = ["EvalZeroArity.java"], + deps = [ + ":execution_frame_android", + ":planned_interpretable_android", + "//common/values:cel_value_android", + "//common/values:values_android", + "//runtime:evaluation_exception", + "//runtime:interpretable_android", + "//runtime:resolved_overload_android", + ], +) + java_library( name = "eval_unary", srcs = ["EvalUnary.java"], @@ -224,6 +427,21 @@ java_library( ], ) +cel_android_library( + name = "eval_unary_android", + srcs = ["EvalUnary.java"], + deps = [ + ":eval_helpers_android", + ":execution_frame_android", + ":planned_interpretable_android", + "//common/values:cel_value_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"], @@ -239,6 +457,21 @@ java_library( ], ) +cel_android_library( + name = "eval_var_args_call_android", + srcs = ["EvalVarArgsCall.java"], + deps = [ + ":eval_helpers_android", + ":execution_frame_android", + ":planned_interpretable_android", + "//common/values:cel_value_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"], @@ -256,6 +489,23 @@ 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: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 = "eval_or", srcs = ["EvalOr.java"], @@ -269,6 +519,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 +545,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 +570,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 +598,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 +627,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 +656,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 +687,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 +715,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"], @@ -381,9 +741,24 @@ java_library( ], ) +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:values_android", + "//runtime:interpretable_android", + ], +) + java_library( name = "localized_evaluation_exception", srcs = ["LocalizedEvaluationException.java"], + # used_by_android deps = [ "//common:error_codes", "//common/exceptions:runtime_exception", @@ -400,6 +775,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 +795,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/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/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..844281b26 100644 --- a/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java +++ b/runtime/src/main/java/dev/cel/runtime/planner/ProgramPlanner.java @@ -60,7 +60,6 @@ @Immutable @Internal public final class ProgramPlanner { - private final CelTypeProvider typeProvider; private final CelValueProvider valueProvider; private final DefaultDispatcher dispatcher; 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/test/java/dev/cel/runtime/BUILD.bazel b/runtime/src/test/java/dev/cel/runtime/BUILD.bazel index 097282f6b..78f77e30e 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", @@ -161,6 +162,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..eb0410504 100644 --- a/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java +++ b/runtime/src/test/java/dev/cel/runtime/CelLiteInterpreterTest.java @@ -37,7 +37,7 @@ protected CelRuntimeBuilder newBaseRuntimeBuilder(CelOptions celOptions) { dev.cel.expr.conformance.proto2.TestAllTypesCelDescriptor.getDescriptor(), TestAllTypesCelDescriptor.getDescriptor())) .addLibraries(CelOptionalLibrary.INSTANCE) - .setOptions(celOptions.toBuilder().enableCelValue(true).build()); + .setOptions(celOptions); } @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 4b2468538..57de6b286 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) 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..6f4b2d991 100644 --- a/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel +++ b/runtime/src/test/java/dev/cel/runtime/planner/BUILD.bazel @@ -38,6 +38,7 @@ java_library( "//compiler", "//compiler:compiler_builder", "//extensions", + "//extensions:optional_library", "//parser:macro", "//runtime", "//runtime:dispatcher", 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..2e8f4afab 100644 --- a/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java +++ b/runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java @@ -64,6 +64,7 @@ import dev.cel.expr.conformance.proto3.TestAllTypes; import dev.cel.expr.conformance.proto3.TestAllTypes.NestedMessage; import dev.cel.extensions.CelExtensions; +import dev.cel.extensions.CelOptionalLibrary; import dev.cel.parser.CelStandardMacro; import dev.cel.runtime.CelEvaluationException; import dev.cel.runtime.CelFunctionBinding; @@ -79,7 +80,7 @@ @RunWith(TestParameterInjector.class) public final class ProgramPlannerTest { - // Note that the following deps will be built from top-level builder APIs + // Note that the following deps are ordinarily built from top-level builder APIs private static final CelOptions CEL_OPTIONS = CelOptions.current().build(); private static final CelTypeProvider TYPE_PROVIDER = new CombinedCelTypeProvider( @@ -126,6 +127,7 @@ public final class ProgramPlannerTest { .addVar("int_var", SimpleType.INT) .addVar("dyn_var", SimpleType.DYN) .addVar("really.long.abbr.ident", SimpleType.DYN) + .setContainer(CEL_CONTAINER) .addFunctionDeclarations( newFunctionDeclaration("zero", newGlobalOverload("zero_overload", SimpleType.INT)), newFunctionDeclaration("error", newGlobalOverload("error_overload", SimpleType.INT)), @@ -143,9 +145,8 @@ public final class ProgramPlannerTest { "concat_bytes_bytes", SimpleType.BYTES, SimpleType.BYTES, SimpleType.BYTES), newMemberOverload( "bytes_concat_bytes", SimpleType.BYTES, SimpleType.BYTES, SimpleType.BYTES))) + .addLibraries(CelOptionalLibrary.INSTANCE, CelExtensions.comprehensions()) .addMessageTypes(TestAllTypes.getDescriptor()) - .addLibraries(CelExtensions.optional(), CelExtensions.comprehensions()) - .setContainer(CEL_CONTAINER) .build(); /**