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);
}
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()));
}
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);
}
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);
}
Aggregations