Search in sources :

Example 21 with Functional

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

the class RefinementVisitor method checkOverloadedParameters.

private void checkOverloadedParameters(Tree.Declaration that, Declaration member) {
    String name = member.getName();
    Declaration abstraction = member.getScope().getDirectMember(name, null, false);
    if (abstraction != null) {
        Functional fun = (Functional) member;
        List<Parameter> parameters = fun.getFirstParameterList().getParameters();
        for (Parameter param : parameters) {
            if (param.isDefaulted()) {
                that.addError("overloaded function parameter must be required: parameter '" + param.getName() + "' is defaulted");
            }
        }
        Unit unit = that.getUnit();
        for (Declaration dec : abstraction.getOverloads()) {
            if (dec == member)
                break;
            Functional other = (Functional) dec;
            List<Parameter> otherParams = other.getFirstParameterList().getParameters();
            if (otherParams.size() == parameters.size()) {
                boolean allSame = true;
                for (int i = 0; i < parameters.size(); i++) {
                    TypeDeclaration paramType = erasedType(parameters.get(i), unit);
                    TypeDeclaration otherType = erasedType(otherParams.get(i), unit);
                    if (paramType != null && otherType != null && !paramType.equals(otherType)) {
                        allSame = false;
                        break;
                    }
                }
                if (allSame) {
                    that.addError("non-unique parameter list erasure for overloaded function: each overloaded declaration of '" + name + "' must have a distinct parameter list erasure");
                }
            }
        }
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 22 with Functional

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

the class TypeArgumentInference method getInferredTypeArgsForStaticReference.

/**
 * Infer type arguments for the qualifying type in a
 * static method reference that is directly invoked.
 * This method does not correctly handle stuff like
 * constructors or Java static methods.
 *
 * @param that the invocation
 * @param type the type whose type arguments we're
 *             inferring (the qualifying type)
 * @param receiverType
 */
List<Type> getInferredTypeArgsForStaticReference(Tree.InvocationExpression that, TypeDeclaration type, Type receiverType, Tree.MemberOrTypeExpression primary) {
    Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
    Declaration invoked = primary.getDeclaration();
    if (pal == null) {
        return null;
    } else {
        if (invoked instanceof Functional) {
            List<PositionalArgument> args = pal.getPositionalArguments();
            Functional fun = (Functional) invoked;
            List<ParameterList> parameterLists = fun.getParameterLists();
            if (args.isEmpty() || parameterLists.isEmpty()) {
                return null;
            } else {
                // a static method ref invocation has exactly
                // one meaningful argument (the instance of
                // the receiving type)
                Tree.PositionalArgument arg = args.get(0);
                if (arg == null) {
                    return null;
                } else {
                    Type at = arg.getTypeModel();
                    Type tt = type.getType();
                    List<TypeParameter> typeParams = type.getTypeParameters();
                    List<Type> typeArgs = new ArrayList<Type>(typeParams.size());
                    for (TypeParameter tp : typeParams) {
                        Type it = inferTypeArg(tp, tt, at, // TODO: is this 100% correct?
                        false, arg);
                        if (it == null || it.containsUnknowns()) {
                            that.addError("could not infer type argument from given arguments: type parameter '" + tp.getName() + "' could not be inferred");
                        }
                        typeArgs.add(it);
                    }
                    return constrainInferredTypes(typeParams, typeArgs, receiverType, invoked);
                }
            }
        } else {
            return null;
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) PositionalArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 23 with Functional

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

the class TypeArgumentInference method getInferredTypeArgsForFunctionRef.

/**
 * Infer the type arguments for a reference to a
 * generic function that occurs as an argument in
 * an invocation.
 * @param receiverType
 */
List<Type> getInferredTypeArgsForFunctionRef(Tree.StaticMemberOrTypeExpression smte, Type receiverType, boolean secondList) {
    Tree.TypeArguments typeArguments = smte.getTypeArguments();
    if (typeArguments instanceof Tree.InferredTypeArguments) {
        // the model object for the function ref
        Declaration reference = smte.getDeclaration();
        List<TypeParameter> typeParameters = getTypeParametersAccountingForTypeConstructor(reference);
        if (typeParameters == null || typeParameters.isEmpty()) {
            // nothing to infer
            return NO_TYPE_ARGS;
        } else {
            // set earlier in inferParameterTypes()
            TypedReference paramTypedRef = smte.getTargetParameter();
            Type paramType = smte.getParameterType();
            // the function ref is being passed
            if (paramType == null && paramTypedRef != null) {
                paramType = paramTypedRef.getFullType();
            }
            if (paramType == null) {
                return null;
            }
            if (isArgumentToGenericParameter(paramTypedRef, paramType)) {
                return null;
            }
            Declaration paramDec;
            Declaration parameterizedDec;
            if (paramTypedRef != null) {
                paramDec = paramTypedRef.getDeclaration();
                parameterizedDec = (Declaration) paramDec.getContainer();
            } else {
                paramDec = null;
                parameterizedDec = null;
            }
            // better algorithm
            if (!smte.getStaticMethodReferencePrimary() && reference instanceof Functional && paramDec instanceof Functional && paramTypedRef != null) {
                // callable parameter
                return inferFunctionRefTypeArgs(smte, receiverType, secondList, reference, typeParameters, paramTypedRef, paramDec, parameterizedDec);
            } else {
                // improve this, including in the spec)
                if (unit.isSequentialType(paramType)) {
                    paramType = unit.getSequentialElementType(paramType);
                }
                if (unit.isCallableType(paramType)) {
                    // the parameter has type Callable
                    return inferFunctionRefTypeArgs(smte, receiverType, secondList, reference, typeParameters, paramType, parameterizedDec);
                } else if (secondList) {
                    // arguments (NOT BLESSED BY SPEC!)
                    return inferNullaryFunctionCallTypeArgs(smte, receiverType, reference, typeParameters, paramType, parameterizedDec);
                } else {
                    return null;
                }
            }
        }
    } else {
        // not inferring
        return null;
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 24 with Functional

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

the class ExpressionVisitor method visitDirectInvocation.

/**
 * Typecheck a direct invocation.
 */
private void visitDirectInvocation(Tree.InvocationExpression that) {
    Tree.Term primary = unwrapExpressionUntilTerm(that.getPrimary());
    if (primary == null) {
        return;
    }
    Tree.MemberOrTypeExpression mte = (Tree.MemberOrTypeExpression) primary;
    Reference prf = mte.getTarget();
    Declaration dec = mte.getDeclaration();
    Functional fun = (Functional) dec;
    if (dec != null) {
        if (!(primary instanceof Tree.ExtendedTypeExpression)) {
            if (dec instanceof Class) {
                Class c = (Class) dec;
                if (c.isAbstract()) {
                    that.addError("abstract class may not be instantiated: '" + dec.getName(unit) + "'");
                }
            }
        }
        Tree.NamedArgumentList nal = that.getNamedArgumentList();
        if (nal != null && dec.isAbstraction()) {
            // TODO: this is not really right - it's the fact
            // that we're calling Java and don't have
            // meaningful parameter names that is the
            // real problem, not the overload
            that.addError("overloaded declarations may not be called using named arguments: '" + dec.getName(unit) + "'");
        }
        // that.setTypeModel(prf.getType());
        Type ct = primary.getTypeModel();
        if (ct != null) {
            List<Type> tal = ct.getTypeArgumentList();
            if (!tal.isEmpty()) {
                // pull the return type out of the Callable
                that.setTypeModel(tal.get(0));
            }
        }
        if (nal != null) {
            List<ParameterList> parameterLists = fun.getParameterLists();
            if (!parameterLists.isEmpty() && !parameterLists.get(0).isNamedParametersSupported()) {
                that.addError("named invocations of Java methods not supported");
            }
        }
        if (dec.isAbstraction()) {
        // nothing to check the argument types against
        // that.addError("no matching overloaded declaration");
        } else {
            // typecheck arguments using the parameter list
            // of the target declaration
            checkInvocationArguments(that, prf, fun);
        }
    }
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ModelUtil.findMatchingOverloadedClass(org.eclipse.ceylon.model.typechecker.model.ModelUtil.findMatchingOverloadedClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 25 with Functional

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

the class ExpressionVisitor method inferParameterTypes.

/**
 * Infer parameter types for an anonymous function.
 */
private boolean inferParameterTypes(Reference pr, Parameter param, Tree.Expression e, boolean variadic, boolean error) {
    FunctionOrValue model = param.getModel();
    if (e != null && model != null) {
        Tree.Term term = unwrapExpressionUntilTerm(e.getTerm());
        TypedReference tpr = pr.getTypedParameter(param);
        if (term instanceof Tree.InvocationExpression) {
            Tree.InvocationExpression ie = (Tree.InvocationExpression) term;
            Tree.PositionalArgumentList pal = ie.getPositionalArgumentList();
            Tree.NamedArgumentList nal = ie.getNamedArgumentList();
            if (pal != null && pal.getPositionalArguments().isEmpty() || nal != null && nal.getNamedArguments().isEmpty()) {
                term = ie.getPrimary();
            }
        }
        if (term instanceof Tree.FunctionArgument) {
            Tree.FunctionArgument anon = (Tree.FunctionArgument) term;
            if (model instanceof Functional) {
                // and could be removed
                return inferParameterTypesFromCallableParameter(pr, param, anon, error);
            } else {
                Type paramType = tpr.getFullType();
                if (variadic) {
                    paramType = unit.getIteratedType(paramType);
                }
                paramType = callableFromUnion(paramType);
                if (unit.isCallableType(paramType)) {
                    return inferParameterTypesFromCallableType(paramType, param, anon, error);
                }
            }
        }
    }
    return true;
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

Functional (org.eclipse.ceylon.model.typechecker.model.Functional)58 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)30 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)28 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)27 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)25 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)24 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)24 Type (org.eclipse.ceylon.model.typechecker.model.Type)22 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)13 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)13 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)12 Value (org.eclipse.ceylon.model.typechecker.model.Value)12 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)11 Class (org.eclipse.ceylon.model.typechecker.model.Class)11 Function (org.eclipse.ceylon.model.typechecker.model.Function)11 Reference (org.eclipse.ceylon.model.typechecker.model.Reference)11 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)10 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 AnalyzerUtil.checkCasesDisjoint (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint)8