Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 105 additions & 93 deletions core/src/main/java/org/jruby/RubyArray.java

Large diffs are not rendered by default.

18 changes: 8 additions & 10 deletions core/src/main/java/org/jruby/RubyChain.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.jruby.anno.JRubyMethod;

import org.jruby.runtime.Block;
import org.jruby.RubyFixnum;

import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
Expand Down Expand Up @@ -94,7 +93,7 @@ public static RubyChain newChain(ThreadContext context, IRubyObject[] enums) {
@JRubyMethod(rest = true)
public IRubyObject each(ThreadContext context, IRubyObject[] args, Block block) {
if (!block.isGiven()) {
return RubyEnumerator.enumeratorizeWithSize(context, this, "each", args, enumSizeFn(context));
return RubyEnumerator.enumeratorizeWithSize(context, this, "each", args, RubyChain::size);
}

for (int i = 0; i < enums.length; i++) {
Expand All @@ -105,14 +104,13 @@ public IRubyObject each(ThreadContext context, IRubyObject[] args, Block block)
return this;
}

private SizeFn enumSizeFn(final ThreadContext context) {
final RubyChain self = this;
return new SizeFn() {
@Override
public IRubyObject size(ThreadContext context, IRubyObject[] args) {
return self.size(context);
}
};
/**
* A size method suitable for lambda method reference implementation of {@link SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])}
*
* @see SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])
*/
private static IRubyObject size(ThreadContext context, RubyChain self, IRubyObject[] args) {
return self.size(context);
}

// enum_chain_rewind
Expand Down
173 changes: 93 additions & 80 deletions core/src/main/java/org/jruby/RubyEnumerable.java

Large diffs are not rendered by default.

41 changes: 19 additions & 22 deletions core/src/main/java/org/jruby/RubyEnumerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ private RubyEnumerator(Ruby runtime, RubyClass type, IRubyObject object, IRubyOb
/**
* Transform object into an Enumerator with the given size
*/
public static IRubyObject enumeratorizeWithSize(ThreadContext context, final IRubyObject object, String method, IRubyObject[] args, SizeFn sizeFn) {
public static <T extends IRubyObject> IRubyObject enumeratorizeWithSize(ThreadContext context, final T object, String method, IRubyObject[] args, SizeFn<T> sizeFn) {
Ruby runtime = context.runtime;
return new RubyEnumerator(runtime, runtime.getEnumerator(), object, runtime.fastNewSymbol(method), args, null, sizeFn);
}

public static IRubyObject enumeratorizeWithSize(ThreadContext context, IRubyObject object, String method, SizeFn sizeFn) {
public static <T extends IRubyObject> IRubyObject enumeratorizeWithSize(ThreadContext context, T object, String method, SizeFn<T> sizeFn) {
return enumeratorizeWithSize(context, object, method, NULL_ARRAY, sizeFn);
}

Expand Down Expand Up @@ -206,13 +206,7 @@ public static IRubyObject __from(ThreadContext context, IRubyObject klass, IRuby
RubyEnumerator instance = (RubyEnumerator) ((RubyClass) klass).allocate();

if (size == null) {
if (object instanceof RubyEnumerator) {
size = ((RubyEnumerator) object).size;
if (size != null && !size.respondsTo("call")) size = null;
sizeFn = ((RubyEnumerator) object).sizeFn;
} else {
sizeFn = RubyEnumerable.enumSizeFn(object);
}
sizeFn = RubyEnumerable::size;
}

instance.initialize(context.runtime, object, method, methodArgs, size, sizeFn);
Expand Down Expand Up @@ -487,12 +481,12 @@ protected static IRubyObject newEnumerator(ThreadContext context, IRubyObject ar
@JRubyMethod(required = 1)
public IRubyObject each_with_object(final ThreadContext context, IRubyObject arg, Block block) {
return block.isGiven() ? RubyEnumerable.each_with_objectCommon(context, this, block, arg) :
enumeratorizeWithSize(context, this, "each_with_object", new IRubyObject[]{arg}, enumSizeFn());
enumeratorizeWithSize(context, this, "each_with_object", new IRubyObject[]{arg}, RubyEnumerator::size);
}

@JRubyMethod
public IRubyObject with_object(ThreadContext context, final IRubyObject arg, final Block block) {
return block.isGiven() ? RubyEnumerable.each_with_objectCommon(context, this, block, arg) : enumeratorizeWithSize(context, this, "with_object", new IRubyObject[]{arg}, enumSizeFn());
return block.isGiven() ? RubyEnumerable.each_with_objectCommon(context, this, block, arg) : enumeratorizeWithSize(context, this, "with_object", new IRubyObject[]{arg}, RubyEnumerator::size);
}

@JRubyMethod(rest = true)
Expand Down Expand Up @@ -530,7 +524,7 @@ public IRubyObject each_cons(ThreadContext context, IRubyObject arg, final Block
@JRubyMethod
public final IRubyObject size(ThreadContext context) {
if (sizeFn != null) {
return sizeFn.size(context, methodArgs);
return sizeFn.size(context, object, methodArgs);
}

IRubyObject size = this.size;
Expand All @@ -543,9 +537,7 @@ public final IRubyObject size(ThreadContext context) {
return size;
}

if (context == null) context = metaClass.runtime.getCurrentContext();

return context.nil;
return metaClass.runtime.getNil();
}

public long size() {
Expand All @@ -556,17 +548,22 @@ public long size() {
return -1;
}

private SizeFn enumSizeFn() {
return (context, args) -> this.size(context);
/**
* A size method suitable for lambda method reference implementation of {@link SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])}
*
* @see SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])
*/
private static IRubyObject size(ThreadContext context, RubyEnumerator recv, IRubyObject[] args) {
return recv.size(context);
}

private IRubyObject with_index_common(ThreadContext context, final Block block, final String rubyMethodName, IRubyObject arg) {
final Ruby runtime = context.runtime;
final int index = arg.isNil() ? 0 : RubyNumeric.num2int(arg);
if ( ! block.isGiven() ) {
return arg.isNil() ?
enumeratorizeWithSize(context, this, rubyMethodName, enumSizeFn()) :
enumeratorizeWithSize(context, this, rubyMethodName, new IRubyObject[]{runtime.newFixnum(index)}, enumSizeFn());
enumeratorizeWithSize(context, this, rubyMethodName, RubyEnumerator::size) :
enumeratorizeWithSize(context, this, rubyMethodName, new IRubyObject[]{runtime.newFixnum(index)}, RubyEnumerator::size);
}

return RubyEnumerable.callEach(context, sites(context).each, this, new RubyEnumerable.EachWithIndex(block, index));
Expand Down Expand Up @@ -653,10 +650,10 @@ public Spliterator<Object> spliterator(final int mod) {
* SizeFn#size are kept in sync with the size of the created enum (i.e. if the object underlying an enumerator
* changes, calls to SizeFn#size should reflect that change).
*
* TODO (CON): fix this to receive context and state to we're not reallocating it all the time
* @param <T> the enumerated object's type
*/
public interface SizeFn {
IRubyObject size(ThreadContext context, IRubyObject[] args);
public interface SizeFn<T extends IRubyObject> {
IRubyObject size(ThreadContext context, T self, IRubyObject[] args);
}

private static JavaSites.FiberSites sites(ThreadContext context) {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.math.BigInteger;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.RubyEnumerator.SizeFn;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
Expand Down Expand Up @@ -293,7 +294,7 @@ public IRubyObject times(ThreadContext context, Block block) {
}
return this;
}
return RubyEnumerator.enumeratorizeWithSize(context, this, "times", timesSizeFn());
return RubyEnumerator.enumeratorizeWithSize(context, this, "times", RubyInteger::timesSize);
}
/** rb_fix_ceil
*
Expand Down
35 changes: 20 additions & 15 deletions core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
Expand Up @@ -930,8 +930,13 @@ public RubyFixnum rb_size(ThreadContext context) {
return context.runtime.newFixnum(size);
}

private SizeFn enumSizeFn() {
return (context, args) -> this.rb_size(context);
/**
* A size method suitable for lambda method reference implementation of {@link SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])}
*
* @see SizeFn#size(ThreadContext, IRubyObject, IRubyObject[])
*/
private static IRubyObject size(ThreadContext context, RubyHash recv, IRubyObject[] args) {
return recv.rb_size(context);
}

/** rb_hash_empty_p
Expand Down Expand Up @@ -1489,7 +1494,7 @@ public void visit(ThreadContext context, RubyHash self, IRubyObject key, IRubyOb

@JRubyMethod(name = {"each", "each_pair"})
public IRubyObject each(final ThreadContext context, final Block block) {
return block.isGiven() ? each_pairCommon(context, block) : enumeratorizeWithSize(context, this, "each", enumSizeFn());
return block.isGiven() ? each_pairCommon(context, block) : enumeratorizeWithSize(context, this, "each", RubyHash::size);
}

public IRubyObject each19(final ThreadContext context, final Block block) {
Expand Down Expand Up @@ -1530,7 +1535,7 @@ public void visit(ThreadContext context, RubyHash self, IRubyObject key, IRubyOb

@JRubyMethod
public IRubyObject each_value(final ThreadContext context, final Block block) {
return block.isGiven() ? each_valueCommon(context, block) : enumeratorizeWithSize(context, this, "each_value", enumSizeFn());
return block.isGiven() ? each_valueCommon(context, block) : enumeratorizeWithSize(context, this, "each_value", RubyHash::size);
}

/** rb_hash_each_key
Expand All @@ -1551,7 +1556,7 @@ public void visit(ThreadContext context, RubyHash self, IRubyObject key, IRubyOb

@JRubyMethod
public IRubyObject each_key(final ThreadContext context, final Block block) {
return block.isGiven() ? each_keyCommon(context, block) : enumeratorizeWithSize(context, this, "each_key", enumSizeFn());
return block.isGiven() ? each_keyCommon(context, block) : enumeratorizeWithSize(context, this, "each_key", RubyHash::size);
}

@JRubyMethod(name = "transform_keys")
Expand All @@ -1562,7 +1567,7 @@ public IRubyObject transform_keys(final ThreadContext context, final Block block
return result;
}

return enumeratorizeWithSize(context, this, "transform_keys", enumSizeFn());
return enumeratorizeWithSize(context, this, "transform_keys", RubyHash::size);
}

private static class TransformKeysVisitor extends VisitorWithState<RubyHash> {
Expand Down Expand Up @@ -1599,7 +1604,7 @@ public IRubyObject transform_keys_bang(final ThreadContext context, final Block
return this;
}

return enumeratorizeWithSize(context, this, "transform_keys!", enumSizeFn());
return enumeratorizeWithSize(context, this, "transform_keys!", RubyHash::size);
}

@JRubyMethod(name = "transform_values!")
Expand All @@ -1611,7 +1616,7 @@ public IRubyObject transform_values_bang(final ThreadContext context, final Bloc
return this;
}

return enumeratorizeWithSize(context, this, "transform_values!", enumSizeFn());
return enumeratorizeWithSize(context, this, "transform_values!", RubyHash::size);
}

private static class TransformValuesVisitor extends VisitorWithState<Block> {
Expand All @@ -1626,7 +1631,7 @@ public void visit(ThreadContext context, RubyHash self, IRubyObject key, IRubyOb
public IRubyObject select_bang(final ThreadContext context, final Block block) {
if (block.isGiven()) return keep_ifCommon(context, block) ? this : context.nil;

return enumeratorizeWithSize(context, this, "select!", enumSizeFn());
return enumeratorizeWithSize(context, this, "select!", RubyHash::size);
}

@JRubyMethod
Expand All @@ -1636,7 +1641,7 @@ public IRubyObject keep_if(final ThreadContext context, final Block block) {
return this;
}

return enumeratorizeWithSize(context, this, "keep_if", enumSizeFn());
return enumeratorizeWithSize(context, this, "keep_if", RubyHash::size);
}

public boolean keep_ifCommon(final ThreadContext context, final Block block) {
Expand Down Expand Up @@ -1823,7 +1828,7 @@ public IRubyObject delete(ThreadContext context, IRubyObject key) {
@JRubyMethod(name = "select", alias = "filter")
public IRubyObject select(final ThreadContext context, final Block block) {
final Ruby runtime = context.runtime;
if (!block.isGiven()) return enumeratorizeWithSize(context, this, "select", enumSizeFn());
if (!block.isGiven()) return enumeratorizeWithSize(context, this, "select", RubyHash::size);

final RubyHash result = newHash(runtime);

Expand Down Expand Up @@ -1890,7 +1895,7 @@ public void visit(ThreadContext context, RubyHash self, IRubyObject key, IRubyOb

@JRubyMethod
public IRubyObject delete_if(final ThreadContext context, final Block block) {
return block.isGiven() ? delete_ifInternal(context, block) : enumeratorizeWithSize(context, this, "delete_if", enumSizeFn());
return block.isGiven() ? delete_ifInternal(context, block) : enumeratorizeWithSize(context, this, "delete_if", RubyHash::size);
}

private static final class RejectVisitor extends VisitorWithState<Block> {
Expand Down Expand Up @@ -1920,7 +1925,7 @@ public RubyHash rejectInternal(ThreadContext context, Block block) {

@JRubyMethod
public IRubyObject reject(final ThreadContext context, final Block block) {
return block.isGiven() ? rejectInternal(context, block) : enumeratorizeWithSize(context, this, "reject", enumSizeFn());
return block.isGiven() ? rejectInternal(context, block) : enumeratorizeWithSize(context, this, "reject", RubyHash::size);
}

/** rb_hash_reject_bang
Expand All @@ -1935,7 +1940,7 @@ public IRubyObject reject_bangInternal(ThreadContext context, Block block) {

@JRubyMethod(name = "reject!")
public IRubyObject reject_bang(final ThreadContext context, final Block block) {
return block.isGiven() ? reject_bangInternal(context, block) : enumeratorizeWithSize(context, this, "reject!", enumSizeFn());
return block.isGiven() ? reject_bangInternal(context, block) : enumeratorizeWithSize(context, this, "reject!", RubyHash::size);
}

/** rb_hash_clear
Expand Down Expand Up @@ -2809,7 +2814,7 @@ public IRubyObject op_aset(IRubyObject key, IRubyObject value) {

@Deprecated
public IRubyObject each_pair(final ThreadContext context, final Block block) {
return block.isGiven() ? each_pairCommon(context, block) : enumeratorizeWithSize(context, this, "each_pair", enumSizeFn());
return block.isGiven() ? each_pairCommon(context, block) : enumeratorizeWithSize(context, this, "each_pair", RubyHash::size);
}

@Deprecated
Expand Down
Loading