Search in sources :

Example 61 with Declaration

use of org.eclipse.ceylon.model.typechecker.model.Declaration 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 62 with Declaration

use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.

the class ExpressionTransformer method addThisOrObjectQualifierIfRequired.

/**
 * We may need to force a qualified this prefix (direct or outer) in the following cases:
 *
 * - Required because of mixin inheritance with different type arguments (the same is already
 *   done for qualified references, but not for direct references)
 * - The compiler generates anonymous local classes for things like
 *   Callables and Comprehensions. When referring to a member foo
 *   within one of those things we need a qualified {@code this}
 *   to ensure we're accessing the outer instances member, not
 *   a member of the anonymous local class that happens to have the same name.
 */
private JCExpression addThisOrObjectQualifierIfRequired(JCExpression qualExpr, Tree.StaticMemberOrTypeExpression expr, Declaration decl) {
    // find out the real target
    Declaration typeDecl;
    if (Decl.isConstructor(decl))
        typeDecl = ModelUtil.getConstructedClass(decl);
    else
        typeDecl = decl;
    if (qualExpr == null && // statics are not members that can be inherited
    !decl.isStatic() && (!Decl.isConstructor(decl) || !Decl.isConstructor(typeDecl)) && typeDecl.isMember() && // and have a name mapping)
    expr.getTarget().getDeclaration() == decl && !ModelUtil.isLocalToInitializer(typeDecl) && !isWithinSuperInvocation()) {
        // First check whether the expression is captured from an enclosing scope
        TypeDeclaration outer = Decl.getOuterScopeOfMemberInvocation(expr, typeDecl);
        if (outer != null) {
            Type targetType = expr.getTarget().getQualifyingType();
            Type declarationContainerType = ((TypeDeclaration) outer).getType();
            // check if we need a variance cast
            VarianceCastResult varianceCastResult = getVarianceCastResult(targetType, declarationContainerType);
            // if we are within a comprehension body, or if we need a variance cast
            if (isWithinSyntheticClassBody() || varianceCastResult != null) {
                if (decl.isShared() && outer instanceof Interface) {
                    // always prefer qualified
                    qualExpr = makeQualifiedDollarThis(declarationContainerType);
                } else {
                    // Class or companion class,
                    qualExpr = naming.makeQualifiedThis(makeJavaType(((TypeDeclaration) outer).getType(), JT_RAW | (outer instanceof Interface ? JT_COMPANION : 0)));
                }
                // add the variance cast if required
                if (varianceCastResult != null) {
                    qualExpr = applyVarianceCasts(qualExpr, targetType, varianceCastResult, 0);
                }
            }
        } else if (typeDecl.isClassOrInterfaceMember()) {
            ClassOrInterface container;
            if (((ClassOrInterface) typeDecl.getContainer()).isAnonymous() && ((ClassOrInterface) typeDecl.getContainer()).isToplevel()) {
                // easy
                container = (Class) typeDecl.getContainer();
            } else {
                // find the import
                Import foundImport = statementGen().findImport(expr, decl);
                container = (Class) foundImport.getTypeDeclaration();
            }
            Value value = (Value) ((Package) container.getContainer()).getMember(container.getName(), null, false);
            qualExpr = make().Apply(null, naming.makeName(value, Naming.NA_FQ | Naming.NA_WRAPPER | Naming.NA_MEMBER), List.<JCExpression>nil());
        } else if (decl.isMember() && !expr.getStaticMethodReference()) {
            throw new BugException(expr, decl.getQualifiedNameString() + " was unexpectedly a member");
        }
    }
    return qualExpr;
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) Import(org.eclipse.ceylon.model.typechecker.model.Import) 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) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Package(org.eclipse.ceylon.model.typechecker.model.Package) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 63 with Declaration

use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.

the class ExpressionTransformer method transformTypeArguments.

private final void transformTypeArguments(CallBuilder callBuilder, Tree.StaticMemberOrTypeExpression mte) {
    java.util.List<TypeParameter> tps = null;
    Declaration declaration = mte.getDeclaration();
    if (!mte.getTypeModel().isTypeConstructor()) {
        tps = Strategy.getEffectiveTypeParameters(declaration);
    } else {
        for (TypeParameter tp : Strategy.getEffectiveTypeParameters(declaration)) {
            callBuilder.typeArgument(makeJavaType(tp.getType(), JT_TYPE_ARGUMENT));
        }
        return;
    }
    if (tps != null) {
        for (TypeParameter tp : tps) {
            Type ta = mte.getTarget().getTypeArguments().get(tp);
            java.util.List<Type> bounds = null;
            boolean needsCastForBounds = false;
            if (!tp.getSatisfiedTypes().isEmpty()) {
                bounds = new ArrayList<Type>(tp.getSatisfiedTypes().size());
                for (Type bound : tp.getSatisfiedTypes()) {
                    // substitute the right type arguments
                    bound = substituteTypeArgumentsForTypeParameterBound(mte.getTarget(), bound);
                    bounds.add(bound);
                    needsCastForBounds |= needsCast(ta, bound, false, false, false);
                }
            }
            boolean hasMultipleBounds;
            Type firstBound;
            if (bounds != null) {
                hasMultipleBounds = bounds.size() > 1;
                firstBound = bounds.isEmpty() ? null : bounds.get(0);
            } else {
                hasMultipleBounds = false;
                firstBound = null;
            }
            if (willEraseToObject(ta) || needsCastForBounds) {
                boolean boundsSelfDependent = isBoundsSelfDependant(tp);
                if (hasDependentTypeParameters(tps, tp) || // and we cannot represent the intersection type in Java so give up
                hasMultipleBounds || // if we are going to use the first bound and it is self-dependent, we will make it raw
                boundsSelfDependent || (firstBound != null && willEraseToObject(firstBound))) {
                    // so at some point we'll have to introduce an intersection type AST node to satisfy multiple bounds
                    if (hasMultipleBounds) {
                        callBuilder.typeArguments(List.<JCExpression>nil());
                        return;
                    }
                    // if we have a bound
                    if (firstBound != null) {
                        // if it's self-dependent we cannot satisfy it without a raw type
                        if (boundsSelfDependent)
                            callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT | JT_RAW));
                        else
                            callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT));
                    } else {
                        // no bound, let's go with Object then
                        callBuilder.typeArgument(makeJavaType(typeFact().getObjectType(), JT_TYPE_ARGUMENT));
                    }
                } else if (firstBound == null) {
                    callBuilder.typeArgument(makeJavaType(ta, JT_TYPE_ARGUMENT));
                } else {
                    callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT));
                }
            } else {
                callBuilder.typeArgument(makeJavaType(ta, JT_TYPE_ARGUMENT));
            }
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) 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 64 with Declaration

use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.

the class ExpressionTransformer method transformConstructorDelegation.

/**
 * Transform a delegated constructor call ({@code extends XXX()})
 * which may be either a superclass initializer/constructor or a
 * same-class constructor.
 * @param extendedType
 * @param delegation The kind of delegation
 * @param invocation
 * @param classBuilder
 * @return
 */
JCStatement transformConstructorDelegation(Node extendedType, CtorDelegation delegation, Tree.InvocationExpression invocation, ClassDefinitionBuilder classBuilder, boolean forDelegationConstructor) {
    if (delegation != null && delegation.isError()) {
        return delegation.makeThrow(this);
    }
    Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) invocation.getPrimary()).getDeclaration();
    java.util.List<ParameterList> paramLists = ((Functional) primaryDeclaration).getParameterLists();
    if (paramLists.isEmpty()) {
        classBuilder.getInitBuilder().delegateCall(at(extendedType).Exec(makeErroneous(extendedType, "compiler bug: super class " + primaryDeclaration.getName() + " is missing parameter list")));
        return null;
    }
    SuperInvocation builder = new SuperInvocation(this, classBuilder.getForDefinition(), delegation, invocation, paramLists.get(0), forDelegationConstructor);
    CallBuilder callBuilder = CallBuilder.instance(this);
    boolean prevFnCall = withinInvocation(true);
    try {
        if (invocation.getPrimary() instanceof Tree.StaticMemberOrTypeExpression) {
            transformTypeArguments(callBuilder, (Tree.StaticMemberOrTypeExpression) invocation.getPrimary());
        }
        at(builder.getNode());
        JCExpression expr = null;
        Scope outerDeclaration;
        if (Decl.isConstructor(primaryDeclaration)) {
            outerDeclaration = builder.getPrimaryDeclaration().getContainer().getContainer();
        } else {
            outerDeclaration = builder.getPrimaryDeclaration().getContainer();
        }
        if ((Strategy.generateInstantiator(builder.getPrimaryDeclaration()) || builder.getPrimaryDeclaration() instanceof Class) && outerDeclaration instanceof Interface && !((Interface) outerDeclaration).isJava()) {
            // If the subclass is inner to an interface then it will be
            // generated inner to the companion and we need to qualify the
            // super(), *unless* the subclass is nested within the same
            // interface as it's superclass.
            Scope outer = builder.getSub().getContainer();
            while (!(outer instanceof Package)) {
                if (outer == outerDeclaration) {
                    expr = naming.makeSuper();
                    break;
                }
                outer = outer.getContainer();
            }
            if (expr == null) {
                if (delegation.isSelfDelegation()) {
                    throw new BugException();
                }
                Interface iface = (Interface) outerDeclaration;
                JCExpression superQual;
                if (ModelUtil.getClassOrInterfaceContainer(classBuilder.getForDefinition(), false) instanceof Interface) {
                    superQual = naming.makeCompanionAccessorCall(naming.makeQuotedThis(), iface);
                } else {
                    superQual = naming.makeCompanionFieldName(iface);
                }
                expr = naming.makeQualifiedSuper(superQual);
            }
        } else {
            expr = delegation.isSelfDelegation() ? naming.makeThis() : naming.makeSuper();
        }
        final List<JCExpression> superArguments = transformSuperInvocationArguments(classBuilder, builder, callBuilder);
        JCExpression superExpr = callBuilder.invoke(expr).arguments(superArguments).build();
        return at(extendedType).Exec(superExpr);
    // classBuilder.getInitBuilder().superCall(at(extendedType).Exec(superExpr));
    } finally {
        withinInvocation(prevFnCall);
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Package(org.eclipse.ceylon.model.typechecker.model.Package) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 65 with Declaration

use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.

the class EeVisitor method visit.

@Override
public void visit(Tree.Declaration that) {
    super.visit(that);
    Declaration a = that.getDeclarationModel();
    if (that.getAnnotationList() != null && that.getAnnotationList().getAnnotations() != null) {
        for (Tree.Annotation an : that.getAnnotationList().getAnnotations()) {
            Declaration ad = ((Tree.BaseMemberOrTypeExpression) an.getPrimary()).getDeclaration();
            if (ad != null) {
                String qualifiedName = ad.getQualifiedNameString();
                if ("java.lang::transient".equals(qualifiedName)) {
                    setModifier(a, TRANSIENT);
                }
                if ("java.lang::volatile".equals(qualifiedName)) {
                    setModifier(a, VOLATILE);
                }
                if ("java.lang::synchronized".equals(qualifiedName)) {
                    setModifier(a, SYNCHRONIZED);
                }
                if ("java.lang::strictfp".equals(qualifiedName)) {
                    setModifier(a, STRICTFP);
                }
            // note: native is handledby the typechecker
            }
        }
    }
}
Also used : Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Annotation(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Annotation)

Aggregations

Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)370 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)309 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)264 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)129 Type (org.eclipse.ceylon.model.typechecker.model.Type)100 Class (org.eclipse.ceylon.model.typechecker.model.Class)78 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)74 Value (org.eclipse.ceylon.model.typechecker.model.Value)73 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)72 Function (org.eclipse.ceylon.model.typechecker.model.Function)71 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)71 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)63 ArrayList (java.util.ArrayList)61 AnalyzerUtil.getPackageTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration)60 AnalyzerUtil.getTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)60 ModelUtil.getNativeDeclaration (org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration)57 AnalyzerUtil.getPackageTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration)51 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)50 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)48 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)45