Search in sources :

Example 71 with JCExpression

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

the class ExpressionTransformer method applyJavaCoercions.

private JCExpression applyJavaCoercions(JCExpression ret, Type exprType, Type expectedType) {
    if (expectedType == null)
        return ret;
    Type nonSimpleExprType = exprType;
    exprType = simplifyType(exprType);
    expectedType = simplifyType(expectedType);
    if (isCeylonString(exprType) && isJavaCharSequence(expectedType)) {
        // FIXME: only do this if boxed, or rather, do not box in the first place
        if (isOptional(nonSimpleExprType)) {
            Naming.SyntheticName varName = naming.temp();
            JCExpression test = make().Binary(JCTree.Tag.NE, varName.makeIdent(), makeNull());
            JCExpression convert = make().Apply(null, makeQualIdent(varName.makeIdent(), "toString"), List.<JCTree.JCExpression>nil());
            JCExpression cond = make().Conditional(test, convert, makeNull());
            JCExpression typeExpr = makeJavaType(typeFact().getObjectType());
            return makeLetExpr(varName, null, typeExpr, ret, cond);
        } else {
            return make().Apply(null, makeQualIdent(ret, "toString"), List.<JCTree.JCExpression>nil());
        }
    }
    // TODO: obsolete code?
    if (isJavaCharSequence(exprType) && expectedType.isExactly(typeFact().getStringDeclaration().getType())) {
        return make().Apply(null, makeQualIdent(ret, "toString"), List.<JCTree.JCExpression>nil());
    }
    // end of obsolete code
    if (isCeylonArray(exprType) && isJavaArray(expectedType)) {
        JCExpression result;
        if (isOptional(nonSimpleExprType)) {
            Naming.SyntheticName varName = naming.temp();
            JCExpression test = make().Binary(JCTree.Tag.NE, varName.makeIdent(), makeNull());
            JCExpression convert = make().Apply(null, makeQualIdent(varName.makeIdent(), "toArray"), List.<JCTree.JCExpression>nil());
            JCExpression cond = make().Conditional(test, convert, makeNull());
            JCExpression typeExpr = makeJavaType(typeFact().getObjectType());
            result = makeLetExpr(varName, null, typeExpr, ret, cond);
        } else {
            result = make().Apply(null, makeQualIdent(ret, "toArray"), List.<JCTree.JCExpression>nil());
        }
        JCExpression targetType = makeJavaType(expectedType, JT_NO_PRIMITIVES);
        return make().TypeCast(targetType, result);
    }
    if (isCeylonClassOrInterfaceModel(exprType) && isJavaClass(expectedType) && !(ret instanceof JCTree.JCFieldAccess && ret.toString().endsWith(".class"))) {
        // FIXME: perhaps cast as RAW?
        JCTree arg = ret;
        // into Util.classErasure(.org.eclipse.ceylon.compiler.java.test.interop.LambdasJava.class)
        while (arg instanceof JCTree.JCTypeCast) arg = ((JCTree.JCTypeCast) arg).getExpression();
        if (arg instanceof JCTree.JCMethodInvocation) {
            JCExpression methodSelect = ((JCTree.JCMethodInvocation) arg).getMethodSelect();
            if (methodSelect instanceof JCTree.JCFieldAccess) {
                JCTree.JCFieldAccess methodField = (JCTree.JCFieldAccess) methodSelect;
                if (methodField.getIdentifier().toString().equals("typeLiteral") && methodField.getExpression() instanceof JCTree.JCFieldAccess && ((JCTree.JCFieldAccess) methodField.getExpression()).toString().equals(".ceylon.language.meta.typeLiteral_")) {
                    JCExpression classLiteral = extractClassLiteralFromTypeDescriptor(((JCTree.JCMethodInvocation) arg).getArguments().get(0));
                    if (classLiteral != null)
                        // FIXME: pass type arg explicitly?
                        return utilInvocation().classErasure(classLiteral);
                }
            }
        }
        // make sure erasure doesn't get in the way of calling this method
        if (willEraseToObject(exprType))
            ret = make().TypeCast(makeJavaType(typeFact().getClassOrInterfaceModelType(typeFact().getObjectType())), ret);
        // FIXME: pass type arg explicitly?
        return utilInvocation().javaClassForModel(ret);
    }
    return ret;
}
Also used : JCMethodInvocation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCMethodInvocation) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCTypeCast(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeCast) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 72 with JCExpression

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

the class ExpressionTransformer method transform.

// 
// Unary and Binary operators that can be overridden
// 
// Unary operators
public JCExpression transform(Tree.NotOp op) {
    // No need for an erasure cast since Term must be Boolean and we never need to erase that
    JCExpression term = transformExpression(op.getTerm(), CodegenUtil.getBoxingStrategy(op), op.getTypeModel());
    JCUnary jcu = at(op).Unary(JCTree.Tag.NOT, term);
    return jcu;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCUnary(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCUnary)

Example 73 with JCExpression

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

the class ExpressionTransformer method transformArg.

protected final JCExpression transformArg(SimpleInvocation invocation, int argIndex) {
    final Tree.Term expr = invocation.getArgumentExpression(argIndex);
    if (invocation.hasParameter(argIndex)) {
        Type type = invocation.getParameterType(argIndex);
        if (invocation.isParameterSequenced(argIndex) && // Java methods need their underlying type preserved
        !invocation.isJavaVariadicMethod()) {
            if (!invocation.isArgumentSpread(argIndex)) {
                // If the parameter is sequenced and the argument is not ...
                // then the expected type of the *argument* is the type arg to Iterator
                type = typeFact().getIteratedType(type);
            } else if (invocation.getArgumentType(argIndex).getSupertype(typeFact().getSequentialDeclaration()) == null) {
                // On the other hand, if the parameter is sequenced and the argument is spread,
                // but not sequential, then transformArguments() will use getSequence(),
                // so we only need to expect an Iterable type
                type = org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType(typeFact().getIterableDeclaration(), typeFact().getIteratedType(type), typeFact().getIteratedAbsentType(type));
            }
        }
        BoxingStrategy boxingStrategy = invocation.getParameterBoxingStrategy(argIndex);
        int flags = 0;
        if (!invocation.isParameterRaw(argIndex))
            flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_NOT_RAW;
        if (invocation.isParameterWithConstrainedTypeParameters(argIndex))
            flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS;
        if (invocation.isParameterWithDependentCovariantTypeParameters(argIndex))
            flags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS;
        if (invocation.erasedArgument(unwrapExpressionUntilTerm(expr))) {
            flags |= EXPR_DOWN_CAST;
        }
        if (!expr.getSmall() && invocation.getParameterSmall(argIndex)) {
            flags |= ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK;
        }
        boolean coerced = invocation.isParameterCoerced(argIndex);
        if (coerced) {
            flags |= ExpressionTransformer.EXPR_IS_COERCED;
            if (invocation.isParameterJavaVariadic(argIndex) && type.isSequential()) {
                type = typeFact().getSequentialElementType(type);
            }
        }
        JCExpression ret = transformExpression(expr, boxingStrategy, type, flags);
        // We can coerce most SAMs in transformExpression, EXCEPT invocation
        // calls which we do here.
        Term term = Decl.unwrapExpressionsUntilTerm(expr);
        if (coerced && term instanceof Tree.InvocationExpression && isFunctionalResult(term.getTypeModel()) && checkForFunctionalInterface(type) != null) {
            return transformFunctionalInterfaceBridge((Tree.InvocationExpression) term, ret, type);
        }
        return ret;
    } else {
        // Overloaded methods don't have a reference to a parameter
        // so we have to treat them differently. Also knowing it's
        // overloaded we know we're dealing with Java code so we unbox
        Type type = expr.getTypeModel();
        return expressionGen().transformExpression(expr, BoxingStrategy.UNBOXED, type);
    }
}
Also used : UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) TreeUtil.unwrapExpressionUntilTerm(org.eclipse.ceylon.compiler.typechecker.tree.TreeUtil.unwrapExpressionUntilTerm)

Example 74 with JCExpression

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

the class ExpressionTransformer method makeTopLevelValueOrFunctionLiteral.

private JCTree makeTopLevelValueOrFunctionLiteral(Tree.MemberLiteral expr) {
    Declaration declaration = expr.getDeclaration();
    JCExpression toplevelCall = makeTopLevelValueOrFunctionDeclarationLiteral(declaration);
    if (!expr.getWantsDeclaration()) {
        ListBuffer<JCExpression> closedTypeArgs = new ListBuffer<JCExpression>();
        // expr is of type Function<Type,Arguments> or Value<Get,Set> so we can get its type like that
        JCExpression reifiedType = makeReifiedTypeArgument(expr.getTypeModel().getTypeArgumentList().get(0));
        closedTypeArgs.append(reifiedType);
        if (Decl.isMethod(declaration)) {
            // expr is of type Function<Type,Arguments> so we can get its arguments type like that
            Type argumentsType = typeFact().getCallableTuple(expr.getTypeModel());
            JCExpression reifiedArguments = makeReifiedTypeArgument(argumentsType);
            closedTypeArgs.append(reifiedArguments);
            if (expr.getTypeArgumentList() != null) {
                java.util.List<Type> typeModels = expr.getTypeArgumentList().getTypeModels();
                if (typeModels != null) {
                    JCExpression closedTypesExpr = getClosedTypesSequential(typeModels);
                    // must apply it
                    closedTypeArgs.append(closedTypesExpr);
                }
            }
        } else {
            JCExpression reifiedSet;
            Type ptype;
            if (!((Value) declaration).isVariable())
                ptype = typeFact().getNothingType();
            else
                ptype = expr.getTypeModel().getTypeArgumentList().get(0);
            reifiedSet = makeReifiedTypeArgument(ptype);
            closedTypeArgs.append(reifiedSet);
        }
        toplevelCall = make().Apply(null, makeSelect(toplevelCall, "apply"), closedTypeArgs.toList());
        // add cast
        Type exprType = expr.getTypeModel().resolveAliases();
        JCExpression typeClass = makeJavaType(exprType, JT_NO_PRIMITIVES);
        JCExpression rawTypeClass = makeJavaType(exprType, JT_NO_PRIMITIVES | JT_RAW);
        return make().TypeCast(typeClass, make().TypeCast(rawTypeClass, toplevelCall));
    }
    return toplevelCall;
}
Also used : UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 75 with JCExpression

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

the class ExpressionTransformer method transform.

public JCExpression transform(Tree.ScaleOp op) {
    OperatorTranslation operator = Operators.getOperator(Tree.ScaleOp.class);
    Tree.Term scalableTerm = op.getRightTerm();
    Type scalableTermType = getSupertype(scalableTerm, typeFact().getScalableDeclaration());
    SyntheticName scaleableName = naming.alias("scalable");
    JCVariableDecl scaleable = makeVar(scaleableName, makeJavaType(scalableTermType, JT_NO_PRIMITIVES), transformExpression(scalableTerm, BoxingStrategy.BOXED, scalableTermType));
    Tree.Term scaleTerm = op.getLeftTerm();
    SyntheticName scaleName = naming.alias("scale");
    Type scaleType = getTypeArgument(scalableTermType, 0);
    JCExpression scaleValue;
    if (isCeylonInteger(scaleTerm.getTypeModel()) && isCeylonFloat(scaleType)) {
        // Disgusting coercion
        scaleValue = transformExpression(scaleTerm, BoxingStrategy.UNBOXED, scalableTerm.getTypeModel());
        scaleValue = boxType(scaleValue, typeFact().getFloatType());
    } else {
        scaleValue = transformExpression(scaleTerm, BoxingStrategy.BOXED, scaleType);
    }
    JCVariableDecl scale = makeVar(scaleName, makeJavaType(scaleType, JT_NO_PRIMITIVES), scaleValue);
    at(op);
    return make().LetExpr(List.<JCStatement>of(scale, scaleable), transformOverridableBinaryOperator(op, operator, OptimisationStrategy.NONE, scaleableName.makeIdent(), scaleName.makeIdent(), null, null, op.getTypeModel()).build());
}
Also used : UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) OperatorTranslation(org.eclipse.ceylon.compiler.java.codegen.Operators.OperatorTranslation) AssignmentOperatorTranslation(org.eclipse.ceylon.compiler.java.codegen.Operators.AssignmentOperatorTranslation)

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