Search in sources :

Example 26 with Function

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

the class NamedArgumentInvocation method transformPrimary.

protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr, String selector) {
    if (Decl.isJavaStaticOrInterfacePrimary(getPrimary())) {
        Declaration methodOrClass = ((Tree.QualifiedMemberOrTypeExpression) getPrimary()).getDeclaration();
        if (methodOrClass instanceof Function) {
            return new TransformedInvocationPrimary(gen.naming.makeName((Function) methodOrClass, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED), null);
        } else if (methodOrClass instanceof Class) {
            return new TransformedInvocationPrimary(gen.makeJavaType(((Class) methodOrClass).getType(), JT_RAW | JT_NO_PRIMITIVES), null);
        }
    }
    if (isMemberRefInvocation()) {
        JCExpression callable = gen.expressionGen().transformMemberReference((Tree.QualifiedMemberOrTypeExpression) getPrimary(), (Tree.MemberOrTypeExpression) getQmePrimary());
        // The callable is a Callable we generate ourselves, it can never be erased to Object so there's no need to unerase
        selector = Naming.getCallableMethodName();
        return new TransformedInvocationPrimary(callable, selector);
    }
    JCExpression actualPrimExpr;
    if (getPrimary() instanceof Tree.QualifiedTypeExpression && ((Tree.QualifiedTypeExpression) getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression && !Decl.isConstructor(getPrimaryDeclaration())) {
        actualPrimExpr = gen.naming.makeQualifiedThis(primaryExpr);
    } else {
        actualPrimExpr = primaryExpr;
    }
    if (getPrimary() instanceof Tree.BaseTypeExpression) {
        Tree.BaseTypeExpression type = (Tree.BaseTypeExpression) getPrimary();
        Declaration declaration = type.getDeclaration();
        if (Strategy.generateInstantiator(declaration)) {
            if (Decl.withinInterface(declaration)) {
                if (primaryExpr != null) {
                    // if we have some other primary then respect that
                    actualPrimExpr = primaryExpr;
                } else {
                    // if the class being instantiated is 
                    // within a class we expect the instantiation to be
                    // accessible from `this`, so use null
                    // otherwise we must be in an companion class, so we 
                    // need to qualify the instantiator invocation with $this
                    actualPrimExpr = type.getScope().getInheritingDeclaration(declaration) instanceof Class ? null : gen.naming.makeQuotedThis();
                }
            } else if (declaration.isToplevel()) {
                actualPrimExpr = null;
            }
        // if the decl is not toplevel (but the primary is a base type
        // we must be invoking a member imported from an object
        // in which case the qualifer is needed.
        }
        if (Decl.isConstructor(declaration)) {
            selector = null;
        }
    } else {
        if (getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression) {
            Tree.QualifiedMemberOrTypeExpression type = (Tree.QualifiedMemberOrTypeExpression) getPrimary();
            Declaration declaration = type.getDeclaration();
            if (Decl.isConstructor(declaration)) {
                if (Decl.withinInterface(Decl.getConstructedClass(declaration))) {
                    if (Strategy.generateInstantiator(declaration)) {
                        actualPrimExpr = primaryExpr != null ? primaryExpr : gen.naming.makeQuotedThis();
                    } else {
                        actualPrimExpr = null;
                    }
                }
            }
        } else if (getPrimary() instanceof Tree.BaseMemberOrTypeExpression) {
            Tree.BaseMemberOrTypeExpression type = (Tree.BaseMemberOrTypeExpression) getPrimary();
            Declaration declaration = type.getDeclaration();
            if (Decl.isConstructor(declaration)) {
                selector = null;
            }
        }
        if (isIndirect()) {
            if (getPrimaryDeclaration() != null && (Decl.isGetter(getPrimaryDeclaration()) || Decl.isToplevel(getPrimaryDeclaration()) || (Decl.isValueOrSharedOrCapturedParam(getPrimaryDeclaration()) && Decl.isCaptured(getPrimaryDeclaration()) && !Decl.isLocalNotInitializer(getPrimaryDeclaration())))) {
                // We need to invoke the getter to obtain the Callable
                actualPrimExpr = gen.make().Apply(null, gen.naming.makeQualIdent(primaryExpr, selector), List.<JCExpression>nil());
            } else if (selector != null) {
                actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
            } else if (getPrimaryDeclaration() == null || !((TypedDeclaration) getPrimaryDeclaration()).getType().isTypeConstructor()) {
                actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
            }
            actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
            if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
                selector = Naming.getCallableVariadicMethodName();
                this.callable = true;
            } else {
                selector = Naming.getCallableMethodName();
                this.callable = true;
            }
            // If it's indirect the primary might be erased
            actualPrimExpr = gen.expressionGen().applyErasureAndBoxing(actualPrimExpr, getPrimary().getTypeModel(), getPrimary().getTypeErased(), // boxed
            true, BoxingStrategy.BOXED, getPrimary().getTypeModel(), 0);
        } else if ((getPrimaryDeclaration() instanceof Function && // i.e. functional parameter
        ((Function) getPrimaryDeclaration()).isParameter() && // not class member, or not shared/captured
        (!JvmBackendUtil.createMethod((Function) getPrimaryDeclaration())) || // we need to access the Callable parameter, no the member method
        gen.expressionGen().isWithinDefaultParameterExpression(getPrimaryDeclaration().getContainer()))) {
            if (selector != null) {
                actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
            } else {
                actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration) getPrimaryDeclaration(), Naming.NA_MEMBER);
            }
            actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
            if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
                selector = Naming.getCallableVariadicMethodName();
                this.callable = true;
            } else {
                selector = Naming.getCallableMethodName();
                this.callable = true;
            }
        }
    }
    return new TransformedInvocationPrimary(actualPrimExpr, selector);
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Function(com.redhat.ceylon.model.typechecker.model.Function) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) 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) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) QualifiedTypeExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression)

Example 27 with Function

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

the class NamedArgumentInvocation method appendVarsForDefaulted.

private boolean appendVarsForDefaulted(java.util.List<Parameter> declaredParams) {
    boolean hasDefaulted = false;
    if (!Decl.isOverloaded(getPrimaryDeclaration())) {
        // append any arguments for defaulted parameters
        for (Parameter param : declaredParams) {
            if (bound.contains(param)) {
                continue;
            }
            final JCExpression argExpr;
            if (Strategy.hasDefaultParameterValueMethod(param)) {
                // special handling for "element" optional param of java array constructors
                if (getPrimaryDeclaration() instanceof Class && gen.isJavaArray(((Class) getPrimaryDeclaration()).getType())) {
                    // default values are hard-coded to Java default values, and are actually ignored
                    continue;
                } else if (getQmePrimary() != null && gen.isJavaArray(getQmePrimary().getTypeModel())) {
                    // we support array methods with optional parameters
                    if (getPrimaryDeclaration() instanceof Function && getPrimaryDeclaration().getName().equals("copyTo")) {
                        if (param.getName().equals("sourcePosition") || param.getName().equals("destinationPosition")) {
                            argExpr = gen.makeInteger(0);
                            hasDefaulted |= true;
                        } else if (param.getName().equals("length")) {
                            argExpr = gen.makeSelect(varBaseName.suffixedBy(Suffix.$argthis$).makeIdent(), "length");
                            hasDefaulted |= true;
                        } else {
                            argExpr = gen.makeErroneous(this.getNode(), "compiler bug: argument to copyTo method of java array type not supported: " + param.getName());
                        }
                    } else {
                        argExpr = gen.makeErroneous(this.getNode(), "compiler bug: virtual method of java array type not supported: " + getPrimaryDeclaration());
                    }
                } else {
                    argExpr = makeDefaultedArgumentMethodCall(param);
                    hasDefaulted |= true;
                }
            } else if (Strategy.hasEmptyDefaultArgument(param)) {
                argExpr = gen.makeEmptyAsSequential(true);
            } else if (gen.typeFact().isIterableType(param.getType())) {
                // must be an iterable we need to fill with empty
                // FIXME: deal with this erasure bug later
                argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty());
            } else {
                // more expensive but worth a try
                Type appliedType = gen.getTypeForParameter(param, producedReference, AbstractTransformer.TP_TO_BOUND);
                if (gen.typeFact().isIterableType(appliedType)) {
                    argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty());
                } else {
                    argExpr = gen.makeErroneous(this.getNode(), "compiler bug: missing argument, and parameter is not defaulted");
                }
            }
            appendDefaulted(param, argExpr);
        }
    }
    return hasDefaulted;
}
Also used : Function(com.redhat.ceylon.model.typechecker.model.Function) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass)

Example 28 with Function

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

the class AbstractTransformer method getTypeForParameter.

Type getTypeForParameter(Parameter parameter, Reference producedReference, int flags) {
    /* this method is bogus: It's really trying to answer 
         * "what's the type of the java declaration of the given parameter", 
         * but using the ceylon type system to do so. 
         */
    boolean functional = parameter.getModel() instanceof Function;
    if (producedReference == null) {
        return parameter.getType();
    }
    final TypedReference producedTypedReference = producedReference.getTypedParameter(parameter);
    final Type type = functional ? producedTypedReference.getFullType() : producedTypedReference.getType();
    final TypedDeclaration producedParameterDecl = producedTypedReference.getDeclaration();
    final Type declType = producedParameterDecl.getType();
    // be more resilient to upstream errors
    if (declType == null)
        return typeFact.getUnknownType();
    if (isJavaVariadic(parameter) && (flags & TP_SEQUENCED_TYPE) == 0) {
        // type of param must be Iterable<T>
        Type elementType = typeFact.getIteratedType(type);
        if (elementType == null) {
            log.error("ceylon", "Invalid type for Java variadic parameter: " + type.asQualifiedString());
            return type;
        }
        return elementType;
    }
    if (declType.isClassOrInterface()) {
        return type;
    } else if ((declType.isTypeParameter()) && (flags & TP_TO_BOUND) != 0) {
        if (!declType.getSatisfiedTypes().isEmpty()) {
            // use upper bound
            Type upperBound = declType.getSatisfiedTypes().get(0);
            // make sure we apply the type arguments
            upperBound = substituteTypeArgumentsForTypeParameterBound(producedReference, upperBound);
            Type self = upperBound.getDeclaration().getSelfType();
            if (self != null) {
                // make sure we apply the type arguments
                Type selfUpperBound = self.substitute(upperBound);
                if (!willEraseToObject(selfUpperBound) && (willEraseToObject(type) || expressionGen().needsCast(type, selfUpperBound, false, false, false))) {
                    return selfUpperBound;
                }
            }
            if (!willEraseToObject(upperBound) && (willEraseToObject(type) || expressionGen().needsCast(type, upperBound, false, false, false))) {
                return upperBound;
            }
        }
    }
    return type;
}
Also used : Function(com.redhat.ceylon.model.typechecker.model.Function) 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) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference)

Example 29 with Function

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

the class AbstractTransformer method makeReifiedTypeArgumentResolved.

private JCExpression makeReifiedTypeArgumentResolved(Type pt, boolean qualified) {
    if (pt.isUnion()) {
        // FIXME: refactor this shite
        List<JCExpression> typeTestArguments = List.nil();
        java.util.List<Type> typeParameters = pt.getCaseTypes();
        if (typeParameters.size() == 2) {
            Type alternative = null;
            if (typeParameters.get(0).isEmpty())
                alternative = typeParameters.get(1);
            else if (typeParameters.get(1).isEmpty())
                alternative = typeParameters.get(0);
            if (alternative != null && alternative.isTuple()) {
                JCExpression tupleType = makeTupleTypeDescriptor(alternative, true);
                if (tupleType != null)
                    return tupleType;
            }
        }
        for (int i = typeParameters.size() - 1; i >= 0; i--) {
            typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
        }
        return make().Apply(null, makeSelect(makeTypeDescriptorType(), "union"), typeTestArguments);
    } else if (pt.isIntersection()) {
        List<JCExpression> typeTestArguments = List.nil();
        java.util.List<Type> typeParameters = pt.getSatisfiedTypes();
        for (int i = typeParameters.size() - 1; i >= 0; i--) {
            typeTestArguments = typeTestArguments.prepend(makeReifiedTypeArgument(typeParameters.get(i)));
        }
        return make().Apply(null, makeSelect(makeTypeDescriptorType(), "intersection"), typeTestArguments);
    } else if (pt.isNothing()) {
        return makeNothingTypeDescriptor();
    }
    TypeDeclaration declaration = pt.getDeclaration();
    if (declaration instanceof Constructor) {
        pt = pt.getExtendedType();
        declaration = pt.getDeclaration();
    }
    if (pt.isClassOrInterface()) {
        if (declaration.isJavaEnum()) {
            pt = pt.getExtendedType();
            declaration = pt.getDeclaration();
        }
        // see if we have an alias for it
        if (supportsReifiedAlias((ClassOrInterface) declaration)) {
            JCExpression qualifier = naming.makeDeclarationName(declaration, DeclNameFlag.QUALIFIED);
            return makeSelect(qualifier, naming.getTypeDescriptorAliasName());
        }
        if (pt.isTuple()) {
            JCExpression tupleType = makeTupleTypeDescriptor(pt, false);
            if (tupleType != null)
                return tupleType;
        }
        // no alias, must build it
        List<JCExpression> typeTestArguments = makeReifiedTypeArgumentsResolved(pt.getTypeArgumentList(), qualified);
        JCExpression thisType = makeUnerasedClassLiteral(declaration);
        // do we have variance overrides?
        Map<TypeParameter, SiteVariance> varianceOverrides = pt.getVarianceOverrides();
        if (!varianceOverrides.isEmpty()) {
            // we need to pass them as second argument then, in an array
            ListBuffer<JCExpression> varianceElements = new ListBuffer<JCExpression>();
            for (TypeParameter typeParameter : declaration.getTypeParameters()) {
                SiteVariance useSiteVariance = varianceOverrides.get(typeParameter);
                String selector;
                if (useSiteVariance != null) {
                    switch(useSiteVariance) {
                        case IN:
                            selector = "IN";
                            break;
                        case OUT:
                            selector = "OUT";
                            break;
                        default:
                            selector = "NONE";
                            break;
                    }
                } else {
                    selector = "NONE";
                }
                JCExpression varianceElement = make().Select(makeIdent(syms().ceylonVarianceType), names().fromString(selector));
                varianceElements.append(varianceElement);
            }
            JCNewArray varianceArray = make().NewArray(makeIdent(syms().ceylonVarianceType), List.<JCExpression>nil(), varianceElements.toList());
            typeTestArguments = typeTestArguments.prepend(varianceArray);
        }
        typeTestArguments = typeTestArguments.prepend(thisType);
        JCExpression classDescriptor = make().Apply(null, makeSelect(makeTypeDescriptorType(), "klass"), typeTestArguments);
        Type qualifyingType = pt.getQualifyingType();
        JCExpression containerType = null;
        if (qualifyingType == null && // ignore qualifying types of static java declarations
        (Decl.isCeylon(declaration) || !declaration.isStaticallyImportable())) {
            // it may be contained in a function or value, and we want its type
            Declaration enclosingDeclaration = getDeclarationContainer(declaration);
            if (enclosingDeclaration instanceof TypedDeclaration)
                containerType = makeTypedDeclarationTypeDescriptorResolved((TypedDeclaration) enclosingDeclaration);
            else if (enclosingDeclaration instanceof TypeDeclaration) {
                qualifyingType = ((TypeDeclaration) enclosingDeclaration).getType();
            }
        }
        if (qualifyingType != null && qualifyingType.getDeclaration() instanceof Constructor) {
            qualifyingType = qualifyingType.getQualifyingType();
        }
        if (qualifyingType != null) {
            containerType = makeReifiedTypeArgumentResolved(qualifyingType, true);
        }
        if (containerType == null) {
            return classDescriptor;
        } else {
            return make().Apply(null, makeSelect(makeTypeDescriptorType(), "member"), List.of(containerType, classDescriptor));
        }
    } else if (pt.isTypeParameter()) {
        TypeParameter tp = (TypeParameter) declaration;
        String name = naming.getTypeArgumentDescriptorName(tp);
        if (!qualified || isTypeParameterSubstituted(tp))
            return makeUnquotedIdent(name);
        Scope container = tp.getContainer();
        JCExpression qualifier = null;
        if (container instanceof Class) {
            qualifier = naming.makeQualifiedThis(makeJavaType(((Class) container).getType(), JT_RAW));
        } else if (container instanceof Interface) {
            qualifier = naming.makeQualifiedThis(makeJavaType(((Interface) container).getType(), JT_COMPANION | JT_RAW));
        } else if (container instanceof Function) {
            // name must be a unique name, as returned by getTypeArgumentDescriptorName
            return makeUnquotedIdent(name);
        } else {
            throw BugException.unhandledCase(container);
        }
        return makeSelect(qualifier, name);
    } else {
        throw BugException.unhandledDeclarationCase(declaration);
    }
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) ListBuffer(com.sun.tools.javac.util.ListBuffer) 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) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) SiteVariance(com.redhat.ceylon.model.typechecker.model.SiteVariance) Scope(com.redhat.ceylon.model.typechecker.model.Scope) ArrayList(java.util.ArrayList) List(com.sun.tools.javac.util.List) LinkedList(java.util.LinkedList) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) Class(com.redhat.ceylon.model.typechecker.model.Class) 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) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface)

Example 30 with Function

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

the class LinkRenderer method getUrl.

private String getUrl(Object to, Declaration anchor) {
    String url;
    List<Function> methods = new ArrayList<Function>();
    while (to instanceof Function) {
        Function method = (Function) to;
        methods.add(method);
        to = method.getContainer();
    }
    if (isInCurrentModule(to)) {
        url = getLocalUrl(to);
    } else {
        url = getExternalUrl(to);
    }
    if (url != null && anchor != null) {
        String sectionPackageAnchor = "#section-package";
        if (url.endsWith(sectionPackageAnchor)) {
            url = url.substring(0, url.length() - sectionPackageAnchor.length());
        }
        StringBuilder fragment = new StringBuilder();
        if (!methods.isEmpty()) {
            Collections.reverse(methods);
            for (Function method : methods) {
                fragment.append(method.getName());
                fragment.append("-");
            }
        }
        fragment.append(anchor.getName());
        url = url + "#" + fragment;
    }
    return url;
}
Also used : Function(com.redhat.ceylon.model.typechecker.model.Function) ArrayList(java.util.ArrayList)

Aggregations

Function (com.redhat.ceylon.model.typechecker.model.Function)74 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)35 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)35 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)33 Type (com.redhat.ceylon.model.typechecker.model.Type)33 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)26 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)26 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)25 Value (com.redhat.ceylon.model.typechecker.model.Value)25 Class (com.redhat.ceylon.model.typechecker.model.Class)23 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)22 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)20 JCTree (com.sun.tools.javac.tree.JCTree)18 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)17 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)17 ArrayList (java.util.ArrayList)14 ParameterList (com.redhat.ceylon.model.typechecker.model.ParameterList)13 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)12 MethodDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)11 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)11