use of ceylon.language.meta.model.InvocationException in project ceylon by eclipse.
the class Metamodel method namedApply.
public static <Return> Return namedApply(Callable<? extends Return> function, DefaultValueProvider defaultValueProvider, org.eclipse.ceylon.model.typechecker.model.Functional declaration, ceylon.language.Iterable<? extends ceylon.language.Entry<? extends ceylon.language.String, ? extends java.lang.Object>, ? extends java.lang.Object> arguments, List<Type> parameterProducedTypes) {
// FIXME: throw for Java declarations
java.util.Map<java.lang.String, java.lang.Object> argumentMap = collectArguments(arguments);
java.util.List<Parameter> parameters = declaration.getFirstParameterList().getParameters();
// store the values in an array
Array<java.lang.Object> values = new Array<java.lang.Object>(Anything.$TypeDescriptor$, parameters.size(), (java.lang.Object) null);
int parameterIndex = 0;
for (Parameter parameter : parameters) {
// get the parameter value and remove it so we can keep track of those we used
java.lang.Object value;
if (argumentMap.containsKey(parameter.getName())) {
value = argumentMap.remove(parameter.getName());
// we have a value: check the type
Type argumentType = Metamodel.getProducedType(value);
Type parameterType = parameterProducedTypes.get(parameterIndex);
if (!argumentType.isSubtypeOf(parameterType))
throw new ceylon.language.meta.model.IncompatibleTypeException("Invalid argument " + parameter.getName() + ", expected type " + parameterType + " but got " + argumentType);
} else {
// make sure it has a default value
if (!parameter.isDefaulted())
throw new InvocationException("Missing value for non-defaulted parameter " + parameter.getName());
// we need to fetch the default value
value = defaultValueProvider.getDefaultParameterValue(parameter, values, parameterIndex);
argumentMap.remove(parameter.getName());
}
values.set(parameterIndex++, value);
}
// do we have extra unknown/unused parameters left?
if (!argumentMap.isEmpty()) {
for (String name : argumentMap.keySet()) {
throw new InvocationException("No such parameter " + name);
}
}
// FIXME: don't we need to spread any variadic param?
// now do a regular invocation
Sequential<? extends Object> argumentSequence = values.sequence();
// we can trust any variadic or pseudo-variadic since we checked parameter by parameter (no spreading possible)
return Util.apply(function, argumentSequence, null);
}
use of ceylon.language.meta.model.InvocationException in project ceylon by eclipse.
the class Metamodel method apply.
public static <Return> Return apply(Callable<? extends Return> function, Sequential<?> arguments, List<Type> parameterProducedTypes, int firstDefaulted, int variadicIndex) {
int argumentCount = Util.toInt(arguments.getSize());
int parameters = parameterProducedTypes.size();
// check minimum
if (firstDefaulted == -1) {
if (argumentCount < parameters)
throw new InvocationException("Not enough arguments to function. Expected " + parameters + " but got only " + argumentCount);
} else if (argumentCount < firstDefaulted)
throw new InvocationException("Not enough arguments to function. Expected at least " + firstDefaulted + " but got only " + argumentCount);
// check maximum
if (variadicIndex == -1) {
if (argumentCount > parameters)
throw new InvocationException("To many arguments to function. Expected at most " + parameters + " but got " + argumentCount);
}
// if we're variadic we accept any number
// now check their types
Iterator<?> it = arguments.iterator();
Object arg;
int i = 0;
Type variadicElement = null;
if (variadicIndex != -1)
// it must be a Sequential<T>
variadicElement = parameterProducedTypes.get(variadicIndex).getTypeArgumentList().get(0);
while ((arg = it.next()) != finished_.get_()) {
Type parameterType = variadicIndex == -1 || i < variadicIndex ? // normal param
parameterProducedTypes.get(i) : // variadic param
variadicElement;
Type argumentType = Metamodel.getProducedType(arg);
if (!argumentType.isSubtypeOf(parameterType))
throw new IncompatibleTypeException("Invalid argument " + i + ", expected type " + parameterType + " but got " + argumentType);
i++;
}
// they are all good, let's call it
TypeDescriptor variadicElementType = variadicElement != null ? Metamodel.getTypeDescriptorForProducedType(variadicElement) : null;
return Util.apply(function, arguments, variadicElementType);
}
Aggregations