Skip to content

Commit

Permalink
[Truffle] Fixed String#[](Regexp, int).
Browse files Browse the repository at this point in the history
When calling String#[] with a Regexp and a negative index, the negative index can't normalize to 0.  Whereas that is valid for MatchData#[], in String#[] it should return nil().  This case in especially annoying because the 'capture' parameter can be any Object that responds to either to_int or to_sym.  Handling all these coercion cases in Java is incredibly verbose, so I opted to execute a Ruby snippet equivalent to what Rubinius would have done.
  • Loading branch information
nirvdrum committed Mar 31, 2015
1 parent df07cb4 commit 2aded96
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 26 deletions.
1 change: 0 additions & 1 deletion spec/truffle/tags/core/string/element_reference_tags.txt
@@ -1,3 +1,2 @@
fails:String#[] with Range calls to_int on range arguments
fails:String#[] with Range works with Range subclasses
fails:String#[] with Regexp, index returns nil if there is no capture for the given index
Expand Up @@ -461,9 +461,7 @@ private RubyString formatSlow(RubyString format, Object[] args) {
public abstract static class GetIndexNode extends CoreMethodNode {

@Child private ToIntNode toIntNode;
@Child private CallDispatchHeadNode getMatchDataIndexNode;
@Child private CallDispatchHeadNode includeNode;
@Child private CallDispatchHeadNode matchNode;
@Child private CallDispatchHeadNode dupNode;
@Child private StringPrimitiveNodes.StringSubstringPrimitiveNode substringNode;

Expand All @@ -476,9 +474,7 @@ public GetIndexNode(RubyContext context, SourceSection sourceSection) {
public GetIndexNode(GetIndexNode prev) {
super(prev);
toIntNode = prev.toIntNode;
getMatchDataIndexNode = prev.getMatchDataIndexNode;
includeNode = prev.includeNode;
matchNode = prev.matchNode;
dupNode = prev.dupNode;
substringNode = prev.substringNode;
}
Expand Down Expand Up @@ -567,32 +563,13 @@ public Object slice(VirtualFrame frame, RubyString string, Object start, Object

@Specialization
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, UndefinedPlaceholder capture) {
notDesignedForCompilation();

return slice(frame, string, regexp, 0);
}

@Specialization(guards = "!isUndefinedPlaceholder(arguments[2])")
public Object slice(VirtualFrame frame, RubyString string, RubyRegexp regexp, Object capture) {
notDesignedForCompilation();

if (matchNode == null) {
CompilerDirectives.transferToInterpreter();
matchNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

final Object matchData = matchNode.call(frame, regexp, "match", null, string);

if (matchData == nil()) {
return matchData;
}

if (getMatchDataIndexNode == null) {
CompilerDirectives.transferToInterpreter();
getMatchDataIndexNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}

return getMatchDataIndexNode.call(frame, matchData, "[]", null, capture);
// Extract from Rubinius's definition of String#[].
return ruby(frame, "match, str = subpattern(index, other); Regexp.last_match = match; str", "index", regexp, "other", capture);
}

@Specialization
Expand Down

0 comments on commit 2aded96

Please sign in to comment.