Search in sources :

Example 96 with Type

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

the class ExpressionTransformer method transform.

public JCExpression transform(Tree.WithinOp op) {
    Tree.Term middleTerm = op.getTerm();
    Tree.Bound lowerBound = op.getLowerBound();
    OperatorTranslation lowerOp = Operators.getOperator(lowerBound instanceof Tree.OpenBound ? Tree.SmallerOp.class : Tree.SmallAsOp.class);
    Tree.Term lowerTerm = lowerBound.getTerm();
    Tree.Bound upperBound = op.getUpperBound();
    OperatorTranslation upperOp = Operators.getOperator(upperBound instanceof Tree.OpenBound ? Tree.SmallerOp.class : Tree.SmallAsOp.class);
    Tree.Term upperTerm = upperBound.getTerm();
    Type middleType = getComparableType(middleTerm);
    Type lowerType = getComparableType(lowerTerm);
    Type upperType = getComparableType(upperTerm);
    // If any of the terms is optimizable, then use optimized
    OptimisationStrategy opt;
    boolean optimizeLower = lowerOp.isTermOptimisable(lowerTerm, lowerType, this) == OptimisationStrategy.OPTIMISE || lowerOp.isTermOptimisable(middleTerm, middleType, this) == OptimisationStrategy.OPTIMISE;
    boolean optimizeUpper = upperOp.isTermOptimisable(middleTerm, middleType, this) == OptimisationStrategy.OPTIMISE || upperOp.isTermOptimisable(upperTerm, upperType, this) == OptimisationStrategy.OPTIMISE;
    if ((lowerType.isExactly(middleType) && middleType.isExactly(upperType) && (optimizeLower || // if all same type and any optimizable
    optimizeUpper)) || (// otherwise onle if all optimizable
    optimizeLower && optimizeUpper)) {
        opt = OptimisationStrategy.OPTIMISE;
    } else {
        opt = OptimisationStrategy.NONE;
    }
    SyntheticName middleName = naming.alias("middle");
    List<JCStatement> vars = List.<JCStatement>of(makeVar(middleName, makeJavaType(middleType, opt.getBoxingStrategy() == BoxingStrategy.UNBOXED ? 0 : JT_NO_PRIMITIVES), transformExpression(middleTerm, opt.getBoxingStrategy(), middleType)));
    JCExpression lower = transformBound(middleName, middleType, lowerType, lowerOp, opt, middleTerm, lowerBound, false);
    JCExpression upper = transformBound(middleName, middleType, upperType, upperOp, opt, middleTerm, upperBound, true);
    at(op);
    OperatorTranslation andOp = Operators.getOperator(Tree.AndOp.class);
    OptimisationStrategy optimisationStrategy = OptimisationStrategy.OPTIMISE;
    return make().LetExpr(vars, transformOverridableBinaryOperator(andOp, optimisationStrategy, lower, upper, null, null, op.getTypeModel()));
}
Also used : Term(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) AssignmentOperatorTranslation(com.redhat.ceylon.compiler.java.codegen.Operators.AssignmentOperatorTranslation) OperatorTranslation(com.redhat.ceylon.compiler.java.codegen.Operators.OperatorTranslation) 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) OptimisationStrategy(com.redhat.ceylon.compiler.java.codegen.Operators.OptimisationStrategy)

Example 97 with Type

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

the class ExpressionTransformer method applyErasureAndBoxing.

JCExpression applyErasureAndBoxing(JCExpression result, Type exprType, boolean exprErased, boolean exprBoxed, boolean exprUntrustedType, BoxingStrategy boxingStrategy, Type expectedType, int flags) {
    if (exprType != null)
        exprType = exprType.resolveAliases();
    if (expectedType != null)
        expectedType = expectedType.resolveAliases();
    boolean canCast = false;
    if (expectedType != null && // don't add cast to an erased type 
    !willEraseToObject(expectedType)) {
        // only try to cast boxed types, no point otherwise
        if (exprBoxed) {
            boolean expectedTypeIsNotRaw = (flags & EXPR_EXPECTED_TYPE_NOT_RAW) != 0;
            boolean expectedTypeHasConstrainedTypeParameters = (flags & EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS) != 0;
            boolean expectedTypeHasDependentCovariantTypeParameters = (flags & EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS) != 0;
            boolean downCast = (flags & EXPR_DOWN_CAST) != 0;
            int companionFlags = (flags & EXPR_WANTS_COMPANION) != 0 ? AbstractTransformer.JT_COMPANION : 0;
            // special case for returning Null expressions
            if (isNull(exprType)) {
                // don't add cast for null
                if (!isNullValue(exprType) || // of different types using the "of" operator
                downCast) {
                    // in some cases we may have an instance of Null, which is of type java.lang.Object, being
                    // returned in a context where we expect a String? (aka ceylon.language.String) so even though
                    // the instance at hand will really be null, we need a up-cast to it
                    JCExpression targetType = makeJavaType(expectedType, AbstractTransformer.JT_RAW | companionFlags);
                    result = make().TypeCast(targetType, result);
                }
            } else if (exprType.isExactlyNothing()) {
                // type param erasure
                JCExpression targetType = makeJavaType(expectedType, AbstractTransformer.JT_NO_PRIMITIVES | companionFlags);
                result = make().TypeCast(targetType, result);
            } else if (// expression was forcibly erased
            exprErased || // bounds that are different from what we think the expression type should be
            exprUntrustedType || // see https://github.com/ceylon/ceylon-compiler/issues/1557
            expectedTypeHasDependentCovariantTypeParameters || // some type parameter somewhere needs a cast
            needsCast(exprType, expectedType, expectedTypeIsNotRaw, expectedTypeHasConstrainedTypeParameters, downCast) || // if the exprType is raw and the expected type isn't
            (exprType.isRaw() && (expectedTypeIsNotRaw || !isTurnedToRaw(expectedType)))) {
                // save this before we simplify it because we lose that flag doing so
                boolean exprIsRaw = exprType.isRaw();
                boolean expectedTypeIsRaw = isTurnedToRaw(expectedType) && !expectedTypeIsNotRaw;
                // (unless the other type is already raw)
                if ((!exprIsRaw && hasTypeParameters(expectedType)) || (downCast && !expectedTypeIsRaw && hasTypeParameters(exprType))) {
                    Type rawType = hasTypeParameters(expectedType) ? expectedType : exprType;
                    JCExpression rawTypeExpr = makeJavaType(rawType, AbstractTransformer.JT_TYPE_ARGUMENT | AbstractTransformer.JT_RAW | companionFlags);
                    result = make().TypeCast(rawTypeExpr, result);
                    // expr is now raw
                    exprIsRaw = true;
                    // let's not add another downcast if we got a cast: one is enough
                    downCast = false;
                    // same for forced erasure
                    exprErased = false;
                    exprUntrustedType = false;
                }
                // simplify the type
                // (without the underlying type, because the cast is always to a non-primitive)
                exprType = simplifyType(expectedType).withoutUnderlyingType();
                // if the expr is not raw, we need a cast
                // if the expr is raw:
                //  don't even try making an actual cast if there are bounded type parameters in play, because going raw is much safer
                //  also don't try making the cast if the expected type is raw because anything goes
                boolean needsTypedCast = !exprIsRaw || (!expectedTypeHasConstrainedTypeParameters && !expectedTypeHasDependentCovariantTypeParameters && !expectedTypeIsRaw);
                if (needsTypedCast || // make sure that downcasts get at least one cast
                downCast || // same for forced erasure
                exprUntrustedType) {
                    // it figures out that there's no intersection between the two types, but we know better
                    if (exprUntrustedType && !exprIsRaw) {
                        result = make().TypeCast(syms().objectType, result);
                    }
                    // Do the actual cast
                    JCExpression targetType = makeJavaType(expectedType, AbstractTransformer.JT_TYPE_ARGUMENT | companionFlags);
                    result = make().TypeCast(targetType, result);
                }
            } else
                canCast = true;
        } else
            canCast = true;
    }
    // If expr type if Self<T> and expected type is T we need to cast before any unboxing
    if (exprType.getDeclaration().getSelfType() != null && expectedType != null && expectedType.isExactly(exprType.getTypeArguments().get(exprType.getDeclaration().getSelfType().getDeclaration()))) {
        result = applySelfTypeCasts(result, exprType, exprBoxed, BoxingStrategy.BOXED, expectedType);
        exprType = expectedType;
    }
    // we must do the boxing after the cast to the proper type
    JCExpression ret = boxUnboxIfNecessary(result, exprBoxed, exprType, boxingStrategy, expectedType);
    // very special case for nothing that we need to "unbox" to a primitive type
    if (exprType != null && exprType.isExactlyNothing() && boxingStrategy == BoxingStrategy.UNBOXED) {
        // in this case we have to use the expected type
        ret = unboxType(ret, expectedType);
    }
    // now check if we need variance casts
    if (canCast) {
        ret = applyVarianceCasts(ret, exprType, exprBoxed, boxingStrategy, expectedType, flags);
    }
    ret = applySelfTypeCasts(ret, exprType, exprBoxed, boxingStrategy, expectedType);
    ret = applyJavaTypeConversions(ret, exprType, expectedType, boxingStrategy, exprBoxed, flags);
    return ret;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression)

Example 98 with Type

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

the class ExpressionTransformer method transformExpression.

//
// Any sort of expression
JCExpression transformExpression(final TypedDeclaration declaration, final Tree.Term expr) {
    // make sure we use the best declaration for boxing and type
    TypedReference typedRef = getTypedReference(declaration);
    TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
    Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
    // the non-widening type of the innermost callable
    if (declaration instanceof Functional && Decl.isMpl((Functional) declaration)) {
        for (int i = ((Functional) declaration).getParameterLists().size(); i > 1; i--) {
            nonWideningType = getReturnTypeOfCallable(nonWideningType);
        }
    }
    // respect the refining definition of optionality
    nonWideningType = propagateOptionality(declaration.getType(), nonWideningType);
    BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(nonWideningTypedRef.getDeclaration());
    return transformExpression(expr, boxing, nonWideningType);
}
Also used : Functional(com.redhat.ceylon.model.typechecker.model.Functional) Type(com.redhat.ceylon.model.typechecker.model.Type) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference)

Example 99 with Type

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

the class ExpressionTransformer method lostTypeParameterInInheritance.

private boolean lostTypeParameterInInheritance(ClassOrInterface exprDecl, ClassOrInterface commonDecl, boolean searchInterfaces, boolean lostTypeParameter) {
    // stop if we found the common decl
    if (Decl.equal(exprDecl, commonDecl))
        return lostTypeParameter;
    if (searchInterfaces) {
        // find a match in interfaces
        for (Type pt : exprDecl.getSatisfiedTypes()) {
            // FIXME: this is very heavy-handed because we consider that once we've lost a type parameter we've lost them all
            // but we could optimise this by checking:
            // 1/ which type parameter we've really lost
            // 2/ if the type parameters we're passing to our super type actually depend in any way from type parameters we've lost
            boolean lostTypeParameter2 = lostTypeParameter || isTurnedToRaw(pt);
            pt = simplifyType(pt);
            // it has to be an interface
            Interface interf = (Interface) pt.getDeclaration();
            if (lostTypeParameterInInheritance(interf, commonDecl, searchInterfaces, lostTypeParameter2))
                return true;
        }
    }
    // search for super classes
    Type extendedType = exprDecl.getExtendedType();
    if (extendedType != null) {
        // FIXME: see above
        boolean lostTypeParameter2 = lostTypeParameter || isTurnedToRaw(extendedType);
        extendedType = simplifyType(extendedType);
        // it has to be a Class
        Class extendedTypeDeclaration = (Class) extendedType.getDeclaration();
        // looks like Object's superclass is Object, so stop right there
        if (extendedTypeDeclaration != typeFact().getObjectDeclaration())
            return lostTypeParameterInInheritance(extendedTypeDeclaration, commonDecl, searchInterfaces, lostTypeParameter2);
    }
    // didn't find it
    return false;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 100 with Type

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

the class ClassTransformer method addMissingUnrefinedMembers.

/** 
     * Recover from members not being refined in the class hierarchy 
     * by generating a stub method that throws.
     */
private void addMissingUnrefinedMembers(Node def, Class classModel, ClassDefinitionBuilder classBuilder) {
    for (Reference unrefined : classModel.getUnimplementedFormals()) {
        //classModel.getMember(memberName, null, false);
        Declaration formalMember = unrefined.getDeclaration();
        String errorMessage = "formal member '" + formalMember.getName() + "' of '" + ((TypeDeclaration) formalMember.getContainer()).getName() + "' not implemented in class hierarchy";
        java.util.List<Type> params = new java.util.ArrayList<Type>();
        if (formalMember instanceof Generic) {
            for (TypeParameter tp : ((Generic) formalMember).getTypeParameters()) {
                params.add(tp.getType());
            }
        }
        if (formalMember instanceof Value) {
            addRefinedThrowerAttribute(classBuilder, errorMessage, classModel, (Value) formalMember);
        } else if (formalMember instanceof Function) {
            addRefinedThrowerMethod(classBuilder, errorMessage, classModel, (Function) formalMember);
        } else if (formalMember instanceof Class && formalMember.isClassMember()) {
            addRefinedThrowerInstantiatorMethod(classBuilder, errorMessage, classModel, (Class) formalMember, unrefined);
        }
    // formal member class of interface handled in
    // makeDelegateToCompanion()
    }
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) Generic(com.redhat.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(com.redhat.ceylon.model.loader.model.JavaBeanValue) Value(com.redhat.ceylon.model.typechecker.model.Value) 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) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

Type (com.redhat.ceylon.model.typechecker.model.Type)237 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)98 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)87 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)56 JCTree (com.sun.tools.javac.tree.JCTree)53 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)51 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)46 Class (com.redhat.ceylon.model.typechecker.model.Class)45 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)43 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)41 IntersectionType (com.redhat.ceylon.model.typechecker.model.IntersectionType)37 UnionType (com.redhat.ceylon.model.typechecker.model.UnionType)37 Test (org.junit.Test)37 TypeParser (com.redhat.ceylon.model.loader.TypeParser)36 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)34 Function (com.redhat.ceylon.model.typechecker.model.Function)33 Interface (com.redhat.ceylon.model.typechecker.model.Interface)30 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)30 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)29 ArrayList (java.util.ArrayList)28