Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Kernel conversion methods #1445

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions core/kernel.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,10 @@ module Kernel : BasicObject
#
# Array(:foo) # => [:foo]
#
def self?.Array: (NilClass x) -> [ ]
| [T] (::Array[T] x) -> ::Array[T]
| [T] (::Range[T] x) -> ::Array[T]
| [T] (_Each[T] x) -> ::Array[T]
| [K, V] (::Hash[K, V] x) -> ::Array[[ K, V ]]
| [T] (T x) -> ::Array[T]
def self?.Array: (nil) -> []
| [T] (Array[T] ary) -> Array[T]
| [T] (_ToAry[T] | _ToA[T] array_like) -> Array[T]
| [T] (T ele) -> [T]

# <!--
# rdoc-file=complex.c
Expand Down Expand Up @@ -446,8 +444,11 @@ module Kernel : BasicObject
#
# See String#to_c.
#
def self?.Complex: (Numeric | String x, ?Numeric | String y, ?exception: bool exception) -> Complex

def self?.Complex: (_ToC complex_like, ?exception: true) -> Complex
| (_ToC complex_like, exception: bool) -> Complex?
| (Numeric | String real, ?Numeric | String imag, ?exception: true) -> Complex
| (Numeric | String real, ?Numeric | String imag, exception: bool) -> Complex?
| (untyped, ?untyped, exception: false) -> nil
# <!--
# rdoc-file=kernel.rb
# - Float(arg, exception: true) -> float or nil
Expand All @@ -464,8 +465,9 @@ module Kernel : BasicObject
# Float(nil) #=> TypeError: can't convert nil into Float
# Float("123.0_badstring", exception: false) #=> nil
#
def self?.Float: (Numeric | String x, ?exception: bool exception) -> Float

def self?.Float: (_ToF float_like, ?exception: true) -> Float
| (_ToF float_like, exception: bool) -> Float?
| (untyped, exception: false) -> nil
# <!--
# rdoc-file=object.c
# - Hash(object) -> object or new_hash
Expand All @@ -488,7 +490,8 @@ module Kernel : BasicObject
# Hash(nil) # => {}
# Hash([]) # => {}
#
def self?.Hash: [K, V] (Object x) -> ::Hash[K, V]
def self?.Hash: [K, V] (nil | [] _empty) -> Hash[K, V]
sampersand marked this conversation as resolved.
Show resolved Hide resolved
| [K, V] (_ToHash[K, V] hash_like) -> Hash[K, V]

# <!--
# rdoc-file=object.c
Expand Down Expand Up @@ -574,9 +577,11 @@ module Kernel : BasicObject
# With `exception` given as `false`, an exception of any kind is suppressed and
# `nil` is returned.
#
def self?.Integer: (Numeric | String arg, ?exception: bool exception) -> Integer
| (String arg, ?Integer base, ?exception: bool exception) -> Integer

def self?.Integer: (_ToInt | _ToI int_like, ?exception: true) -> Integer
| (_ToInt | _ToI int_like, exception: bool) -> Integer?
| (string str, ?int base, ?exception: true) -> Integer
| (string str, ?int base, exception: bool) -> Integer?
| (untyped, ?untyped, exception: false) -> nil
# <!--
# rdoc-file=rational.c
# - Rational(x, y, exception: true) -> rational or nil
Expand Down Expand Up @@ -614,7 +619,17 @@ module Kernel : BasicObject
#
# See also String#to_r.
#
def self?.Rational: (Numeric | String | Object x, ?Numeric | String y, ?exception: bool exception) -> Rational
def self?.Rational: (_ToInt | _ToR rational_like, ?exception: true) -> Rational
| (_ToInt | _ToR rational_like, exception: bool) -> Rational?
| (_ToInt | _ToR numer, ?_ToInt | _ToR denom, ?exception: true) -> Rational
| (_ToInt | _ToR numer, ?_ToInt | _ToR denom, exception: bool) -> Rational?
| [T] (Numeric&_RationalDiv[T] numer, Numeric denom, ?exception: bool) -> T
| [T < Numeric] (T value, 1, ?exception: bool) -> T
| (untyped, ?untyped, exception: false) -> nil

interface _RationalDiv[T]
sampersand marked this conversation as resolved.
Show resolved Hide resolved
def /: (Numeric) -> T
end

# <!--
# rdoc-file=object.c
Expand All @@ -630,7 +645,7 @@ module Kernel : BasicObject
#
# Raises `TypeError` if `object` cannot be converted to a string.
#
def self?.String: (_ToStr | _ToS x) -> String
def self?.String: (string | _ToS string_like) -> String

# <!--
# rdoc-file=eval.c
Expand Down
104 changes: 90 additions & 14 deletions test/stdlib/Kernel_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,49 +285,125 @@ def test_untaint

def test_Array
Array(nil)
Array('foo')
Array(['foo'])
Array(1..4)
Array({foo: 1})

# We add the `.first.whatever` tests to make sure that we're being returned the right type.
Array([1,2,3]).first.even?
Array(ToArray.new(1,2)).first.even?
Array(ToA.new(1,2)).first.even?
Array(1..4).first.even?
Array({34 => 'hello'}).first.first.even?

Array('foo').first.upcase
Array(['foo']).first.upcase
end

def test_Complex
Complex(1.3)
Complex(42)
Complex(1, 2)
Complex('42', exception: true)
Complex(1.3).real?
Complex(1.3, exception: true).real?
Complex(1.3, exception: false)&.real?
Complex(1.3, exception: $VERBOSE)&.real? # `$VERBOSE` is an undecidable-at-compile-time bool.

Complex('1+2i')
Complex(1r)
Complex(Class.new(Numeric).new)

# The `Kernel#Complex` function is the only place in the entire stdlib that uses `.to_c`
def (obj = BasicObject.new).to_c
1+3i
end
Complex(obj)

Complex(1.3, '1i')
Complex(Class.new(Numeric).new, "1")
end

def test_Float
Float(42)
Float(42).infinite?
Float(42, exception: true).real?
Float(42, exception: false)&.real?
Float(42, exception: $VERBOSE)&.real? # `$VERBOSE` is an undecidable-at-compile-time bool.

Float(1.4)
Float('1.4')
Float('1.4', exception: true)
Float(ToF.new)
end

def test_Hash
Hash(nil)
Hash([])

Hash({key: 1})
Hash(ToHash.new)
end

def test_Integer
Integer(42)
Integer(42).even?
Integer(42, exception: true).even?
Integer(42, exception: false)&.even?
Integer(42, exception: $VERBOSE)&.even? # `$VERBOSE` is an undecidable-at-compile-time bool.

Integer(2.3)
Integer('2', exception: true)
Integer('11', 2, exception: true)
Integer(ToInt.new)
Integer(ToI.new)

Integer('2').even?
Integer('2', exception: true).even?
Integer('2', exception: false)&.even?
Integer('2', exception: $VERBOSE)&.even? # `$VERBOSE` is an undecidable-at-compile-time bool.

Integer('11', 2)
Integer(ToStr.new('11'), ToInt.new(12))
end

# These two classes are required to for `test_Rational`, and the `Class.new(Numeric)` construct
# doesn't type check them properly (yet.)
class Rational_RationalDiv < Numeric
def /(numeric) "Hello!" end
end
class Rational_OneCase < Numeric
def __unique_method_name__; 34 end
end

def test_Rational
Rational(42)
Rational(42).integer?
Rational(42, exception: true).integer?
Rational(42, exception: false)&.integer?
Rational(42, exception: $VERBOSE)&.integer? # `$VERBOSE` is an undecidable-at-compile-time bool.

def (test_rational = BasicObject.new).to_r
1r
end

Rational(ToInt.new)
Rational(test_rational)

Rational(42.0, 3)
Rational('42.0', 3, exception: true)
Rational(ToInt.new, test_rational)
Rational(test_rational, ToInt.new, exception: false)

rational_div = Rational_RationalDiv.new
# `Rational` ignores `exception:` in the `_RationalDiv` variant.
Rational(rational_div, Class.new(Numeric).new).upcase
Rational(rational_div, Class.new(Numeric).new, exception: true).upcase
Rational(rational_div, Class.new(Numeric).new, exception: false).upcase
Rational(rational_div, Class.new(Numeric).new, exception: $VERBOSE).upcase

one_case = Rational_OneCase.new
# `Rational` also ignores `exception:` in the `(Numeric, 1)` variant.
Rational(one_case, 1).__unique_method_name__
Rational(one_case, 1, exception: true).__unique_method_name__
Rational(one_case, 1, exception: false).__unique_method_name__
Rational(one_case, 1, exception: $VERBOSE).__unique_method_name__
end

def test_String
String('foo')
String([])
String(nil)

String(ToS.new)
String(ToStr.new)
end

def test___callee__
Expand Down
30 changes: 30 additions & 0 deletions test/stdlib/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,16 @@ def allows_error(*errors)
include VersionHelper
end

class ToI
def initialize(value = 3)
@value = value
end

def to_i
@value
end
end

class ToInt
def initialize(value = 3)
@value = value
Expand Down Expand Up @@ -432,6 +442,16 @@ def to_s
end
end

class ToA
def initialize(*args)
@args = args
end

def to_a
@args
end
end

class ToArray
def initialize(*args)
@args = args
Expand All @@ -440,6 +460,16 @@ def initialize(*args)
def to_ary
@args
end
end

class ToHash
def initialize(hash = { 'hello' => 'world' })
@hash = hash
end

def to_hash
@hash
end
end

class ToPath
Expand Down