Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Truffle] Implement Fixnum#+ with a Rational argument.
  • Loading branch information
nirvdrum committed Jan 8, 2015
1 parent f58aec1 commit 79b8135
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
27 changes: 27 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
Expand Up @@ -13,12 +13,16 @@
import com.oracle.truffle.api.ExactMath;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.methods.UnsupportedOperationBehavior;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyBignum;
import org.jruby.truffle.runtime.core.RubyString;

Expand Down Expand Up @@ -63,12 +67,16 @@ public RubyBignum negWithOverflow(long value) {
@CoreMethod(names = "+", required = 1)
public abstract static class AddNode extends BignumNodes.BignumCoreMethodNode {

@Child protected DispatchHeadNode rationalAdd;

public AddNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
rationalAdd = new DispatchHeadNode(context);
}

public AddNode(AddNode prev) {
super(prev);
rationalAdd = prev.rationalAdd;
}

@Specialization(rewriteOn = ArithmeticException.class)
Expand Down Expand Up @@ -101,6 +109,16 @@ public Object add(int a, RubyBignum b) {
return fixnumOrBignum(bignum(a).add(b));
}

@Specialization
public Object add(VirtualFrame frame, int a, RubyBasicObject b) {
if (b.getLogicalClass() == getContext().getCoreLibrary().getRationalClass()) {
return rationalAdd.call(frame, b, "+", null, a);
} else {
// TODO (nirvdrum Jan. 7, 2015) Figure out what the proper exception message format is -- Symbols show the value, not the class name.
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantCoerce(b.getLogicalClass().getName(), "Fixnum", this));
}
}

@Specialization(rewriteOn = ArithmeticException.class)
public long add(long a, int b) {
return ExactMath.addExact(a, b);
Expand Down Expand Up @@ -131,6 +149,15 @@ public Object add(long a, RubyBignum b) {
return fixnumOrBignum(bignum(a).add(b));
}

@Specialization
public Object add(VirtualFrame frame, long a, RubyBasicObject b) {
if (b.getLogicalClass() == getContext().getCoreLibrary().getRationalClass()) {
return rationalAdd.call(frame, b, "+", null, a);
} else {
// TODO (nirvdrum Jan. 7, 2015) Figure out what the proper exception message format is -- Symbols show the value, not the class name.
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantCoerce(b.getLogicalClass().getName(), "Fixnum", this));
}
}
}

@CoreMethod(names = "-", required = 1)
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
Expand Up @@ -78,6 +78,7 @@ public class CoreLibrary {
@CompilerDirectives.CompilationFinal private RubyClass processClass;
@CompilerDirectives.CompilationFinal private RubyClass rangeClass;
@CompilerDirectives.CompilationFinal private RubyClass rangeErrorClass;
@CompilerDirectives.CompilationFinal private RubyClass rationalClass;
@CompilerDirectives.CompilationFinal private RubyClass regexpClass;
@CompilerDirectives.CompilationFinal private RubyClass regexpErrorClass;
@CompilerDirectives.CompilationFinal private RubyClass rubyTruffleErrorClass;
Expand Down Expand Up @@ -243,6 +244,7 @@ public void initialize() {
rangeClass = new RubyClass(context, objectClass, objectClass, "Range");
rangeErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RangeError");
rangeErrorClass.setAllocator(new RubyException.ExceptionAllocator());
rationalClass = new RubyClass(context, objectClass, numericClass, "Rational");
regexpClass = new RubyClass(context, objectClass, objectClass, "Regexp");
regexpClass.setAllocator(new RubyRegexp.RegexpAllocator());
regexpErrorClass = new RubyClass(context, objectClass, standardErrorClass, "RegexpError");
Expand Down Expand Up @@ -599,6 +601,11 @@ public RubyException typeErrorBadCoercion(Object from, String to, String coercio
getLogicalClass(coercedTo).getName()), currentNode);
}

public RubyException typeErrorCantCoerce(Object from, String to, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return typeError(String.format("%s can't be coerced into %s", from, to), currentNode);
}

public RubyException nameError(String message, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(nameErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
Expand Down Expand Up @@ -788,6 +795,10 @@ public RubyClass getRangeClass() {
return rangeClass;
}

public RubyClass getRationalClass() {
return rationalClass;
}

public RubyClass getRegexpClass() {
return regexpClass;
}
Expand Down

0 comments on commit 79b8135

Please sign in to comment.