Search in sources :

Example 41 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ExpressionTransformer method transformSuperOf.

private JCExpression transformSuperOf(Node node, Tree.Primary superPrimary, String forMemberName) {
    Tree.Term superOf = eliminateParens(superPrimary);
    if (!(superOf instanceof Tree.OfOp)) {
        throw new BugException();
    }
    Tree.Type superType = ((Tree.OfOp) superOf).getType();
    if (!(eliminateParens(((Tree.OfOp) superOf).getTerm()) instanceof Tree.Super)) {
        throw new BugException();
    }
    TypeDeclaration inheritedFrom = superType.getTypeModel().getDeclaration();
    if (inheritedFrom instanceof Interface) {
        inheritedFrom = (TypeDeclaration) inheritedFrom.getMember(forMemberName, null, false).getContainer();
    }
    return widenSuper(node, inheritedFrom);
}
Also used : Term(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 42 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ExpressionTransformer method lostTypeParameterInInheritance.

private boolean lostTypeParameterInInheritance(Type exprType, Type commonType) {
    if (exprType.getDeclaration() instanceof ClassOrInterface == false || commonType.getDeclaration() instanceof ClassOrInterface == false)
        return false;
    ClassOrInterface exprDecl = (ClassOrInterface) exprType.getDeclaration();
    ClassOrInterface commonDecl = (ClassOrInterface) commonType.getDeclaration();
    // do not search interfaces if the common declaration is a class, because interfaces cannot be subtypes of a class
    boolean searchInterfaces = commonDecl instanceof Interface;
    return lostTypeParameterInInheritance(exprDecl, commonDecl, searchInterfaces, false);
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 43 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ExpressionTransformer method transform.

// 
// Operator-Assignment expressions
public JCExpression transform(final Tree.ArithmeticAssignmentOp op) {
    final AssignmentOperatorTranslation operator = Operators.getAssignmentOperator(op.getClass());
    if (operator == null) {
        return makeErroneous(op, "compiler bug: " + op.getNodeType() + " is not a supported arithmetic assignment operator");
    }
    // see if we can optimise it
    if (op.getUnboxed() && CodegenUtil.isDirectAccessVariable(op.getLeftTerm())) {
        return optimiseAssignmentOperator(op, operator);
    }
    // we can use unboxed types if both operands are unboxed
    final boolean boxResult = !op.getUnboxed();
    // find the proper type
    Interface compoundType = op.getUnit().getNumericDeclaration();
    if (op instanceof Tree.AddAssignOp) {
        compoundType = op.getUnit().getSummableDeclaration();
    } else if (op instanceof Tree.SubtractAssignOp) {
        compoundType = op.getUnit().getInvertableDeclaration();
    } else if (op instanceof Tree.RemainderAssignOp) {
        compoundType = op.getUnit().getIntegralDeclaration();
    }
    final Type leftType = getSupertype(op.getLeftTerm(), compoundType);
    final Type resultType = getMostPreciseType(op.getLeftTerm(), getTypeArgument(leftType, 0));
    // Normally we don't look at the RHS type because it can lead to unknown types, but if we want to extract its
    // underlying type we have to, and we deal with any eventual unknown type. Presumably unknown types will not have
    // any useful underlying type anyways.
    // Note  that looking at the RHS allows us to not have the issue of using the LHS type wrongly for the RHS type when
    // the LHS type is Float and the RHS type is Integer with implicit Float coercion
    Type rightSupertype = getSupertype(op.getRightTerm(), compoundType);
    if (rightSupertype == null || rightSupertype.isUnknown()) {
        // supertype could be null if, e.g. right type is Nothing
        rightSupertype = leftType;
    }
    Type rightTypeArgument = getTypeArgument(rightSupertype);
    if (rightTypeArgument == null || rightTypeArgument.isUnknown())
        rightTypeArgument = getTypeArgument(leftType);
    final Type rightType = getMostPreciseType(op.getLeftTerm(), rightTypeArgument);
    // we work on boxed types
    return transformAssignAndReturnOperation(op, op.getLeftTerm(), boxResult, leftType, resultType, new AssignAndReturnOperationFactory() {

        @Override
        public JCExpression getNewValue(JCExpression previousValue) {
            // make this call: previousValue OP RHS
            JCExpression ret = transformOverridableBinaryOperator(op.getLeftTerm(), op.getRightTerm(), rightType, operator.binaryOperator, boxResult ? OptimisationStrategy.NONE : OptimisationStrategy.OPTIMISE, previousValue, op.getTypeModel());
            return ret;
        }
    });
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) AssignmentOperatorTranslation(com.redhat.ceylon.compiler.java.codegen.Operators.AssignmentOperatorTranslation) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 44 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ExpressionTransformer method isNaturalTarget.

/**
 * Whether an annotation (with the given {@code annotationCtorDecl}
 * annotation constructor) used on the given declaration ({@code useSite})
 * should be added to the Java annotations of the given generated program
 * elements ({@code target})
 * @param annotationCtorDecl
 * @param useSite
 * @param target
 * @return
 */
private boolean isNaturalTarget(// use site is either a Declaration, or a Package, or a Module,
Function annotationCtorDecl, // module imports
Object useSite, OutputElement target) {
    EnumSet<AnnotationTarget> interopTargets;
    if (annotationCtorDecl instanceof AnnotationProxyMethod) {
        AnnotationProxyMethod annotationProxyMethod = (AnnotationProxyMethod) annotationCtorDecl;
        if (annotationProxyMethod.getAnnotationTarget() == target) {
            // Foo__WHATEVER, so honour the WHATEVER
            return true;
        }
        interopTargets = annotationProxyMethod.getProxyClass().getAnnotationTarget();
    } else {
        interopTargets = null;
    }
    if (useSite instanceof Declaration) {
        if (ModelUtil.isConstructor((Declaration) useSite)) {
            if (useSite instanceof Functional) {
                return target == OutputElement.CONSTRUCTOR;
            } else if (useSite instanceof Value) {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Class) {
            if (((Class) useSite).getParameterList() != null && interopTargets != null && interopTargets.contains(AnnotationTarget.CONSTRUCTOR) && !interopTargets.contains(AnnotationTarget.TYPE)) {
                return target == OutputElement.CONSTRUCTOR;
            }
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Interface) {
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Value) {
            Value value = (Value) useSite;
            TypeDeclaration decltype = typeFact().getValueDeclarationType().getDeclaration();
            if (value.isParameter() && !value.isShared() && !(value.isCaptured() && value.isMember())) {
                return target == OutputElement.PARAMETER;
            } else if (annotationCtorDecl instanceof AnnotationProxyMethod) {
                if (value.isLate() || value.isVariable()) {
                    return target == OutputElement.SETTER;
                } else if (!value.isTransient()) {
                    return target == OutputElement.FIELD;
                } else {
                    return target == OutputElement.GETTER;
                }
            } else {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Setter) {
            return target == OutputElement.SETTER;
        } else if (useSite instanceof Function) {
            return target == OutputElement.METHOD;
        } else if (useSite instanceof Constructor) {
            return target == OutputElement.CONSTRUCTOR;
        } else if (useSite instanceof TypeAlias) {
            return target == OutputElement.TYPE;
        }
    } else if (useSite instanceof Package) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Module) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Tree.ImportModule) {
        return target == OutputElement.FIELD;
    }
    throw new RuntimeException("" + useSite);
}
Also used : AnnotationTarget(com.redhat.ceylon.model.loader.model.AnnotationTarget) AnnotationProxyMethod(com.redhat.ceylon.model.loader.model.AnnotationProxyMethod) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Setter(com.redhat.ceylon.model.typechecker.model.Setter) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Package(com.redhat.ceylon.model.typechecker.model.Package) Module(com.redhat.ceylon.model.typechecker.model.Module) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 45 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ExpressionTransformer method transform.

public JCTree transform(Tree.IndexExpression access) {
    // depends on the operator
    Tree.ElementOrRange elementOrRange = access.getElementOrRange();
    boolean isElement = elementOrRange instanceof Tree.Element;
    // let's see what types there are
    Type leftType = access.getPrimary().getTypeModel();
    // find the corresponding supertype
    Interface leftSuperTypeDeclaration;
    if (isElement)
        leftSuperTypeDeclaration = typeFact().getCorrespondenceDeclaration();
    else
        leftSuperTypeDeclaration = typeFact().getRangedDeclaration();
    Type leftCorrespondenceOrRangeType = leftType.getSupertype(leftSuperTypeDeclaration);
    Type rightType = getTypeArgument(leftCorrespondenceOrRangeType, 0);
    // now find the access code
    JCExpression safeAccess;
    if (isElement) {
        // can we use getFromFirst() to avoid boxing the index?
        boolean listOptim = leftType.isSubtypeOf(typeFact().getListDeclaration().appliedType(null, Collections.singletonList(typeFact().getAnythingType())));
        Type leftTypeForGetCall = listOptim ? leftType.getSupertype(typeFact().getListDeclaration()) : leftCorrespondenceOrRangeType;
        Tree.Primary primary = access.getPrimary();
        JCExpression lhs;
        boolean isSuper = isSuper(primary);
        if (isSuper || isSuperOf(primary)) {
            TypeDeclaration leftDeclaration = null;
            // has a concrete super implementation
            if (listOptim) {
                Declaration member = leftType.getDeclaration().getMember("getFromFirst", null, false);
                if (member == null || member.isFormal()) {
                    listOptim = false;
                } else {
                    leftDeclaration = (TypeDeclaration) member.getContainer();
                }
            }
            // if we did not already find the right supertype, try with "get"
            if (leftDeclaration == null) {
                Declaration member = leftType.getDeclaration().getMember("get", null, false);
                leftDeclaration = (TypeDeclaration) member.getContainer();
            }
            if (isSuper)
                lhs = transformSuper(access, leftDeclaration);
            else
                lhs = transformSuperOf(access, access.getPrimary(), listOptim ? "getFromFirst" : "get");
        } else {
            lhs = transformExpression(access.getPrimary(), BoxingStrategy.BOXED, leftTypeForGetCall);
        }
        Tree.Element element = (Tree.Element) elementOrRange;
        // do the index
        JCExpression index = transformExpression(element.getExpression(), listOptim ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED, rightType);
        // tmpVar.item(index)
        safeAccess = at(access).Apply(List.<JCTree.JCExpression>nil(), makeSelect(lhs, listOptim ? "getFromFirst" : "get"), List.of(index));
        // Because tuple index access has the type of the indexed element
        // (not the union of types in the sequential) a typecast may be required.
        Type sequentialElementType = getTypeArgument(leftCorrespondenceOrRangeType, 1);
        Type expectedType = access.getTypeModel();
        int flags = 0;
        if (!expectedType.isExactly(sequentialElementType) && // could be optional too, for regular Correspondence item access
        !expectedType.isExactly(typeFact().getOptionalType(sequentialElementType)))
            flags |= EXPR_DOWN_CAST;
        safeAccess = applyErasureAndBoxing(safeAccess, sequentialElementType, CodegenUtil.hasTypeErased(access), true, BoxingStrategy.BOXED, expectedType, flags);
    } else {
        // do the indices
        Tree.ElementRange range = (Tree.ElementRange) elementOrRange;
        JCExpression start = transformExpression(range.getLowerBound(), BoxingStrategy.BOXED, rightType);
        // is this a span or segment?
        String method;
        final List<JCExpression> args;
        if (range.getLowerBound() != null && range.getLength() != null) {
            method = "measure";
            JCExpression length = transformExpression(range.getLength(), BoxingStrategy.UNBOXED, typeFact().getIntegerType());
            args = List.of(start, length);
        } else if (range.getLowerBound() == null) {
            method = "spanTo";
            JCExpression end = transformExpression(range.getUpperBound(), BoxingStrategy.BOXED, rightType);
            args = List.of(end);
        } else if (range.getUpperBound() == null) {
            method = "spanFrom";
            args = List.of(start);
        } else if (range.getLowerBound() != null && range.getUpperBound() != null) {
            method = "span";
            JCExpression end = transformExpression(range.getUpperBound(), BoxingStrategy.BOXED, rightType);
            args = List.of(start, end);
        } else {
            method = "unknown";
            args = List.<JCExpression>of(makeErroneous(range, "compiler bug: unhandled range"));
        }
        JCExpression lhs;
        Tree.Primary primary = access.getPrimary();
        boolean isSuper = isSuper(primary);
        if (isSuper || isSuperOf(primary)) {
            Declaration member = leftType.getDeclaration().getMember(method, null, false);
            TypeDeclaration leftDeclaration = (TypeDeclaration) member.getContainer();
            if (isSuper)
                lhs = transformSuper(access, leftDeclaration);
            else
                lhs = transformSuperOf(access, access.getPrimary(), method);
        } else {
            lhs = transformExpression(access.getPrimary(), BoxingStrategy.BOXED, leftCorrespondenceOrRangeType);
        }
        // Because tuple open span access has the type of the indexed element
        // (not a sequential of the union of types in the ranged) a typecast may be required.
        Type rangedSpanType = getTypeArgument(leftCorrespondenceOrRangeType, 2);
        Type expectedType = access.getTypeModel();
        int flags = 0;
        if (!expectedType.isExactly(rangedSpanType)) {
            flags |= EXPR_DOWN_CAST;
            // make sure we barf properly if we missed a heuristics
            if (method.equals("spanFrom")) {
                // make a "Util.<method>(lhs, start, end)" call
                at(access);
                safeAccess = utilInvocation().tuple_spanFrom(args.prepend(lhs));
            } else {
                safeAccess = makeErroneous(access, "compiler bug: only the spanFrom method should be specialised for Tuples");
            }
        } else {
            // make a "lhs.<method>(start, end)" call
            safeAccess = at(access).Apply(List.<JCTree.JCExpression>nil(), makeSelect(lhs, method), args);
        }
        safeAccess = applyErasureAndBoxing(safeAccess, rangedSpanType, CodegenUtil.hasTypeErased(access), true, BoxingStrategy.BOXED, expectedType, flags);
    }
    return safeAccess;
}
Also used : OutputElement(com.redhat.ceylon.model.loader.model.OutputElement) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Aggregations

Interface (com.redhat.ceylon.model.typechecker.model.Interface)56 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)53 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)35 Type (com.redhat.ceylon.model.typechecker.model.Type)30 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)21 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)20 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)18 JCTree (com.sun.tools.javac.tree.JCTree)18 Class (com.redhat.ceylon.model.typechecker.model.Class)17 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)17 LazyInterface (com.redhat.ceylon.model.loader.model.LazyInterface)14 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)12 Scope (com.redhat.ceylon.model.typechecker.model.Scope)10 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)10 Function (com.redhat.ceylon.model.typechecker.model.Function)9 Value (com.redhat.ceylon.model.typechecker.model.Value)9 TypeParser (com.redhat.ceylon.model.loader.TypeParser)8 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)8 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)8 IntersectionType (com.redhat.ceylon.model.typechecker.model.IntersectionType)8