// Other args begin at index 0
int argIndex = 0;
// Pre(-opt and rest) required args
ListNode preArgs = argsNode.getPre();
for (int i = 0; i < numPreReqd; i++, argIndex++) {
receiveRequiredArg(preArgs.get(i), s, argIndex, false, -1, -1);
}
// Fixup opt/rest
opt = opt > 0 ? opt : 0;
rest = rest > -1 ? 1 : 0;
// Now for opt args
if (opt > 0) {
ListNode optArgs = argsNode.getOptArgs();
for (int j = 0; j < opt; j++, argIndex++) {
// Jump to 'l' if this arg is not null. If null, fall through and build the default value!
Label l = s.getNewLabel();
OptArgNode n = (OptArgNode)optArgs.get(j);
String argName = n.getName();
Variable av = s.getNewLocalVariable(argName, 0);
if (s instanceof IRMethod) ((IRMethod)s).addArgDesc("opt", argName);
// You need at least required+j+1 incoming args for this opt arg to get an arg at all
s.addInstr(new ReceiveOptArgInstr19(av, argIndex, required+j+1));
s.addInstr(BNEInstr.create(av, UndefinedValue.UNDEFINED, l)); // if 'av' is not undefined, go to default
build(n.getValue(), s);
s.addInstr(new LabelInstr(l));
}
}
// Rest arg
if (rest > 0) {
// Consider: def foo(*); .. ; end
// For this code, there is no argument name available from the ruby code.
// So, we generate an implicit arg name
String argName = argsNode.getRestArgNode().getName();
if (s instanceof IRMethod) ((IRMethod)s).addArgDesc("rest", argName == null ? "" : argName);
argName = (argName == null || argName.equals("")) ? "%_arg_array" : argName;
// You need at least required+opt+1 incoming args for the rest arg to get any args at all
// If it is going to get something, then it should ignore required+opt args from the beginning
// because they have been accounted for already.
s.addInstr(new ReceiveRestArgInstr19(s.getNewLocalVariable(argName, 0), argIndex, required, opt));
argIndex++;
}
// Post(-opt and rest) required args
ListNode postArgs = argsNode.getPost();
for (int i = 0; i < numPostReqd; i++) {
receiveRequiredArg(postArgs.get(i), s, i, true, numPreReqd, numPostReqd);
}
// Now, receive the block arg
// -- for methods, we always receive it (implicitly, if the block arg is not explicit)
// -- for closures, only if it is explicitly present