Skip to content

Commit c94ddcf

Browse files
l46kokcopybara-github
authored andcommitted
Add planner integration and async evaluation engine
PiperOrigin-RevId: 974934411
1 parent c182a1d commit c94ddcf

19 files changed

Lines changed: 6019 additions & 183 deletions

runtime/planner/BUILD.bazel

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,48 @@ java_library(
2222
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:planned_program"],
2323
)
2424

25+
cel_android_library(
26+
name = "planned_program_android",
27+
visibility = ["//:internal"],
28+
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:planned_program_android"],
29+
)
30+
2531
java_library(
2632
name = "async_gate",
2733
testonly = 1,
2834
visibility = ["//:internal"],
2935
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_gate"],
3036
)
3137

38+
cel_android_library(
39+
name = "async_gate_android",
40+
testonly = 1,
41+
visibility = ["//:internal"],
42+
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_gate_android"],
43+
)
44+
3245
java_library(
3346
name = "async_completion_coordinator",
3447
testonly = 1,
3548
visibility = ["//:internal"],
3649
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_completion_coordinator"],
3750
)
51+
52+
cel_android_library(
53+
name = "async_completion_coordinator_android",
54+
testonly = 1,
55+
visibility = ["//:internal"],
56+
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_completion_coordinator_android"],
57+
)
58+
59+
java_library(
60+
name = "async_call_state_tracker",
61+
visibility = ["//:internal"],
62+
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_call_state_tracker"],
63+
)
64+
65+
cel_android_library(
66+
name = "async_call_state_tracker_android",
67+
visibility = ["//:internal"],
68+
exports = ["//runtime/src/main/java/dev/cel/runtime/planner:async_call_state_tracker_android"],
69+
)

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,6 @@ java_library(
829829
":function_binding",
830830
":function_resolver",
831831
":partial_vars",
832-
":program",
833832
":proto_message_runtime_equality",
834833
":runtime",
835834
":runtime_equality",
@@ -855,7 +854,6 @@ java_library(
855854
"//runtime:activation",
856855
"//runtime:interpretable",
857856
"//runtime:proto_message_activation_factory",
858-
"//runtime:resolved_overload",
859857
"//runtime/planner:planned_program",
860858
"//runtime/planner:program_planner",
861859
"//runtime/standard:type",

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

Lines changed: 40 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -112,22 +112,7 @@ public Program createProgram(CelAbstractSyntaxTree ast) throws CelEvaluationExce
112112
return toRuntimeProgram(planner().plan(ast));
113113
}
114114

115-
private static final CelFunctionResolver EMPTY_FUNCTION_RESOLVER =
116-
new CelFunctionResolver() {
117-
@Override
118-
public Optional<CelResolvedOverload> findOverloadMatchingArgs(
119-
String functionName, Collection<String> overloadIds, Object[] args) {
120-
return Optional.empty();
121-
}
122-
123-
@Override
124-
public Optional<CelResolvedOverload> findOverloadMatchingArgs(
125-
String functionName, Object[] args) {
126-
return Optional.empty();
127-
}
128-
};
129-
130-
public Program toRuntimeProgram(dev.cel.runtime.Program program) {
115+
private Program toRuntimeProgram(PlannedProgram program) {
131116
return new Program() {
132117

133118
@Override
@@ -148,11 +133,10 @@ public Object eval(Map<String, ?> mapValue, CelFunctionResolver lateBoundFunctio
148133

149134
@Override
150135
public Object eval(Message message) throws CelEvaluationException {
151-
PlannedProgram plannedProgram = (PlannedProgram) program;
152-
return plannedProgram.evalOrThrow(
153-
plannedProgram.interpretable(),
154-
ProtoMessageActivationFactory.fromProto(message, plannedProgram.options()),
155-
EMPTY_FUNCTION_RESOLVER,
136+
return program.evalOrThrow(
137+
program.interpretable(),
138+
ProtoMessageActivationFactory.fromProto(message, program.options()),
139+
CelFunctionResolver.EMPTY,
156140
/* partialVars= */ null,
157141
/* listener= */ null);
158142
}
@@ -190,12 +174,6 @@ public ListenableFuture<Object> evalAsync(
190174
return program.evalAsync(mapValue, lateBoundFunctionResolver);
191175
}
192176

193-
@Override
194-
public ListenableFuture<Object> evalAsync(Message message) {
195-
throw new UnsupportedOperationException(
196-
"evalAsync is not supported by this Program implementation.");
197-
}
198-
199177
@Override
200178
public ListenableFuture<Object> evalAsync(CelVariableResolver resolver) {
201179
return program.evalAsync(resolver);
@@ -212,40 +190,43 @@ public ListenableFuture<Object> evalAsync(PartialVars partialVars) {
212190
return program.evalAsync(partialVars);
213191
}
214192

193+
@Override
194+
public ListenableFuture<Object> evalAsync(Message message) {
195+
checkNotNull(message, "message");
196+
return program.evalAsync(
197+
ProtoMessageActivationFactory.fromProto(message, program.options()),
198+
CelFunctionResolver.EMPTY,
199+
/* partialVars= */ null);
200+
}
201+
215202
@Override
216203
public Object trace(CelEvaluationListener listener) throws CelEvaluationException {
217-
return ((PlannedProgram) program)
218-
.trace(GlobalResolver.EMPTY, EMPTY_FUNCTION_RESOLVER, null, listener);
204+
return program.trace(GlobalResolver.EMPTY, CelFunctionResolver.EMPTY, null, listener);
219205
}
220206

221207
@Override
222208
public Object trace(Map<String, ?> mapValue, CelEvaluationListener listener)
223209
throws CelEvaluationException {
224-
return ((PlannedProgram) program)
225-
.trace(Activation.copyOf(mapValue), EMPTY_FUNCTION_RESOLVER, null, listener);
210+
return program.trace(
211+
Activation.copyOf(mapValue), CelFunctionResolver.EMPTY, null, listener);
226212
}
227213

228214
@Override
229215
public Object trace(Message message, CelEvaluationListener listener)
230216
throws CelEvaluationException {
231-
PlannedProgram plannedProgram = (PlannedProgram) program;
232-
return plannedProgram.evalOrThrow(
233-
plannedProgram.interpretable(),
234-
ProtoMessageActivationFactory.fromProto(message, plannedProgram.options()),
235-
EMPTY_FUNCTION_RESOLVER,
217+
return program.evalOrThrow(
218+
program.interpretable(),
219+
ProtoMessageActivationFactory.fromProto(message, program.options()),
220+
CelFunctionResolver.EMPTY,
236221
/* partialVars= */ null,
237222
listener);
238223
}
239224

240225
@Override
241226
public Object trace(CelVariableResolver resolver, CelEvaluationListener listener)
242227
throws CelEvaluationException {
243-
return ((PlannedProgram) program)
244-
.trace(
245-
(name) -> resolver.find(name).orElse(null),
246-
EMPTY_FUNCTION_RESOLVER,
247-
null,
248-
listener);
228+
return program.trace(
229+
(name) -> resolver.find(name).orElse(null), CelFunctionResolver.EMPTY, null, listener);
249230
}
250231

251232
@Override
@@ -254,12 +235,8 @@ public Object trace(
254235
CelFunctionResolver lateBoundFunctionResolver,
255236
CelEvaluationListener listener)
256237
throws CelEvaluationException {
257-
return ((PlannedProgram) program)
258-
.trace(
259-
(name) -> resolver.find(name).orElse(null),
260-
lateBoundFunctionResolver,
261-
null,
262-
listener);
238+
return program.trace(
239+
(name) -> resolver.find(name).orElse(null), lateBoundFunctionResolver, null, listener);
263240
}
264241

265242
@Override
@@ -268,23 +245,22 @@ public Object trace(
268245
CelFunctionResolver lateBoundFunctionResolver,
269246
CelEvaluationListener listener)
270247
throws CelEvaluationException {
271-
return ((PlannedProgram) program)
272-
.trace(Activation.copyOf(mapValue), lateBoundFunctionResolver, null, listener);
248+
return program.trace(
249+
Activation.copyOf(mapValue), lateBoundFunctionResolver, null, listener);
273250
}
274251

275252
@Override
276253
public Object trace(PartialVars partialVars, CelEvaluationListener listener)
277254
throws CelEvaluationException {
278-
return ((PlannedProgram) program)
279-
.trace(
280-
(name) -> partialVars.resolver().find(name).orElse(null),
281-
EMPTY_FUNCTION_RESOLVER,
282-
partialVars,
283-
listener);
255+
return program.trace(
256+
(name) -> partialVars.resolver().find(name).orElse(null),
257+
CelFunctionResolver.EMPTY,
258+
partialVars,
259+
listener);
284260
}
285261

286262
@Override
287-
public Object advanceEvaluation(UnknownContext context) throws CelEvaluationException {
263+
public Object advanceEvaluation(UnknownContext context) {
288264
throw new UnsupportedOperationException("Unsupported operation.");
289265
}
290266
};
@@ -347,6 +323,10 @@ public abstract Builder setAsyncEvaluationOptions(
347323
@Override
348324
public abstract CelValueProvider valueProvider();
349325

326+
abstract CelAsyncEvaluationOptions asyncEvaluationOptions();
327+
328+
abstract Optional<ListeningExecutorService> asyncExecutor();
329+
350330
abstract CelStandardFunctions standardFunctions();
351331

352332
abstract ExtensionRegistry extensionRegistry();
@@ -604,7 +584,9 @@ public CelRuntime build() {
604584
celValueConverter,
605585
container(),
606586
options(),
607-
lateBoundFunctionNamesBuilder().build());
587+
lateBoundFunctionNamesBuilder().build(),
588+
asyncEvaluationOptions(),
589+
asyncExecutor().orElse(null));
608590
setPlanner(planner);
609591

610592
setFunctionBindings(ImmutableMap.copyOf(mutableFunctionBindings));

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,12 @@ public Optional<Object> findInMap(Map<?, ?> map, Object index) {
135135
* comparable even if they are not of the same type, where type differences are usually trivially
136136
* false.
137137
*/
138-
@SuppressWarnings({"rawtypes", "unchecked"})
138+
@SuppressWarnings({"rawtypes", "unchecked", "ReferenceEquality"})
139139
public boolean objectEquals(Object x, Object y) {
140140
if (celOptions.disableCelStandardEquality()) {
141141
return Objects.equals(x, y);
142142
}
143-
if (x == y) {
143+
if (x == y && !isNan(x)) {
144144
return true;
145145
}
146146
x = runtimeHelpers.adaptValue(x);
@@ -237,7 +237,9 @@ public int hashCode(Object object) {
237237

238238
object = runtimeHelpers.adaptValue(object);
239239
if (object instanceof Number) {
240-
return Double.hashCode(((Number) object).doubleValue());
240+
double value = ((Number) object).doubleValue();
241+
// Normalize -0.0 to 0.0. objectEquals reports the two as equal, so they must hash alike.
242+
return Double.hashCode(value == 0.0d ? 0.0d : value);
241243
}
242244
if (object instanceof Iterable) {
243245
int h = 1;
@@ -276,6 +278,10 @@ private static Optional<Long> unsignedToLongLossless(UnsignedLong v) {
276278
return Optional.empty();
277279
}
278280

281+
private static boolean isNan(Object value) {
282+
return value instanceof Number && Double.isNaN(((Number) value).doubleValue());
283+
}
284+
279285
RuntimeEquality(RuntimeHelpers runtimeHelpers, CelOptions celOptions) {
280286
this.runtimeHelpers = runtimeHelpers;
281287
this.celOptions = celOptions;

0 commit comments

Comments
 (0)