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

Commits on Feb 6, 2015

  1. Copy the full SHA
    76913e2 View commit details
  2. Copy the full SHA
    1d41e85 View commit details
  3. Copy the full SHA
    3fef31d View commit details
  4. Copy the full SHA
    e0857c7 View commit details
  5. Copy the full SHA
    09cb264 View commit details
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/

package org.jruby.truffle.nodes.coerce;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyString;

@NodeChild(value = "child", type = RubyNode.class)
public abstract class ToStrNode extends RubyNode {

@Child private CallDispatchHeadNode toStr;

public ToStrNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = DispatchHeadNodeFactory.createMethodCall(context);
}

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

@Specialization
public RubyString coerceRubyString(RubyString string) {
return string;
}

@Specialization(guards = "!isRubyString")
public RubyString coerceObject(VirtualFrame frame, Object object) {
notDesignedForCompilation();

final Object coerced;

try {
coerced = toStr.call(frame, object, "to_str", null);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
getContext().getCoreLibrary().typeErrorNoImplicitConversion(object, "String", this));
} else {
throw e;
}
}

if (coerced instanceof RubyString) {
return (RubyString) coerced;
} else {
CompilerDirectives.transferToInterpreter();

throw new RaiseException(
getContext().getCoreLibrary().typeErrorBadCoercion(object, "String", "to_str", coerced, this));
}
}

@Override
public abstract RubyString executeRubyString(VirtualFrame frame);

public abstract RubyString executeRubyString(VirtualFrame frame, Object object);

@Override
public final Object execute(VirtualFrame frame) {
return executeRubyString(frame);
}
}
66 changes: 18 additions & 48 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
@@ -25,6 +28,8 @@
import org.jruby.truffle.nodes.cast.BooleanCastNodeFactory;
import org.jruby.truffle.nodes.cast.NumericToFloatNode;
import org.jruby.truffle.nodes.cast.NumericToFloatNodeFactory;
import org.jruby.truffle.nodes.coerce.ToStrNode;
import org.jruby.truffle.nodes.coerce.ToStrNodeFactory;
import org.jruby.truffle.nodes.control.WhileNode;
import org.jruby.truffle.nodes.core.KernelNodesFactory.SameOrEqualNodeFactory;
import org.jruby.truffle.nodes.dispatch.*;
@@ -513,19 +518,27 @@ public Object dup(VirtualFrame frame, RubyBasicObject self) {
}

@CoreMethod(names = "eval", isModuleFunction = true, required = 1, optional = 3)
public abstract static class EvalNode extends CoreMethodNode {
@NodeChildren({
@NodeChild(value = "source", type = RubyNode.class),
@NodeChild(value = "binding", type = RubyNode.class),
@NodeChild(value = "filename", type = RubyNode.class),
@NodeChild(value = "lineNumber", type = RubyNode.class)
})
public abstract static class EvalNode extends RubyNode {

@Child private CallDispatchHeadNode toStr;
@Child private BindingNode bindingNode;

public EvalNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = DispatchHeadNodeFactory.createMethodCall(context);
}

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

@CreateCast("source") public RubyNode coerceSourceToString(RubyNode source) {
return ToStrNodeFactory.create(getContext(), getSourceSection(), source);
}

protected RubyBinding getCallerBinding(VirtualFrame frame) {
@@ -574,57 +587,14 @@ public Object eval(RubyString source, RubyBinding binding, RubyString filename,
return getContext().eval(source.getBytes(), binding, false, this);
}

@Specialization(guards = "!isRubyString(arguments[0])")
public Object eval(VirtualFrame frame, RubyBasicObject object, UndefinedPlaceholder binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
notDesignedForCompilation();

return evalCoerced(frame, object, getCallerBinding(frame), true, filename, lineNumber);
}

@Specialization(guards = "!isRubyString(arguments[0])")
public Object eval(VirtualFrame frame, RubyBasicObject object, RubyBinding binding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
notDesignedForCompilation();

return evalCoerced(frame, object, binding, false, filename, lineNumber);
}

@Specialization(guards = "!isRubyBinding(arguments[1])")
public Object eval(RubyBasicObject source, RubyBasicObject badBinding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
@Specialization(guards = "!isRubyBinding(binding)")
public Object eval(RubyString source, RubyBasicObject badBinding, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
throw new RaiseException(
getContext().getCoreLibrary().typeError(
String.format("wrong argument type %s (expected binding)",
badBinding.getLogicalClass().getName()),
this));
}

private Object evalCoerced(VirtualFrame frame, RubyBasicObject object, RubyBinding binding, boolean ownScopeForAssignments, UndefinedPlaceholder filename, UndefinedPlaceholder lineNumber) {
Object coerced;

try {
coerced = toStr.call(frame, object, "to_str", null);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == getContext().getCoreLibrary().getNoMethodErrorClass()) {
throw new RaiseException(
getContext().getCoreLibrary().typeError(
String.format("no implicit conversion of %s into String", object.getLogicalClass().getName()),
this));
} else {
throw e;
}
}

if (coerced instanceof RubyString) {
return getContext().eval(((RubyString) coerced).getBytes(), binding, ownScopeForAssignments, this);
} else {
throw new RaiseException(
getContext().getCoreLibrary().typeError(
String.format("can't convert %s to String (%s#to_str gives %s)",
object.getLogicalClass().getName(),
object.getLogicalClass().getName(),
getContext().getCoreLibrary().getLogicalClass(coerced).getName()),
this));
}
}
}

@CoreMethod(names = "exec", isModuleFunction = true, required = 1, argumentsAsArray = true)
Original file line number Diff line number Diff line change
@@ -23,6 +23,8 @@
import org.joni.Region;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.coerce.ToStrNode;
import org.jruby.truffle.nodes.coerce.ToStrNodeFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
@@ -552,11 +554,11 @@ public RubyString chompBangWithString(RubyString string, RubyString stringToChom
@CoreMethod(names = "count", argumentsAsArray = true)
public abstract static class CountNode extends CoreMethodNode {

@Child private CallDispatchHeadNode toStr;
@Child private ToStrNode toStr;

public CountNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
toStr = DispatchHeadNodeFactory.createMethodCall(context);
toStr = ToStrNodeFactory.create(context, sourceSection, null);
}

public CountNode(CountNode prev) {
@@ -580,30 +582,7 @@ 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));

}
}
otherStrings[i] = toStr.executeRubyString(frame, args[i]);
}

return string.count(otherStrings);