use of org.eclipse.ceylon.model.typechecker.model.ParameterList in project ceylon by eclipse.
the class ExpressionVisitor method setArgumentParameters.
/**
* Set up references from positional arguments to
* parameters for later use during type inference. This
* is only necessary here because in the case of an
* overloaded Java function or constructors, the
* overload has not been resolved the first time we
* visit the arguments. So we need to revisit them here
* with the fully-resolved overloaded version.
*
* @param that an invocation
* @param invoked the thing being invoked
*/
private void setArgumentParameters(Tree.InvocationExpression that, Declaration invoked) {
if (invoked instanceof Functional) {
Functional fun = (Functional) invoked;
List<ParameterList> pls = fun.getParameterLists();
if (!pls.isEmpty()) {
ParameterList pl = pls.get(0);
// no need to do named arg lists because
// they can't be used with overloaded decs
Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
if (pal != null) {
List<Tree.PositionalArgument> args = pal.getPositionalArguments();
List<Parameter> params = pl.getParameters();
for (int i = 0, j = 0; i < args.size() && j < params.size(); i++) {
Tree.PositionalArgument arg = args.get(i);
Parameter param = params.get(j);
if (arg != null && param != null) {
arg.setParameter(param);
}
if (param == null || !param.isSequenced()) {
j++;
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.ParameterList in project ceylon by eclipse.
the class ExpressionVisitor method checkClassAliasParameters.
private void checkClassAliasParameters(Class alias, Tree.ClassDeclaration that, Tree.InvocationExpression ie) {
Tree.Primary primary = ie.getPrimary();
Tree.ExtendedTypeExpression smte = (Tree.ExtendedTypeExpression) primary;
Functional classOrConstructor = (Functional) smte.getDeclaration();
ParameterList cpl = classOrConstructor.getFirstParameterList();
ParameterList apl = alias.getParameterList();
if (cpl != null && apl != null) {
List<Parameter> cplps = cpl.getParameters();
List<Parameter> aplps = apl.getParameters();
int cps = cplps.size();
int aps = aplps.size();
if (cps != aps) {
that.getParameterList().addUnsupportedError("wrong number of initializer parameters declared by class alias: '" + alias.getName() + "'");
}
for (int i = 0; i < cps && i < aps; i++) {
Parameter ap = aplps.get(i);
Parameter cp = cplps.get(i);
Reference target = smte.getTarget();
FunctionOrValue apm = ap.getModel();
if (apm != null && target != null) {
Type pt = target.getTypedParameter(cp).getFullType();
Type apt = apm.getReference().getFullType();
if (!isTypeUnknown(pt) && !isTypeUnknown(apt) && !apt.isSubtypeOf(pt)) {
that.addUnsupportedError("alias parameter '" + ap.getName() + "' must be assignable to corresponding class parameter '" + cp.getName() + "'" + notAssignableMessage(apt, pt, that));
}
}
}
// temporary restrictions
checkAliasedClass(that, cpl, apl);
}
}
use of org.eclipse.ceylon.model.typechecker.model.ParameterList in project ceylon by eclipse.
the class RefinementVisitor method refineMethod.
private void refineMethod(Function assignedMethod, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedMethod.isFormal() && !assignedMethod.isDefault() && !assignedMethod.isShortcutRefinement()) {
// this condition is here to squash a dupe message
bme.addError("inherited method may not be refined: " + message(assignedMethod) + " is declared neither 'formal' nor 'default'", 510);
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedMethod.getContainer();
String name = assignedMethod.getName();
List<Type> signature = getSignature(assignedMethod);
boolean variadic = isVariadic(assignedMethod);
Declaration refined = ci.getRefinedMember(name, signature, variadic);
Function root = refined instanceof Function ? (Function) refined : assignedMethod;
Reference rm = getRefinedMemberReference(assignedMethod, c);
Function method = new Function();
method.setName(name);
List<Tree.ParameterList> paramLists;
List<TypeParameter> typeParams;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
paramLists = pe.getParameterLists();
Tree.TypeParameterList typeParameterList = pe.getTypeParameterList();
if (typeParameterList != null) {
typeParams = new ArrayList<TypeParameter>();
for (Tree.TypeParameterDeclaration tpd : typeParameterList.getTypeParameterDeclarations()) {
typeParams.add(tpd.getDeclarationModel());
}
} else {
typeParams = null;
}
} else {
paramLists = emptyList();
typeParams = null;
}
Unit unit = that.getUnit();
final Map<TypeParameter, Type> subs;
if (typeParams != null) {
// the type parameters are written
// down in the shortcut refinement
method.setTypeParameters(typeParams);
// TODO: check 'em!!
// no need to check them because
// this case is actually disallowed
// elsewhere (specification statements
// may not have type parameters)
subs = NO_SUBSTITUTIONS;
} else if (assignedMethod.isParameterized()) {
if (me instanceof Tree.ParameterizedExpression) {
// we have parameters, but no type parameters
bme.addError("refined method is generic: '" + assignedMethod.getName(unit) + "' declares type parameters");
subs = NO_SUBSTITUTIONS;
} else {
// we're assigning a method reference
// so we need to magic up some "fake"
// type parameters
subs = copyTypeParametersFromRefined(assignedMethod, method, unit);
}
} else {
subs = NO_SUBSTITUTIONS;
}
int i = 0;
for (ParameterList pl : assignedMethod.getParameterLists()) {
Tree.ParameterList params = paramLists.size() <= i ? null : paramLists.get(i++);
createRefiningParameterList(rm, method, params, unit, subs, pl);
}
method.setShared(true);
method.setActual(true);
method.getAnnotations().add(new Annotation("shared"));
method.getAnnotations().add(new Annotation("actual"));
method.setRefinedDeclaration(root);
method.setUnit(unit);
method.setContainer(c);
method.setScope(c);
method.setShortcutRefinement(true);
method.setDeclaredVoid(assignedMethod.isDeclaredVoid());
Declaration rmd = rm.getDeclaration();
if (rmd instanceof TypedDeclaration) {
TypedDeclaration rmtd = (TypedDeclaration) rmd;
method.setUncheckedNullType(rmtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(method);
c.addMember(method);
that.setRefinement(true);
that.setDeclaration(method);
that.setRefined(root);
unit.addDeclaration(method);
Scope scope = that.getScope();
if (scope instanceof Specification) {
Specification spec = (Specification) scope;
spec.setDeclaration(method);
}
setRefiningType(c, ci, name, signature, variadic, root, method, unit, subs);
inheritDefaultedArguments(method);
}
use of org.eclipse.ceylon.model.typechecker.model.ParameterList in project ceylon by eclipse.
the class TypeArgumentInference method inferFunctionRefTypeArgs.
/**
* Infer type arguments for a direct function
* ref (i.e. not a value ref with a type
* constructor type) that occurs as an argument
* to a callable parameter.
*/
private List<Type> inferFunctionRefTypeArgs(Tree.StaticMemberOrTypeExpression smte, Type receiverType, boolean secondList, Declaration reference, List<TypeParameter> typeParameters, TypedReference paramTypedRef, Declaration paramDec, Declaration parameterizedDec) {
Reference arg = appliedReference(smte);
Functional fun = (Functional) reference;
List<ParameterList> apls = fun.getParameterLists();
Functional pfun = (Functional) paramDec;
List<ParameterList> ppls = pfun.getParameterLists();
if (apls.isEmpty() || ppls.isEmpty()) {
// TODO: to give a nicer error
return null;
} else {
ParameterList aplf = apls.get(secondList ? 1 : 0);
ParameterList pplf = ppls.get(0);
List<Parameter> apl = aplf.getParameters();
List<Parameter> ppl = pplf.getParameters();
boolean[] specifiedParams = specifiedParameters(apl.size(), ppl.size());
List<Type> inferredTypes = new ArrayList<Type>(typeParameters.size());
for (TypeParameter tp : typeParameters) {
boolean findUpperBounds = isEffectivelyContravariant(tp, reference, specifiedParams, secondList);
Type it = inferFunctionRefTypeArg(smte, tp, typeParameters, paramTypedRef, parameterizedDec, arg, apl, ppl, findUpperBounds);
inferredTypes.add(it);
}
return constrainInferredTypes(typeParameters, inferredTypes, receiverType, reference);
}
}
use of org.eclipse.ceylon.model.typechecker.model.ParameterList in project ceylon by eclipse.
the class TypeArgumentInference method getInferredTypeArgsForReference.
/**
* Infer type arguments for a given generic declaration,
* using the value arguments of an invocation of a given
* declaration.
*
* @param that the invocation
* @param invoked the thing actually being invoked
* @param generic the thing we're inferring type
* arguments for, which may not be the thing
* actually being invoked
* @param receiverType
*
* @return a list of inferred type arguments
*/
List<Type> getInferredTypeArgsForReference(Tree.InvocationExpression that, Declaration invoked, Declaration generic, Type receiverType) {
if (invoked instanceof Functional) {
Functional functional = (Functional) invoked;
List<ParameterList> parameterLists = functional.getParameterLists();
if (parameterLists.isEmpty()) {
return null;
} else {
List<Type> typeArgs = new ArrayList<Type>();
List<TypeParameter> typeParameters = generic.getTypeParameters();
for (TypeParameter tp : typeParameters) {
ParameterList pl = parameterLists.get(0);
Type it = inferTypeArgument(that, receiverType, tp, pl, invoked);
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(typeParameters, typeArgs, receiverType, invoked);
}
} else {
return null;
}
}
Aggregations