Search in sources :

Example 1 with Call

use of com.google.api.expr.v1alpha1.Expr.Call in project cel-java by projectnessie.

the class Unparser method visitCallBinary.

void visitCallBinary(Call expr) {
    String fun = expr.getFunction();
    List<Expr> args = expr.getArgsList();
    Expr lhs = args.get(0);
    // add parens if the current operator is lower precedence than the lhs expr operator.
    boolean lhsParen = isComplexOperatorWithRespectTo(fun, lhs);
    Expr rhs = args.get(1);
    // add parens if the current operator is lower precedence than the rhs expr operator,
    // or the same precedence and the operator is left recursive.
    boolean rhsParen = isComplexOperatorWithRespectTo(fun, rhs);
    if (!rhsParen && isLeftRecursive(fun)) {
        rhsParen = isSamePrecedence(Operator.precedence(fun), rhs);
    }
    visitMaybeNested(lhs, lhsParen);
    String unmangled = Operator.findReverseBinaryOperator(fun);
    if (unmangled == null) {
        throw new IllegalStateException(String.format("cannot unmangle operator: %s", fun));
    }
    str.append(" ");
    str.append(unmangled);
    str.append(" ");
    visitMaybeNested(rhs, rhsParen);
}
Also used : Expr(com.google.api.expr.v1alpha1.Expr)

Example 2 with Call

use of com.google.api.expr.v1alpha1.Expr.Call 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 3 with Call

use of com.google.api.expr.v1alpha1.Expr.Call in project cel-java by projectnessie.

the class AstPruner method maybePruneConditional.

Expr maybePruneConditional(Expr node) {
    if (!existsWithUnknownValue(node.getId())) {
        return null;
    }
    Call call = node.getCallExpr();
    Val condVal = value(call.getArgs(0).getId());
    if (condVal == null || isUnknownOrError(condVal)) {
        return null;
    }
    if (condVal == True) {
        return call.getArgs(1);
    }
    return call.getArgs(2);
}
Also used : Val(org.projectnessie.cel.common.types.ref.Val) Call(com.google.api.expr.v1alpha1.Expr.Call)

Example 4 with Call

use of com.google.api.expr.v1alpha1.Expr.Call in project cel-java by projectnessie.

the class AstPruner method prune.

Expr prune(Expr node) {
    if (node == null) {
        return null;
    }
    Val val = value(node.getId());
    if (val != null && !isUnknownOrError(val)) {
        Expr newNode = maybeCreateLiteral(node.getId(), val);
        if (newNode != null) {
            return newNode;
        }
    }
    switch(node.getExprKindCase()) {
        case SELECT_EXPR:
            Select select = node.getSelectExpr();
            Expr operand = prune(select.getOperand());
            if (operand != null && operand != select.getOperand()) {
                return Expr.newBuilder().setId(node.getId()).setSelectExpr(Select.newBuilder().setOperand(operand).setField(select.getField()).setTestOnly(select.getTestOnly())).build();
            }
            break;
        case CALL_EXPR:
            Call call = node.getCallExpr();
            Expr newExpr = maybePruneFunction(node);
            if (newExpr != null) {
                newExpr = prune(newExpr);
                return newExpr;
            }
            boolean prunedCall = false;
            List<Expr> args = call.getArgsList();
            List<Expr> newArgs = new ArrayList<>(args.size());
            for (int i = 0; i < args.size(); i++) {
                Expr arg = args.get(i);
                newArgs.add(arg);
                Expr newArg = prune(arg);
                if (newArg != null && newArg != arg) {
                    prunedCall = true;
                    newArgs.set(i, newArg);
                }
            }
            Call newCall = Call.newBuilder().setFunction(call.getFunction()).setTarget(call.getTarget()).addAllArgs(newArgs).build();
            Expr newTarget = prune(call.getTarget());
            if (newTarget != null && newTarget != call.getTarget()) {
                prunedCall = true;
                newCall = Call.newBuilder().setFunction(call.getFunction()).setTarget(newTarget).addAllArgs(newArgs).build();
            }
            if (prunedCall) {
                return Expr.newBuilder().setId(node.getId()).setCallExpr(newCall).build();
            }
            break;
        case LIST_EXPR:
            CreateList list = node.getListExpr();
            List<Expr> elems = list.getElementsList();
            List<Expr> newElems = new ArrayList<>(elems.size());
            boolean prunedList = false;
            for (int i = 0; i < elems.size(); i++) {
                Expr elem = elems.get(i);
                newElems.add(elem);
                Expr newElem = prune(elem);
                if (newElem != null && newElem != elem) {
                    newElems.set(i, newElem);
                    prunedList = true;
                }
            }
            if (prunedList) {
                return Expr.newBuilder().setId(node.getId()).setListExpr(CreateList.newBuilder().addAllElements(newElems)).build();
            }
            break;
        case STRUCT_EXPR:
            boolean prunedStruct = false;
            CreateStruct struct = node.getStructExpr();
            List<Entry> entries = struct.getEntriesList();
            String messageType = struct.getMessageName();
            List<Entry> newEntries = new ArrayList<>(entries.size());
            for (int i = 0; i < entries.size(); i++) {
                Entry entry = entries.get(i);
                newEntries.add(entry);
                Expr mapKey = entry.getMapKey();
                Expr newKey = mapKey != Entry.getDefaultInstance().getMapKey() ? prune(mapKey) : null;
                Expr newValue = prune(entry.getValue());
                if ((newKey == null || newKey == mapKey) && (newValue == null || newValue == entry.getValue())) {
                    continue;
                }
                prunedStruct = true;
                Entry newEntry;
                if (!messageType.isEmpty()) {
                    newEntry = Entry.newBuilder().setFieldKey(entry.getFieldKey()).setValue(newValue).build();
                } else {
                    newEntry = Entry.newBuilder().setMapKey(newKey).setValue(newValue).build();
                }
                newEntries.set(i, newEntry);
            }
            if (prunedStruct) {
                return Expr.newBuilder().setId(node.getId()).setStructExpr(CreateStruct.newBuilder().setMessageName(messageType).addAllEntries(entries)).build();
            }
            break;
        case COMPREHENSION_EXPR:
            Comprehension compre = node.getComprehensionExpr();
            // Only the range of the comprehension is pruned since the state tracking only records
            // the last iteration of the comprehension and not each step in the evaluation which
            // means that the any residuals computed in between might be inaccurate.
            Expr newRange = prune(compre.getIterRange());
            if (newRange != null && newRange != compre.getIterRange()) {
                return Expr.newBuilder().setId(node.getId()).setComprehensionExpr(Comprehension.newBuilder().setIterVar(compre.getIterVar()).setIterRange(newRange).setAccuVar(compre.getAccuVar()).setAccuInit(compre.getAccuInit()).setLoopCondition(compre.getLoopCondition()).setLoopStep(compre.getLoopStep()).setResult(compre.getResult())).build();
            }
    }
    // allocation cost at another point. So go with the simple approach - at least for now.
    return node;
}
Also used : Val(org.projectnessie.cel.common.types.ref.Val) Call(com.google.api.expr.v1alpha1.Expr.Call) CreateStruct(com.google.api.expr.v1alpha1.Expr.CreateStruct) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString) Comprehension(com.google.api.expr.v1alpha1.Expr.Comprehension) CreateList(com.google.api.expr.v1alpha1.Expr.CreateList) Entry(com.google.api.expr.v1alpha1.Expr.CreateStruct.Entry) Expr(com.google.api.expr.v1alpha1.Expr) Select(com.google.api.expr.v1alpha1.Expr.Select)

Example 5 with Call

use of com.google.api.expr.v1alpha1.Expr.Call in project cel-java by projectnessie.

the class ConformanceServerTest method fullPipeline.

/**
 * fullPipeline parses, checks, and evaluates the CEL expression in source and returns the result
 * from the Eval call.
 */
FullPipelineResult fullPipeline(String source) {
    // Parse
    ParseRequest preq = ParseRequest.newBuilder().setCelSource(source).build();
    ParseResponse pres = stub.parse(preq);
    assertThat(pres.isInitialized()).isTrue();
    ParsedExpr parsedExpr = pres.getParsedExpr();
    assertThat(parsedExpr.isInitialized()).isTrue();
    assertThat(parsedExpr.getExpr().isInitialized()).isTrue();
    // Check
    CheckRequest creq = CheckRequest.newBuilder().setParsedExpr(parsedExpr).build();
    CheckResponse cres = stub.check(creq);
    assertThat(cres.isInitialized()).isTrue();
    CheckedExpr checkedExpr = cres.getCheckedExpr();
    assertThat(checkedExpr.isInitialized()).isTrue();
    // Eval
    EvalRequest ereq = EvalRequest.newBuilder().setCheckedExpr(checkedExpr).build();
    EvalResponse eres = stub.eval(ereq);
    assertThat(eres.isInitialized()).isTrue();
    assertThat(eres.getResult().isInitialized()).isTrue();
    return new FullPipelineResult(pres, cres, eres);
}
Also used : EvalRequest(com.google.api.expr.v1alpha1.EvalRequest) ParseRequest(com.google.api.expr.v1alpha1.ParseRequest) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) ParsedExpr(com.google.api.expr.v1alpha1.ParsedExpr) CheckResponse(com.google.api.expr.v1alpha1.CheckResponse) CheckRequest(com.google.api.expr.v1alpha1.CheckRequest) ParseResponse(com.google.api.expr.v1alpha1.ParseResponse) EvalResponse(com.google.api.expr.v1alpha1.EvalResponse)

Aggregations

CheckedExpr (com.google.api.expr.v1alpha1.CheckedExpr)7 Expr (com.google.api.expr.v1alpha1.Expr)7 ParsedExpr (com.google.api.expr.v1alpha1.ParsedExpr)6 Type (com.google.api.expr.v1alpha1.Type)6 Call (com.google.api.expr.v1alpha1.Expr.Call)5 MapType (com.google.api.expr.v1alpha1.Type.MapType)4 ArrayList (java.util.ArrayList)3 CheckerEnv.dynElementType (org.projectnessie.cel.checker.CheckerEnv.dynElementType)3 CheckerEnv.getObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.getObjectWellKnownType)3 CheckerEnv.isObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.isObjectWellKnownType)3 FieldType (org.projectnessie.cel.common.types.ref.FieldType)3 Val (org.projectnessie.cel.common.types.ref.Val)3 Decl (com.google.api.expr.v1alpha1.Decl)2 IdentDecl (com.google.api.expr.v1alpha1.Decl.IdentDecl)2 Comprehension (com.google.api.expr.v1alpha1.Expr.Comprehension)2 Select (com.google.api.expr.v1alpha1.Expr.Select)2 ParseRequest (com.google.api.expr.v1alpha1.ParseRequest)2 ParseResponse (com.google.api.expr.v1alpha1.ParseResponse)2 Reference (com.google.api.expr.v1alpha1.Reference)2 Test (org.junit.jupiter.api.Test)2