Permalink
Browse files

Move String#to_dbl to Rubinius::Type::coerce_to_float

This change broke the behavior of many Math methods that do not accept
string arguments. To fix this, Rubinius::Type::coerce_to_float_for_numeric
was added and is analogous to MRI's rb_to_float.
  • Loading branch information...
1 parent 8601f64 commit d9b379aec115b7fca5a33787da09a3bfda8c0ab3 @zaeleus committed Mar 27, 2012
@@ -10,7 +10,7 @@ def self.pattern(size, str)
end
def to_f
- to_dbl(false)
+ Rubinius::Type::coerce_to_float self
end
alias_method :convert_float, :to_f
@@ -130,9 +130,4 @@ def resize_capacity(count)
Rubinius.primitive :string_resize_capacity
raise PrimitiveFailure, "String#resize_capacity failed"
end
-
- def to_dbl(strict)
- Rubinius.primitive :string_to_dbl
- raise ArgumentError, "invalid value for Float"
- end
end
View
@@ -11,5 +11,16 @@ def self.coerce_to_array(obj)
# array if it's not one.
return obj.to_a
end
+
+ def self.coerce_to_float(obj, strict=false)
+ case obj
+ when String
+ value = Rubinius.invoke_primitive :string_to_f, obj, strict
+ raise ArgumentError, "invalid value for Float" if value.nil?
+ value
+ else
+ Float(obj)
+ end
+ end
end
end
View
@@ -13,6 +13,23 @@ def self.coerce_to_array(obj)
return [obj]
end
+ def self.coerce_to_float(obj, strict=false)
+ case obj
+ when Numeric
+ coerce_to obj, Float, :to_f
+ when Float
+ return obj
+ when String
+ value = Rubinius.invoke_primitive :string_to_f, obj, strict
+ raise ArgumentError, "invalid value for Float" if value.nil?
+ value
+ when nil, true, false
+ raise TypeError, "can't convert #{obj.inspect} into Float"
+ else
+ raise TypeError, "can't convert #{obj.class} into Float"
+ end
+ end
+
def self.object_encoding(obj)
Rubinius.primitive :encoding_get_object_encoding
raise PrimitiveFailure, "Rubinius::Type.object_encoding primitive failed"
@@ -132,7 +132,7 @@ def Float(obj)
when Float
obj
when String
- obj.to_dbl(true)
+ Rubinius::Type.coerce_to_float(obj, true)
else
coerced_value = Rubinius::Type.coerce_to(obj, Float, :to_f)
if coerced_value.nan?
@@ -220,7 +220,7 @@ def Float(obj)
when Float
obj
when String
- obj.to_dbl(true)
+ Rubinius::Type.coerce_to_float(obj, true)
else
Rubinius::Type.coerce_to(obj, Float, :to_f)
end
View
@@ -15,25 +15,25 @@ class DomainError < SystemCallError
end
def atan2(y, x)
- y = Rubinius::Type.coerce_to_float y
- x = Rubinius::Type.coerce_to_float x
+ y = Rubinius::Type.coerce_to_float_for_numeric y
+ x = Rubinius::Type.coerce_to_float_for_numeric x
FFI::Platform::Math.atan2 y, x
end
def cos(x)
- FFI::Platform::Math.cos Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.cos Rubinius::Type.coerce_to_float_for_numeric(x)
end
def sin(x)
- FFI::Platform::Math.sin Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.sin Rubinius::Type.coerce_to_float_for_numeric(x)
end
def tan(x)
- FFI::Platform::Math.tan Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.tan Rubinius::Type.coerce_to_float_for_numeric(x)
end
def acos(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'acos' unless x.abs <= 1.0
@@ -45,43 +45,43 @@ def acos(x)
end
def asin(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'asin' unless x.abs <= 1.0
FFI::Platform::Math.asin x
end
def atan(x)
- FFI::Platform::Math.atan Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.atan Rubinius::Type.coerce_to_float_for_numeric(x)
end
def cosh(x)
- FFI::Platform::Math.cosh Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.cosh Rubinius::Type.coerce_to_float_for_numeric(x)
end
def sinh(x)
- FFI::Platform::Math.sinh Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.sinh Rubinius::Type.coerce_to_float_for_numeric(x)
end
def tanh(x)
- FFI::Platform::Math.tanh Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.tanh Rubinius::Type.coerce_to_float_for_numeric(x)
end
def acosh(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'acosh' unless x >= 1.0
FFI::Platform::Math.acosh x
end
def asinh(x)
- FFI::Platform::Math.asinh Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.asinh Rubinius::Type.coerce_to_float_for_numeric(x)
end
# This is wierd, but we need to only do the ERANGE check if
# there is an ERANGE.
if Errno.const_defined?(:ERANGE)
def atanh(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'atanh' unless x.abs <= 1.0
FFI::Platform::POSIX.errno = 0
@@ -101,7 +101,7 @@ def atanh(x)
else
def atanh(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'atanh' unless x.abs <= 1.0
FFI::Platform::POSIX.errno = 0
@@ -114,29 +114,29 @@ def atanh(x)
end
def exp(x)
- FFI::Platform::Math.exp Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.exp Rubinius::Type.coerce_to_float_for_numeric(x)
end
def log2(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'log2' unless x >= 0.0
FFI::Platform::Math.log2 x
end
def log10(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'log10' unless x >= 0.0
FFI::Platform::Math.log10 x
end
def sqrt(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'sqrt' unless x >= 0.0
FFI::Platform::Math.sqrt x
end
def frexp(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
FFI::MemoryPointer.new :int do |exp|
result = FFI::Platform::Math.frexp x, exp
[result, exp.read_int]
@@ -146,7 +146,7 @@ def frexp(x)
def ldexp(x, n)
n = Rubinius::Type.coerce_to(n, Integer, :to_int)
- FFI::Platform::Math.ldexp Rubinius::Type.coerce_to_float(x), n
+ FFI::Platform::Math.ldexp Rubinius::Type.coerce_to_float_for_numeric(x), n
end
# Rubinius-specific, used in Marshal
@@ -158,16 +158,16 @@ def modf(x)
end
def hypot(x, y)
- x = Rubinius::Type.coerce_to_float x
- y = Rubinius::Type.coerce_to_float y
+ x = Rubinius::Type.coerce_to_float_for_numeric x
+ y = Rubinius::Type.coerce_to_float_for_numeric y
FFI::Platform::Math.hypot x, y
end
def erf(x)
- FFI::Platform::Math.erf Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.erf Rubinius::Type.coerce_to_float_for_numeric(x)
end
def erfc(x)
- FFI::Platform::Math.erfc Rubinius::Type.coerce_to_float(x)
+ FFI::Platform::Math.erfc Rubinius::Type.coerce_to_float_for_numeric(x)
end
end
View
@@ -2,7 +2,7 @@
module Math
def log(x)
- x = Rubinius::Type.coerce_to_float(x)
+ x = Rubinius::Type.coerce_to_float_for_numeric(x)
raise DomainError, 'log' unless x >= 0.0
FFI::Platform::Math.log x
end
View
@@ -28,11 +28,11 @@ module Math
]
def cbrt(x)
- x = Rubinius::Type.coerce_to_float x
+ x = Rubinius::Type.coerce_to_float_for_numeric x
end
def gamma(x)
- x = Rubinius::Type.coerce_to_float x
+ x = Rubinius::Type.coerce_to_float_for_numeric x
return Float::INFINITY if x == 0.0
return Float::NAN if x.nan?
@@ -57,7 +57,7 @@ def gamma(x)
end
def lgamma(x)
- x = Rubinius::Type.coerce_to_float x
+ x = Rubinius::Type.coerce_to_float_for_numeric x
if sign = x.infinite?
raise DomainError, "lgamma" if sign == -1
@@ -72,12 +72,12 @@ def lgamma(x)
end
def log(x, base=undefined)
- x = Rubinius::Type.coerce_to_float x
+ x = Rubinius::Type.coerce_to_float_for_numeric x
raise DomainError, 'log' unless x >= 0.0
return -Float::INFINITY if x == 0.0
y = FFI::Platform::Math.log x
unless base.equal? undefined
- base = Rubinius::Type.coerce_to_float base
+ base = Rubinius::Type.coerce_to_float_for_numeric base
y /= log(base)
end
y
View
@@ -6,8 +6,8 @@ def self.coerce_to_path(obj)
StringValue(obj)
end
- def self.coerce_to_float(obj)
- Float(obj)
+ def self.coerce_to_float_for_numeric(obj)
+ coerce_to_float(obj, true)
end
def self.coerce_to_symbol(obj)
View
@@ -43,17 +43,20 @@ def self.coerce_to_path(obj)
end
end
- def self.coerce_to_float(obj)
- case obj
- when Numeric
- coerce_to obj, Float, :to_f
- when Float
- return obj
- when nil, true, false
- raise TypeError, "can't convert #{obj.inspect} into Float"
- else
- raise TypeError, "can't convert #{obj.class} into Float"
+ # Analogous to MRI's rb_to_float. This is primarily used in Math.
+ def self.coerce_to_float_for_numeric(obj)
+ return obj if object_kind_of? obj, Float
+
+ unless object_kind_of? obj, Numeric
+ case obj
+ when nil, true, false
+ raise TypeError, "can't convert #{obj.inspect} into Float"
+ else
+ raise TypeError, "can't convert #{obj.class} into Float"
+ end
end
+
+ coerce_to obj, Float, :to_f
end
def self.coerce_to_symbol(obj)
View
@@ -906,23 +906,13 @@ namespace rubinius {
Float* String::to_f(STATE, Object* strict) {
const char* str = c_str(state);
- if(strict == cTrue) {
- if(byte_size() > (native_int)strlen(str)) return nil<Float>();
+ if(strict == cTrue && byte_size() > (native_int)strlen(str)) {
+ return nil<Float>();
}
return Float::from_cstr(state, str, strict);
}
- Float* String::to_dbl_prim(STATE, Object* strict) {
- Float* value = String::to_f(state, strict);
-
- if(value->nil_p()) {
- return (Float*)Primitives::failure();
- }
-
- return value;
- }
-
// Character-wise logical AND of two strings. Modifies the receiver.
String* String::apply_and(STATE, String* other) {
native_int count;
View
@@ -175,11 +175,9 @@ namespace rubinius {
/** Append length bytes from C string. Returns self. */
String* append(STATE, const char* other, native_int length);
+ // Rubinius.primitive :string_to_f
Float* to_f(STATE, Object* strict = cTrue);
- // Rubinius.primitive :string_to_dbl
- Float* to_dbl_prim(STATE, Object* strict);
-
Integer* to_i(STATE, Fixnum* base = Fixnum::from(0), Object* strict = cTrue);
// Rubinius.primitive :string_to_inum

0 comments on commit d9b379a

Please sign in to comment.