Skip to content

Commit 5a4c3fc

Browse files
l46kokcopybara-github
authored andcommitted
Add the capability to inline constants during type-check
PiperOrigin-RevId: 865652604
1 parent 026cae6 commit 5a4c3fc

File tree

15 files changed

+200
-31
lines changed

15 files changed

+200
-31
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ java_library(
3131
"//common:compiler_common",
3232
"//common:container",
3333
"//common:options",
34+
"//common/ast",
3435
"//common/internal:env_visitor",
3536
"//common/internal:file_descriptor_converter",
3637
"//common/types:cel_proto_types",

bundle/src/main/java/dev/cel/bundle/CelBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import dev.cel.common.CelFunctionDecl;
3030
import dev.cel.common.CelOptions;
3131
import dev.cel.common.CelVarDecl;
32+
import dev.cel.common.ast.CelConstant;
3233
import dev.cel.common.types.CelType;
3334
import dev.cel.common.types.CelTypeProvider;
3435
import dev.cel.common.values.CelValueProvider;
@@ -101,6 +102,13 @@ public interface CelBuilder {
101102
@CanIgnoreReturnValue
102103
CelBuilder addVar(String name, CelType type);
103104

105+
/**
106+
* Adds a named constant declaration to the CEL environment. The declared constant will be inlined
107+
* into the expression during type-check.
108+
*/
109+
@CanIgnoreReturnValue
110+
CelBuilder addConstant(String name, CelConstant celConstant);
111+
104112
/** Add variable and function {@code declarations} to the CEL environment. */
105113
@CanIgnoreReturnValue
106114
CelBuilder addDeclarations(Decl... declarations);

bundle/src/main/java/dev/cel/bundle/CelImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import dev.cel.common.CelSource;
3939
import dev.cel.common.CelValidationResult;
4040
import dev.cel.common.CelVarDecl;
41+
import dev.cel.common.ast.CelConstant;
4142
import dev.cel.common.internal.EnvVisitable;
4243
import dev.cel.common.internal.EnvVisitor;
4344
import dev.cel.common.internal.FileDescriptorSetConverter;
@@ -214,6 +215,12 @@ public CelBuilder addVar(String name, CelType type) {
214215
return this;
215216
}
216217

218+
@Override
219+
public CelBuilder addConstant(String name, CelConstant celConstant) {
220+
compilerBuilder.addConstant(name, celConstant);
221+
return this;
222+
}
223+
217224
@Override
218225
public CelBuilder addDeclarations(Decl... declarations) {
219226
compilerBuilder.addDeclarations(declarations);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ java_library(
8080
"//common:options",
8181
"//common:source_location",
8282
"//common/annotations",
83+
"//common/ast",
8384
"//common/ast:expr_converter",
8485
"//common/internal:env_visitor",
8586
"//common/internal:errors",
@@ -108,6 +109,7 @@ java_library(
108109
"//common:compiler_common",
109110
"//common:container",
110111
"//common:options",
112+
"//common/ast",
111113
"//common/types:type_providers",
112114
"@cel_spec//proto/cel/expr:checked_java_proto",
113115
"@maven//:com_google_errorprone_error_prone_annotations",

checker/src/main/java/dev/cel/checker/CelCheckerBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import dev.cel.common.CelFunctionDecl;
2626
import dev.cel.common.CelOptions;
2727
import dev.cel.common.CelVarDecl;
28+
import dev.cel.common.ast.CelConstant;
2829
import dev.cel.common.types.CelType;
2930
import dev.cel.common.types.CelTypeProvider;
3031

@@ -69,6 +70,13 @@ public interface CelCheckerBuilder {
6970
@CanIgnoreReturnValue
7071
CelCheckerBuilder addVarDeclarations(Iterable<CelVarDecl> celVarDecls);
7172

73+
/**
74+
* Adds a named constant declaration to the CEL environment. The declared constant will be inlined
75+
* into the expression during type-check.
76+
*/
77+
@CanIgnoreReturnValue
78+
CelCheckerBuilder addConstant(String name, CelConstant celConstant);
79+
7280
/**
7381
* Add one or more {@link ProtoTypeMask} values. The {@code ProtoTypeMask} values will be used to
7482
* compute a set of {@code Decl} values using a protobuf message's fields as the names and types

checker/src/main/java/dev/cel/checker/CelCheckerLegacyImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import dev.cel.common.CelValidationResult;
4343
import dev.cel.common.CelVarDecl;
4444
import dev.cel.common.annotations.Internal;
45+
import dev.cel.common.ast.CelConstant;
4546
import dev.cel.common.ast.CelExprConverter;
4647
import dev.cel.common.internal.EnvVisitable;
4748
import dev.cel.common.internal.EnvVisitor;
@@ -50,6 +51,7 @@
5051
import dev.cel.common.types.CelType;
5152
import dev.cel.common.types.CelTypeProvider;
5253
import dev.cel.common.types.ProtoMessageTypeProvider;
54+
import dev.cel.common.types.SimpleType;
5355
import java.util.ArrayList;
5456
import java.util.Arrays;
5557
import java.util.List;
@@ -285,6 +287,27 @@ public CelCheckerBuilder addVarDeclarations(Iterable<CelVarDecl> celVarDecls) {
285287
return this;
286288
}
287289

290+
@Override
291+
public CelCheckerBuilder addConstant(String name, CelConstant celConstant) {
292+
switch (celConstant.getKind()) {
293+
case NOT_SET:
294+
case TIMESTAMP_VALUE:
295+
case DURATION_VALUE:
296+
throw new IllegalArgumentException("Unsupported constant: " + celConstant.getKind());
297+
default:
298+
break;
299+
}
300+
301+
this.identDeclarations.add(
302+
CelIdentDecl.newBuilder()
303+
.setName(name)
304+
.setType(SimpleType.DYN)
305+
.setConstant(celConstant)
306+
.setIsInlinable(true)
307+
.build());
308+
return this;
309+
}
310+
288311
@Override
289312
public CelCheckerBuilder addProtoTypeMasks(ProtoTypeMask... typeMasks) {
290313
checkNotNull(typeMasks);

checker/src/main/java/dev/cel/checker/CelIdentDecl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public abstract class CelIdentDecl {
5252
/** Documentation string for the identifier. */
5353
public abstract String doc();
5454

55+
/** If set, the identifier will get inlined as a constant value during type-check. */
56+
abstract boolean isInlinable();
57+
5558
/** Converts a {@link CelIdentDecl} to a protobuf equivalent form {@code Decl} */
5659
public static Decl celIdentToDecl(CelIdentDecl identDecl) {
5760
IdentDecl.Builder identBuilder =
@@ -71,7 +74,7 @@ public static CelIdentDecl newIdentDeclaration(String name, CelType type) {
7174
}
7275

7376
public static Builder newBuilder() {
74-
return new AutoValue_CelIdentDecl.Builder().setDoc("");
77+
return new AutoValue_CelIdentDecl.Builder().setDoc("").setIsInlinable(false);
7578
}
7679

7780
/** Builder for configuring the {@link CelIdentDecl}. */
@@ -92,6 +95,8 @@ public abstract static class Builder {
9295
@CanIgnoreReturnValue
9396
public abstract Builder setDoc(String value);
9497

98+
public abstract Builder setIsInlinable(boolean value);
99+
95100
@CanIgnoreReturnValue
96101
public Builder clearConstant() {
97102
return setConstant(Optional.empty());

checker/src/main/java/dev/cel/checker/Env.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -919,13 +919,8 @@ public static class DeclGroup {
919919

920920
/** Construct an empty {@code DeclGroup}. */
921921
public DeclGroup() {
922-
this(new HashMap<>(), new HashMap<>());
923-
}
924-
925-
/** Construct a new {@code DeclGroup} from the input {@code idents} and {@code functions}. */
926-
public DeclGroup(Map<String, CelIdentDecl> idents, Map<String, CelFunctionDecl> functions) {
927-
this.functions = functions;
928-
this.idents = idents;
922+
this.functions = new HashMap<>();
923+
this.idents = new HashMap<>();
929924
}
930925

931926
/**
@@ -959,11 +954,6 @@ public void putIdent(CelIdentDecl ident) {
959954
public void putFunction(CelFunctionDecl function) {
960955
functions.put(function.name(), function);
961956
}
962-
963-
/** Create a copy of the {@code DeclGroup} with immutable identifier and function maps. */
964-
public DeclGroup immutableCopy() {
965-
return new DeclGroup(getIdents(), getFunctions());
966-
}
967957
}
968958

969959
/**

checker/src/main/java/dev/cel/checker/ExprChecker.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,18 @@ private void visit(CelMutableExpr expr, CelMutableIdent ident) {
264264
// Overwrite the identifier with its fully qualified name.
265265
expr.setIdent(CelMutableIdent.create(refName));
266266
}
267-
env.setType(expr, decl.type());
268-
env.setRef(expr, makeReference(refName, decl));
267+
268+
if (decl.isInlinable()) {
269+
decl.constant()
270+
.ifPresent(
271+
constant -> {
272+
expr.setConstant(constant);
273+
visit(expr, expr.constant());
274+
});
275+
} else {
276+
env.setType(expr, decl.type());
277+
env.setRef(expr, makeReference(refName, decl));
278+
}
269279
}
270280

271281
private void visit(CelMutableExpr expr, CelMutableSelect select) {

checker/src/test/java/dev/cel/checker/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,12 @@ java_library(
4040
"//common/types:json",
4141
"//common/types:message_type_provider",
4242
"//common/types:type_providers",
43+
"//common/values",
44+
"//common/values:cel_byte_string",
4345
"//compiler",
4446
"//compiler:compiler_builder",
4547
"//parser:macro",
48+
"//parser:unparser",
4649
"//testing:adorner",
4750
"//testing:cel_baseline_test_case",
4851
"@maven//:junit_junit",

0 commit comments

Comments
 (0)