use of com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload in project cel-java by projectnessie.
the class CELTest method HomogeneousAggregateLiterals.
@Test
void HomogeneousAggregateLiterals() {
Env e = newCustomEnv(declarations(Decls.newVar("name", Decls.String), Decls.newFunction(Operator.In.id, Decls.newOverload(Overloads.InList, asList(Decls.String, Decls.newListType(Decls.String)), Decls.Bool), Decls.newOverload(Overloads.InMap, asList(Decls.String, Decls.newMapType(Decls.String, Decls.Bool)), Decls.Bool))), homogeneousAggregateLiterals());
// t.Run("err_list", func(t *testing.T) {
AstIssuesTuple xIss = e.compile("name in ['hello', 0]");
assertThat(xIss.getIssues()).isNotNull();
assertThat(xIss.hasIssues()).isTrue();
// })
// t.Run("err_map_key", func(t *testing.T) {
xIss = e.compile("name in {'hello':'world', 1:'!'}");
assertThat(xIss.getIssues()).isNotNull();
assertThat(xIss.hasIssues()).isTrue();
// })
// t.Run("err_map_val", func(t *testing.T) {
xIss = e.compile("name in {'hello':'world', 'goodbye':true}");
assertThat(xIss.getIssues()).isNotNull();
assertThat(xIss.hasIssues()).isTrue();
// })
ProgramOption funcs = functions(Overload.binary(Operator.In.id, (lhs, rhs) -> {
if (rhs.type().hasTrait(Trait.ContainerType)) {
return ((Container) rhs).contains(lhs);
}
return valOrErr(rhs, "no such overload");
}));
// t.Run("ok_list", func(t *testing.T) {
AstIssuesTuple astIss = e.compile("name in ['hello', 'world']");
assertThat(astIss.hasIssues()).isFalse();
Program prg = e.program(astIss.getAst(), funcs);
EvalResult out = prg.eval(mapOf("name", "world"));
assertThat(out.getVal()).isSameAs(True);
// })
// t.Run("ok_map", func(t *testing.T) {
astIss = e.compile("name in {'hello': false, 'world': true}");
assertThat(astIss.hasIssues()).isFalse();
prg = e.program(astIss.getAst(), funcs);
out = prg.eval(mapOf("name", "world"));
assertThat(out.getVal()).isSameAs(True);
// })
}
use of com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload in project cel-java by projectnessie.
the class CheckerEnvTest method overlappingOverload.
@Test
void overlappingOverload() {
CheckerEnv env = newStandardCheckerEnv(Container.defaultContainer, newRegistry());
Type paramA = Decls.newTypeParamType("A");
List<String> typeParamAList = singletonList("A");
Assertions.assertThatThrownBy(() -> env.add(Decls.newFunction(Overloads.TypeConvertDyn, Decls.newParameterizedOverload(Overloads.ToDyn, singletonList(paramA), Decls.Dyn, typeParamAList)))).hasMessage("overlapping overload for name 'dyn' (type '(type_param: \"A\") -> dyn' with overloadId: 'to_dyn' cannot be distinguished from '(type_param: \"A\") -> dyn' with overloadId: 'to_dyn')");
}
use of com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload in project cel-java by projectnessie.
the class Checker method resolveOverload.
OverloadResolution resolveOverload(Location loc, Decl fn, Expr.Builder target, List<Expr.Builder> args) {
List<Type> argTypes = new ArrayList<>();
if (target != null) {
Type argType = getType(target);
if (argType == null) {
throw new ErrException("Could not resolve type for target '%s'", target);
}
argTypes.add(argType);
}
for (int i = 0; i < args.size(); i++) {
Expr.Builder arg = args.get(i);
Type argType = getType(arg);
if (argType == null) {
throw new ErrException("Could not resolve type for argument %d '%s'", i, arg);
}
argTypes.add(argType);
}
Type resultType = null;
Reference checkedRef = null;
for (Overload overload : fn.getFunction().getOverloadsList()) {
if ((target == null && overload.getIsInstanceFunction()) || (target != null && !overload.getIsInstanceFunction())) {
// not a compatible call style.
continue;
}
Type overloadType = Decls.newFunctionType(overload.getResultType(), overload.getParamsList());
if (overload.getTypeParamsCount() > 0) {
// Instantiate overload's type with fresh type variables.
Mapping substitutions = newMapping();
for (String typePar : overload.getTypeParamsList()) {
substitutions.add(Decls.newTypeParamType(typePar), newTypeVar());
}
overloadType = substitute(substitutions, overloadType, false);
}
List<Type> candidateArgTypes = overloadType.getFunction().getArgTypesList();
if (isAssignableList(argTypes, candidateArgTypes)) {
if (checkedRef == null) {
checkedRef = newFunctionReference(Collections.singletonList(overload.getOverloadId()));
} else {
checkedRef = checkedRef.toBuilder().addOverloadId(overload.getOverloadId()).build();
}
// First matching overload, determines result type.
Type fnResultType = substitute(mappings, overloadType.getFunction().getResultType(), false);
if (resultType == null) {
resultType = fnResultType;
} else if (!isDyn(resultType) && !fnResultType.equals(resultType)) {
resultType = Decls.Dyn;
}
}
}
if (resultType == null) {
errors.noMatchingOverload(loc, fn.getName(), argTypes, target != null);
// resultType = Decls.Error;
return null;
}
return newResolution(checkedRef, resultType);
}
use of com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload in project cel-java by projectnessie.
the class CheckerEnv method sanitizeFunction.
// sanitizeFunction replaces well-known types referenced by message name with their equivalent
// CEL built-in type instances.
Decl sanitizeFunction(Decl decl) {
FunctionDecl fn = decl.getFunction();
// Determine whether the declaration requires replacements from proto-based message type
// references to well-known CEL type references.
boolean needsSanitizing = false;
for (Overload o : fn.getOverloadsList()) {
if (isObjectWellKnownType(o.getResultType())) {
needsSanitizing = true;
break;
}
for (Type p : o.getParamsList()) {
if (isObjectWellKnownType(p)) {
needsSanitizing = true;
break;
}
}
}
// Early return if the declaration requires no modification.
if (!needsSanitizing) {
return decl;
}
// Sanitize all of the overloads if any overload requires an update to its type references.
List<Overload> overloads = new ArrayList<>(fn.getOverloadsCount());
for (Overload o : fn.getOverloadsList()) {
boolean sanitized = false;
Type rt = o.getResultType();
if (isObjectWellKnownType(rt)) {
rt = getObjectWellKnownType(rt);
sanitized = true;
}
List<Type> params = new ArrayList<>(o.getParamsCount());
for (Type p : o.getParamsList()) {
if (isObjectWellKnownType(p)) {
params.add(getObjectWellKnownType(p));
sanitized = true;
} else {
params.add(p);
}
}
// If sanitized, replace the overload definition.
Overload ov;
if (sanitized) {
if (o.getIsInstanceFunction()) {
ov = Decls.newInstanceOverload(o.getOverloadId(), params, rt);
} else {
ov = Decls.newOverload(o.getOverloadId(), params, rt);
}
} else {
// Otherwise, preserve the original overload.
ov = o;
}
overloads.add(ov);
}
return Decls.newFunction(decl.getName(), overloads);
}
use of com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload in project cel-java by projectnessie.
the class CheckerEnv method addOverload.
/**
* addOverload adds overload to function declaration f. Returns one or more errorMsg values if the
* overload overlaps with an existing overload or macro.
*/
Decl addOverload(Decl f, Overload overload, List<String> errMsgs) {
FunctionDecl function = f.getFunction();
Mapping emptyMappings = newMapping();
Type overloadFunction = Decls.newFunctionType(overload.getResultType(), overload.getParamsList());
Type overloadErased = substitute(emptyMappings, overloadFunction, true);
boolean hasErr = false;
for (Overload existing : function.getOverloadsList()) {
Type existingFunction = Decls.newFunctionType(existing.getResultType(), existing.getParamsList());
Type existingErased = substitute(emptyMappings, existingFunction, true);
boolean overlap = isAssignable(emptyMappings, overloadErased, existingErased) != null || isAssignable(emptyMappings, existingErased, overloadErased) != null;
if (overlap && overload.getIsInstanceFunction() == existing.getIsInstanceFunction()) {
errMsgs.add(overlappingOverloadError(f.getName(), overload.getOverloadId(), overloadFunction, existing.getOverloadId(), existingFunction));
hasErr = true;
}
}
for (Macro macro : Macro.AllMacros) {
if (macro.function().equals(f.getName()) && macro.isReceiverStyle() == overload.getIsInstanceFunction() && macro.argCount() == overload.getParamsCount()) {
errMsgs.add(overlappingMacroError(f.getName(), macro.argCount()));
hasErr = true;
}
}
if (hasErr) {
return f;
}
function = function.toBuilder().addOverloads(overload).build();
f = f.toBuilder().setFunction(function).build();
return f;
}
Aggregations