Search in sources :

Example 81 with JCExpression

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

the class ExpressionTransformer method transformExpression.

JCExpression transformExpression(final Tree.Term expr, BoxingStrategy boxingStrategy, Type expectedType, int flags) {
    if (expr == null) {
        return null;
    }
    at(expr);
    if (inStatement && boxingStrategy != BoxingStrategy.INDIFFERENT) {
        // We're not directly inside the ExpressionStatement anymore
        inStatement = false;
    }
    // Cope with things like ((expr))
    // FIXME: shouldn't that be in the visitor?
    Tree.Term term = expr;
    while (term instanceof Tree.Expression) {
        term = ((Tree.Expression) term).getTerm();
    }
    JCExpression result;
    if (term instanceof Tree.IfExpression) {
        flags |= EXPR_IS_NOT_BASE_MEMBER;
    }
    CeylonVisitor v = gen().visitor;
    final ListBuffer<JCTree> prevDefs = v.defs;
    final boolean prevInInitializer = v.inInitializer;
    final ClassDefinitionBuilder prevClassBuilder = v.classBuilder;
    final Type prevExpectedType = this.expectedType;
    final boolean prevCoerced = this.coerced;
    try {
        v.defs = new ListBuffer<JCTree>();
        v.inInitializer = false;
        v.classBuilder = gen().current();
        this.expectedType = expectedType;
        this.coerced = (flags & EXPR_IS_COERCED) != 0;
        term.visit(v);
        if (v.hasResult()) {
            result = v.getSingleResult();
            if (result == null) {
                throw new BugException(term, "visitor yielded multiple results");
            }
        } else {
            throw new BugException(term, "visitor didn't yield any result");
        }
    } catch (BugException e) {
        result = e.makeErroneous(this, expr);
    } finally {
        v.classBuilder = prevClassBuilder;
        v.inInitializer = prevInInitializer;
        v.defs = prevDefs;
        this.coerced = prevCoerced;
        this.expectedType = prevExpectedType;
    }
    if ((flags & EXPR_TARGET_ACCEPTS_NULL) == 0 && expectedType != null && hasUncheckedNulls(expr) && expectedType.isSubtypeOf(typeFact().getObjectType()) && !knownNullSafe(term)) {
        result = utilInvocation().checkNull(result);
        flags |= EXPR_HAS_NULL_CHECK_FENCE;
    }
    result = applyErasureAndBoxing(result, expr, boxingStrategy, expectedType, flags);
    return result;
}
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) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) LetExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LetExpression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)

Example 82 with JCExpression

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

the class ExpressionTransformer method transformInvocation.

private JCExpression transformInvocation(Invocation invocation, CallBuilder callBuilder, TransformedInvocationPrimary transformedPrimary) {
    invocation.location(callBuilder);
    boolean needsCast = false;
    if (Decl.isConstructorPrimary(invocation.getPrimary())) {
        Tree.StaticMemberOrTypeExpression qte = (Tree.StaticMemberOrTypeExpression) invocation.getPrimary();
        // instantiator
        Constructor ctor = ModelUtil.getConstructor(qte.getDeclaration());
        if (Strategy.generateInstantiator(ctor)) {
            needsCast = Strategy.isInstantiatorUntyped(ctor);
            if (qte instanceof Tree.QualifiedMemberExpression && ((Tree.QualifiedMemberExpression) qte).getPrimary() instanceof Tree.QualifiedTypeExpression && isCeylonCallable(getReturnTypeOfCallable(invocation.getPrimary().getTypeModel()))) {
                callBuilder.invoke(naming.makeQualIdent(transformedPrimary.expr, "$call$"));
            } else {
                callBuilder.typeArguments(List.<JCExpression>nil());
                java.util.List<Type> typeModels = qte.getTypeArguments().getTypeModels();
                if (typeModels != null) {
                    for (Type tm : typeModels) {
                        callBuilder.typeArgument(makeJavaType(tm, AbstractTransformer.JT_TYPE_ARGUMENT));
                    }
                }
                callBuilder.invoke(naming.makeInstantiatorMethodName(transformedPrimary.expr, ModelUtil.getConstructedClass(ctor)));
            }
        } else if (typeFact().isJavaArrayType(ModelUtil.getConstructedClass(ctor).getType())) {
            callBuilder.arrayWith(invocation.getReturnType().getQualifyingType(), makeJavaType(invocation.getReturnType(), JT_CLASS_NEW));
        } else {
            if (ModelUtil.getConstructedClass(invocation.getPrimaryDeclaration()).isMember() && invocation.getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression && !(((Tree.QualifiedMemberOrTypeExpression) invocation.getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression)) {
                callBuilder.instantiate(new ExpressionAndType(transformedPrimary.expr, null), makeJavaType(invocation.getReturnType(), JT_CLASS_NEW | (transformedPrimary.expr == null ? 0 : JT_NON_QUALIFIED)));
            } else {
                callBuilder.instantiate(makeJavaType(invocation.getReturnType(), JT_CLASS_NEW));
            }
        }
    } else if (invocation.getQmePrimary() != null && isJavaArray(invocation.getQmePrimary().getTypeModel()) && transformedPrimary.selector != null && (transformedPrimary.selector.equals("get") || transformedPrimary.selector.equals("set"))) {
        if (transformedPrimary.selector.equals("get"))
            callBuilder.arrayRead(transformedPrimary.expr);
        else if (transformedPrimary.selector.equals("set")) {
            callBuilder.arrayWrite(transformedPrimary.expr);
            Type arrayType = invocation.getQmePrimary().getTypeModel().resolveAliases();
            if (isJavaObjectArray(arrayType) && invocation instanceof PositionalInvocation) {
                Type elementType = arrayType.getTypeArgumentList().get(0);
                Type argumentType = ((PositionalInvocation) invocation).getArgumentType(1);
                if (!argumentType.isSubtypeOf(typeFact().getOptionalType(elementType)))
                    callBuilder.javaArrayWriteNeedsCast(true);
            }
        } else
            return makeErroneous(invocation.getNode(), "compiler bug: extraneous array selector: " + transformedPrimary.selector);
    } else if (invocation.isUnknownArguments()) {
        // if we have an unknown parameter list, like Callble<Ret,Args>, need to prepend the callable
        // to the argument list, and invoke Util.apply
        // note that ATM the typechecker only allows a single argument to be passed in spread form in this
        // case so we don't need to look at parameter types
        JCExpression callableTypeExpr = makeJavaType(invocation.getPrimary().getTypeModel());
        ExpressionAndType callableArg = new ExpressionAndType(transformedPrimary.expr, callableTypeExpr);
        Type returnType = invocation.getReturnType();
        JCExpression returnTypeExpr = makeJavaType(returnType, JT_NO_PRIMITIVES);
        callBuilder.prependArgumentAndType(callableArg);
        callBuilder.typeArgument(returnTypeExpr);
        callBuilder.invoke(make().Select(make().QualIdent(syms().ceylonUtilType.tsym), names().fromString("apply")));
    } else if (invocation.isOnValueType()) {
        JCExpression primTypeExpr = makeJavaType(invocation.getQmePrimary().getTypeModel(), JT_NO_PRIMITIVES | JT_VALUE_TYPE);
        callBuilder.invoke(naming.makeQuotedQualIdent(primTypeExpr, transformedPrimary.selector));
    } else {
        callBuilder.invoke(naming.makeQuotedQualIdent(transformedPrimary.expr, transformedPrimary.selector));
    }
    JCExpression result = callBuilder.build();
    if (needsCast) {
        result = make().TypeCast(makeJavaType(invocation.getReturnType()), result);
    }
    return result;
}
Also used : Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) 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) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 83 with JCExpression

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

the class ExpressionTransformer method transform.

public JCTree transform(Tree.MemberLiteral expr) {
    at(expr);
    Declaration declaration = expr.getDeclaration();
    if (declaration == null)
        return makeErroneous(expr, "compiler bug: missing declaration");
    if (declaration.isToplevel()) {
        return makeTopLevelValueOrFunctionLiteral(expr);
    } else if (expr.getWantsDeclaration()) {
        return makeMemberValueOrFunctionDeclarationLiteral(expr, declaration);
    } else {
        // get its produced ref
        Reference producedReference = expr.getTarget();
        // it's a member we get from its container type
        Type containerType = producedReference.getQualifyingType();
        // if we have no container type it means we have an object member
        boolean objectMember = containerType.getDeclaration().isAnonymous();
        JCExpression memberCall;
        if (objectMember) {
            // We don't care about the type args for the cast, nor for the reified container expr, because
            // we take the real reified container type from the container instance, and that one has the type
            // arguments
            containerType = ((Class) declaration.getContainer()).getType();
        }
        JCExpression typeCall = makeTypeLiteralCall(containerType, false, expr.getTypeModel());
        // make sure we cast it to ClassOrInterface
        String metatypeName;
        if (Decl.isConstructor(declaration)) {
            Class constructedClass = ModelUtil.getConstructedClass(declaration);
            Declaration container = getDeclarationContainer(constructedClass);
            if (constructedClass.isToplevel() || container instanceof TypeDeclaration == false) {
                metatypeName = "Class";
            } else {
                metatypeName = "MemberClass";
            }
        } else {
            metatypeName = "ClassOrInterface";
        }
        TypeDeclaration classOrInterfaceDeclaration = (TypeDeclaration) typeFact().getLanguageModuleModelDeclaration(metatypeName);
        JCExpression classOrInterfaceTypeExpr = makeJavaType(classOrInterfaceDeclaration.appliedReference(null, Arrays.asList(containerType)).getType());
        typeCall = make().TypeCast(classOrInterfaceTypeExpr, typeCall);
        // we will need a TD for the container
        // Note that we don't use Basic for the container for object members, because that's not how we represent
        // anonymous types.
        JCExpression reifiedContainerExpr = makeReifiedTypeArgument(containerType);
        // make a raw call and cast
        if (Decl.isConstructor(declaration)) {
            Type callableType = producedReference.getFullType();
            /*JCExpression reifiedArgumentsExpr;
                if (Decl.isEnumeratedConstructor(Decl.getConstructor(declaration))) {
                    reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType.getQualifyingType()));
                } else {
                    reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
                }*/
            JCExpression reifiedArguments;
            if (ModelUtil.isEnumeratedConstructor(ModelUtil.getConstructor(declaration))) {
                reifiedArguments = makeReifiedTypeArgument(typeFact().getNothingType());
            } else {
                reifiedArguments = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
            }
            List<JCExpression> arguments = List.of(reifiedArguments, ceylonLiteral(declaration.getName()));
            JCExpression classModel = makeSelect(typeCall, "getDeclaredConstructor");
            memberCall = make().Apply(null, classModel, arguments);
        } else if (declaration instanceof Function) {
            // we need to get types for each type argument
            JCExpression closedTypesExpr = null;
            if (expr.getTypeArgumentList() != null) {
                java.util.List<Type> typeModels = expr.getTypeArgumentList().getTypeModels();
                if (typeModels != null) {
                    closedTypesExpr = getClosedTypesSequential(typeModels);
                }
            }
            // we also need type descriptors for ret and args
            Type callableType = producedReference.getFullType();
            JCExpression reifiedReturnTypeExpr = makeReifiedTypeArgument(typeFact().getCallableReturnType(callableType));
            JCExpression reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
            List<JCExpression> arguments;
            if (closedTypesExpr != null)
                arguments = List.of(reifiedContainerExpr, reifiedReturnTypeExpr, reifiedArgumentsExpr, ceylonLiteral(declaration.getName()), closedTypesExpr);
            else
                arguments = List.of(reifiedContainerExpr, reifiedReturnTypeExpr, reifiedArgumentsExpr, ceylonLiteral(declaration.getName()));
            memberCall = make().Apply(null, makeSelect(typeCall, "getMethod"), arguments);
        } else if (declaration instanceof Value) {
            JCExpression reifiedGetExpr = makeReifiedTypeArgument(producedReference.getType());
            String getterName = "getAttribute";
            Type ptype;
            if (!((Value) declaration).isVariable())
                ptype = typeFact().getNothingType();
            else
                ptype = producedReference.getType();
            JCExpression reifiedSetExpr = makeReifiedTypeArgument(ptype);
            memberCall = make().Apply(null, makeSelect(typeCall, getterName), List.of(reifiedContainerExpr, reifiedGetExpr, reifiedSetExpr, ceylonLiteral(declaration.getName())));
        } else {
            return makeErroneous(expr, "Unsupported member type: " + declaration);
        }
        // if(objectMember){
        // // now get the instance and bind it
        // // I don't think we need any expected type since objects can't be erased
        // JCExpression object = transformExpression(expr.getObjectExpression());
        // // reset the location after we transformed the expression
        // memberCall = at(expr).Apply(null, makeSelect(memberCall, "bind"), List.of(object));
        // }
        // cast the member call because we invoke it with no Java generics
        memberCall = make().TypeCast(makeJavaType(expr.getTypeModel(), JT_RAW | JT_NO_PRIMITIVES), memberCall);
        memberCall = make().TypeCast(makeJavaType(expr.getTypeModel(), JT_NO_PRIMITIVES), memberCall);
        return memberCall;
    }
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Function(org.eclipse.ceylon.model.typechecker.model.Function) 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) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) CondList(org.eclipse.ceylon.compiler.java.codegen.StatementTransformer.CondList) List(org.eclipse.ceylon.langtools.tools.javac.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 84 with JCExpression

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

the class ExpressionTransformer method transformOverridableUnaryOperator.

private JCExpression transformOverridableUnaryOperator(Tree.UnaryOperatorExpression op, Type expectedType) {
    at(op);
    Tree.Term term = op.getTerm();
    OperatorTranslation operator = Operators.getOperator(op.getClass());
    if (operator == null) {
        return makeErroneous(op, "compiler bug: " + op.getClass() + " is an unhandled operator class");
    }
    JCExpression ret;
    if (operator.getUnOpOptimisationStrategy(op, op.getTerm(), this).useJavaOperator()) {
        // optimisation for unboxed types
        JCExpression expr = transformExpression(term, BoxingStrategy.UNBOXED, expectedType, EXPR_WIDEN_PRIM);
        // unary + is essentially a NOOP
        if (operator == OperatorTranslation.UNARY_POSITIVE)
            return expr;
        ret = make().Unary(operator.javacOperator, expr);
        ret = unAutoPromote(ret, op.getTypeModel(), op.getSmall());
    } else {
        if (operator == OperatorTranslation.UNARY_POSITIVE) {
            // is the self type of Invertible, so use the type of op
            return transformExpression(term, BoxingStrategy.BOXED, op.getTypeModel());
        }
        ret = make().Apply(null, makeSelect(transformExpression(term, BoxingStrategy.BOXED, expectedType), Naming.getGetterName(operator.getCeylonMethodName())), List.<JCExpression>nil());
    }
    return ret;
}
Also used : 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) OperatorTranslation(org.eclipse.ceylon.compiler.java.codegen.Operators.OperatorTranslation) AssignmentOperatorTranslation(org.eclipse.ceylon.compiler.java.codegen.Operators.AssignmentOperatorTranslation)

Example 85 with JCExpression

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

the class ExpressionTransformer method transformArgumentsForCallableSpecifier.

private List<ExpressionAndType> transformArgumentsForCallableSpecifier(CallableSpecifierInvocation invocation) {
    List<ExpressionAndType> result = List.<ExpressionAndType>nil();
    int argIndex = 0;
    for (Parameter parameter : invocation.getMethod().getFirstParameterList().getParameters()) {
        Type exprType = expressionGen().getTypeForParameter(parameter, null, TP_TO_BOUND);
        Parameter declaredParameter = invocation.getMethod().getFirstParameterList().getParameters().get(argIndex);
        JCExpression arg = naming.makeName(parameter.getModel(), Naming.NA_IDENT);
        arg = expressionGen().applyErasureAndBoxing(arg, exprType, !parameter.getModel().getUnboxed(), // Callables always have boxed params
        BoxingStrategy.BOXED, declaredParameter.getType());
        result = result.append(new ExpressionAndType(arg, makeJavaType(declaredParameter.getType())));
        argIndex++;
    }
    return result;
}
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) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter)

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