Take this spec:
I've reimplemented it here for simplicity:
class Mock
def coerce(x)
[1, 10]
end
end
p 1.fdiv(Mock.new)That calls fdiv on a Fixnum:
def fdiv(other)
self.to_f / other
endThat converts the receiver to a Float and calls /. As the RHS is a Mock the primitive for Float#/ will fail and will call redo_coerced.
def divide(other)
Rubinius.primitive :float_div
redo_coerced :/, other
endThat calls other.coerce. Our mock object returns [1, 10] for this. Then we re-call / on the first value, with the operand as the right value. That's 1./(10). That does integral division.
def math_coerce(other, error=:coerce_error)
begin
values = other.coerce(self)
rescue
if error == :coerce_error
raise TypeError, "#{other.class} can't be coerced into #{self.class}"
else
raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
end
end
unless Rubinius::Type.object_kind_of?(values, Array) && values.length == 2
raise TypeError, "coerce must return [x, y]"
end
return values[1], values[0]
end
def redo_coerced(meth, right)
b, a = math_coerce(right)
a.__send__ meth, b
endSo why does the test produce a Float, 0.1? When I run this code in Truffle I get a Fixnum, 0, which makes sense to me reading the code, but it isn't right.