Skip to content

Commit 7d97f4a

Browse files
committed
[Truffle] Fixnum#fdiv specs all passing.
1 parent 8c74bc3 commit 7d97f4a

File tree

7 files changed

+86
-1
lines changed

7 files changed

+86
-1
lines changed

core/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java

+1
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ public int div(@SuppressWarnings("unused") long a, @SuppressWarnings("unused") R
640640
// TODO(CS): not entirely sure this is correct
641641
return 0;
642642
}
643+
643644
}
644645

645646
@CoreMethod(names = "%", required = 1)

core/src/main/java/org/jruby/truffle/nodes/core/FloatNodes.java

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.oracle.truffle.api.utilities.ConditionProfile;
1818
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
1919
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
20+
import org.jruby.truffle.runtime.DebugOperations;
2021
import org.jruby.truffle.runtime.RubyCallStack;
2122
import org.jruby.truffle.runtime.RubyContext;
2223
import org.jruby.truffle.runtime.control.RaiseException;
@@ -254,6 +255,15 @@ public double div(double a, RubyBignum b) {
254255
return a / b.doubleValue();
255256
}
256257

258+
@Specialization(guards = {
259+
"!isInteger(arguments[1])",
260+
"!isLong(arguments[1])",
261+
"!isDouble(arguments[1])",
262+
"!isRubyBignum(arguments[1])"})
263+
public Object div(double a, Object b) {
264+
return DebugOperations.send(getContext(), a, "redo_coerced", null, getContext().getSymbolTable().getSymbol("/"), b);
265+
}
266+
257267
}
258268

259269
@CoreMethod(names = "%", required = 1)

core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/fixnum.rb

+8
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,12 @@ def coerce(other)
3333
super other
3434
end
3535

36+
def fdiv(n)
37+
if n.kind_of?(Fixnum)
38+
to_f / n
39+
else
40+
redo_coerced :fdiv, n
41+
end
42+
end
43+
3644
end

core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/float.rb

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828

2929
class Float < Numeric
3030

31+
def coerce(other)
32+
return [other, self] if other.kind_of? Float
33+
[Float(other), self]
34+
end
35+
3136
def to_r
3237
f, e = Math.frexp self
3338
f = Math.ldexp(f, MANT_DIG).to_i

core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/kernel.rb

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ def Rational(a, b = 1)
4242
end
4343
module_function :Rational
4444

45+
def Float(obj)
46+
case obj
47+
when String
48+
Rubinius::Type.coerce_string_to_float obj, true
49+
else
50+
Rubinius::Type.coerce_object_to_float obj
51+
end
52+
end
53+
module_function :Float
54+
4555
##
4656
# MRI uses a macro named StringValue which has essentially the same
4757
# semantics as obj.coerce_to(String, :to_str), but rather than using that

core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/numeric.rb

+52
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,58 @@
2828

2929
class Numeric
3030

31+
#--
32+
# We deviate from MRI behavior here because we ensure that Fixnum op Bignum
33+
# => Bignum (possibly normalized to Fixnum)
34+
#
35+
# Note these differences on MRI, where a is a Fixnum, b is a Bignum
36+
#
37+
# a.coerce b => [Float, Float]
38+
# b.coerce a => [Bignum, Bignum]
39+
#++
40+
41+
def coerce(other)
42+
if other.instance_of? self.class
43+
return [other, self]
44+
end
45+
46+
[Float(other), Float(self)]
47+
end
48+
49+
##
50+
# This method mimics the semantics of MRI's do_coerce function
51+
# in numeric.c. Note these differences between it and #coerce:
52+
#
53+
# 1.2.coerce("2") => [2.0, 1.2]
54+
# 1.2 + "2" => TypeError: String can't be coerced into Float
55+
#
56+
# See also Integer#coerce
57+
58+
def math_coerce(other, error=:coerce_error)
59+
begin
60+
values = other.coerce(self)
61+
rescue
62+
if error == :coerce_error
63+
raise TypeError, "#{other.class} can't be coerced into #{self.class}"
64+
else
65+
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
66+
end
67+
end
68+
69+
unless Rubinius::Type.object_kind_of?(values, Array) && values.length == 2
70+
raise TypeError, "coerce must return [x, y]"
71+
end
72+
73+
return values[1], values[0]
74+
end
75+
private :math_coerce
76+
77+
def redo_coerced(meth, right)
78+
b, a = math_coerce(right)
79+
a.__send__ meth, b
80+
end
81+
private :redo_coerced
82+
3183
def zero?
3284
self == 0
3385
end

spec/truffle/tags/core/fixnum/fdiv_tags.txt

-1
This file was deleted.

0 commit comments

Comments
 (0)