Skip to content

Commit c4386b4

Browse files
l46kokcopybara-github
authored andcommitted
Plan CreateMap
PiperOrigin-RevId: 828705611
1 parent 02ac761 commit c4386b4

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ java_library(
1717
":eval_attribute",
1818
":eval_const",
1919
":eval_create_list",
20+
":eval_create_map",
2021
":planned_program",
2122
"//:auto_value",
2223
"//common:cel_ast",
@@ -104,3 +105,16 @@ java_library(
104105
"@maven//:com_google_guava_guava",
105106
],
106107
)
108+
109+
java_library(
110+
name = "eval_create_map",
111+
srcs = ["EvalCreateMap.java"],
112+
deps = [
113+
"//runtime",
114+
"//runtime:evaluation_listener",
115+
"//runtime:function_resolver",
116+
"//runtime:interpretable",
117+
"@maven//:com_google_errorprone_error_prone_annotations",
118+
"@maven//:com_google_guava_guava",
119+
],
120+
)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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.common.base.Preconditions;
18+
import com.google.common.collect.ImmutableMap;
19+
import com.google.errorprone.annotations.Immutable;
20+
import dev.cel.runtime.CelEvaluationException;
21+
import dev.cel.runtime.CelEvaluationListener;
22+
import dev.cel.runtime.CelFunctionResolver;
23+
import dev.cel.runtime.GlobalResolver;
24+
import dev.cel.runtime.Interpretable;
25+
26+
@Immutable
27+
final class EvalCreateMap implements Interpretable {
28+
29+
// Array contents are not mutated
30+
@SuppressWarnings("Immutable")
31+
private final Interpretable[] keys;
32+
33+
// Array contents are not mutated
34+
@SuppressWarnings("Immutable")
35+
private final Interpretable[] values;
36+
37+
@Override
38+
public Object eval(GlobalResolver resolver) throws CelEvaluationException {
39+
ImmutableMap.Builder<Object, Object> builder =
40+
ImmutableMap.builderWithExpectedSize(keys.length);
41+
for (int i = 0; i < keys.length; i++) {
42+
builder.put(keys[i].eval(resolver), values[i].eval(resolver));
43+
}
44+
return builder.buildOrThrow();
45+
}
46+
47+
48+
@Override
49+
public Object eval(GlobalResolver resolver, CelEvaluationListener listener) {
50+
// TODO: Implement support
51+
throw new UnsupportedOperationException("Not yet supported");
52+
}
53+
54+
@Override
55+
public Object eval(GlobalResolver resolver, CelFunctionResolver lateBoundFunctionResolver) {
56+
// TODO: Implement support
57+
throw new UnsupportedOperationException("Not yet supported");
58+
}
59+
60+
@Override
61+
public Object eval(GlobalResolver resolver, CelFunctionResolver lateBoundFunctionResolver,
62+
CelEvaluationListener listener) {
63+
// TODO: Implement support
64+
throw new UnsupportedOperationException("Not yet supported");
65+
}
66+
67+
68+
static EvalCreateMap create(Interpretable[] keys, Interpretable[] values) {
69+
return new EvalCreateMap(keys, values);
70+
}
71+
72+
private EvalCreateMap(Interpretable[] keys, Interpretable[] values) {
73+
Preconditions.checkArgument(keys.length == values.length);
74+
this.keys = keys;
75+
this.values = values;
76+
}
77+
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import dev.cel.common.ast.CelConstant;
2525
import dev.cel.common.ast.CelExpr;
2626
import dev.cel.common.ast.CelExpr.CelList;
27+
import dev.cel.common.ast.CelExpr.CelMap;
2728
import dev.cel.common.ast.CelReference;
2829
import dev.cel.common.types.CelKind;
2930
import dev.cel.common.types.CelType;
@@ -69,6 +70,8 @@ private Interpretable plan(CelExpr celExpr, PlannerContext ctx) {
6970
return planIdent(celExpr, ctx);
7071
case LIST:
7172
return planCreateList(celExpr, ctx);
73+
case MAP:
74+
return planCreateMap(celExpr, ctx);
7275
case NOT_SET:
7376
throw new UnsupportedOperationException("Unsupported kind: " + celExpr.getKind());
7477
default:
@@ -141,6 +144,22 @@ private Interpretable planCreateList(CelExpr celExpr, PlannerContext ctx) {
141144
return EvalCreateList.create(values);
142145
}
143146

147+
private Interpretable planCreateMap(CelExpr celExpr, PlannerContext ctx) {
148+
CelMap map = celExpr.map();
149+
150+
ImmutableList<CelMap.Entry> entries = map.entries();
151+
Interpretable[] keys = new Interpretable[entries.size()];
152+
Interpretable[] values = new Interpretable[entries.size()];
153+
154+
for (int i = 0; i < entries.size(); i++) {
155+
CelMap.Entry entry = entries.get(i);
156+
keys[i] = plan(entry.key(), ctx);
157+
values[i] = plan(entry.value(), ctx);
158+
}
159+
160+
return EvalCreateMap.create(keys, values);
161+
}
162+
144163
@AutoValue
145164
abstract static class PlannerContext {
146165

runtime/src/test/java/dev/cel/runtime/planner/ProgramPlannerTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ public void plan_createList() throws Exception {
124124
assertThat(result).containsExactly(1L, "foo", true, ImmutableList.of(2L, false)).inOrder();
125125
}
126126

127+
@Test
128+
@SuppressWarnings("unchecked") // test only
129+
public void plan_createMap() throws Exception {
130+
CelAbstractSyntaxTree ast = compile("{'foo': 1, true: 'bar'}");
131+
Program program = PLANNER.plan(ast);
132+
133+
ImmutableMap<Object, Object> result = (ImmutableMap<Object, Object>) program.eval();
134+
135+
assertThat(result).containsExactly("foo", 1L, true, "bar").inOrder();
136+
}
137+
127138
@Test
128139
public void planIdent_typeLiteral(@TestParameter TypeLiteralTestCase testCase) throws Exception {
129140
if (isParseOnly) {

0 commit comments

Comments
 (0)