Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d281884824fa
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cd044f4fa08b
Choose a head ref
  • 2 commits
  • 3 files changed
  • 2 contributors

Commits on Nov 5, 2014

  1. Fix multiple Range stdlib failures

    * Add ducktyping support for Array#[], Array#[]=, String#[], and String#[]=
    * Fix re-initialize check on initialize_copy
    * Fix infinite recursion when inspecting cyclical ranges
    cheald committed Nov 5, 2014
    Copy the full SHA
    451b1c7 View commit details
  2. Merge pull request #2103 from cheald/fix_multiple_range_failures

    Fix multiple Range stdlib failures. I will followup commit to show how I would change @JrubyMethod signatures and reduce use of getRuby.getCurrentContext.
    enebo committed Nov 5, 2014
    Copy the full SHA
    cd044f4 View commit details
Showing with 87 additions and 44 deletions.
  1. +16 −0 core/src/main/java/org/jruby/RubyArray.java
  2. +44 −44 core/src/main/java/org/jruby/RubyRange.java
  3. +27 −0 core/src/main/java/org/jruby/RubyString.java
16 changes: 16 additions & 0 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -1317,6 +1317,14 @@ private IRubyObject arefCommon(IRubyObject arg0) {
if (arg0 instanceof RubyRange) {
long[] beglen = ((RubyRange) arg0).begLen(realLength, 0);
return beglen == null ? getRuntime().getNil() : subseq(beglen[0], beglen[1]);
} else if (arg0.respondsTo("begin") && arg0.respondsTo("end")) {
IRubyObject begin = arg0.callMethod(getRuntime().getCurrentContext(), "begin");
IRubyObject end = arg0.callMethod(getRuntime().getCurrentContext(), "end");
IRubyObject excl = arg0.callMethod(getRuntime().getCurrentContext(), "exclude_end?");
RubyRange rng = RubyRange.newRange(getRuntime(), getRuntime().getCurrentContext(), begin, end, ((RubyBoolean)excl).isTrue() );

long[] beglen = rng.begLen(realLength, 0);
return beglen == null ? getRuntime().getNil() : subseq(beglen[0], beglen[1]);
}
return entry(RubyNumeric.num2long(arg0));
}
@@ -1364,6 +1372,14 @@ public IRubyObject aset19(IRubyObject arg0, IRubyObject arg1) {
RubyRange range = (RubyRange)arg0;
long beg = range.begLen0(realLength);
splice(beg, range.begLen1(realLength, beg), arg1, true);
} else if (arg0.respondsTo("begin") && arg0.respondsTo("end")) {
IRubyObject begin = arg0.callMethod(getRuntime().getCurrentContext(), "begin");
IRubyObject end = arg0.callMethod(getRuntime().getCurrentContext(), "end");
IRubyObject excl = arg0.callMethod(getRuntime().getCurrentContext(), "exclude_end?");
RubyRange rng = RubyRange.newRange(getRuntime(), getRuntime().getCurrentContext(), begin, end, ((RubyBoolean)excl).isTrue() );

long beg = rng.begLen0(realLength);
splice(beg, rng.begLen1(realLength, beg), arg1, true);
} else {
store(RubyNumeric.num2long(arg0), arg1);
}
88 changes: 44 additions & 44 deletions core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
@@ -251,7 +251,18 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block u
init(context, args[0], args[1], args.length > 2 && args[2].isTrue());
return getRuntime().getNil();
}


@JRubyMethod(required = 1, visibility = PRIVATE)
public IRubyObject initialize_copy(IRubyObject orig) {
if (!begin.isNil() || !end.isNil()) {
throw getRuntime().newNameError("`initialize' called twice", "initialize");
}

RubyRange other = (RubyRange)orig;
init(getRuntime().getCurrentContext(), other.begin, other.end, other.isExclusive);
return getRuntime().getNil();
}

@JRubyMethod(name = "hash")
public RubyFixnum hash(ThreadContext context) {
long hash = isExclusive ? 1 : 0;
@@ -268,35 +279,34 @@ public RubyFixnum hash(ThreadContext context) {
private static byte[] DOTDOTDOT = "...".getBytes();
private static byte[] DOTDOT = "..".getBytes();

@JRubyMethod(name = "inspect")
public IRubyObject inspect(ThreadContext context) {
RubyString str = inspect(context, begin).strDup(context.runtime);
RubyString str2 = inspect(context, end);

str.cat(isExclusive ? DOTDOTDOT : DOTDOT);
str.concat(str2);
str.infectBy(str2);
return str;
private IRubyObject inspectValue(IRubyObject value) {
return getRuntime().execRecursiveOuter(new Ruby.RecursiveFunction() {
public IRubyObject call(IRubyObject obj, boolean recur) {
if(recur) {
return RubyString.newString(getRuntime(), isExclusive ? "(... ... ...)" : "(... .. ...)");
} else {
return inspect(getRuntime().getCurrentContext(), obj);
}
}
}, value);
}

@JRubyMethod(name = "to_s")
public IRubyObject to_s(ThreadContext context) {
RubyString str = RubyString.objAsString(context, begin).strDup(context.runtime);
RubyString str2 = RubyString.objAsString(context, end);

str.cat(isExclusive ? DOTDOTDOT : DOTDOT);
str.concat(str2);
str.infectBy(str2);
return str;

@JRubyMethod(name = {"inspect", "to_s"})
public IRubyObject inspect(final ThreadContext context) {
RubyString i1 = ((RubyString) inspectValue(begin)).strDup(context.runtime);
RubyString i2 = (RubyString) inspectValue(end);
i1.cat(isExclusive ? DOTDOTDOT : DOTDOT);
i1.append(i2);
i1.infectBy(i2);
return i1;
}

@JRubyMethod(name = "exclude_end?")
public RubyBoolean exclude_end_p() {
return getRuntime().newBoolean(isExclusive);
}

@JRubyMethod(name = "==", required = 1)
@JRubyMethod(name = {"==", "eql?"}, required = 1)
@Override
public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
if (this == other) return getRuntime().getTrue();
@@ -310,19 +320,6 @@ public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
return getRuntime().getFalse();
}

@JRubyMethod(name = "eql?", required = 1)
public IRubyObject eql_p(ThreadContext context, IRubyObject other) {
if (this == other) return getRuntime().getTrue();
if (!(other instanceof RubyRange)) return getRuntime().getFalse();
RubyRange otherRange = (RubyRange)other;

if (eqlInternal(context, begin, otherRange.begin) &&
eqlInternal(context, end, otherRange.end) &&
isExclusive == otherRange.isExclusive) return getRuntime().getTrue();

return getRuntime().getFalse();
}

private static abstract class RangeCallBack {
abstract void call(ThreadContext context, IRubyObject arg);
}
@@ -454,19 +451,22 @@ public IRubyObject each19(final ThreadContext context, final Block block) {
throw runtime.newTypeError("can't iterate from Time");
} else if (begin instanceof RubyFixnum && end instanceof RubyFixnum) {
fixnumEach(context, runtime, block);
} else if (begin instanceof RubyString) {
((RubyString) begin).uptoCommon19(context, end, isExclusive, block);
} else if (begin instanceof RubySymbol) {
begin.asString().uptoCommon19(context, end.asString(), isExclusive, block, true);
} else {
if (!begin.respondsTo("succ")) throw getRuntime().newTypeError(
"can't iterate from " + begin.getMetaClass().getName());
rangeEach(context, new RangeCallBack() {
@Override
void call(ThreadContext context, IRubyObject arg) {
block.yield(context, arg);
}
});
IRubyObject tmp = begin.checkStringType();
if(!tmp.isNil()) {
((RubyString) tmp).uptoCommon19(context, end, isExclusive, block);
} else {
if (!begin.respondsTo("succ")) throw getRuntime().newTypeError(
"can't iterate from " + begin.getMetaClass().getName());
rangeEach(context, new RangeCallBack() {
@Override
void call(ThreadContext context, IRubyObject arg) {
block.yield(context, arg);
}
});
}
}
return this;
}
27 changes: 27 additions & 0 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -3056,6 +3056,14 @@ private IRubyObject byteARef(Ruby runtime, IRubyObject idx) {
return begLen == null ? runtime.getNil() : byteSubstr(runtime, begLen[0], begLen[1]);
} else if (idx instanceof RubyFixnum) {
index = RubyNumeric.fix2int((RubyFixnum)idx);
} else if (idx.respondsTo("begin") && idx.respondsTo("end")) {
IRubyObject begin = idx.callMethod(getRuntime().getCurrentContext(), "begin");
IRubyObject end = idx.callMethod(getRuntime().getCurrentContext(), "end");
IRubyObject excl = idx.callMethod(getRuntime().getCurrentContext(), "exclude_end?");
RubyRange rng = RubyRange.newRange(getRuntime(), getRuntime().getCurrentContext(), begin, end, ((RubyBoolean)excl).isTrue() );

int[] begLen = rng.begLenInt(getByteList().length(), 0);
return begLen == null ? runtime.getNil() : byteSubstr(runtime, begLen[0], begLen[1]);
} else {
index = RubyNumeric.num2int(idx);
}
@@ -3211,6 +3219,15 @@ public IRubyObject op_aref19(ThreadContext context, IRubyObject arg) {
int len = strLength();
int[] begLen = ((RubyRange) arg).begLenInt(len, 0);
return begLen == null ? runtime.getNil() : substr19(runtime, begLen[0], begLen[1]);
} else if (arg.respondsTo("begin") && arg.respondsTo("end")) {
int len = strLength();
IRubyObject begin = arg.callMethod(getRuntime().getCurrentContext(), "begin");
IRubyObject end = arg.callMethod(getRuntime().getCurrentContext(), "end");
IRubyObject excl = arg.callMethod(getRuntime().getCurrentContext(), "exclude_end?");
RubyRange rng = RubyRange.newRange(getRuntime(), getRuntime().getCurrentContext(), begin, end, ((RubyBoolean)excl).isTrue() );

int[] begLen = rng.begLenInt(len, 0);
return begLen == null ? runtime.getNil() : substr19(runtime, begLen[0], begLen[1]);
}
return op_aref19(runtime, RubyNumeric.num2int(arg));
}
@@ -3327,6 +3344,16 @@ public IRubyObject op_aset19(ThreadContext context, IRubyObject arg0, IRubyObjec
} else if (arg0 instanceof RubyRange) {
int[] begLen = ((RubyRange) arg0).begLenInt(strLength(), 2);
replaceInternal19(begLen[0], begLen[1], arg1.convertToString());
return arg1;
} else if (arg0.respondsTo("begin") && arg0.respondsTo("end")) {
IRubyObject begin = arg0.callMethod(getRuntime().getCurrentContext(), "begin");
IRubyObject end = arg0.callMethod(getRuntime().getCurrentContext(), "end");
IRubyObject excl = arg0.callMethod(getRuntime().getCurrentContext(), "exclude_end?");
RubyRange rng = RubyRange.newRange(getRuntime(), getRuntime().getCurrentContext(), begin, end, ((RubyBoolean)excl).isTrue() );

int[] begLen = rng.begLenInt(strLength(), 2);
replaceInternal19(begLen[0], begLen[1], arg1.convertToString());

return arg1;
}
return op_aset19(context, RubyNumeric.num2int(arg0), arg1);