final boolean forceSequenced, final boolean generateVars) {
if (!args.isEmpty()) {
final List<String> argvars = new ArrayList<String>(args.size());
boolean first=true;
boolean opened=false;
ProducedType sequencedType=null;
for (Tree.PositionalArgument arg : args) {
Tree.Expression expr;
final Parameter pd = arg.getParameter();
if (arg instanceof Tree.ListedArgument) {
if (!first) gen.out(",");
expr = ((Tree.ListedArgument) arg).getExpression();
ProducedType exprType = expr.getTypeModel();
boolean dyncheck = gen.isInDynamicBlock() && pd != null && !Util.isTypeUnknown(pd.getType())
&& exprType.containsUnknowns();
if (forceSequenced || (pd != null && pd.isSequenced())) {
if (dyncheck) {
//We don't have a real type so get the one declared in the parameter
exprType = pd.getType();
}
if (sequencedType == null) {
sequencedType=exprType;
} else {
ArrayList<ProducedType> cases = new ArrayList<ProducedType>(2);
Util.addToUnion(cases, sequencedType);
Util.addToUnion(cases, exprType);
if (cases.size() > 1) {
UnionType ut = new UnionType(that.getUnit());
ut.setCaseTypes(cases);
sequencedType = ut.getType();
} else {
sequencedType = cases.get(0);
}
}
if (!opened) {
if (generateVars) {
final String argvar = names.createTempVariable();
argvars.add(argvar);
gen.out(argvar, "=");
}
gen.out("[");
}
opened=true;
} else if (generateVars) {
final String argvar = names.createTempVariable();
argvars.add(argvar);
gen.out(argvar, "=");
}
final int boxType = pd==null?0:gen.boxUnboxStart(expr.getTerm(), pd.getModel());
if (dyncheck) {
Map<TypeParameter,ProducedType> targs = null;
if (primary instanceof Tree.MemberOrTypeExpression) {
targs = ((Tree.MemberOrTypeExpression)primary).getTarget().getTypeArguments();
}
TypeUtils.generateDynamicCheck(expr, pd.getType(), gen, false, targs);
} else {
arg.visit(gen);
}
if (boxType == 4) {
gen.out(",");
//Add parameters
describeMethodParameters(expr.getTerm());
gen.out(",");
TypeUtils.printTypeArguments(arg, arg.getTypeModel().getTypeArguments(), gen, false,
arg.getTypeModel().getVarianceOverrides());
}
gen.boxUnboxEnd(boxType);
} else if (arg instanceof Tree.SpreadArgument || arg instanceof Tree.Comprehension) {
if (arg instanceof Tree.SpreadArgument) {
expr = ((Tree.SpreadArgument) arg).getExpression();
} else {
expr = null;
}
if (opened) {
SequenceGenerator.closeSequenceWithReifiedType(that,
gen.getTypeUtils().wrapAsIterableArguments(sequencedType), gen);
gen.out(".chain(");
sequencedType=null;
} else if (!first) {
gen.out(",");
}
if (arg instanceof Tree.SpreadArgument) {
TypedDeclaration td = pd == null ? null : pd.getModel();
int boxType = gen.boxUnboxStart(expr.getTerm(), td);
if (boxType == 4) {
arg.visit(gen);
gen.out(",");
describeMethodParameters(expr.getTerm());
gen.out(",");
TypeUtils.printTypeArguments(arg, arg.getTypeModel().getTypeArguments(), gen, false,
arg.getTypeModel().getVarianceOverrides());
} else if (pd == null) {
if (gen.isInDynamicBlock() && primary instanceof Tree.MemberOrTypeExpression
&& ((Tree.MemberOrTypeExpression)primary).getDeclaration() == null
&& arg.getTypeModel() != null && arg.getTypeModel().getDeclaration().inherits((gen.getTypeUtils().tuple))) {
//Spread dynamic parameter
ProducedType tupleType = arg.getTypeModel();
ProducedType targ = tupleType.getTypeArgumentList().get(2);
arg.visit(gen);
gen.out(".$_get(0)");
int i = 1;
while (!targ.getDeclaration().inherits(gen.getTypeUtils().empty)) {
gen.out(",");
arg.visit(gen);
gen.out(".$_get("+(i++)+")");
targ = targ.getTypeArgumentList().get(2);
}
} else {
arg.visit(gen);
}
} else if (pd.isSequenced()) {
arg.visit(gen);
} else {
final String specialSpreadVar = gen.getNames().createTempVariable();
gen.out("(", specialSpreadVar, "=");
args.get(args.size()-1).visit(gen);
gen.out(".sequence(),");
if (pd.isDefaulted()) {
gen.out(gen.getClAlias(), "nn$(",
specialSpreadVar, ".$_get(0))?", specialSpreadVar,
".$_get(0):undefined)");
} else {
gen.out(specialSpreadVar, ".$_get(0))");
}
//Find out if there are more params
final List<Parameter> moreParams;
final Declaration pdd = pd.getDeclaration();
boolean found = false;
if (pdd instanceof Method) {
moreParams = ((Method)pdd).getParameterLists().get(0).getParameters();
} else if (pdd instanceof com.redhat.ceylon.compiler.typechecker.model.Class) {
moreParams = ((com.redhat.ceylon.compiler.typechecker.model.Class)pdd).getParameterList().getParameters();
} else {
//Check the parameters of the primary (obviously a callable, so this is a Tuple)
List<Parameter> cparms = gen.getTypeUtils().convertTupleToParameters(
primary.getTypeModel().getTypeArgumentList().get(1));
cparms.remove(0);
moreParams = cparms;
found = true;
}
if (moreParams != null) {
int c = 1;
for (Parameter restp : moreParams) {
if (found) {
final String cs=Integer.toString(c++);
if (restp.isDefaulted()) {
gen.out(",", gen.getClAlias(), "nn$(", specialSpreadVar,
".$_get(", cs, "))?", specialSpreadVar, ".$_get(", cs, "):undefined");
} else {
gen.out(",", specialSpreadVar, ".$_get(", cs, ")");
}
} else {
found = restp.equals(pd);
}
}
}
}
gen.boxUnboxEnd(boxType);
} else {
((Tree.Comprehension)arg).visit(gen);
}
if (opened) {
gen.out(",");
if (expr == null) {
//it's a comprehension
TypeUtils.printTypeArguments(that,
gen.getTypeUtils().wrapAsIterableArguments(arg.getTypeModel()), gen, false, null);
} else {
ProducedType spreadType = TypeUtils.findSupertype(gen.getTypeUtils().sequential,
expr.getTypeModel());
if (spreadType == null) {
//Go directly to Iterable
spreadType = TypeUtils.findSupertype(gen.getTypeUtils().iterable, expr.getTypeModel());
}
TypeUtils.printTypeArguments(that, spreadType.getTypeArguments(), gen, false,
spreadType.getVarianceOverrides());
}
gen.out(")");
}
if (arg instanceof Tree.Comprehension) {
break;