Search in sources :

Example 6 with Generic

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

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 (declaration instanceof Generic) {
        tps = ((Generic) declaration).getTypeParameters();
    }
    if (mte.getTypeModel().isTypeConstructor()) {
        for (TypeParameter tp : tps) {
            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(com.redhat.ceylon.model.typechecker.model.TypeParameter) Type(com.redhat.ceylon.model.typechecker.model.Type) Generic(com.redhat.ceylon.model.typechecker.model.Generic) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 7 with Generic

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

the class AbstractTransformer method canUseFastFailTypeTest.

private boolean canUseFastFailTypeTest(Type type) {
    if (type.getDeclaration() instanceof ClassOrInterface == false)
        return false;
    boolean isRaw = !type.getDeclaration().getTypeParameters().isEmpty();
    Type qualifyingType = type.getQualifyingType();
    if (qualifyingType == null && // ignore qualifying types of static java declarations
    (Decl.isCeylon(type.getDeclaration()) || !type.getDeclaration().isStaticallyImportable())) {
        Declaration declaration = type.getDeclaration();
        boolean local = false;
        do {
            // getDeclarationContainer will skip some containers we don't want to consider, so it's not good
            // for checking locality, rely on isLocal for that.
            local |= Decl.isLocal(declaration);
            // it may be contained in a function or value, and we want its type
            Declaration enclosingDeclaration = getDeclarationContainer(declaration);
            if (enclosingDeclaration instanceof TypedDeclaration) {
                local = true;
                // look up the containers
                declaration = enclosingDeclaration;
            } else if (enclosingDeclaration instanceof TypeDeclaration) {
                // we can't do instanceof on a local whose outer types contain type parameters, unless the local is raw
                if (enclosingDeclaration instanceof Generic && local && !isRaw && !((Generic) enclosingDeclaration).getTypeParameters().isEmpty())
                    return false;
                // look up the containers
                declaration = enclosingDeclaration;
            } else {
                // that's fucked up
                break;
            }
        // go up every containing typed declaration
        } while (declaration != null);
        // we can fast-fail!
        return true;
    } else if (qualifyingType != null) {
        // we can only fast-fail if the qualifying type can also be fast-failed
        return canUseFastFailTypeTest(qualifyingType);
    } else {
        // we can fast-fail!
        return true;
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) Generic(com.redhat.ceylon.model.typechecker.model.Generic) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 8 with Generic

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

the class AbstractTransformer method getRefinedTypedReference.

private TypedReference getRefinedTypedReference(TypedReference typedReference, TypedDeclaration refinedDeclaration) {
    TypeDeclaration refinedContainer = (TypeDeclaration) refinedDeclaration.getContainer();
    Type refinedContainerType = typedReference.getQualifyingType().getSupertype(refinedContainer);
    ArrayList<Type> typeArgs = new ArrayList<Type>();
    if (typedReference.getDeclaration() instanceof Generic) {
        for (TypeParameter tp : ((Generic) typedReference.getDeclaration()).getTypeParameters()) {
            typeArgs.add(typedReference.getTypeArguments().get(tp));
        }
    }
    return refinedDeclaration.appliedTypedReference(refinedContainerType, typeArgs);
}
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) Generic(com.redhat.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 9 with Generic

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

the class AbstractTransformer method collectQualifyingTypeArguments.

/**
     * Collects all the type parameters and arguments required for an interface that's been pulled up to the
     * toplevel, including its containing type and method type parameters.
     */
private void collectQualifyingTypeArguments(java.util.List<TypeParameter> qualifyingTypeParameters, Map<TypeParameter, Type> qualifyingTypeArguments, java.util.List<Reference> qualifyingTypes) {
    // make sure we only add type parameters with the same name once, as duplicates are erased from the target interface
    // since they cannot be accessed
    Set<String> names = new HashSet<String>();
    // walk the qualifying types backwards to make sure we only add a TP with the same name once and the outer one wins
    for (int i = qualifyingTypes.size() - 1; i >= 0; i--) {
        Reference qualifiedType = qualifyingTypes.get(i);
        Map<TypeParameter, Type> tas = qualifiedType.getTypeArguments();
        java.util.List<TypeParameter> tps = ((Generic) qualifiedType.getDeclaration()).getTypeParameters();
        // add any type params for this type
        if (tps != null) {
            int index = 0;
            for (TypeParameter tp : tps) {
                // add it only once
                if (names.add(tp.getName())) {
                    // start putting all these type parameters at 0 and then in order
                    // so that outer type params end up before inner type params but
                    // order is preserved within each type
                    qualifyingTypeParameters.add(index++, tp);
                    qualifyingTypeArguments.put(tp, tas.get(tp));
                }
            }
        }
        // add any container method TP
        Declaration declaration = qualifiedType.getDeclaration();
        if (Decl.isLocal(declaration)) {
            Scope scope = declaration.getContainer();
            // collect every container method until the next type or package
            java.util.List<Function> methods = new LinkedList<Function>();
            while (scope != null && scope instanceof ClassOrInterface == false && scope instanceof Package == false) {
                if (scope instanceof Function) {
                    methods.add((Function) scope);
                }
                scope = scope.getContainer();
            }
            // methods are sorted inner to outer, which is the order we're following here for types
            for (Function method : methods) {
                java.util.List<TypeParameter> methodTypeParameters = method.getTypeParameters();
                if (methodTypeParameters != null) {
                    int index = 0;
                    for (TypeParameter tp : methodTypeParameters) {
                        // add it only once
                        if (names.add(tp.getName())) {
                            // start putting all these type parameters at 0 and then in order
                            // so that outer type params end up before inner type params but
                            // order is preserved within each type
                            qualifyingTypeParameters.add(index++, tp);
                            qualifyingTypeArguments.put(tp, tp.getType());
                        }
                    }
                }
            }
        }
    }
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) Generic(com.redhat.ceylon.model.typechecker.model.Generic) LinkedList(java.util.LinkedList) Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) Scope(com.redhat.ceylon.model.typechecker.model.Scope) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Package(com.redhat.ceylon.model.typechecker.model.Package) HashSet(java.util.HashSet)

Example 10 with Generic

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

the class ClassTransformer method makeParamDefaultValueMethod.

/**
     * Creates a (possibly abstract) method for retrieving the value for a 
     * defaulted parameter
     * @param typeParameterList 
     */
MethodDefinitionBuilder makeParamDefaultValueMethod(boolean noBody, Declaration container, Tree.ParameterList params, Tree.Parameter currentParam) {
    at(currentParam);
    Parameter parameter = currentParam.getParameterModel();
    if (!Strategy.hasDefaultParameterValueMethod(parameter)) {
        throw new BugException();
    }
    MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.systemMethod(this, Naming.getDefaultedParamMethodName(container, parameter));
    methodBuilder.ignoreModelAnnotations();
    if (container != null && Decl.isAnnotationConstructor(container)) {
        AnnotationInvocation ac = (AnnotationInvocation) ((Function) container).getAnnotationConstructor();
        for (AnnotationConstructorParameter acp : ac.getConstructorParameters()) {
            if (acp.getParameter().equals(parameter) && acp.getDefaultArgument() != null) {
                methodBuilder.userAnnotations(acp.getDefaultArgument().makeDpmAnnotations(expressionGen()));
            }
        }
    }
    int modifiers = 0;
    if (noBody) {
        modifiers |= PUBLIC | ABSTRACT;
    } else if (container == null || !(container instanceof Class && Strategy.defaultParameterMethodStatic(container))) {
        // initializers can override parameter defaults
        modifiers |= FINAL;
    }
    if (container != null && container.isShared()) {
        modifiers |= PUBLIC;
    } else if (container == null || (!container.isToplevel() && !noBody)) {
        modifiers |= PRIVATE;
    }
    boolean staticMethod = Strategy.defaultParameterMethodStatic(container);
    if (staticMethod) {
        // static default parameter methods should be consistently public so that if non-shared class Top and
        // shared class Bottom which extends Top both have the same default param name, we don't get an error
        // if the Bottom class tries to "hide" a static public method with a private one
        modifiers &= ~PRIVATE;
        modifiers |= STATIC | PUBLIC;
    }
    methodBuilder.modifiers(modifiers);
    if (container instanceof Constructor) {
        copyTypeParameters((Class) container.getContainer(), methodBuilder);
        methodBuilder.reifiedTypeParameters(((Class) container.getContainer()).getTypeParameters());
    } else if (container instanceof Generic) {
        // make sure reified type parameters are accepted
        copyTypeParameters((Generic) container, methodBuilder);
        methodBuilder.reifiedTypeParameters(((Generic) container).getTypeParameters());
    }
    WideningRules wideningRules = !staticMethod && container instanceof Class ? WideningRules.CAN_WIDEN : WideningRules.NONE;
    // Add any of the preceding parameters as parameters to the method
    for (Tree.Parameter p : params.getParameters()) {
        if (p.equals(currentParam)) {
            break;
        }
        at(p);
        methodBuilder.parameter(p.getParameterModel(), null, 0, wideningRules);
    }
    // The method's return type is the same as the parameter's type
    NonWideningParam nonWideningParam = methodBuilder.getNonWideningParam(currentParam.getParameterModel().getModel(), wideningRules);
    methodBuilder.resultType(nonWideningParam.nonWideningDecl, nonWideningParam.nonWideningType, nonWideningParam.flags);
    // The implementation of the method
    if (noBody) {
        methodBuilder.noBody();
    } else {
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(Decl.getDefaultArgument(currentParam).getExpression());
        if (error != null) {
            methodBuilder.body(this.makeThrowUnresolvedCompilationError(error));
        } else {
            java.util.List<TypeParameter> copiedTypeParameters = null;
            if (container instanceof Generic) {
                copiedTypeParameters = ((Generic) container).getTypeParameters();
                if (copiedTypeParameters != null)
                    addTypeParameterSubstitution(copiedTypeParameters);
            }
            try {
                JCExpression expr = expressionGen().transform(currentParam);
                JCBlock body = at(currentParam).Block(0, List.<JCStatement>of(at(currentParam).Return(expr)));
                methodBuilder.block(body);
            } finally {
                if (copiedTypeParameters != null)
                    popTypeParameterSubstitution();
            }
        }
    }
    return methodBuilder;
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) NonWideningParam(com.redhat.ceylon.compiler.java.codegen.MethodDefinitionBuilder.NonWideningParam) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Generic(com.redhat.ceylon.model.typechecker.model.Generic) WideningRules(com.redhat.ceylon.compiler.java.codegen.MethodDefinitionBuilder.WideningRules) 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) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) 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)

Aggregations

Generic (com.redhat.ceylon.model.typechecker.model.Generic)12 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)9 Type (com.redhat.ceylon.model.typechecker.model.Type)8 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)7 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)7 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)6 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)4 ArrayList (java.util.ArrayList)4 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)3 Package (com.redhat.ceylon.model.typechecker.model.Package)3 Scope (com.redhat.ceylon.model.typechecker.model.Scope)3 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)3 Class (com.redhat.ceylon.model.typechecker.model.Class)2 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)2 Function (com.redhat.ceylon.model.typechecker.model.Function)2 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)2 Reference (com.redhat.ceylon.model.typechecker.model.Reference)2 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)2 Value (com.redhat.ceylon.model.typechecker.model.Value)2 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)2