final int minimumTupleArguments = typeFact().getTupleMinimumLength(tupleArgument.getTypeModel());
final boolean tupleUnbounded = typeFact().isTupleLengthUnbounded(tupleArgument.getTypeModel());
final ProducedType callableType = invocation.getPrimary().getTypeModel().getFullType();
// Only evaluate the tuple expr once
SyntheticName tupleAlias = naming.alias("tuple");
JCExpression tupleType;
JCExpression tupleExpr = transformExpression(tupleArgument, BoxingStrategy.BOXED, null);
tupleType = makeJavaType(typeFact().getSequentialDeclaration().getType(), JT_RAW);
tupleExpr = make().TypeCast(makeJavaType(typeFact().getSequentialDeclaration().getType(), JT_RAW), tupleExpr);
callBuilder.appendStatement(makeVar(tupleAlias, tupleType, tupleExpr));
if (callBuilder.getArgumentHandling() == 0) {
// XXX Hack: Only do this if we're not already doing
// something funky with arguments e.g. SpreadOp
callBuilder.argumentHandling(CallBuilder.CB_LET, naming.alias("spreadarg"));
}
callBuilder.voidMethod(invocation.getReturnType() == null
|| Decl.isUnboxedVoid(invocation.getPrimaryDeclaration()));
/* Cases:
*[] -> () => nothing
*[] -> (Integer=) => nothing
*[] -> (Integer*) => nothing
*[Integer] -> (Integer) => extract
*[Integer] -> (Integer=) => extract
*[Integer] -> (Integer*) => pass the tuple as-is
*[Integer*] -> (Integer*) => pass the tuple as-is
*[Integer+] -> (Integer*) => pass the tuple as-is
*[Integer] -> (Integer, Integer*) => extract and drop the tuple
*[Integer,Integer] -> (Integer, Integer) => extract
*[Integer,Integer] -> (Integer=, Integer=) => extract
*[Integer,Integer] -> (Integer, Integer*) => extract and pass the tuple rest
*[Integer,Integer*] -> (Integer, Integer*) => extract and pass the tuple rest
*[Integer,Integer+] -> (Integer, Integer*) => extract and pass the tuple rest
*/
int spreadArgIndex = argIndex;
final int maxParameters = getNumParametersOfCallable(callableType);
boolean variadic = maxParameters > 0 && invocation.isParameterSequenced(maxParameters-1);
// we extract from the tuple not more than we have tuple members, but even less than that if we don't
// have enough parameters to put them in
final int argumentsToExtract = Math.min(argIndex + minimumTupleArguments, variadic ? maxParameters - 1 : maxParameters);
for (; spreadArgIndex < argumentsToExtract; spreadArgIndex++) {
boxingStrategy = invocation.getParameterBoxingStrategy(spreadArgIndex);
ProducedType paramType = getParameterTypeOfCallable(callableType, spreadArgIndex);
JCExpression tupleIndex = boxType(make().Literal((long)spreadArgIndex-argIndex),
typeFact().getIntegerDeclaration().getType());
JCExpression tupleElement = make().Apply(null,
naming.makeQualIdent(tupleAlias.makeIdent(), "get"),
List.<JCExpression>of(tupleIndex));
tupleElement = applyErasureAndBoxing(tupleElement,
typeFact().getAnythingDeclaration().getType(),
true, boxingStrategy, paramType);
JCExpression argType = makeJavaType(paramType, boxingStrategy == BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0);
result = result.append(new ExpressionAndType(tupleElement, argType));
}
// if we're variadic AND
// - the tuple is unbounded (which means we must have an unknown number of elements left to pass)
// - OR the tuple is bounded but we did not pass them all
if (variadic
&& (tupleUnbounded || argumentsToExtract < (minimumTupleArguments + argIndex))) {
boxingStrategy = invocation.getParameterBoxingStrategy(spreadArgIndex);
ProducedType paramType = getParameterTypeOfCallable(callableType, spreadArgIndex);
JCExpression tupleElement = tupleAlias.makeIdent();
// argIndex = 1, tuple = [Integer], params = [Integer, Integer*], spreadArgIndex = 1 => no span
// argIndex = 0, tuple = [Integer+], params = [Integer, Integer*], spreadArgIndex = 1 => spanFrom(1)
if(spreadArgIndex - argIndex > 0){
JCExpression tupleIndex = boxType(make().Literal((long)spreadArgIndex-argIndex),
typeFact().getIntegerDeclaration().getType());