Skip to content

Commit a53f818

Browse files
committed
Update Kernel#Integer parameter conversion
1 parent 3ea67e4 commit a53f818

File tree

6 files changed

+48
-71
lines changed

6 files changed

+48
-71
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Bug fixes:
7070
* Fixed `ENV.udpate` implementation.
7171
* Fixed argument handling in `Kernel.printf`.
7272
* Fixed character length after conversion to binary from a non-US-ASCII String.
73+
* Fixed `Kernel#Integer` conversion.
7374

7475
Compatibility:
7576

lib/truffle/truffle/cext.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ def rb_intern(str)
781781
end
782782

783783
def rb_cstr_to_inum(string, base, raise)
784-
TrufflePrimitive.string_to_inum string, base, raise != 0
784+
TrufflePrimitive.string_to_inum string, base, raise != 0, true
785785
end
786786

787787
def rb_cstr_to_dbl(string, badcheck)

spec/tags/core/kernel/Integer_tags.txt

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/main/java/org/truffleruby/core/string/StringNodes.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4675,7 +4675,7 @@ protected boolean indexAtEitherBounds(DynamicObject string, int index) {
46754675
public static abstract class StringToInumPrimitiveNode extends PrimitiveArrayArgumentsNode {
46764676

46774677
@Specialization
4678-
protected Object stringToInum(DynamicObject string, int fixBase, boolean strict,
4678+
protected Object stringToInum(DynamicObject string, int fixBase, boolean strict, boolean raiseOnError,
46794679
@Cached("new()") FixnumOrBignumNode fixnumOrBignumNode,
46804680
@Cached RopeNodes.BytesNode bytesNode,
46814681
@Cached BranchProfile exceptionProfile) {
@@ -4690,6 +4690,9 @@ protected Object stringToInum(DynamicObject string, int fixBase, boolean strict,
46904690
strict);
46914691
} catch (RaiseException e) {
46924692
exceptionProfile.enter();
4693+
if (!raiseOnError) {
4694+
return nil();
4695+
}
46934696
throw e;
46944697
}
46954698
}

src/main/ruby/truffleruby/core/kernel.rb

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -88,44 +88,49 @@ def Hash(obj)
8888
end
8989
module_function :Hash
9090

91-
def Integer(obj, base=nil)
91+
def Integer(obj, base=0, exception: true)
9292
obj = Truffle::Interop.unbox_if_needed(obj)
93+
converted_base = Truffle::Type.rb_check_to_integer(base, :to_int)
94+
base = converted_base.nil? ? 0 : converted_base
95+
raise_exception = !exception.equal?(false)
9396

94-
if obj.kind_of? String
95-
if obj.empty?
96-
raise ArgumentError, 'invalid value for Integer: (empty string)'
97-
else
98-
base ||= 0
99-
return TrufflePrimitive.string_to_inum(obj, base, true)
100-
end
101-
end
102-
103-
if base
104-
raise ArgumentError, 'base is only valid for String values'
105-
end
106-
107-
case obj
108-
when Integer
109-
obj
110-
when Float
111-
if obj.nan? or obj.infinite?
112-
raise FloatDomainError, "unable to coerce #{obj} to Integer"
113-
else
114-
obj.to_int
115-
end
116-
when NilClass
117-
raise TypeError, "can't convert nil into Integer"
97+
if String === obj
98+
TrufflePrimitive.string_to_inum(obj, base, true, !exception.equal?(false))
11899
else
119-
# Can't use coerce_to or try_convert because I think there is an
120-
# MRI bug here where it will return the value without checking
121-
# the return type.
122-
if obj.respond_to? :to_int
123-
if val = obj.to_int
124-
return val
100+
bad_base_check = Proc.new do
101+
if base != 0
102+
return nil unless raise_exception
103+
raise ArgumentError, 'base is only valid for String values'
125104
end
126105
end
106+
case obj
107+
when Integer
108+
bad_base_check.call
109+
obj
110+
when Float
111+
bad_base_check.call
112+
if obj.nan? or obj.infinite?
113+
return nil unless raise_exception
114+
end
115+
# TODO BJF 14-Jan-2020 Add fixable conversion logic
116+
obj.to_int
117+
when NilClass
118+
bad_base_check.call
119+
return nil unless raise_exception
120+
raise TypeError, "can't convert nil into Integer"
121+
else
122+
if base != 0
123+
converted_to_str_obj = Truffle::Type.rb_check_convert_type(obj, String, :to_str)
124+
return TrufflePrimitive.string_to_inum(converted_to_str_obj, base, true, raise_exception) unless converted_to_str_obj.nil?
125+
return nil unless raise_exception
126+
raise ArgumentError, 'base is only valid for String values'
127+
end
128+
converted_to_int_obj = Truffle::Type.rb_check_to_integer(obj, :to_int)
129+
return converted_to_int_obj unless converted_to_int_obj.nil?
127130

128-
Truffle::Type.coerce_to obj, Integer, :to_i
131+
return Truffle::Type.rb_check_to_integer(obj, :to_i) unless raise_exception
132+
Truffle::Type.rb_convert_type(obj, Integer, :to_i)
133+
end
129134
end
130135
end
131136
module_function :Integer

src/main/ruby/truffleruby/core/string.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def lstrip
157157
end
158158

159159
def oct
160-
TrufflePrimitive.string_to_inum(self, -8, false)
160+
TrufflePrimitive.string_to_inum(self, -8, false, true)
161161
end
162162

163163
# Treats leading characters from <i>self</i> as a string of hexadecimal digits
@@ -169,7 +169,7 @@ def oct
169169
# "0".hex #=> 0
170170
# "wombat".hex #=> 0
171171
def hex
172-
TrufflePrimitive.string_to_inum(self, 16, false)
172+
TrufflePrimitive.string_to_inum(self, 16, false, true)
173173
end
174174

175175
def reverse
@@ -307,7 +307,7 @@ def to_i(base=10)
307307
raise ArgumentError, "illegal radix #{base}"
308308
end
309309

310-
TrufflePrimitive.string_to_inum(self, base, false)
310+
TrufflePrimitive.string_to_inum(self, base, false, true)
311311
end
312312

313313
def tr(source, replacement)
@@ -696,8 +696,8 @@ def upto(stop, exclusive=false)
696696

697697
begin
698698
# If both the start and end values are strings representing integer values, the encoding must be US-ASCII.
699-
TrufflePrimitive.string_to_inum(self, 10, true)
700-
TrufflePrimitive.string_to_inum(stop, 10, true)
699+
TrufflePrimitive.string_to_inum(self, 10, true, true)
700+
TrufflePrimitive.string_to_inum(stop, 10, true, true)
701701
enc = Encoding::US_ASCII
702702
rescue ArgumentError
703703
enc = self.encoding

0 commit comments

Comments
 (0)