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");
}
}
}
}
}
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;
}
}
}
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;
}
}
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);
}
}
}
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;
}
Aggregations