Search in sources :

Example 1 with Comprehension

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

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

the class Checker method checkComprehension.

void checkComprehension(Expr.Builder e) {
    Comprehension.Builder comp = e.getComprehensionExprBuilder();
    check(comp.getIterRangeBuilder());
    check(comp.getAccuInitBuilder());
    Type accuType = getType(comp.getAccuInitBuilder());
    Type rangeType = getType(comp.getIterRangeBuilder());
    Type varType;
    switch(kindOf(rangeType)) {
        case kindList:
            varType = rangeType.getListType().getElemType();
            break;
        case kindMap:
            // Ranges over the keys.
            varType = rangeType.getMapType().getKeyType();
            break;
        case kindDyn:
        case kindError:
        case kindTypeParam:
            // Set the range type to DYN to prevent assignment to a potentionally incorrect type
            // at a later point in type-checking. The isAssignable call will update the type
            // substitutions for the type param under the covers.
            isAssignable(Decls.Dyn, rangeType);
            // Set the range iteration variable to type DYN as well.
            varType = Decls.Dyn;
            break;
        default:
            errors.notAComprehensionRange(location(comp.getIterRangeBuilder()), rangeType);
            varType = Decls.Error;
            break;
    }
    // Create a scope for the comprehension since it has a local accumulation variable.
    // This scope will contain the accumulation variable used to compute the result.
    env = env.enterScope();
    env.add(Decls.newVar(comp.getAccuVar(), accuType));
    // Create a block scope for the loop.
    env = env.enterScope();
    env.add(Decls.newVar(comp.getIterVar(), varType));
    // Check the variable references in the condition and step.
    check(comp.getLoopConditionBuilder());
    assertType(comp.getLoopConditionBuilder(), Decls.Bool);
    check(comp.getLoopStepBuilder());
    assertType(comp.getLoopStepBuilder(), accuType);
    // Exit the loop's block scope before checking the result.
    env = env.exitScope();
    check(comp.getResultBuilder());
    // Exit the comprehension scope.
    env = env.exitScope();
    setType(e, getType(comp.getResultBuilder()));
}
Also used : CheckerEnv.getObjectWellKnownType(org.projectnessie.cel.checker.CheckerEnv.getObjectWellKnownType) CheckerEnv.isObjectWellKnownType(org.projectnessie.cel.checker.CheckerEnv.isObjectWellKnownType) CheckerEnv.dynElementType(org.projectnessie.cel.checker.CheckerEnv.dynElementType) Type(com.google.api.expr.v1alpha1.Type) MapType(com.google.api.expr.v1alpha1.Type.MapType) FieldType(org.projectnessie.cel.common.types.ref.FieldType) Comprehension(com.google.api.expr.v1alpha1.Expr.Comprehension)

Aggregations

Comprehension (com.google.api.expr.v1alpha1.Expr.Comprehension)2 Expr (com.google.api.expr.v1alpha1.Expr)1 Call (com.google.api.expr.v1alpha1.Expr.Call)1 CreateList (com.google.api.expr.v1alpha1.Expr.CreateList)1 CreateStruct (com.google.api.expr.v1alpha1.Expr.CreateStruct)1 Entry (com.google.api.expr.v1alpha1.Expr.CreateStruct.Entry)1 Select (com.google.api.expr.v1alpha1.Expr.Select)1 Type (com.google.api.expr.v1alpha1.Type)1 MapType (com.google.api.expr.v1alpha1.Type.MapType)1 ByteString (com.google.protobuf.ByteString)1 ArrayList (java.util.ArrayList)1 CheckerEnv.dynElementType (org.projectnessie.cel.checker.CheckerEnv.dynElementType)1 CheckerEnv.getObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.getObjectWellKnownType)1 CheckerEnv.isObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.isObjectWellKnownType)1 FieldType (org.projectnessie.cel.common.types.ref.FieldType)1 Val (org.projectnessie.cel.common.types.ref.Val)1