Search in sources :

Example 1 with Overload

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);
// })
}
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) EvalResult(org.projectnessie.cel.Program.EvalResult) Env.newEnv(org.projectnessie.cel.Env.newEnv) Env.newCustomEnv(org.projectnessie.cel.Env.newCustomEnv) AstIssuesTuple(org.projectnessie.cel.Env.AstIssuesTuple) Test(org.junit.jupiter.api.Test)

Example 2 with Overload

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')");
}
Also used : Type(com.google.api.expr.v1alpha1.Type) CheckerEnv.newStandardCheckerEnv(org.projectnessie.cel.checker.CheckerEnv.newStandardCheckerEnv) Test(org.junit.jupiter.api.Test)

Example 3 with Overload

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);
}
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) Expr(com.google.api.expr.v1alpha1.Expr) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) Overload(com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload) ErrException(org.projectnessie.cel.common.types.Err.ErrException) Reference(com.google.api.expr.v1alpha1.Reference) ArrayList(java.util.ArrayList) Mapping.newMapping(org.projectnessie.cel.checker.Mapping.newMapping)

Example 4 with Overload

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);
}
Also used : Types.formatCheckedType(org.projectnessie.cel.checker.Types.formatCheckedType) Type(com.google.api.expr.v1alpha1.Type) ErrType(org.projectnessie.cel.common.types.Err.ErrType) Overload(com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload) ArrayList(java.util.ArrayList) FunctionDecl(com.google.api.expr.v1alpha1.Decl.FunctionDecl)

Example 5 with Overload

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;
}
Also used : Types.formatCheckedType(org.projectnessie.cel.checker.Types.formatCheckedType) Type(com.google.api.expr.v1alpha1.Type) ErrType(org.projectnessie.cel.common.types.Err.ErrType) Overload(com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload) Macro(org.projectnessie.cel.parser.Macro) Mapping.newMapping(org.projectnessie.cel.checker.Mapping.newMapping) FunctionDecl(com.google.api.expr.v1alpha1.Decl.FunctionDecl)

Aggregations

Type (com.google.api.expr.v1alpha1.Type)5 Overload (com.google.api.expr.v1alpha1.Decl.FunctionDecl.Overload)4 CheckedExpr (com.google.api.expr.v1alpha1.CheckedExpr)3 FunctionDecl (com.google.api.expr.v1alpha1.Decl.FunctionDecl)3 Expr (com.google.api.expr.v1alpha1.Expr)3 Decl (com.google.api.expr.v1alpha1.Decl)2 IdentDecl (com.google.api.expr.v1alpha1.Decl.IdentDecl)2 Call (com.google.api.expr.v1alpha1.Expr.Call)2 ArrayList (java.util.ArrayList)2 Test (org.junit.jupiter.api.Test)2 Mapping.newMapping (org.projectnessie.cel.checker.Mapping.newMapping)2 Types.formatCheckedType (org.projectnessie.cel.checker.Types.formatCheckedType)2 ErrType (org.projectnessie.cel.common.types.Err.ErrType)2 Macro (org.projectnessie.cel.parser.Macro)2 Ident (com.google.api.expr.v1alpha1.Expr.Ident)1 ParsedExpr (com.google.api.expr.v1alpha1.ParsedExpr)1 Reference (com.google.api.expr.v1alpha1.Reference)1 MapType (com.google.api.expr.v1alpha1.Type.MapType)1 Arrays.asList (java.util.Arrays.asList)1 Collections.emptyList (java.util.Collections.emptyList)1