Search in sources :

Example 11 with Constructor

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

the class ClassTransformer method addAmbiguousMember.

private void addAmbiguousMember(ClassDefinitionBuilder classBuilder, Interface model, String name) {
    Declaration member = model.getMember(name, null, false);
    Type satisfiedType = model.getType().getSupertype(model);
    if (member instanceof Class) {
        Class klass = (Class) member;
        if (Strategy.generateInstantiator(member) && !klass.hasConstructors()) {
            // instantiator method implementation
            generateInstantiatorDelegate(classBuilder, satisfiedType, model, klass, null, model.getType(), false);
        }
        if (klass.hasConstructors()) {
            for (Declaration m : klass.getMembers()) {
                if (m instanceof Constructor && Strategy.generateInstantiator(m)) {
                    Constructor ctor = (Constructor) m;
                    generateInstantiatorDelegate(classBuilder, satisfiedType, model, klass, ctor, model.getType(), false);
                }
            }
        }
    } else if (member instanceof Function) {
        Function method = (Function) member;
        final TypedReference typedMember = satisfiedType.getTypedMember(method, Collections.<Type>emptyList());
        java.util.List<java.util.List<Type>> producedTypeParameterBounds = producedTypeParameterBounds(typedMember, method);
        final java.util.List<TypeParameter> typeParameters = method.getTypeParameters();
        final java.util.List<Parameter> parameters = method.getFirstParameterList().getParameters();
        for (Parameter param : parameters) {
            if (Strategy.hasDefaultParameterOverload(param)) {
                MethodDefinitionBuilder overload = new DefaultedArgumentMethodTyped(null, MethodDefinitionBuilder.method(this, method), typedMember, true).makeOverload(method.getFirstParameterList(), param, typeParameters);
                overload.modifiers(PUBLIC | ABSTRACT);
                classBuilder.method(overload);
            }
        }
        final MethodDefinitionBuilder concreteMemberDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, method.getTypeParameters(), producedTypeParameterBounds, typedMember.getType(), naming.selector(method), method.getFirstParameterList().getParameters(), ((Function) member).getTypeErased(), null, DelegateType.OTHER, false);
        classBuilder.method(concreteMemberDelegate);
    } else if (member instanceof Value || member instanceof Setter) {
        TypedDeclaration attr = (TypedDeclaration) member;
        final TypedReference typedMember = satisfiedType.getTypedMember(attr, Collections.<Type>emptyList());
        if (member instanceof Value) {
            final MethodDefinitionBuilder getterDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typedMember.getType(), Naming.getGetterName(attr), Collections.<Parameter>emptyList(), attr.getTypeErased(), null, DelegateType.OTHER, false);
            classBuilder.method(getterDelegate);
        }
        if (member instanceof Setter) {
            final MethodDefinitionBuilder setterDelegate = makeDelegateToCompanion(null, typedMember, model.getType(), PUBLIC | ABSTRACT, Collections.<TypeParameter>emptyList(), Collections.<java.util.List<Type>>emptyList(), typeFact().getAnythingType(), Naming.getSetterName(attr), Collections.<Parameter>singletonList(((Setter) member).getParameter()), ((Setter) member).getTypeErased(), null, DelegateType.OTHER, false);
            classBuilder.method(setterDelegate);
        }
    }
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) 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) Setter(com.redhat.ceylon.model.typechecker.model.Setter) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) ArrayList(java.util.ArrayList) AnnotationList(com.redhat.ceylon.compiler.typechecker.tree.Tree.AnnotationList) List(com.sun.tools.javac.util.List) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) 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)

Example 12 with Constructor

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

the class ExpressionTransformer method transform.

public JCTree transform(Tree.TypeLiteral expr) {
    at(expr);
    if (!expr.getWantsDeclaration()) {
        if (expr.getDeclaration() instanceof Constructor) {
            JCExpression classLiteral = makeTypeLiteralCall(expr.getType().getTypeModel().getQualifyingType(), false, expr.getTypeModel());
            TypeDeclaration classModelDeclaration = (TypeDeclaration) typeFact().getLanguageModuleModelDeclaration(expr.getType().getTypeModel().getQualifyingType().getDeclaration().isMember() ? "MemberClass" : "Class");
            JCTypeCast typeCast = make().TypeCast(makeJavaType(classModelDeclaration.appliedType(null, List.of(expr.getType().getTypeModel().getQualifyingType(), typeFact().getNothingType()))), classLiteral);
            Type callableType = expr.getTypeModel().getFullType();
            JCExpression reifiedArgumentsExpr = makeReifiedTypeArgument(typeFact().getCallableTuple(callableType));
            return make().Apply(null, naming.makeQualIdent(typeCast, "getConstructor"), List.<JCExpression>of(reifiedArgumentsExpr, make().Literal(expr.getDeclaration().getName())));
        } else {
            return makeTypeLiteralCall(expr.getType().getTypeModel(), true, expr.getTypeModel());
        }
    } else if (expr.getDeclaration() instanceof TypeParameter) {
        // we must get it from its container
        TypeParameter declaration = (TypeParameter) expr.getDeclaration();
        Node node = expr;
        return makeTypeParameterDeclaration(node, declaration);
    } else if (expr.getDeclaration() instanceof Constructor || expr instanceof Tree.NewLiteral) {
        Constructor ctor;
        if (expr.getDeclaration() instanceof Constructor) {
            ctor = (Constructor) expr.getDeclaration();
        } else {
            ctor = Decl.getDefaultConstructor((Class) expr.getDeclaration());
        }
        JCExpression metamodelCall = makeTypeDeclarationLiteral(Decl.getConstructedClass(ctor));
        metamodelCall = make().TypeCast(makeJavaType(typeFact().getClassDeclarationType(), JT_RAW), metamodelCall);
        metamodelCall = make().Apply(null, naming.makeQualIdent(metamodelCall, "getConstructorDeclaration"), List.<JCExpression>of(make().Literal(ctor.getName() == null ? "" : ctor.getName())));
        if (Decl.isEnumeratedConstructor(ctor)) {
            metamodelCall = make().TypeCast(makeJavaType(typeFact().getValueConstructorDeclarationType(), JT_RAW), metamodelCall);
        } else /*else if (Decl.isDefaultConstructor(ctor)){
                metamodelCall = make().TypeCast(
                        makeJavaType(typeFact().getDefaultConstructorDeclarationType(), JT_RAW), metamodelCall);
            } */
        {
            metamodelCall = make().TypeCast(makeJavaType(typeFact().getCallableConstructorDeclarationType(), JT_RAW), metamodelCall);
        }
        return metamodelCall;
    } else if (expr.getDeclaration() instanceof ClassOrInterface || expr.getDeclaration() instanceof TypeAlias) {
        // use the generated class to get to the declaration literal
        JCExpression metamodelCall = makeTypeDeclarationLiteral((TypeDeclaration) expr.getDeclaration());
        Type exprType = expr.getTypeModel().resolveAliases();
        // now cast if required
        if (!exprType.isExactly(((TypeDeclaration) typeFact().getLanguageModuleDeclarationDeclaration("NestableDeclaration")).getType())) {
            JCExpression type = makeJavaType(exprType, JT_NO_PRIMITIVES);
            return make().TypeCast(type, metamodelCall);
        }
        return metamodelCall;
    } else {
        return makeErroneous(expr, "compiler bug: " + expr.getDeclaration() + " is an unsupported declaration type");
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Type(com.redhat.ceylon.model.typechecker.model.Type) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTypeCast(com.sun.tools.javac.tree.JCTree.JCTypeCast) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Node(com.redhat.ceylon.compiler.typechecker.tree.Node) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 13 with Constructor

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

the class ExpressionTransformer method transformArgumentsForSimpleInvocation.

private List<ExpressionAndType> transformArgumentsForSimpleInvocation(SimpleInvocation invocation, CallBuilder callBuilder) {
    final Constructor superConstructor = invocation.getConstructor();
    CtorDelegation constructorDelegation;
    if (invocation instanceof SuperInvocation) {
        constructorDelegation = ((SuperInvocation) invocation).getDelegation();
    } else {
        constructorDelegation = null;
    }
    List<ExpressionAndType> result = List.<ExpressionAndType>nil();
    if (!(invocation instanceof SuperInvocation) || !((SuperInvocation) invocation).isDelegationDelegation()) {
        int numArguments = invocation.getNumArguments();
        if (invocation.getNumParameters() == 0) {
            // skip transforming arguments
            // (Usually, numArguments would already be null, but it's possible to call a
            //  parameterless function with a *[] argument - see #1593.)
            numArguments = 0;
        }
        boolean wrapIntoArray = false;
        ListBuffer<JCExpression> arrayWrap = new ListBuffer<JCExpression>();
        for (int argIndex = 0; argIndex < numArguments; argIndex++) {
            BoxingStrategy boxingStrategy = invocation.getParameterBoxingStrategy(argIndex);
            Type parameterType = invocation.getParameterType(argIndex);
            // to avoid ambiguity of foo(1,2) for foo(int...) and foo(Object...) methods
            if (!wrapIntoArray && invocation.isParameterSequenced(argIndex) && invocation.isJavaMethod() && boxingStrategy == BoxingStrategy.UNBOXED && willEraseToPrimitive(typeFact().getDefiniteType(parameterType)) && !invocation.isSpread())
                wrapIntoArray = true;
            ExpressionAndType exprAndType;
            if (invocation.isArgumentSpread(argIndex)) {
                if (!invocation.isParameterSequenced(argIndex)) {
                    result = transformSpreadTupleArgument(invocation, callBuilder, result, argIndex);
                    break;
                }
                if (invocation.isJavaMethod()) {
                    // if it's a java method we need a special wrapping
                    exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
                    argIndex = numArguments;
                } else {
                    Type argType = invocation.getArgumentType(argIndex);
                    if (argType.getSupertype(typeFact().getSequentialDeclaration()) != null) {
                        exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
                    } else if (argType.getSupertype(typeFact().getIterableDeclaration()) != null) {
                        exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
                        JCExpression sequential = iterableToSequential(exprAndType.expression);
                        if (invocation.isParameterVariadicPlus(argIndex)) {
                            Type iteratedType = typeFact().getIteratedType(argType);
                            sequential = utilInvocation().castSequentialToSequence(sequential, iteratedType);
                        }
                        exprAndType = new ExpressionAndType(sequential, exprAndType.type);
                    } else {
                        exprAndType = new ExpressionAndType(makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"), makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"));
                    }
                }
            } else if (!invocation.isParameterSequenced(argIndex) || // if it's sequenced, Java and there's no spread at all, pass it along
            (invocation.isParameterSequenced(argIndex) && invocation.isJavaMethod() && !invocation.isSpread())) {
                exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
                // This is not required for primitive arrays since they are not Object[]
                if (numArguments == 1 && invocation.isIndirect()) {
                    Type argumentType = invocation.getArgumentType(0);
                    if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
                        exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(typeFact().getObjectType()), exprAndType.expression), exprAndType.type);
                    }
                } else if (invocation.isParameterSequenced(argIndex) && invocation.isJavaMethod() && !invocation.isSpread()) {
                    // in fact, the very same problem happens when passing null or object arrays to a java variadic method
                    Type argumentType = invocation.getArgumentType(argIndex);
                    if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
                        // remove any ambiguity
                        exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(parameterType), exprAndType.expression), exprAndType.type);
                    }
                }
            } else {
                // we must have a sequenced param
                if (invocation.isSpread()) {
                    exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
                    argIndex = numArguments;
                } else {
                    exprAndType = transformVariadicArgument(invocation, numArguments, argIndex, parameterType);
                    argIndex = numArguments;
                }
            }
            if (!wrapIntoArray) {
                if (argIndex == 0 && invocation.isCallable() && !invocation.isArgumentSpread(numArguments - 1)) {
                    exprAndType = new ExpressionAndType(make().TypeCast(make().Type(syms().objectType), exprAndType.expression), make().Type(syms().objectType));
                }
                result = result.append(exprAndType);
            } else {
                arrayWrap.append(exprAndType.expression);
            }
        }
        if (invocation.isIndirect() && invocation.isParameterSequenced(numArguments) && !invocation.isArgumentSpread(numArguments - 1) && ((IndirectInvocation) invocation).getNumParameters() > numArguments) {
            // Calling convention for indirect variadic invocation's requires
            // explicit variadic argument (can't use the overloading trick)
            result = result.append(new ExpressionAndType(makeEmptyAsSequential(true), make().Erroneous()));
        }
        if (wrapIntoArray) {
            // must have at least one arg, so take the last one
            Type parameterType = invocation.getParameterType(numArguments - 1);
            JCExpression arrayType = makeJavaType(parameterType, JT_RAW);
            JCNewArray arrayExpr = make().NewArray(arrayType, List.<JCExpression>nil(), arrayWrap.toList());
            JCExpression arrayTypeExpr = make().TypeArray(makeJavaType(parameterType, JT_RAW));
            result = result.append(new ExpressionAndType(arrayExpr, arrayTypeExpr));
        }
    } else {
        for (Parameter p : constructorDelegation.getConstructor().getParameterList().getParameters()) {
            result = result.append(new ExpressionAndType(naming.makeName(p.getModel(), Naming.NA_IDENT | Naming.NA_ALIASED), null));
        }
    }
    boolean concreteDelegation = invocation instanceof SuperInvocation && ((SuperInvocation) invocation).getDelegation().isConcreteSelfDelegation();
    if (superConstructor == null && concreteDelegation) {
        Constructor delegateTo = ((SuperInvocation) invocation).getDelegation().getConstructor();
        result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(delegateTo, true), naming.makeNamedConstructorType(delegateTo, true)));
    } else if (superConstructor != null && constructorDelegation != null && constructorDelegation.isSelfDelegation()) {
        result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(superConstructor, concreteDelegation), naming.makeNamedConstructorType(superConstructor, concreteDelegation)));
    } else if (superConstructor != null && !Decl.isDefaultConstructor(superConstructor)) {
        result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(superConstructor, concreteDelegation), naming.makeNamedConstructorType(superConstructor, concreteDelegation)));
    }
    return result;
}
Also used : Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) ListBuffer(com.sun.tools.javac.util.ListBuffer) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) AnalyzerUtil.isIndirectInvocation(com.redhat.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isIndirectInvocation) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray)

Example 14 with Constructor

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

the class ExpressionTransformer method addInterfaceImplAccessorIfRequired.

//
// Array access
private JCExpression addInterfaceImplAccessorIfRequired(JCExpression qualExpr, Tree.StaticMemberOrTypeExpression expr, Declaration decl) {
    // For interfaces we sometimes need to access either the interface instance or its $impl class
    if (decl instanceof Constructor) {
        decl = (Class) Decl.container(decl);
    }
    Scope declContainer = Decl.container(decl);
    if (qualExpr != null && // this is only for interface containers
    declContainer instanceof Interface && // we only ever need the $impl if the declaration is not shared
    !decl.isShared() && (!(expr instanceof Tree.QualifiedMemberExpression) || !isSuperOrSuperOf(((Tree.QualifiedMemberExpression) expr).getPrimary()))) {
        Interface declaration = (Interface) declContainer;
        // access the interface $impl instance
        qualExpr = naming.makeCompanionAccessorCall(qualExpr, declaration);
        // so we need to cast it to the type of the companion
        if (Decl.isAncestorLocal(declaration)) {
            Type type;
            // try to find the best type
            if (expr instanceof Tree.QualifiedMemberOrTypeExpression)
                type = ((Tree.QualifiedMemberOrTypeExpression) expr).getPrimary().getTypeModel();
            else
                type = declaration.getType();
            qualExpr = make().TypeCast(makeJavaType(type, JT_COMPANION), qualExpr);
        }
    }
    return qualExpr;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) Scope(com.redhat.ceylon.model.typechecker.model.Scope) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 15 with Constructor

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

the class Decl method isPrivateAccessRequiringUpcast.

/**
     * Is the member private and not visible from the primary (i.e. is an 
     * upcast required to be able to see that member) 
     */
public static boolean isPrivateAccessRequiringUpcast(Tree.StaticMemberOrTypeExpression qual) {
    if (qual instanceof Tree.QualifiedMemberOrTypeExpression) {
        Tree.Primary primary = ((Tree.QualifiedMemberOrTypeExpression) qual).getPrimary();
        Declaration decl = qual.getDeclaration();
        return decl.isMember() && !decl.isShared() && !(decl instanceof Constructor) && decl.getContainer() instanceof Class && !Decl.equalScopeDecl(decl.getContainer(), primary.getTypeModel().getDeclaration());
    }
    return false;
}
Also used : Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) LazyClass(com.redhat.ceylon.model.loader.model.LazyClass) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)26 Type (com.redhat.ceylon.model.typechecker.model.Type)17 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)16 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)15 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)14 Class (com.redhat.ceylon.model.typechecker.model.Class)13 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)12 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)11 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)11 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)10 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)10 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)10 Function (com.redhat.ceylon.model.typechecker.model.Function)9 Value (com.redhat.ceylon.model.typechecker.model.Value)9 JCTree (com.sun.tools.javac.tree.JCTree)9 Interface (com.redhat.ceylon.model.typechecker.model.Interface)8 ThrowerCatchallConstructor (com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor)7 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)7 ArrayList (java.util.ArrayList)7 TypeAlias (com.redhat.ceylon.model.typechecker.model.TypeAlias)6