Navigation Menu

Skip to content

Commit

Permalink
[Truffle] Backreference specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Dec 8, 2014
1 parent 25a91e7 commit 87d78de
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 24 deletions.
Expand Up @@ -127,9 +127,17 @@ public Object isDefined(VirtualFrame frame) {
notDesignedForCompilation();

if (isGlobal) {
if (readNode.getName().equals("$~") || readNode.isSet((RubyBasicObject) receiver.execute(frame))) {
final RubyBasicObject recieverValue = (RubyBasicObject) receiver.execute(frame);

if (readNode.getName().equals("$~")) {
return getContext().makeString("global-variable");
} else{
} else if (readNode.isSet(recieverValue)) {
if (readNode.execute(recieverValue) == getContext().getCoreLibrary().getNilObject()) {
return getContext().getCoreLibrary().getNilObject();
} else {
return getContext().makeString("global-variable");
}
} else {
return getContext().getCoreLibrary().getNilObject();
}
}
Expand Down
Expand Up @@ -381,6 +381,8 @@ public RubyClass getMetaClass(Object object) {
return fixnumClass;
} else if (object instanceof Double) {
return floatClass;
} else if (object == null) {
throw new RuntimeException();
} else {
throw new UnsupportedOperationException(String.format("Don't know how to get the metaclass for %s", object.getClass()));
}
Expand All @@ -403,6 +405,8 @@ public RubyClass getLogicalClass(Object object) {
return fixnumClass;
} else if (object instanceof Double) {
return floatClass;
} else if (object == null) {
throw new RuntimeException();
} else {
throw new UnsupportedOperationException(String.format("Don't know how to get the logical class for %s", object.getClass()));
}
Expand Down
42 changes: 27 additions & 15 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
Expand Up @@ -99,21 +99,22 @@ public Object matchCommon(ByteList bytes, boolean operator) {
final RubyNilClass nil = getContext().getCoreLibrary().getNilObject();

if (operator) {
for (int n = 0; n < 10; n++) {
set(frame, "$" + n, nil);
for (int n = 1; n < 10; n++) {
setThread("$" + n, nil);
}
}

if (match == -1) {
set(frame, "$&", nil);
set(frame, "$~", nil);
set(frame, "$`", nil);
set(frame, "$'", nil);
setFrame(frame, "$&", nil);
setFrame(frame, "$`", nil);
setFrame(frame, "$'", nil);

if (operator) {
set(frame, "$+", nil);
setFrame(frame, "$+", nil);
}

setThread("$~", nil);

return getContext().getCoreLibrary().getNilObject();
}

Expand All @@ -134,7 +135,10 @@ public Object matchCommon(ByteList bytes, boolean operator) {
}

values[n] = groupString;
set(frame, "$" + n, groupString);

if (n > 0 && n < 10) {
setThread("$" + n, groupString);
}
} else {
if (start == -1 || end == -1) {
values[n] = getContext().getCoreLibrary().getNilObject();
Expand All @@ -155,17 +159,17 @@ public Object matchCommon(ByteList bytes, boolean operator) {
nonNil--;
}

set(frame, "$+", values[nonNil]);
setFrame(frame, "$+", values[nonNil]);
} else {
set(frame, "$+", getContext().getCoreLibrary().getNilObject());
setFrame(frame, "$+", getContext().getCoreLibrary().getNilObject());
}
}

set(frame, "$`", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(0, region.beg[0]).dup()));
set(frame, "$'", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(region.end[0], bytes.length() - region.end[0]).dup()));
set(frame, "$&", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(region.beg[0], region.end[0] - region.beg[0]).dup()));
setFrame(frame, "$`", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(0, region.beg[0]).dup()));
setFrame(frame, "$'", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(region.end[0], bytes.length() - region.end[0]).dup()));
setFrame(frame, "$&", new RubyString(context.getCoreLibrary().getStringClass(), bytes.makeShared(region.beg[0], region.end[0] - region.beg[0]).dup()));

set(frame, "$~", matchObject);
setThread("$~", matchObject);

if (operator) {
return matcher.getBegin();
Expand All @@ -174,7 +178,9 @@ public Object matchCommon(ByteList bytes, boolean operator) {
}
}

private void set(Frame frame, String name, Object value) {
private void setFrame(Frame frame, String name, Object value) {
assert value != null;

while (frame != null) {
final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(name);

Expand All @@ -187,6 +193,12 @@ private void set(Frame frame, String name, Object value) {
}
}

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

getContext().getThreadManager().getCurrentThread().getThreadLocals().setInstanceVariable(name, value);
}

@CompilerDirectives.SlowPath
public RubyString gsub(String string, String replacement) {
final RubyContext context = getContext();
Expand Down
Expand Up @@ -73,6 +73,7 @@ public RubyThread(RubyClass rubyClass, ThreadManager manager) {
super(rubyClass);
this.manager = manager;
threadLocals = new RubyBasicObject(rubyClass.getContext().getCoreLibrary().getObjectClass());
threadLocals.switchToPrivateLayout();
}

public void initialize(RubyContext context, RubyNode currentNode, RubyProc block) {
Expand Down
Expand Up @@ -78,8 +78,8 @@ public class BodyTranslator extends Translator {
debugIgnoredCalls.add("upto");
}

public static final Set<String> FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$~", "$+", "$&", "$`", "$'", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9"));
public static final Set<String> THREAD_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_"));
public static final Set<String> FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$+", "$&", "$`", "$'"));
public static final Set<String> THREAD_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_", "$~", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9"));

public BodyTranslator(RubyNode currentNode, RubyContext context, BodyTranslator parent, TranslatorEnvironment environment, Source source, boolean topLevel) {
super(currentNode, context, source);
Expand Down Expand Up @@ -1027,6 +1027,10 @@ public RubyNode visitGlobalAsgnNode(org.jruby.ast.GlobalAsgnNode node) {
if (readOnlyGlobalVariables.contains(name)) {
return new WriteReadOnlyGlobalNode(context, sourceSection, name, rhs);
} else if (THREAD_LOCAL_GLOBAL_VARIABLES.contains(name)) {
if (name.equals("$~")) {
rhs = new CheckMatchVariableTypeNode(context, sourceSection, rhs);
}

final ThreadLocalObjectNode threadLocalVariablesObjectNode = new ThreadLocalObjectNode(context, sourceSection);
return new WriteInstanceVariableNode(context, sourceSection, name, threadLocalVariablesObjectNode, rhs, true);
} else if (FRAME_LOCAL_GLOBAL_VARIABLES.contains(name)) {
Expand Down Expand Up @@ -1057,12 +1061,9 @@ public RubyNode visitGlobalAsgnNode(org.jruby.ast.GlobalAsgnNode node) {

return ((ReadNode) localVarNode).makeWriteNode(rhs);
} else {
if (name.equals("$~")) {
rhs = new CheckMatchVariableTypeNode(context, sourceSection, rhs);
}

final ObjectLiteralNode globalVariablesObjectNode = new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject());
return new WriteInstanceVariableNode(context, sourceSection, name, globalVariablesObjectNode, rhs, true);

}
}

Expand Down
1 change: 1 addition & 0 deletions spec/truffle/tags/language/predefined_tags.txt
Expand Up @@ -61,3 +61,4 @@ fails:Predefined global $-0 raises a TypeError if assigned a Fixnum
fails:Predefined global $-0 raises a TypeError if assigned a boolean
fails:Global variable $0 raises a TypeError when not given an object that can be coerced to a String
fails:Predefined global $~ raises an error if assigned an object not nil or instanceof MatchData
fails:Predefined global $~ is set at the method-scoped level rather than block-scoped
1 change: 0 additions & 1 deletion spec/truffle/tags/language/regexp/back-references_tags.txt

This file was deleted.

0 comments on commit 87d78de

Please sign in to comment.