Search in sources :

Example 1 with FieldType

use of org.projectnessie.cel.common.types.ref.FieldType in project cel-java by projectnessie.

the class Checker method checkSelect.

void checkSelect(Expr.Builder e) {
    Select.Builder sel = e.getSelectExprBuilder();
    // Before traversing down the tree, try to interpret as qualified name.
    String qname = Container.toQualifiedName(e.build());
    if (qname != null) {
        Decl ident = env.lookupIdent(qname);
        if (ident != null) {
            if (sel.getTestOnly()) {
                errors.expressionDoesNotSelectField(location(e));
                setType(e, Decls.Bool);
                return;
            }
            // Rewrite the node to be a variable reference to the resolved fully-qualified
            // variable name.
            setType(e, ident.getIdent().getType());
            setReference(e, newIdentReference(ident.getName(), ident.getIdent().getValue()));
            String identName = ident.getName();
            e.getIdentExprBuilder().setName(identName);
            return;
        }
    }
    // Interpret as field selection, first traversing down the operand.
    check(sel.getOperandBuilder());
    Type targetType = getType(sel.getOperandBuilder());
    // Assume error type by default as most types do not support field selection.
    Type resultType = Decls.Error;
    switch(kindOf(targetType)) {
        case kindMap:
            // Maps yield their value type as the selection result type.
            MapType mapType = targetType.getMapType();
            resultType = mapType.getValueType();
            break;
        case kindObject:
            // Objects yield their field type declaration as the selection result type, but only if
            // the field is defined.
            FieldType fieldType = lookupFieldType(location(e), targetType.getMessageType(), sel.getField());
            if (fieldType != null) {
                resultType = fieldType.type;
            }
            break;
        case kindTypeParam:
            // Set the operand 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, targetType);
            // Also, set the result type to DYN.
            resultType = Decls.Dyn;
            break;
        default:
            // in order to allow forward progress on the check.
            if (isDynOrError(targetType)) {
                resultType = Decls.Dyn;
            } else {
                errors.typeDoesNotSupportFieldSelection(location(e), targetType);
            }
            break;
    }
    if (sel.getTestOnly()) {
        resultType = Decls.Bool;
    }
    setType(e, 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) Select(com.google.api.expr.v1alpha1.Expr.Select) IdentDecl(com.google.api.expr.v1alpha1.Decl.IdentDecl) Decl(com.google.api.expr.v1alpha1.Decl) MapType(com.google.api.expr.v1alpha1.Type.MapType) FieldType(org.projectnessie.cel.common.types.ref.FieldType)

Example 2 with FieldType

use of org.projectnessie.cel.common.types.ref.FieldType in project cel-java by projectnessie.

the class Checker method checkCreateMessage.

void checkCreateMessage(Expr.Builder e) {
    CreateStruct.Builder msgVal = e.getStructExprBuilder();
    // Determine the type of the message.
    Type messageType = Decls.Error;
    Decl decl = env.lookupIdent(msgVal.getMessageName());
    if (decl == null) {
        errors.undeclaredReference(location(e), env.container.name(), msgVal.getMessageName());
        return;
    }
    // Ensure the type name is fully qualified in the AST.
    msgVal.setMessageName(decl.getName());
    setReference(e, newIdentReference(decl.getName(), null));
    IdentDecl ident = decl.getIdent();
    Types.Kind identKind = kindOf(ident.getType());
    if (identKind != Kind.kindError) {
        if (identKind != Kind.kindType) {
            errors.notAType(location(e), ident.getType());
        } else {
            messageType = ident.getType().getType();
            if (kindOf(messageType) != Kind.kindObject) {
                errors.notAMessageType(location(e), messageType);
                messageType = Decls.Error;
            }
        }
    }
    if (isObjectWellKnownType(messageType)) {
        setType(e, getObjectWellKnownType(messageType));
    } else {
        setType(e, messageType);
    }
    // Check the field initializers.
    for (Entry.Builder ent : msgVal.getEntriesBuilderList()) {
        String field = ent.getFieldKey();
        Expr.Builder value = ent.getValueBuilder();
        check(value);
        Type fieldType = Decls.Error;
        FieldType t = lookupFieldType(locationByID(ent.getId()), messageType.getMessageType(), field);
        if (t != null) {
            fieldType = t.type;
        }
        if (!isAssignable(fieldType, getType(value))) {
            errors.fieldTypeMismatch(locationByID(ent.getId()), field, fieldType, getType(value));
        }
    }
}
Also used : CreateStruct(com.google.api.expr.v1alpha1.Expr.CreateStruct) IdentDecl(com.google.api.expr.v1alpha1.Decl.IdentDecl) Decl(com.google.api.expr.v1alpha1.Decl) FieldType(org.projectnessie.cel.common.types.ref.FieldType) 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) Entry(com.google.api.expr.v1alpha1.Expr.CreateStruct.Entry) Expr(com.google.api.expr.v1alpha1.Expr) CheckedExpr(com.google.api.expr.v1alpha1.CheckedExpr) Kind(org.projectnessie.cel.checker.Types.Kind) IdentDecl(com.google.api.expr.v1alpha1.Decl.IdentDecl)

Example 3 with FieldType

use of org.projectnessie.cel.common.types.ref.FieldType in project cel-java by projectnessie.

the class Checker method lookupFieldType.

FieldType lookupFieldType(Location l, String messageType, String fieldName) {
    if (env.provider.findType(messageType) == null) {
        // This should not happen, anyway, report an error.
        errors.unexpectedFailedResolution(l, messageType);
        return null;
    }
    FieldType ft = env.provider.findFieldType(messageType, fieldName);
    if (ft != null) {
        return ft;
    }
    errors.undefinedField(l, fieldName);
    return null;
}
Also used : FieldType(org.projectnessie.cel.common.types.ref.FieldType)

Aggregations

FieldType (org.projectnessie.cel.common.types.ref.FieldType)3 Decl (com.google.api.expr.v1alpha1.Decl)2 IdentDecl (com.google.api.expr.v1alpha1.Decl.IdentDecl)2 Type (com.google.api.expr.v1alpha1.Type)2 MapType (com.google.api.expr.v1alpha1.Type.MapType)2 CheckerEnv.dynElementType (org.projectnessie.cel.checker.CheckerEnv.dynElementType)2 CheckerEnv.getObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.getObjectWellKnownType)2 CheckerEnv.isObjectWellKnownType (org.projectnessie.cel.checker.CheckerEnv.isObjectWellKnownType)2 CheckedExpr (com.google.api.expr.v1alpha1.CheckedExpr)1 Expr (com.google.api.expr.v1alpha1.Expr)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 Kind (org.projectnessie.cel.checker.Types.Kind)1