Skip to content

Commit

Permalink
Merge pull request #1445 from sampersand/swesterman/23-08-19/update-k…
Browse files Browse the repository at this point in the history
…ernel-conversion-methods

Updated Kernel conversion methods
  • Loading branch information
soutaro authored Aug 22, 2023
2 parents 4f40cf4 + e537860 commit 5421329
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 27 deletions.
44 changes: 31 additions & 13 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,7 +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
Expand All @@ -464,7 +466,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
Expand All @@ -488,7 +492,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]
| [K, V] (_ToHash[K, V] hash_like) -> Hash[K, V]

# <!--
# rdoc-file=object.c
Expand Down Expand Up @@ -574,8 +579,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
Expand Down Expand Up @@ -614,7 +622,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]
def /: (Numeric) -> T
end

# <!--
# rdoc-file=object.c
Expand All @@ -630,7 +648,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

0 comments on commit 5421329

Please sign in to comment.