Search in sources :

Example 11 with Call

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

Example 12 with Call

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

the class Env method check.

/**
 * Check performs type-checking on the input Ast and yields a checked Ast and/or set of Issues.
 *
 * <p>Checking has failed if the returned Issues value and its Issues.Err() value are non-nil.
 * Issues should be inspected if they are non-nil, but may not represent a fatal error.
 *
 * <p>It is possible to have both non-nil Ast and Issues values returned from this call: however,
 * the mere presence of an Ast does not imply that it is valid for use.
 */
public AstIssuesTuple check(Ast ast) {
    // Note, errors aren't currently possible on the Ast to ParsedExpr conversion.
    ParsedExpr pe = astToParsedExpr(ast);
    // Construct the internal checker env, erroring if there is an issue adding the declarations.
    synchronized (once) {
        if (chk == null && chkErr == null) {
            CheckerEnv ce = CheckerEnv.newCheckerEnv(container, provider);
            ce.enableDynamicAggregateLiterals(true);
            if (hasFeature(FeatureDisableDynamicAggregateLiterals)) {
                ce.enableDynamicAggregateLiterals(false);
            }
            try {
                ce.add(declarations);
                chk = ce;
            } catch (RuntimeException e) {
                chkErr = e;
            } catch (Exception e) {
                chkErr = new RuntimeException(e);
            }
        }
    }
    // The once call will ensure that this value is set or nil for all invocations.
    if (chkErr != null) {
        Errors errs = new Errors(ast.getSource());
        errs.reportError(NoLocation, "%s", chkErr.toString());
        return new AstIssuesTuple(null, newIssues(errs));
    }
    ParseResult pr = new ParseResult(pe.getExpr(), new Errors(ast.getSource()), pe.getSourceInfo());
    CheckResult checkRes = Checker.Check(pr, ast.getSource(), chk);
    if (checkRes.hasErrors()) {
        return new AstIssuesTuple(null, newIssues(checkRes.getErrors()));
    }
    // Manually create the Ast to ensure that the Ast source information (which may be more
    // detailed than the information provided by Check), is returned to the caller.
    CheckedExpr ce = checkRes.getCheckedExpr();
    ast = new Ast(ce.getExpr(), ce.getSourceInfo(), ast.getSource(), ce.getReferenceMapMap(), ce.getTypeMapMap());
    return new AstIssuesTuple(ast, Issues.noIssues(ast.getSource()));
}
Also used : Errors(org.projectnessie.cel.common.Errors) AstPruner.pruneAst(org.projectnessie.cel.interpreter.AstPruner.pruneAst) CEL.parsedExprToAst(org.projectnessie.cel.CEL.parsedExprToAst) ParseResult(org.projectnessie.cel.parser.Parser.ParseResult) CheckResult(org.projectnessie.cel.checker.Checker.CheckResult) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) CheckerEnv(org.projectnessie.cel.checker.CheckerEnv) ParsedExpr(com.google.api.expr.v1alpha1.ParsedExpr) CEL.astToParsedExpr(org.projectnessie.cel.CEL.astToParsedExpr)

Example 13 with Call

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

the class Checker method checkCall.

void checkCall(Expr.Builder e) {
    // Note: similar logic exists within the `interpreter/planner.go`. If making changes here
    // please consider the impact on planner.go and consolidate implementations or mirror code
    // as appropriate.
    Call.Builder call = e.getCallExprBuilder();
    List<Expr.Builder> args = call.getArgsBuilderList();
    String fnName = call.getFunction();
    // Traverse arguments.
    for (Expr.Builder arg : args) {
        check(arg);
    }
    // Regular static call with simple name.
    if (call.getTarget() == Expr.getDefaultInstance()) {
        // Check for the existence of the function.
        Decl fn = env.lookupFunction(fnName);
        if (fn == null) {
            errors.undeclaredReference(location(e), env.container.name(), fnName);
            setType(e, Decls.Error);
            return;
        }
        // Overwrite the function name with its fully qualified resolved name.
        call.setFunction(fn.getName());
        // Check to see whether the overload resolves.
        resolveOverloadOrError(location(e), e, fn, null, args);
        return;
    }
    // If a receiver 'target' is present, it may either be a receiver function, or a namespaced
    // function, but not both. Given a.b.c() either a.b.c is a function or c is a function with
    // target a.b.
    // 
    // Check whether the target is a namespaced function name.
    Expr.Builder target = call.getTargetBuilder();
    String qualifiedPrefix = Container.toQualifiedName(target.build());
    if (qualifiedPrefix != null) {
        String maybeQualifiedName = qualifiedPrefix + "." + fnName;
        Decl fn = env.lookupFunction(maybeQualifiedName);
        if (fn != null) {
            // The function name is namespaced and so preserving the target operand would
            // be an inaccurate representation of the desired evaluation behavior.
            // Overwrite with fully-qualified resolved function name sans receiver target.
            call.clearTarget().setFunction(fn.getName());
            resolveOverloadOrError(location(e), e, fn, null, args);
            return;
        }
    }
    // Regular instance call.
    check(target);
    // Overwrite with fully-qualified resolved function name sans receiver target.
    Decl fn = env.lookupFunction(fnName);
    // Function found, attempt overload resolution.
    if (fn != null) {
        resolveOverloadOrError(location(e), e, fn, target, args);
        return;
    }
    // Function name not declared, record error.
    errors.undeclaredReference(location(e), env.container.name(), fnName);
}
Also used : Call(com.google.api.expr.v1alpha1.Expr.Call) Expr(com.google.api.expr.v1alpha1.Expr) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) IdentDecl(com.google.api.expr.v1alpha1.Decl.IdentDecl) Decl(com.google.api.expr.v1alpha1.Decl)

Example 14 with Call

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

the class PbObjectTest method newProtoObject.

@Test
void newProtoObject() {
    ProtoTypeRegistry reg = newRegistry();
    ParsedExpr parsedExpr = ParsedExpr.newBuilder().setSourceInfo(SourceInfo.newBuilder().addAllLineOffsets(Arrays.asList(1, 2, 3)).build()).build();
    reg.registerMessage(parsedExpr);
    Indexer obj = (Indexer) reg.nativeToValue(parsedExpr);
    Indexer si = (Indexer) obj.get(stringOf("source_info"));
    Indexer lo = (Indexer) si.get(stringOf("line_offsets"));
    assertThat(lo.get(intOf(2)).equal(intOf(3))).isSameAs(True);
    Indexer expr = (Indexer) obj.get(stringOf("expr"));
    Indexer call = (Indexer) expr.get(stringOf("call_expr"));
    assertThat(call.get(stringOf("function")).equal(stringOf(""))).isSameAs(True);
}
Also used : Indexer(org.projectnessie.cel.common.types.traits.Indexer) ParsedExpr(com.google.api.expr.v1alpha1.ParsedExpr) Test(org.junit.jupiter.api.Test)

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