Search in sources :

Example 76 with Type

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

the class AbstractTransformer method makeTupleTypeDescriptor.

private JCExpression makeTupleTypeDescriptor(Type pt, boolean firstElementOptional) {
    java.util.List<Type> tupleElementTypes = typeFact().getTupleElementTypes(pt);
    boolean isVariadic = typeFact().isTupleLengthUnbounded(pt);
    boolean atLeastOne = false;
    boolean needsRestSplit = false;
    Type restType = null;
    if (isVariadic) {
        // unwrap the last element
        restType = tupleElementTypes.get(tupleElementTypes.size() - 1);
        // to optimise
        if (restType.isUnknown())
            return null;
        tupleElementTypes.set(tupleElementTypes.size() - 1, typeFact.getSequentialElementType(restType));
        atLeastOne = restType.getDeclaration().inherits(typeFact().getSequenceDeclaration());
        // the last rest element may be a type param, in which case we resolve it at runtime
        needsRestSplit = !restType.getDeclaration().equals(typeFact.getSequenceDeclaration()) && !restType.getDeclaration().equals(typeFact.getSequentialDeclaration());
    }
    int firstDefaulted;
    if (!firstElementOptional) {
        // only do this crazy computation if the first element is not optional (case of []|[A] which is a union type really)
        int minimumLength = typeFact().getTupleMinimumLength(pt);
        // [B+] -> 1
        if (atLeastOne)
            minimumLength--;
        // [A,B=] -> 1
        // [A=,B*] -> 0
        // [A,B+] -> 1
        // [B*] -> 0
        // [B+] -> 0
        // [A,B=] -> 2
        // [A=,B*] -> 1
        // [A,B+] -> 1
        // [B*] -> 0
        // [B+] -> 0
        int nonVariadicParams = tupleElementTypes.size();
        if (isVariadic)
            nonVariadicParams--;
        // [A,B=] -> 2!=1 -> 1
        // [A=,B*] -> 1!=0 -> 0
        // [A,B+] -> 1==1 -> -1
        // [B*] -> 0==0 -> -1
        // [B+] -> 0==0 -> -1
        firstDefaulted = nonVariadicParams != minimumLength ? minimumLength : -1;
    } else {
        firstDefaulted = 0;
    }
    JCExpression restTypeDescriptor = null;
    JCExpression restElementTypeDescriptor = null;
    if (needsRestSplit) {
        Type restElementType = tupleElementTypes.get(tupleElementTypes.size() - 1);
        tupleElementTypes.remove(tupleElementTypes.size() - 1);
        restTypeDescriptor = makeReifiedTypeArgumentResolved(restType, false);
        restElementTypeDescriptor = makeReifiedTypeArgumentResolved(restElementType, false);
    }
    ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
    if (needsRestSplit) {
        args.append(restTypeDescriptor);
        args.append(restElementTypeDescriptor);
    } else {
        args.append(makeBoolean(isVariadic));
        args.append(makeBoolean(atLeastOne));
    }
    args.append(makeInteger(firstDefaulted));
    for (Type element : tupleElementTypes) {
        args.append(makeReifiedTypeArgumentResolved(element, false));
    }
    JCExpression tupleDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), needsRestSplit ? "tupleWithRest" : "tuple"), args.toList());
    return tupleDescriptor;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) ListBuffer(com.sun.tools.javac.util.ListBuffer)

Example 77 with Type

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

the class AbstractTransformer method hasDependentCovariantTypeParameters.

boolean hasDependentCovariantTypeParameters(Type type) {
    if (type.isUnion()) {
        for (Type m : type.getCaseTypes()) if (hasDependentCovariantTypeParameters(m))
            return true;
        return false;
    }
    if (type.isIntersection()) {
        for (Type m : type.getSatisfiedTypes()) if (hasDependentCovariantTypeParameters(m))
            return true;
        return false;
    }
    // check its type arguments
    // special case for Callable which has only a single type param in Java
    boolean isCallable = isCeylonCallable(type);
    // check if any type parameter is dependent on and covariant
    TypeDeclaration declaration = type.getDeclaration();
    java.util.List<TypeParameter> typeParams = declaration.getTypeParameters();
    Map<TypeParameter, Type> typeArguments = type.getTypeArguments();
    for (TypeParameter typeParam : typeParams) {
        Type typeArg = typeArguments.get(typeParam);
        if (type.isCovariant(typeParam) && hasDependentTypeParameters(typeParams, typeParam)) {
            // see if the type argument in question contains type parameters and is erased to Object
            if (containsTypeParameter(typeArg) && willEraseToObject(typeArg))
                return true;
        }
        // now check if we the type argument has the same problem
        if (hasDependentCovariantTypeParameters(typeArg))
            return true;
        // stop after the first type arg for Callable
        if (isCallable)
            break;
    }
    return false;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 78 with Type

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

the class ClassTransformer method transformClassAlias.

private void transformClassAlias(final Tree.ClassDeclaration def, ClassDefinitionBuilder classBuilder) {
    ClassAlias model = (ClassAlias) def.getDeclarationModel();
    Type aliasedClass = model.getExtendedType();
    TypeDeclaration classOrCtor = def.getClassSpecifier().getType().getDeclarationModel();
    while (classOrCtor instanceof ClassAlias) {
        classOrCtor = ((ClassAlias) classOrCtor).getConstructor();
    }
    classBuilder.annotations(makeAtAlias(aliasedClass, classOrCtor instanceof Constructor ? (Constructor) classOrCtor : null));
    classBuilder.isAlias(true);
    MethodDefinitionBuilder instantiator = transformClassAliasInstantiator(def, model, aliasedClass);
    ClassDefinitionBuilder cbInstantiator = null;
    switch(Strategy.defaultParameterMethodOwner(model)) {
        case STATIC:
            cbInstantiator = classBuilder;
            break;
        case OUTER:
            cbInstantiator = classBuilder.getContainingClassBuilder();
            break;
        case OUTER_COMPANION:
            cbInstantiator = classBuilder.getContainingClassBuilder().getCompanionBuilder(Decl.getClassOrInterfaceContainer(model, true));
            break;
        default:
            throw BugException.unhandledEnumCase(Strategy.defaultParameterMethodOwner(model));
    }
    cbInstantiator.method(instantiator);
}
Also used : ClassAlias(com.redhat.ceylon.model.typechecker.model.ClassAlias) Type(com.redhat.ceylon.model.typechecker.model.Type) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 79 with Type

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

the class ClassTransformer method addAmbiguousMembers.

private void addAmbiguousMembers(ClassDefinitionBuilder classBuilder, Interface model) {
    // only if we refine more than one interface
    java.util.List<Type> satisfiedTypes = model.getSatisfiedTypes();
    if (satisfiedTypes.size() <= 1)
        return;
    Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
    for (Type interfaceDecl : model.getSatisfiedTypes()) {
        collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
    }
    Set<Interface> ambiguousInterfaces = new HashSet<Interface>();
    for (Interface satisfiedInterface : satisfiedInterfaces) {
        if (isInheritedWithDifferentTypeArguments(satisfiedInterface, model.getType()) != null) {
            ambiguousInterfaces.add(satisfiedInterface);
        }
    }
    Set<String> treated = new HashSet<String>();
    for (Interface ambiguousInterface : ambiguousInterfaces) {
        for (Declaration member : ambiguousInterface.getMembers()) {
            String name = member.getName();
            // skip if already handled
            if (treated.contains(name))
                continue;
            // skip if it's implemented directly
            if (model.getDirectMember(name, null, false) != null) {
                treated.add(name);
                continue;
            }
            // find if we have different implementations in two direct interfaces
            LOOKUP: for (int i = 0; i < satisfiedTypes.size(); i++) {
                Type firstInterface = satisfiedTypes.get(i);
                Declaration member1 = firstInterface.getDeclaration().getMember(name, null, false);
                // if we can't find it in this interface, move to the next
                if (member1 == null)
                    continue;
                // try to find member in other interfaces
                for (int j = i + 1; j < satisfiedTypes.size(); j++) {
                    Type secondInterface = satisfiedTypes.get(j);
                    Declaration member2 = secondInterface.getDeclaration().getMember(name, null, false);
                    // if we can't find it in this interface, move to the next
                    if (member2 == null)
                        continue;
                    // we have it in two separate interfaces
                    Reference typedMember1 = firstInterface.getTypedReference(member1, Collections.<Type>emptyList());
                    Reference typedMember2 = secondInterface.getTypedReference(member2, Collections.<Type>emptyList());
                    Type type1 = simplifyType(typedMember1.getType());
                    Type type2 = simplifyType(typedMember2.getType());
                    if (!type1.isExactly(type2)) {
                        // treat it and stop looking for other interfaces
                        addAmbiguousMember(classBuilder, model, name);
                        break LOOKUP;
                    }
                }
            }
            // that member has no conflict
            treated.add(name);
        }
    }
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) 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) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) HashSet(java.util.HashSet)

Example 80 with Type

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

the class ClassTransformer method transformSpecifiedMethodBody.

List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
    final Function model = def.getDeclarationModel();
    List<JCStatement> body;
    Tree.MethodDeclaration methodDecl = def;
    boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
    boolean returnNull = false;
    JCExpression bodyExpr;
    Tree.Term term = null;
    if (specifierExpression != null && specifierExpression.getExpression() != null) {
        term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
        if (error != null) {
            return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
        }
    }
    if (!isLazy && term instanceof Tree.FunctionArgument) {
        // Function specified with lambda: Don't bother generating a 
        // Callable, just transform the expr to use as the method body.
        Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
        Type resultType = model.getType();
        returnNull = isAnything(resultType) && fa.getExpression().getUnboxed();
        final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
        final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
        List<Substitution> substitutions = List.nil();
        for (int ii = 0; ii < lambdaParams.size(); ii++) {
            substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
        }
        bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
        for (Substitution subs : substitutions) {
            subs.close();
        }
    } else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
        returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
        Function method = methodDecl.getDeclarationModel();
        boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
        boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
        Invocation invocation;
        if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
            Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
            Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
            invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
        } else if (!lazy && !inlined) {
            // must be a callable we stored
            String name = naming.getMethodSpecifierAttributeName(method);
            invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
        } else if (isCeylonCallableSubtype(term.getTypeModel())) {
            invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
        } else {
            throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
        }
        invocation.handleBoxing(true);
        invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
        bodyExpr = expressionGen().transformInvocation(invocation);
    } else {
        bodyExpr = expressionGen().transformExpression(model, term);
        // The innermost of an MPL method declared void needs to return null
        returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
    }
    if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
        if (returnNull) {
            body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
        } else {
            body = List.<JCStatement>of(make().Return(bodyExpr));
        }
    } else {
        body = List.<JCStatement>of(make().Exec(bodyExpr));
    }
    return body;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) 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) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Type(com.redhat.ceylon.model.typechecker.model.Type) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter)

Aggregations

Type (com.redhat.ceylon.model.typechecker.model.Type)237 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)98 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)87 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)56 JCTree (com.sun.tools.javac.tree.JCTree)53 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)51 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)46 Class (com.redhat.ceylon.model.typechecker.model.Class)45 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)43 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)41 IntersectionType (com.redhat.ceylon.model.typechecker.model.IntersectionType)37 UnionType (com.redhat.ceylon.model.typechecker.model.UnionType)37 Test (org.junit.Test)37 TypeParser (com.redhat.ceylon.model.loader.TypeParser)36 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)34 Function (com.redhat.ceylon.model.typechecker.model.Function)33 Interface (com.redhat.ceylon.model.typechecker.model.Interface)30 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)30 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)29 ArrayList (java.util.ArrayList)28