Skip to content

Commit

Permalink
Simplify processing logic of a single incoming argument in a proc to …
Browse files Browse the repository at this point in the history
…spread

that argument if there are multiple required arguments.

In truth, I was hoping to move away from ever using arityValue in backend
logic past arity() itself.  In fact required() (+ 1 if reqdkwarg) I think
is what we really care about at this point but for the lack of a better name
this is '(arityValue < -1 || arityValue > 1)' atm.  Another reason for not
going further is that in lambda processing we have very similar but slightly
different conditional.  I think this check is right as it says: we have at
least 2 parameters which must be filled and we are only passing one...try
and spread that arg.

The second part was to expost toAry() to be public.

I have pretty reasonable confidence level that the convoluted form-fit we have
before boils to this.  It also makes logical sense as well based on how Ruby
spreads arguments.
enebo committed Dec 5, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent ec525af commit 155ced6
Showing 2 changed files with 7 additions and 27 deletions.
32 changes: 6 additions & 26 deletions core/src/main/java/org/jruby/RubyProc.java
Original file line number Diff line number Diff line change
@@ -36,14 +36,14 @@

import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.IRBlockBody;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.Signature;
import org.jruby.runtime.ThreadContext;
@@ -265,34 +265,14 @@ public static IRubyObject[] prepareArgs(ThreadContext context, Block.Type type,
return args;
}

boolean isFixed = signature.isFixed();
int required = signature.required();
int actual = args.length;
boolean kwargs = blockBody instanceof IRBlockBody && signature.hasKwargs();

// FIXME: This is a hot mess. kwargs factors into destructing a single element array as well. I just weaved it into this logic.
// FIXME: weirdly nearly identical logic exists in prepareBlockArgsInternal but only for lambdas.
// for procs and blocks, single array passed to multi-arg must be spread
if ((signature != Signature.ONE_ARGUMENT && required != 0 && (isFixed || signature != Signature.OPTIONAL) || kwargs) &&
actual == 1 && args[0].respondsTo("to_ary")) {
IRubyObject newAry = Helpers.aryToAry(args[0]);

// This is very common to yield in *IRBlockBody. When we tackle call protocol for blocks this will combine.
if (newAry.isNil()) {
args = new IRubyObject[] { args[0] };
} else if (newAry instanceof RubyArray){
args = ((RubyArray) newAry).toJavaArrayMaybeUnsafe();
} else {
throw context.runtime.newTypeError(args[0].getType().getName() + "#to_ary should return Array");
}
actual = args.length;
}
int arityValue = signature.arityValue();
if (args.length == 1 && (arityValue < -1 || arityValue > 1)) args = IRRuntimeHelpers.toAry(context, args);

// FIXME: This pruning only seems to be needed for any?/all? specs.
// FIXME: This pruning only seems to be needed for calls through java block/calls CallBlock/JavaInternalBlockBody (move to those since pure-Ruby does not seem to need this.
// fixed arity > 0 with mismatch needs a new args array
int kwargsHackRequired = required + (kwargs ? 1 : 0);
if (isFixed && required > 0 && kwargsHackRequired != actual) {
args = ArraySupport.newCopy(args, kwargsHackRequired);
}
if (arityValue > 0 && arityValue != args.length) args = ArraySupport.newCopy(args, arityValue);

return args;
}
Original file line number Diff line number Diff line change
@@ -1631,7 +1631,7 @@ public static RubyFixnum getArgScopeDepth(ThreadContext context, StaticScope cur
return context.runtime.newFixnum(i);
}

private static IRubyObject[] toAry(ThreadContext context, IRubyObject[] args) {
public static IRubyObject[] toAry(ThreadContext context, IRubyObject[] args) {
if (args.length == 1 && args[0].respondsTo("to_ary")) {
IRubyObject newAry = Helpers.aryToAry(args[0]);
if (newAry.isNil()) {

0 comments on commit 155ced6

Please sign in to comment.