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: c116c344ff70
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6335d01e24ca
Choose a head ref
  • 4 commits
  • 5 files changed
  • 1 contributor

Commits on Dec 19, 2014

  1. Copy the full SHA
    08f6e1c View commit details
  2. Copy the full SHA
    9af275a View commit details

Commits on Dec 20, 2014

  1. Copy the full SHA
    25d0ddc View commit details
  2. Copy the full SHA
    6335d01 View commit details
Original file line number Diff line number Diff line change
@@ -258,27 +258,35 @@ public MethodMissingNode(MethodMissingNode prev) {
}

@Specialization
public Object methodMissing(RubyBasicObject self, Object[] args, @SuppressWarnings("unused") UndefinedPlaceholder block) {
public Object methodMissing(Object self, Object[] args, @SuppressWarnings("unused") UndefinedPlaceholder block) {
notDesignedForCompilation();

return methodMissing(self, args, (RubyProc) null);
}

@Specialization
public Object methodMissing(RubyBasicObject self, Object[] args, RubyProc block) {
public Object methodMissing(Object self, Object[] args, RubyProc block) {
notDesignedForCompilation();

final RubySymbol name = (RubySymbol) args[0];
final Object[] sentArgs = Arrays.copyOfRange(args, 1, args.length);
return methodMissing(self, name, sentArgs, block);
}

private Object methodMissing(RubyBasicObject self, RubySymbol name, Object[] args, RubyProc block) {
private Object methodMissing(Object self, RubySymbol name, Object[] args, RubyProc block) {
// TODO: should not be a call to Java toString(), but rather sth like name_err_mesg_to_str() in MRI error.c
if (lastCallWasVCall()) {
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedLocalVariableOrMethod(name.toString(), self.toString(), this));
throw new RaiseException(
getContext().getCoreLibrary().nameErrorUndefinedLocalVariableOrMethod(
name.toString(),
getContext().getCoreLibrary().getLogicalClass(self).getName(),
this));
} else {
throw new RaiseException(getContext().getCoreLibrary().noMethodError(name.toString(), self.toString(), this));
throw new RaiseException(
getContext().getCoreLibrary().noMethodError(
name.toString(),
getContext().getCoreLibrary().getLogicalClass(self).getName(),
this));
}
}

63 changes: 63 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.joni.Option;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.RubyContext;
@@ -326,6 +328,67 @@ public RubyString chompBang(RubyString string) {
}
}

@CoreMethod(names = "count", argumentsAsArray = true)
public abstract static class CountNode extends CoreMethodNode {

@Child protected DispatchHeadNode toStr;

public CountNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = new DispatchHeadNode(context);
}

public CountNode(CountNode prev) {
super(prev);
toStr = prev.toStr;
}

@Specialization
public int count(VirtualFrame frame, RubyString string, Object[] otherStrings) {
notDesignedForCompilation();

if (otherStrings.length == 0) {
throw new RaiseException(getContext().getCoreLibrary().argumentErrorEmptyVarargs(this));
}

return countSlow(frame, string, otherStrings);
}

@CompilerDirectives.SlowPath
private int countSlow(VirtualFrame frame, RubyString string, Object[] args) {
RubyString[] otherStrings = new RubyString[args.length];

for (int i = 0; i < args.length; i++) {
if (args[i] instanceof RubyString) {
otherStrings[i] = (RubyString) args[i];
} else {
Object coerced;

try {
coerced = toStr.call(frame, args[i], "to_str", null);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
throw new RaiseException(
getContext().getCoreLibrary().typeErrorNoImplicitConversion(args[i], "String", this));
} else {
throw e;
}
}

if (coerced instanceof RubyString) {
otherStrings[i] = (RubyString) coerced;
} else {
throw new RaiseException(
getContext().getCoreLibrary().typeErrorBadCoercion(args[i], "String", "to_str", coerced, this));

}
}
}

return string.count(otherStrings);
}
}

@CoreMethod(names = "downcase")
public abstract static class DowncaseNode extends CoreMethodNode {

21 changes: 21 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -422,6 +422,11 @@ public RubyException argumentError(int passed, int required, int optional, Node
return argumentError(String.format("wrong number of arguments (%d for %d..%d)", passed, required, required + optional), currentNode);
}

public RubyException argumentErrorEmptyVarargs(Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return argumentError("wrong number of arguments (0 for 1+)", currentNode);
}

public RubyException indexError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(indexErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
@@ -492,6 +497,22 @@ public RubyException typeErrorIsNotA(String value, String expectedType, Node cur
return typeError(String.format("%s is not a %s", value, expectedType), currentNode);
}

public RubyException typeErrorNoImplicitConversion(Object from, String to, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeError(String.format("no implicit conversion of %s into %s", getLogicalClass(from).getName(), to), currentNode);
}

public RubyException typeErrorBadCoercion(Object from, String to, String coercionMethod, Object coercedTo, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
String badClassName = getLogicalClass(from).getName();
return typeError(String.format("can't convert %s to %s (%s#%s gives %s)",
badClassName,
to,
badClassName,
coercionMethod,
getLogicalClass(coercedTo).getName()), currentNode);
}

public RubyException nameError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(nameErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
21 changes: 21 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyString.java
Original file line number Diff line number Diff line change
@@ -107,6 +107,27 @@ public static String rjust(String string, int length, String padding) {
return builder.toString();
}

public int count(RubyString[] otherStrings) {
if (bytes.getRealSize() == 0) {
return 0;
}

RubyString otherStr = otherStrings[0];
Encoding enc = otherStr.getBytes().getEncoding();

final boolean[]table = new boolean[StringSupport.TRANS_SIZE + 1];
StringSupport.TrTables tables = StringSupport.trSetupTable(otherStr.getBytes(), getContext().getRuntime(), table, null, true, enc);
for (int i = 1; i < otherStrings.length; i++) {
otherStr = otherStrings[i];

// TODO (nirvdrum Dec. 19, 2014): This method should be encoding aware and check that the strings have compatible encodings. See non-Truffle JRuby for a more complete solution.
//enc = checkEncoding(otherStr);
tables = StringSupport.trSetupTable(otherStr.getBytes(), getContext().getRuntime(), table, tables, false, enc);
}

return StringSupport.countCommon19(getBytes(), getContext().getRuntime(), table, tables, enc);
}

public RubyString dump() {
ByteList outputBytes = StringSupport.dumpCommon(getContext().getRuntime(), bytes);

9 changes: 1 addition & 8 deletions spec/truffle/tags/core/string/count_tags.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
fails:String#count counts occurrences of chars from the intersection of the specified sets
fails:String#count raises an ArgumentError when given no arguments
fails:String#count negates sets starting with ^
fails:String#count counts all chars in a sequence
fails:String#count raises if the given sequences are invalid
fails:String#count returns the number of occurrences of a multi-byte character
fails:String#count calls #to_str to convert each set arg to a String
fails:String#count raises a TypeError when a set arg can't be converted to a string
fails:String#count raises if the given sequences are invalid