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: 400b5d69b2f7
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8c8808d3495c
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Jan 12, 2015

  1. Copy the full SHA
    c4e7bbe View commit details
  2. [Truffle] Fixed String#scan with a block.

    Our old approach of collecting the array and then iterating over it sorta worked, but state that changes on each through scan would be lost, such as Regexp.last_match.  Ultimately we needed to yield as we found a match.
    nirvdrum committed Jan 12, 2015
    Copy the full SHA
    8c8808d View commit details
Showing with 53 additions and 7 deletions.
  1. +50 −4 core/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
  2. +3 −3 core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
54 changes: 50 additions & 4 deletions core/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -1105,10 +1105,56 @@ public RubyArray scan(RubyString string, RubyRegexp regexp, UndefinedPlaceholder
public RubyString scan(VirtualFrame frame, RubyString string, RubyRegexp regexp, RubyProc block) {
notDesignedForCompilation();

// TODO (nirvdrum Dec. 18, 2014): Find a way to yield results without needing to materialize as an array first.
Object[] matches = (Object[]) regexp.scan(string);
for (Object match : matches) {
yield(frame, block, match);
// TODO (nirvdrum 12-Jan-15) Figure out a way to make this not just a complete copy & paste of RubyRegexp#scan.

final RubyContext context = getContext();

final byte[] stringBytes = string.getBytes().bytes();
final Encoding encoding = string.getBytes().getEncoding();
final Matcher matcher = regexp.getRegex().matcher(stringBytes);

int p = string.getBytes().getBegin();
int end = 0;
int range = p + string.getBytes().getRealSize();

Object lastGoodMatchData = getContext().getCoreLibrary().getNilObject();

if (regexp.getRegex().numberOfCaptures() == 0) {
while (true) {
Object matchData = regexp.matchCommon(string.getBytes(), false, true, matcher, p + end, range);

if (matchData == context.getCoreLibrary().getNilObject()) {
break;
}

RubyMatchData md = (RubyMatchData) matchData;
Object[] values = md.getValues();

assert values.length == 1;

yield(frame, block, values[0]);

lastGoodMatchData = matchData;
end = StringSupport.positionEndForScan(string.getBytes(), matcher, encoding, p, range);
}

regexp.setThread("$~", lastGoodMatchData);
} else {
while (true) {
Object matchData = regexp.matchCommon(string.getBytes(), false, true, matcher, p + end, stringBytes.length);

if (matchData == context.getCoreLibrary().getNilObject()) {
break;
}

final Object[] captures = ((RubyMatchData) matchData).getCaptures();
yield(frame, block, new RubyArray(context.getCoreLibrary().getArrayClass(), captures, captures.length));

lastGoodMatchData = matchData;
end = StringSupport.positionEndForScan(string.getBytes(), matcher, encoding, p, range);
}

regexp.setThread("$~", lastGoodMatchData);
}

return string;
Original file line number Diff line number Diff line change
@@ -201,7 +201,7 @@ private void setFrame(Frame frame, String name, Object value) {
}
}

private void setThread(String name, Object value) {
public void setThread(String name, Object value) {
assert value != null;

RubyNode.notDesignedForCompilation();
@@ -345,8 +345,8 @@ public Object scan(RubyString string) {
break;
}

allMatches.add(RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(),
((RubyMatchData) matchData).getCaptures()));
final Object[] captures = ((RubyMatchData) matchData).getCaptures();
allMatches.add(new RubyArray(context.getCoreLibrary().getArrayClass(), captures, captures.length));

lastGoodMatchData = matchData;
end = StringSupport.positionEndForScan(string.getBytes(), matcher, encoding, p, range);