Skip to content

Commit a646a78

Browse files
l46kokcopybara-github
authored andcommitted
Plan PresenceTests
PiperOrigin-RevId: 845139549
1 parent 506c2b6 commit a646a78

18 files changed

Lines changed: 934 additions & 91 deletions

common/src/main/java/dev/cel/common/values/CelValueConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
@SuppressWarnings("unchecked") // Unchecked cast of generics due to type-erasure (ex: MapValue).
3434
@Internal
3535
@Immutable
36-
abstract class CelValueConverter {
36+
public abstract class CelValueConverter {
3737

3838
/** Adapts a {@link CelValue} to a plain old Java Object. */
3939
public Object unwrap(CelValue celValue) {

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,16 @@ public static CelEvaluationExceptionBuilder newBuilder(String message, Object...
8383
*/
8484
@Internal
8585
public static CelEvaluationExceptionBuilder newBuilder(CelRuntimeException celRuntimeException) {
86+
// TODO: Temporary until migration is complete.
8687
Throwable cause = celRuntimeException.getCause();
87-
return new CelEvaluationExceptionBuilder(cause.getMessage())
88-
.setCause(cause)
89-
.setErrorCode(celRuntimeException.getErrorCode());
88+
String message =
89+
cause == null
90+
? celRuntimeException.getMessage()
91+
: celRuntimeException.getCause().getMessage();
92+
93+
return new CelEvaluationExceptionBuilder(message)
94+
.setErrorCode(celRuntimeException.getErrorCode())
95+
.setCause(cause);
9096
}
9197

9298
private CelEvaluationExceptionBuilder(String message) {

runtime/src/main/java/dev/cel/runtime/planner/Attribute.java

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,64 +14,13 @@
1414

1515
package dev.cel.runtime.planner;
1616

17-
18-
import com.google.common.collect.ImmutableList;
1917
import com.google.errorprone.annotations.Immutable;
20-
import dev.cel.common.types.CelTypeProvider;
21-
import dev.cel.common.types.TypeType;
2218
import dev.cel.runtime.GlobalResolver;
2319

20+
/** Represents a resolvable symbol or path (such as a variable or a field selection). */
2421
@Immutable
2522
interface Attribute {
2623
Object resolve(GlobalResolver ctx);
2724

28-
final class MaybeAttribute implements Attribute {
29-
private final ImmutableList<Attribute> attributes;
30-
31-
@Override
32-
public Object resolve(GlobalResolver ctx) {
33-
for (Attribute attr : attributes) {
34-
Object value = attr.resolve(ctx);
35-
if (value != null) {
36-
return value;
37-
}
38-
}
39-
40-
// TODO: Handle unknowns
41-
throw new UnsupportedOperationException("Unknown attributes is not supported yet");
42-
}
43-
44-
MaybeAttribute(ImmutableList<Attribute> attributes) {
45-
this.attributes = attributes;
46-
}
47-
}
48-
49-
final class NamespacedAttribute implements Attribute {
50-
private final ImmutableList<String> namespacedNames;
51-
private final CelTypeProvider typeProvider;
52-
53-
@Override
54-
public Object resolve(GlobalResolver ctx) {
55-
for (String name : namespacedNames) {
56-
Object value = ctx.resolve(name);
57-
if (value != null) {
58-
// TODO: apply qualifiers
59-
return value;
60-
}
61-
62-
TypeType type = typeProvider.findType(name).map(TypeType::create).orElse(null);
63-
if (type != null) {
64-
return type;
65-
}
66-
}
67-
68-
// TODO: Handle unknowns
69-
throw new UnsupportedOperationException("Unknown attributes is not supported yet");
70-
}
71-
72-
NamespacedAttribute(CelTypeProvider typeProvider, ImmutableList<String> namespacedNames) {
73-
this.typeProvider = typeProvider;
74-
this.namespacedNames = namespacedNames;
75-
}
76-
}
25+
Attribute addQualifier(Qualifier qualifier);
7726
}

runtime/src/main/java/dev/cel/runtime/planner/AttributeFactory.java

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

1717
import com.google.common.collect.ImmutableList;
18+
import com.google.common.collect.ImmutableSet;
1819
import com.google.errorprone.annotations.Immutable;
1920
import dev.cel.common.CelContainer;
2021
import dev.cel.common.types.CelTypeProvider;
21-
import dev.cel.runtime.planner.Attribute.MaybeAttribute;
22-
import dev.cel.runtime.planner.Attribute.NamespacedAttribute;
22+
import dev.cel.common.values.CelValueConverter;
2323

2424
@Immutable
2525
final class AttributeFactory {
2626

27-
private final CelContainer unusedContainer;
27+
private final CelContainer container;
2828
private final CelTypeProvider typeProvider;
29+
private final CelValueConverter celValueConverter;
2930

3031
NamespacedAttribute newAbsoluteAttribute(String... names) {
31-
return new NamespacedAttribute(typeProvider, ImmutableList.copyOf(names));
32+
return new NamespacedAttribute(typeProvider, celValueConverter, ImmutableSet.copyOf(names));
3233
}
3334

34-
MaybeAttribute newMaybeAttribute(String... names) {
35-
// TODO: Resolve container names
35+
RelativeAttribute newRelativeAttribute(PlannedInterpretable operand) {
36+
return new RelativeAttribute(operand, celValueConverter);
37+
}
38+
39+
MaybeAttribute newMaybeAttribute(String name) {
3640
return new MaybeAttribute(
37-
ImmutableList.of(new NamespacedAttribute(typeProvider, ImmutableList.copyOf(names))));
41+
this,
42+
ImmutableList.of(
43+
new NamespacedAttribute(
44+
typeProvider, celValueConverter, container.resolveCandidateNames(name))));
3845
}
3946

4047
static AttributeFactory newAttributeFactory(
41-
CelContainer celContainer, CelTypeProvider typeProvider) {
42-
return new AttributeFactory(celContainer, typeProvider);
48+
CelContainer celContainer,
49+
CelTypeProvider typeProvider,
50+
CelValueConverter celValueConverter) {
51+
return new AttributeFactory(celContainer, typeProvider, celValueConverter);
4352
}
4453

45-
private AttributeFactory(CelContainer container, CelTypeProvider typeProvider) {
46-
this.unusedContainer = container;
54+
private AttributeFactory(
55+
CelContainer container, CelTypeProvider typeProvider, CelValueConverter celValueConverter) {
56+
this.container = container;
4757
this.typeProvider = typeProvider;
58+
this.celValueConverter = celValueConverter;
4859
}
4960
}

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

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ java_library(
2323
":eval_create_map",
2424
":eval_create_struct",
2525
":eval_or",
26+
":eval_test_only",
2627
":eval_unary",
2728
":eval_var_args_call",
2829
":eval_zero_arity",
30+
":interpretable_attribute",
2931
":planned_interpretable",
3032
":planned_program",
33+
":qualifier",
34+
":string_qualifier",
3135
"//:auto_value",
3236
"//common:cel_ast",
3337
"//common:container",
@@ -36,11 +40,11 @@ java_library(
3640
"//common/ast",
3741
"//common/types",
3842
"//common/types:type_providers",
43+
"//common/values",
3944
"//common/values:cel_value_provider",
4045
"//runtime:dispatcher",
4146
"//runtime:evaluation_exception",
4247
"//runtime:evaluation_exception_builder",
43-
"//runtime:interpretable",
4448
"//runtime:program",
4549
"//runtime:resolved_overload",
4650
"@maven//:com_google_code_findbugs_annotations",
@@ -84,28 +88,77 @@ java_library(
8488
],
8589
)
8690

91+
java_library(
92+
name = "interpretable_attribute",
93+
srcs = ["InterpretableAttribute.java"],
94+
deps = [
95+
":planned_interpretable",
96+
":qualifier",
97+
"@maven//:com_google_errorprone_error_prone_annotations",
98+
],
99+
)
100+
87101
java_library(
88102
name = "attribute",
89103
srcs = [
90104
"Attribute.java",
91105
"AttributeFactory.java",
106+
"MaybeAttribute.java",
107+
"MissingAttribute.java",
108+
"NamespacedAttribute.java",
109+
"RelativeAttribute.java",
92110
],
93111
deps = [
112+
":eval_helpers",
113+
":planned_interpretable",
114+
":qualifier",
94115
"//common:container",
116+
"//common/exceptions:attribute_not_found",
95117
"//common/types",
96118
"//common/types:type_providers",
119+
"//common/values",
120+
"//common/values:cel_value",
97121
"//runtime:interpretable",
98122
"@maven//:com_google_errorprone_error_prone_annotations",
99123
"@maven//:com_google_guava_guava",
100124
],
101125
)
102126

127+
java_library(
128+
name = "qualifier",
129+
srcs = ["Qualifier.java"],
130+
deps = [
131+
"@maven//:com_google_errorprone_error_prone_annotations",
132+
],
133+
)
134+
135+
java_library(
136+
name = "presence_test_qualifier",
137+
srcs = ["PresenceTestQualifier.java"],
138+
deps = [
139+
":attribute",
140+
":qualifier",
141+
"//common/values",
142+
],
143+
)
144+
145+
java_library(
146+
name = "string_qualifier",
147+
srcs = ["StringQualifier.java"],
148+
deps = [
149+
":qualifier",
150+
"//common/exceptions:attribute_not_found",
151+
"//common/values",
152+
],
153+
)
154+
103155
java_library(
104156
name = "eval_attribute",
105157
srcs = ["EvalAttribute.java"],
106158
deps = [
107159
":attribute",
108-
":planned_interpretable",
160+
":interpretable_attribute",
161+
":qualifier",
109162
"//runtime:evaluation_listener",
110163
"//runtime:function_resolver",
111164
"//runtime:interpretable",
@@ -114,6 +167,21 @@ java_library(
114167
],
115168
)
116169

170+
java_library(
171+
name = "eval_test_only",
172+
srcs = ["EvalTestOnly.java"],
173+
deps = [
174+
":interpretable_attribute",
175+
":presence_test_qualifier",
176+
":qualifier",
177+
"//runtime:evaluation_exception",
178+
"//runtime:evaluation_listener",
179+
"//runtime:function_resolver",
180+
"//runtime:interpretable",
181+
"@maven//:com_google_errorprone_error_prone_annotations",
182+
],
183+
)
184+
117185
java_library(
118186
name = "eval_zero_arity",
119187
srcs = ["EvalZeroArity.java"],

runtime/src/main/java/dev/cel/runtime/planner/EvalAttribute.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
import dev.cel.runtime.GlobalResolver;
2121

2222
@Immutable
23-
final class EvalAttribute extends PlannedInterpretable {
23+
final class EvalAttribute extends InterpretableAttribute {
2424

2525
private final Attribute attr;
2626

2727
@Override
2828
public Object eval(GlobalResolver resolver) {
29-
return attr.resolve(resolver);
29+
Object resolved = attr.resolve(resolver);
30+
if (resolved instanceof MissingAttribute) {
31+
((MissingAttribute) resolved).resolve(resolver);
32+
}
33+
34+
return resolved;
3035
}
3136

3237
@Override
@@ -46,9 +51,16 @@ public Object eval(
4651
GlobalResolver resolver,
4752
CelFunctionResolver lateBoundFunctionResolver,
4853
CelEvaluationListener listener) {
54+
// TODO: Implement support
4955
throw new UnsupportedOperationException("Not yet supported");
5056
}
5157

58+
@Override
59+
public EvalAttribute addQualifier(long exprId, Qualifier qualifier) {
60+
Attribute newAttribute = attr.addQualifier(qualifier);
61+
return create(exprId, newAttribute);
62+
}
63+
5264
static EvalAttribute create(long exprId, Attribute attr) {
5365
return new EvalAttribute(exprId, attr);
5466
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.runtime.planner;
16+
17+
import com.google.errorprone.annotations.Immutable;
18+
import dev.cel.runtime.CelEvaluationException;
19+
import dev.cel.runtime.CelEvaluationListener;
20+
import dev.cel.runtime.CelFunctionResolver;
21+
import dev.cel.runtime.GlobalResolver;
22+
23+
@Immutable
24+
final class EvalTestOnly extends InterpretableAttribute {
25+
26+
private final InterpretableAttribute attr;
27+
28+
@Override
29+
public Object eval(GlobalResolver resolver) throws CelEvaluationException {
30+
return attr.eval(resolver);
31+
}
32+
33+
@Override
34+
public Object eval(GlobalResolver resolver, CelEvaluationListener listener) {
35+
// TODO: Implement support
36+
throw new UnsupportedOperationException("Not yet supported");
37+
}
38+
39+
@Override
40+
public Object eval(GlobalResolver resolver, CelFunctionResolver lateBoundFunctionResolver) {
41+
// TODO: Implement support
42+
throw new UnsupportedOperationException("Not yet supported");
43+
}
44+
45+
@Override
46+
public Object eval(
47+
GlobalResolver resolver,
48+
CelFunctionResolver lateBoundFunctionResolver,
49+
CelEvaluationListener listener) {
50+
// TODO: Implement support
51+
throw new UnsupportedOperationException("Not yet supported");
52+
}
53+
54+
@Override
55+
public EvalTestOnly addQualifier(long exprId, Qualifier qualifier) {
56+
PresenceTestQualifier presenceTestQualifier = PresenceTestQualifier.create(qualifier.value());
57+
return new EvalTestOnly(exprId(), attr.addQualifier(exprId, presenceTestQualifier));
58+
}
59+
60+
static EvalTestOnly create(long exprId, InterpretableAttribute attr) {
61+
return new EvalTestOnly(exprId, attr);
62+
}
63+
64+
private EvalTestOnly(long exprId, InterpretableAttribute attr) {
65+
super(exprId);
66+
this.attr = attr;
67+
}
68+
}

0 commit comments

Comments
 (0)