Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions common/src/main/java/dev/cel/common/CelDescriptorUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

package dev.cel.common;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.DescriptorProtos.FileDescriptorSet;
Expand Down Expand Up @@ -63,7 +62,6 @@ public static ImmutableSet<FileDescriptor> getFileDescriptorsForDescriptors(
* <p>Warning: This will produce unique FileDescriptor instances. Use with care especially in
* hermetic environments.
*/
@VisibleForTesting
public static ImmutableSet<FileDescriptor> getFileDescriptorsFromFileDescriptorSet(
FileDescriptorSet fileDescriptorSet) {
return FileDescriptorSetConverter.convert(fileDescriptorSet);
Expand Down
5 changes: 5 additions & 0 deletions runtime/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ java_library(
name = "interpreter_util",
exports = ["//runtime/src/main/java/dev/cel/runtime:interpreter_util"],
)

java_library(
name = "evaluation_listener",
exports = ["//runtime/src/main/java/dev/cel/runtime:evaluation_listener"],
)
18 changes: 15 additions & 3 deletions runtime/src/main/java/dev/cel/runtime/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ java_library(
exports = [":base"],
deps = [
":base",
":evaluation_listener",
":runtime_helper",
":unknown_attributes",
"//:auto_value",
Expand All @@ -85,7 +86,6 @@ java_library(
"//common/ast",
"//common/internal:dynamic_proto",
"//common/types:type_providers",
"//runtime:unknown_attributes",
"@cel_spec//proto/cel/expr:expr_java_proto",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
Expand Down Expand Up @@ -142,6 +142,7 @@ java_library(
],
deps = [
":base",
":evaluation_listener",
":interpreter",
":unknown_attributes",
"//:auto_value",
Expand All @@ -150,7 +151,6 @@ java_library(
"//common:options",
"//common/annotations",
"//common/internal:dynamic_proto",
"//runtime:unknown_attributes",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
Expand Down Expand Up @@ -178,12 +178,12 @@ java_library(
tags = [
],
deps = [
":unknown_attributes",
"//common",
"//common:compiler_common",
"//parser",
"//parser:operator",
"//parser:parser_builder",
"//runtime:unknown_attributes",
"@cel_spec//proto/cel/expr:expr_java_proto",
"@maven//:com_google_guava_guava",
],
Expand Down Expand Up @@ -216,3 +216,15 @@ java_library(
"@maven//:org_jspecify_jspecify",
],
)

java_library(
name = "evaluation_listener",
srcs = ["CelEvaluationListener.java"],
tags = [
],
deps = [
"//common/ast",
"@maven//:com_google_code_findbugs_annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
],
)
40 changes: 40 additions & 0 deletions runtime/src/main/java/dev/cel/runtime/CelEvaluationListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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 javax.annotation.concurrent.ThreadSafe;
import dev.cel.common.ast.CelExpr;

/**
* Functional interface for a callback method invoked by the runtime. Implementations must ensure
* that its instances are unconditionally thread-safe.
*/
@FunctionalInterface
@ThreadSafe
public interface CelEvaluationListener {

/**
* Callback method invoked by the CEL runtime as evaluation progresses through the AST.
*
* @param expr CelExpr that was evaluated to produce the evaluated result.
* @param evaluatedResult Evaluated result.
*/
void callback(CelExpr expr, Object evaluatedResult);

/** Construct a listener that does nothing. */
static CelEvaluationListener noOpListener() {
return (arg1, arg2) -> {};
}
}
52 changes: 47 additions & 5 deletions runtime/src/main/java/dev/cel/runtime/CelRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,41 @@ public Object eval(CelVariableResolver resolver) throws CelEvaluationException {
return evalInternal((name) -> resolver.find(name).orElse(null));
}

/**
* Trace evaluates a compiled program without any variables and invokes the listener as
* evaluation progresses through the AST.
*/
public Object trace(CelEvaluationListener listener) throws CelEvaluationException {
return evalInternal(Activation.EMPTY, listener);
}

/**
* Trace evaluates a compiled program using a {@code mapValue} as the source of input variables.
* The listener is invoked as evaluation progresses through the AST.
*/
public Object trace(Map<String, ?> mapValue, CelEvaluationListener listener)
throws CelEvaluationException {
return evalInternal(Activation.copyOf(mapValue), listener);
}

/**
* Trace evaluates a compiled program using {@code message} fields as the source of input
* variables. The listener is invoked as evaluation progresses through the AST.
*/
public Object trace(Message message, CelEvaluationListener listener)
throws CelEvaluationException {
return evalInternal(Activation.fromProto(message, getOptions()), listener);
}

/**
* Trace evaluates a compiled program using a custom variable {@code resolver}. The listener is
* invoked as evaluation progresses through the AST.
*/
public Object trace(CelVariableResolver resolver, CelEvaluationListener listener)
throws CelEvaluationException {
return evalInternal((name) -> resolver.find(name).orElse(null), listener);
}

/**
* Advance evaluation based on the current unknown context.
*
Expand All @@ -77,18 +112,24 @@ public Object eval(CelVariableResolver resolver) throws CelEvaluationException {
* UnknownTracking} is disabled, this is equivalent to eval.
*/
public Object advanceEvaluation(UnknownContext context) throws CelEvaluationException {
return evalInternal(context);
return evalInternal(context, CelEvaluationListener.noOpListener());
}

private Object evalInternal(GlobalResolver resolver) throws CelEvaluationException {
return evalInternal(UnknownContext.create(resolver));
return evalInternal(resolver, CelEvaluationListener.noOpListener());
}

private Object evalInternal(GlobalResolver resolver, CelEvaluationListener listener)
throws CelEvaluationException {
return evalInternal(UnknownContext.create(resolver), listener);
}

/**
* Evaluate an expr node with an UnknownContext (an activation annotated with which attributes
* are unknown).
*/
private Object evalInternal(UnknownContext context) throws CelEvaluationException {
private Object evalInternal(UnknownContext context, CelEvaluationListener listener)
throws CelEvaluationException {
try {
Interpretable impl = getInterpretable();
if (getOptions().enableUnknownTracking()) {
Expand All @@ -102,9 +143,10 @@ private Object evalInternal(UnknownContext context) throws CelEvaluationExceptio
RuntimeUnknownResolver.builder()
.setResolver(context.variableResolver())
.setAttributeResolver(context.createAttributeResolver())
.build());
.build(),
listener);
} else {
return impl.eval(context.variableResolver());
return impl.eval(context.variableResolver(), listener);
}
} catch (InterpreterException e) {
throw unwrapOrCreateEvaluationException(e);
Expand Down
12 changes: 0 additions & 12 deletions runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,91 +75,79 @@ public static final class Builder implements CelRuntimeBuilder {
private boolean standardEnvironmentEnabled;
private Function<String, Message.Builder> customTypeFactory;

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder setOptions(CelOptions options) {
this.options = options;
return this;
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addFunctionBindings(CelFunctionBinding... bindings) {
return addFunctionBindings(Arrays.asList(bindings));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addFunctionBindings(Iterable<CelFunctionBinding> bindings) {
bindings.forEach(o -> functionBindings.put(o.getOverloadId(), o));
return this;
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addMessageTypes(Descriptor... descriptors) {
return addMessageTypes(Arrays.asList(descriptors));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addMessageTypes(Iterable<Descriptor> descriptors) {
return addFileTypes(CelDescriptorUtil.getFileDescriptorsForDescriptors(descriptors));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addFileTypes(FileDescriptor... fileDescriptors) {
return addFileTypes(Arrays.asList(fileDescriptors));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addFileTypes(Iterable<FileDescriptor> fileDescriptors) {
this.fileTypes.addAll(checkNotNull(fileDescriptors));
return this;
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addFileTypes(FileDescriptorSet fileDescriptorSet) {
return addFileTypes(
CelDescriptorUtil.getFileDescriptorsFromFileDescriptorSet(fileDescriptorSet));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder setTypeFactory(Function<String, Message.Builder> typeFactory) {
this.customTypeFactory = typeFactory;
return this;
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder setStandardEnvironmentEnabled(boolean value) {
standardEnvironmentEnabled = value;
return this;
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addLibraries(CelRuntimeLibrary... libraries) {
checkNotNull(libraries);
return this.addLibraries(Arrays.asList(libraries));
}

/** {@inheritDoc} */
@Override
@CanIgnoreReturnValue
public Builder addLibraries(Iterable<? extends CelRuntimeLibrary> libraries) {
Expand Down
Loading