Search in sources :

Example 1 with InterpretableDecorator

use of org.projectnessie.cel.interpreter.InterpretableDecorator in project cel-java by projectnessie.

the class CELTest method CustomInterpreterDecorator.

@Test
void CustomInterpreterDecorator() {
    AtomicReference<Interpretable> lastInstruction = new AtomicReference<>();
    InterpretableDecorator optimizeArith = i -> {
        lastInstruction.set(i);
        // Only optimize the instruction if it is a call.
        if (!(i instanceof InterpretableCall)) {
            return i;
        }
        InterpretableCall call = (InterpretableCall) i;
        // Only optimize the math functions when they have constant arguments.
        switch(call.function()) {
            case "_+_":
            case "_-_":
            case "_*_":
            case "_/_":
                // These are all binary operators so they should have to arguments
                Interpretable[] args = call.args();
                // an empty activation and the value returns as a constant.
                if (!(args[0] instanceof InterpretableConst) || !(args[1] instanceof InterpretableConst)) {
                    return i;
                }
                Val val = call.eval(emptyActivation());
                if (isError(val)) {
                    throw new RuntimeException(val.toString());
                }
                return newConstValue(call.id(), val);
            default:
                return i;
        }
    };
    Env env = newEnv(declarations(Decls.newVar("foo", Decls.Int)));
    AstIssuesTuple astIss = env.compile("foo == -1 + 2 * 3 / 3");
    env.program(astIss.getAst(), evalOptions(OptPartialEval), customDecorator(optimizeArith));
    assertThat(lastInstruction.get()).isInstanceOf(InterpretableCall.class);
    InterpretableCall call = (InterpretableCall) lastInstruction.get();
    Interpretable[] args = call.args();
    Interpretable lhs = args[0];
    assertThat(lhs).isInstanceOf(InterpretableAttribute.class);
    InterpretableAttribute lastAttr = (InterpretableAttribute) lhs;
    NamespacedAttribute absAttr = (NamespacedAttribute) lastAttr.attr();
    String[] varNames = absAttr.candidateVariableNames();
    assertThat(varNames).containsExactly("foo");
    Interpretable rhs = args[1];
    assertThat(rhs).isInstanceOf(InterpretableConst.class);
    InterpretableConst lastConst = (InterpretableConst) rhs;
    // This is the last number produced by the optimization.
    assertThat(lastConst.value()).isSameAs(IntOne);
}
Also used : BoolT(org.projectnessie.cel.common.types.BoolT) Interpretable(org.projectnessie.cel.interpreter.Interpretable) Macro(org.projectnessie.cel.parser.Macro) Call(com.google.api.expr.v1alpha1.Expr.Call) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) PartialActivation(org.projectnessie.cel.interpreter.Activation.PartialActivation) EnvOption.container(org.projectnessie.cel.EnvOption.container) Macro.newReceiverMacro(org.projectnessie.cel.parser.Macro.newReceiverMacro) Activation.emptyActivation(org.projectnessie.cel.interpreter.Activation.emptyActivation) Disabled(org.junit.jupiter.api.Disabled) InterpretableDecorator(org.projectnessie.cel.interpreter.InterpretableDecorator) Collections.singletonList(java.util.Collections.singletonList) True(org.projectnessie.cel.common.types.BoolT.True) Err.isError(org.projectnessie.cel.common.types.Err.isError) Container(org.projectnessie.cel.common.types.traits.Container) Arrays.asList(java.util.Arrays.asList) CEL.estimateCost(org.projectnessie.cel.CEL.estimateCost) OptPartialEval(org.projectnessie.cel.EvalOption.OptPartialEval) ProtoTypeRegistry.newEmptyRegistry(org.projectnessie.cel.common.types.pb.ProtoTypeRegistry.newEmptyRegistry) ParsedExpr(com.google.api.expr.v1alpha1.ParsedExpr) EnvOption.customTypeProvider(org.projectnessie.cel.EnvOption.customTypeProvider) Val(org.projectnessie.cel.common.types.ref.Val) TypeRegistry(org.projectnessie.cel.common.types.ref.TypeRegistry) InterpretableAttribute(org.projectnessie.cel.interpreter.Interpretable.InterpretableAttribute) Collections.emptyList(java.util.Collections.emptyList) Expr(com.google.api.expr.v1alpha1.Expr) Ident(com.google.api.expr.v1alpha1.Expr.Ident) InterpretableCall(org.projectnessie.cel.interpreter.Interpretable.InterpretableCall) OptExhaustiveEval(org.projectnessie.cel.EvalOption.OptExhaustiveEval) OptTrackState(org.projectnessie.cel.EvalOption.OptTrackState) StringT.stringOf(org.projectnessie.cel.common.types.StringT.stringOf) Decls(org.projectnessie.cel.checker.Decls) CEL.attributePattern(org.projectnessie.cel.CEL.attributePattern) Executors(java.util.concurrent.Executors) Test(org.junit.jupiter.api.Test) ProgramOption.functions(org.projectnessie.cel.ProgramOption.functions) DefaultTypeAdapter(org.projectnessie.cel.common.types.pb.DefaultTypeAdapter) Overload(org.projectnessie.cel.interpreter.functions.Overload) EvalResult(org.projectnessie.cel.Program.EvalResult) Err.newErr(org.projectnessie.cel.common.types.Err.newErr) IntOne(org.projectnessie.cel.common.types.IntT.IntOne) IntStream(java.util.stream.IntStream) Overloads(org.projectnessie.cel.common.types.Overloads) Env.newEnv(org.projectnessie.cel.Env.newEnv) StdLib(org.projectnessie.cel.Library.StdLib) IntT(org.projectnessie.cel.common.types.IntT) Trait(org.projectnessie.cel.common.types.traits.Trait) EnvOption.declarations(org.projectnessie.cel.EnvOption.declarations) CompletableFuture(java.util.concurrent.CompletableFuture) Err.valOrErr(org.projectnessie.cel.common.types.Err.valOrErr) CEL.partialVars(org.projectnessie.cel.CEL.partialVars) AtomicReference(java.util.concurrent.atomic.AtomicReference) EnvOption.customTypeAdapter(org.projectnessie.cel.EnvOption.customTypeAdapter) AstIssuesTuple(org.projectnessie.cel.Env.AstIssuesTuple) Mapper(org.projectnessie.cel.common.types.traits.Mapper) ProgramOption.evalOptions(org.projectnessie.cel.ProgramOption.evalOptions) Assertions.assertThatThrownBy(org.assertj.core.api.Assertions.assertThatThrownBy) Type(com.google.api.expr.v1alpha1.Type) CEL.astToCheckedExpr(org.projectnessie.cel.CEL.astToCheckedExpr) CEL.noVars(org.projectnessie.cel.CEL.noVars) ExecutorService(java.util.concurrent.ExecutorService) Collections.emptyMap(java.util.Collections.emptyMap) CEL.astToString(org.projectnessie.cel.CEL.astToString) ProgramOption.globals(org.projectnessie.cel.ProgramOption.globals) Operator(org.projectnessie.cel.common.operators.Operator) NamespacedAttribute(org.projectnessie.cel.interpreter.AttributeFactory.NamespacedAttribute) UnknownT(org.projectnessie.cel.common.types.UnknownT) Cost(org.projectnessie.cel.interpreter.Coster.Cost) EnvOption.types(org.projectnessie.cel.EnvOption.types) ProgramOption.customDecorator(org.projectnessie.cel.ProgramOption.customDecorator) EnvOption.macros(org.projectnessie.cel.EnvOption.macros) Interpretable.newConstValue(org.projectnessie.cel.interpreter.Interpretable.newConstValue) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) CEL.parsedExprToAst(org.projectnessie.cel.CEL.parsedExprToAst) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) InterpretableConst(org.projectnessie.cel.interpreter.Interpretable.InterpretableConst) CEL.astToParsedExpr(org.projectnessie.cel.CEL.astToParsedExpr) CEL.checkedExprToAst(org.projectnessie.cel.CEL.checkedExprToAst) EvalState(org.projectnessie.cel.interpreter.EvalState) Util.mapOf(org.projectnessie.cel.Util.mapOf) StringT(org.projectnessie.cel.common.types.StringT) EnvOption.homogeneousAggregateLiterals(org.projectnessie.cel.EnvOption.homogeneousAggregateLiterals) Env.newCustomEnv(org.projectnessie.cel.Env.newCustomEnv) EnvOption.abbrevs(org.projectnessie.cel.EnvOption.abbrevs) Val(org.projectnessie.cel.common.types.ref.Val) InterpretableConst(org.projectnessie.cel.interpreter.Interpretable.InterpretableConst) InterpretableDecorator(org.projectnessie.cel.interpreter.InterpretableDecorator) AtomicReference(java.util.concurrent.atomic.AtomicReference) CEL.astToString(org.projectnessie.cel.CEL.astToString) Env.newEnv(org.projectnessie.cel.Env.newEnv) Env.newCustomEnv(org.projectnessie.cel.Env.newCustomEnv) NamespacedAttribute(org.projectnessie.cel.interpreter.AttributeFactory.NamespacedAttribute) InterpretableCall(org.projectnessie.cel.interpreter.Interpretable.InterpretableCall) AstIssuesTuple(org.projectnessie.cel.Env.AstIssuesTuple) Interpretable(org.projectnessie.cel.interpreter.Interpretable) InterpretableAttribute(org.projectnessie.cel.interpreter.Interpretable.InterpretableAttribute) Test(org.junit.jupiter.api.Test)

Example 2 with InterpretableDecorator

use of org.projectnessie.cel.interpreter.InterpretableDecorator in project cel-java by projectnessie.

the class CEL method initInterpretable.

/**
 * initIterpretable creates a checked or unchecked interpretable depending on whether the Ast has
 * been run through the type-checker.
 */
private static Program initInterpretable(Prog p, Ast ast, List<InterpretableDecorator> decorators) {
    InterpretableDecorator[] decs = decorators.toArray(new InterpretableDecorator[0]);
    // slower to execute than their checked counterparts.
    if (!ast.isChecked()) {
        p.interpretable = p.interpreter.newUncheckedInterpretable(ast.getExpr(), decs);
        return p;
    }
    // When the AST has been checked it contains metadata that can be used to speed up program
    // execution.
    CheckedExpr checked = astToCheckedExpr(ast);
    p.interpretable = p.interpreter.newInterpretable(checked, decs);
    return p;
}
Also used : CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) InterpretableDecorator(org.projectnessie.cel.interpreter.InterpretableDecorator)

Example 3 with InterpretableDecorator

use of org.projectnessie.cel.interpreter.InterpretableDecorator in project cel-java by projectnessie.

the class CEL method newProgram.

/**
 * newProgram creates a program instance with an environment, an ast, and an optional list of
 * ProgramOption values.
 *
 * <p>If the program cannot be configured the prog will be nil, with a non-nil error response.
 */
public static Program newProgram(Env e, Ast ast, ProgramOption... opts) {
    // Build the dispatcher, interpreter, and default program value.
    Dispatcher disp = newDispatcher();
    // Ensure the default attribute factory is set after the adapter and provider are
    // configured.
    Prog p = new Prog(e, disp);
    // Configure the program via the ProgramOption values.
    for (ProgramOption opt : opts) {
        if (opt == null) {
            throw new NullPointerException("program options should be non-nil");
        }
        p = opt.apply(p);
        if (p == null) {
            throw new NullPointerException(String.format("program option of type '%s' returned null", opt.getClass().getName()));
        }
    }
    // Set the attribute factory after the options have been set.
    if (p.evalOpts.contains(EvalOption.OptPartialEval)) {
        p.attrFactory = newPartialAttributeFactory(e.getContainer(), e.getTypeAdapter(), e.getTypeProvider());
    } else {
        p.attrFactory = newAttributeFactory(e.getContainer(), e.getTypeAdapter(), e.getTypeProvider());
    }
    Interpreter interp = newInterpreter(disp, e.getContainer(), e.getTypeProvider(), e.getTypeAdapter(), p.attrFactory);
    p.interpreter = interp;
    // Translate the EvalOption flags into InterpretableDecorator instances.
    List<InterpretableDecorator> decorators = new ArrayList<>(p.decorators);
    // Enable constant folding first.
    if (p.evalOpts.contains(EvalOption.OptOptimize)) {
        decorators.add(optimize());
    }
    Prog pp = p;
    // Enable exhaustive eval over state tracking since it offers a superset of features.
    if (p.evalOpts.contains(EvalOption.OptExhaustiveEval)) {
        // State tracking requires that each Eval() call operate on an isolated EvalState
        // object; hence, the presence of the factory.
        ProgFactory factory = state -> {
            List<InterpretableDecorator> decs = new ArrayList<>(decorators);
            decs.add(exhaustiveEval(state));
            Prog clone = new Prog(e, pp.evalOpts, pp.defaultVars, disp, interp, state);
            return initInterpretable(clone, ast, decs);
        };
        return initProgGen(factory);
    } else if (p.evalOpts.contains(EvalOption.OptTrackState)) {
        // Enable state tracking last since it too requires the factory approach but is less
        // featured than the ExhaustiveEval decorator.
        ProgFactory factory = state -> {
            List<InterpretableDecorator> decs = new ArrayList<>(decorators);
            decs.add(trackState(state));
            Prog clone = new Prog(e, pp.evalOpts, pp.defaultVars, disp, interp, state);
            return initInterpretable(clone, ast, decs);
        };
        return initProgGen(factory);
    }
    return initInterpretable(p, ast, decorators);
}
Also used : SourceInfo(com.google.api.expr.v1alpha1.SourceInfo) Interpreter(org.projectnessie.cel.interpreter.Interpreter) AttributePattern.newPartialAttributeFactory(org.projectnessie.cel.interpreter.AttributePattern.newPartialAttributeFactory) Interpreter.exhaustiveEval(org.projectnessie.cel.interpreter.Interpreter.exhaustiveEval) PartialActivation(org.projectnessie.cel.interpreter.Activation.PartialActivation) Interpreter.optimize(org.projectnessie.cel.interpreter.Interpreter.optimize) AttributePattern.newAttributePattern(org.projectnessie.cel.interpreter.AttributePattern.newAttributePattern) EvalState.newEvalState(org.projectnessie.cel.interpreter.EvalState.newEvalState) Activation.emptyActivation(org.projectnessie.cel.interpreter.Activation.emptyActivation) InterpretableDecorator(org.projectnessie.cel.interpreter.InterpretableDecorator) ArrayList(java.util.ArrayList) Dispatcher(org.projectnessie.cel.interpreter.Dispatcher) Interpreter.newInterpreter(org.projectnessie.cel.interpreter.Interpreter.newInterpreter) Interpreter.trackState(org.projectnessie.cel.interpreter.Interpreter.trackState) Source.newInfoSource(org.projectnessie.cel.common.Source.newInfoSource) Map(java.util.Map) Type(com.google.api.expr.v1alpha1.Type) ParsedExpr(com.google.api.expr.v1alpha1.ParsedExpr) Unparser.unparse(org.projectnessie.cel.parser.Unparser.unparse) AttributeFactory.newAttributeFactory(org.projectnessie.cel.interpreter.AttributeFactory.newAttributeFactory) Coster(org.projectnessie.cel.interpreter.Coster) Expr(com.google.api.expr.v1alpha1.Expr) Cost(org.projectnessie.cel.interpreter.Coster.Cost) AttributePattern(org.projectnessie.cel.interpreter.AttributePattern) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) Activation(org.projectnessie.cel.interpreter.Activation) List(java.util.List) Dispatcher.newDispatcher(org.projectnessie.cel.interpreter.Dispatcher.newDispatcher) Activation.newPartialActivation(org.projectnessie.cel.interpreter.Activation.newPartialActivation) Reference(com.google.api.expr.v1alpha1.Reference) Interpreter(org.projectnessie.cel.interpreter.Interpreter) Interpreter.newInterpreter(org.projectnessie.cel.interpreter.Interpreter.newInterpreter) ArrayList(java.util.ArrayList) InterpretableDecorator(org.projectnessie.cel.interpreter.InterpretableDecorator) ArrayList(java.util.ArrayList) List(java.util.List) Dispatcher(org.projectnessie.cel.interpreter.Dispatcher) Dispatcher.newDispatcher(org.projectnessie.cel.interpreter.Dispatcher.newDispatcher)

Aggregations

CheckedExpr (com.google.api.expr.v1alpha1.CheckedExpr)3 Expr (com.google.api.expr.v1alpha1.Expr)2 ParsedExpr (com.google.api.expr.v1alpha1.ParsedExpr)2 Type (com.google.api.expr.v1alpha1.Type)2 InterpretableDecorator (org.projectnessie.cel.interpreter.InterpretableDecorator)2 Call (com.google.api.expr.v1alpha1.Expr.Call)1 Ident (com.google.api.expr.v1alpha1.Expr.Ident)1 Reference (com.google.api.expr.v1alpha1.Reference)1 SourceInfo (com.google.api.expr.v1alpha1.SourceInfo)1 ArrayList (java.util.ArrayList)1 Arrays.asList (java.util.Arrays.asList)1 Collections.emptyList (java.util.Collections.emptyList)1 Collections.emptyMap (java.util.Collections.emptyMap)1 Collections.singletonList (java.util.Collections.singletonList)1 List (java.util.List)1 Map (java.util.Map)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 ExecutorService (java.util.concurrent.ExecutorService)1 Executors (java.util.concurrent.Executors)1 TimeUnit (java.util.concurrent.TimeUnit)1