Search in sources :

Example 1 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class AbstractTransformer method convertToIntForHashAttribute.

/**
 * Turn this long value into an int value by applying (int)(e ^ (e >>> 32))
 */
public JCExpression convertToIntForHashAttribute(JCExpression value) {
    SyntheticName tempName = naming.temp("hash");
    JCExpression type = make().Type(syms().longType);
    JCBinary combine = make().Binary(JCTree.Tag.BITXOR, makeUnquotedIdent(tempName.asName()), make().Binary(JCTree.Tag.USR, makeUnquotedIdent(tempName.asName()), makeInteger(32)));
    return make().TypeCast(syms().intType, makeLetExpr(tempName, null, type, value, combine));
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCBinary(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBinary)

Example 2 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class AbstractTransformer method boxJavaType.

JCExpression boxJavaType(JCExpression expr, Type type) {
    JCExpression allowNull = make().Literal(!type.isSubtypeOf(typeFact().getObjectType()));
    type = simplifyType(type);
    if (type.isSubtypeOf(typeFact().getNullType())) {
        return expr;
    } else if (type.isString()) {
        return expr;
    } else if (type.getDeclaration().equals(typeFact().getListDeclaration())) {
        // Wrappings.toCeylonList().inverse()
        Type elementType = type.getTypeArgumentList().get(0);
        return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(elementType, true) ? javaBoxType(elementType) : makeJavaType(elementType, JT_TYPE_ARGUMENT), makeJavaType(elementType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonList"), List.<JCExpression>of(makeReifiedTypeArgument(elementType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
    } else if (type.getDeclaration().equals(typeFact().getSetDeclaration())) {
        Type elementType = type.getTypeArgumentList().get(0);
        return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(elementType, true) ? javaBoxType(elementType) : makeJavaType(elementType, JT_TYPE_ARGUMENT), makeJavaType(elementType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonSet"), List.<JCExpression>of(makeReifiedTypeArgument(elementType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
    } else if (type.getDeclaration().equals(typeFact().getMapDeclaration())) {
        Type keyType = type.getTypeArgumentList().get(0);
        Type itemType = type.getTypeArgumentList().get(1);
        return make().Apply(null, makeSelect(make().Apply(null, makeSelect(make().Apply(List.<JCExpression>of(isJavaBoxableType(keyType, true) ? javaBoxType(keyType) : makeJavaType(keyType, JT_TYPE_ARGUMENT), isJavaBoxableType(itemType, true) ? javaBoxType(itemType) : makeJavaType(itemType, JT_TYPE_ARGUMENT), makeJavaType(keyType, JT_TYPE_ARGUMENT), makeJavaType(itemType, JT_TYPE_ARGUMENT)), makeQuotedFQIdent("org.eclipse.ceylon.compiler.java.wrapping.Wrappings.toCeylonMap"), List.<JCExpression>of(makeReifiedTypeArgument(keyType), makeReifiedTypeArgument(itemType), allowNull)), "inverted"), List.<JCExpression>nil()), "wrap"), List.<JCExpression>of(expr));
    } else {
        return make().Apply(null, makeSelect(javaBoxType(type), "valueOf"), List.<JCExpression>of(expr));
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)

Example 3 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class AbstractTransformer method makeAtMember.

JCAnnotation makeAtMember(Type type) {
    JCExpression classAttribute = make().Assign(naming.makeUnquotedIdent("klass"), makeClassLiteral(type));
    List<JCExpression> attributes = List.of(classAttribute);
    return make().Annotation(makeIdent(syms().ceylonAtMemberType), attributes);
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)

Example 4 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class AbstractTransformer method makeTypeArgs.

private ListBuffer<JCExpression> makeTypeArgs(boolean isCeylonCallable, int flags, Map<TypeParameter, Type> tas, java.util.List<TypeParameter> tps, Type simpleType) {
    ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
    for (TypeParameter tp : tps) {
        Type ta = tas.get(tp);
        // error handling
        if (ta == null)
            continue;
        boolean isDependedOn = hasDependentTypeParameters(tps, tp);
        // record whether we were initially working with Anything, because getNonNullType turns it into Object
        // and we need to treat "in Anything" specially below
        boolean isAnything = isAnything(ta);
        // we want, so we make sure it's not Null
        if (isOptional(ta) && !isNull(ta)) {
            // For an optional type T?:
            // - The Ceylon type Foo<T?> results in the Java type Foo<T>.
            ta = getNonNullType(ta);
        }
        // In a type argument Foo<X&Object> or Foo<X?> transform to just Foo<X>
        ta = simplifyType(ta);
        if (typeFact().isUnion(ta) || typeFact().isIntersection(ta)) {
            // conform with where raw types would be used between expressions and constructors
            if (((flags & (JT_EXTENDS | JT_SATISFIES)) != 0 && tp.getSelfTypedDeclaration() != null)) {
                // A bit ugly, but we need to escape from the loop and create a raw type, no generics
                if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
                    throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
                typeArgs = null;
                break;
            } else if ((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) == 0) {
                if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
                    throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
                typeArgs = null;
                break;
            }
        // otherwise just go on
        }
        if (isCeylonBoolean(ta) && !isTypeParameter(ta)) {
            ta = typeFact.getBooleanType();
        }
        JCExpression jta;
        if (!tp.getSatisfiedTypes().isEmpty()) {
            boolean needsCastForBounds = false;
            for (Type bound : tp.getSatisfiedTypes()) {
                bound = bound.substitute(tas, null);
                needsCastForBounds |= expressionGen().needsCast(ta, bound, false, false, false);
            }
            if (needsCastForBounds) {
                // replace with the first bound
                ta = tp.getSatisfiedTypes().get(0).substitute(tas, null);
                if (tp.getSatisfiedTypes().size() > 1 || isBoundsSelfDependant(tp) || isBoundsRecursive(simpleType, tp) || willEraseToObject(ta) || // we should reject it for all non-covariant types, unless we're in satisfies/extends
                ((flags & (JT_SATISFIES | JT_EXTENDS)) == 0 && !simpleType.isCovariant(tp))) {
                    if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
                        throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
                    // A bit ugly, but we need to escape from the loop and create a raw type, no generics
                    typeArgs = null;
                    break;
                }
            }
        }
        if (ta.isExactlyNothing() || // use the same erasure rules as bottom: prefer wildcards
        ((flags & (__JT_FULL_TYPE | JT_EXTENDS | JT_SATISFIES)) != 0 && (typeFact().isUnion(ta) || typeFact().isIntersection(ta)))) {
            // For the bottom type Bottom:
            if ((flags & (JT_CLASS_NEW)) != 0) {
                // A bit ugly, but we need to escape from the loop and create a raw type, no generics
                if ((flags & (JT_EXTENDS | JT_SATISFIES)) != 0)
                    throw new BugException("rawSupertype() should prevent this method going raw when JT_EXTENDS | JT_SATISFIES");
                typeArgs = null;
                break;
            } else {
                // Foo<Object> (see https://github.com/ceylon/ceylon-compiler/issues/633 for why)
                if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
                    if (ta.isExactlyNothing()) {
                        jta = make().Type(syms().objectType);
                    } else {
                        if (!tp.getSatisfiedTypes().isEmpty()) {
                            // union or intersection: Use the common upper bound of the types
                            jta = makeJavaType(tp.getSatisfiedTypes().get(0), JT_TYPE_ARGUMENT);
                        } else {
                            jta = make().Type(syms().objectType);
                        }
                    }
                } else if (ta.isExactlyNothing()) {
                    // see https://github.com/ceylon/ceylon-compiler/issues/1003
                    if (simpleType.isContravariant(tp)) {
                        typeArgs = null;
                        break;
                    } else if (tp.isCovariant() && !isDependedOn) {
                        // DO NOT trust use-site covariance for Nothing, because we consider "out Nothing" to be the same
                        // as "Nothing". Only look at declaration-site covariance
                        jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), make().Type(syms().objectType));
                    } else {
                        jta = make().Type(syms().objectType);
                    }
                } else {
                    // see https://github.com/ceylon/ceylon/issues/6365
                    if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp)) /* && !isDependedOn*/
                    {
                        jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
                    } else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
                        jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
                    } else {
                        jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
                    }
                }
            }
        } else {
            // For an ordinary class or interface type T:
            if ((flags & (JT_SATISFIES | JT_EXTENDS)) != 0) {
                // - The Ceylon type Foo<T> appearing in an extends or satisfies clause
                // results in the Java type Foo<T>
                jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
            } else {
                // - Foo<? super T> if Foo is contravariant in T
                if (((flags & JT_CLASS_NEW) == 0) && simpleType.isContravariant(tp) && (!isAnything || tp.isContravariant())) // FIXME: it may be necessary to uncomment this in the future,
                // see https://github.com/ceylon/ceylon/issues/6365
                /*&& !isDependedOn*/
                {
                    // DO NOT trust use-site contravariance for Anything, because we consider "in Anything" to be the same
                    // as "Anything". Only look at declaration-site contravariance
                    jta = make().Wildcard(make().TypeBoundKind(BoundKind.SUPER), makeJavaType(ta, JT_TYPE_ARGUMENT));
                } else if (((flags & JT_CLASS_NEW) == 0) && simpleType.isCovariant(tp) && !isDependedOn) {
                    jta = make().Wildcard(make().TypeBoundKind(BoundKind.EXTENDS), makeJavaType(ta, JT_TYPE_ARGUMENT));
                } else {
                    jta = makeJavaType(ta, JT_TYPE_ARGUMENT);
                }
            }
        }
        typeArgs.add(jta);
        if (isCeylonCallable) {
            // In the runtime Callable only has a single type param
            break;
        }
    }
    return typeArgs;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)

Example 5 with JCExpression

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression in project ceylon by eclipse.

the class AbstractTransformer method makeVariableBoxDecl.

/**
 * Makes a final {@code VariableBox<T>} (or {@code VariableBoxBoolean},
 * {@code VariableBoxLong}, etc) variable decl, so that a variable can
 * be captured.
 * @param init The initial value
 * @param The (value/parameter) declaration which is being accessed through the box.
 */
JCVariableDecl makeVariableBoxDecl(JCExpression init, TypedDeclaration declarationModel) {
    List<JCExpression> args = init != null ? List.<JCExpression>of(init) : List.<JCExpression>nil();
    JCExpression newBox = make().NewClass(null, List.<JCExpression>nil(), makeVariableBoxType(declarationModel), args, null);
    String varName = naming.getVariableBoxName(declarationModel);
    JCTree.JCVariableDecl var = make().VarDef(make().Modifiers(FINAL), names().fromString(varName), makeVariableBoxType(declarationModel), newBox);
    return var;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)

Aggregations

JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)224 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)95 Type (org.eclipse.ceylon.model.typechecker.model.Type)95 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)74 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)53 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)53 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)45 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)41 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)39 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)38 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)33 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)32 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)30 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)28 Function (org.eclipse.ceylon.model.typechecker.model.Function)26 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)22 Value (org.eclipse.ceylon.model.typechecker.model.Value)22 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)21 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)21 Class (org.eclipse.ceylon.model.typechecker.model.Class)17