diff --git a/spec/ruby/core/integer/element_reference_spec.rb b/spec/ruby/core/integer/element_reference_spec.rb index 4c236a11e79b..7197ecdc0323 100644 --- a/spec/ruby/core/integer/element_reference_spec.rb +++ b/spec/ruby/core/integer/element_reference_spec.rb @@ -131,16 +131,10 @@ 0b000001[-3, 4].should == 0b1000 end - it "ignores negative upper boundary" do - 0b101001101[1..-1].should == 0b10100110 - 0b101001101[1..-2].should == 0b10100110 - 0b101001101[1..-3].should == 0b10100110 - end - it "ignores upper boundary smaller than lower boundary" do 0b101001101[4..1].should == 0b10100 0b101001101[4..2].should == 0b10100 - 0b101001101[4..3].should == 0b10100 + 0b101001101[-4..-5].should == 0b1010011010000 end it "raises FloatDomainError if any boundary is infinity" do diff --git a/spec/tags/core/integer/element_reference_tags.txt b/spec/tags/core/integer/element_reference_tags.txt deleted file mode 100644 index 8f3bb6b33cad..000000000000 --- a/spec/tags/core/integer/element_reference_tags.txt +++ /dev/null @@ -1,13 +0,0 @@ -fails:Integer#[] fixnum when index and length passed returns specified number of bits from specified position -fails:Integer#[] fixnum when index and length passed ensures n[i, len] equals to (n >> i) & ((1 << len) - 1) -fails:Integer#[] fixnum when index and length passed moves start position to the most significant bits when negative index passed -fails:Integer#[] fixnum when index and length passed ignores negative length -fails:Integer#[] fixnum when range passed returns bits specified by range -fails:Integer#[] fixnum when range passed ensures n[i..j] equals to (n >> i) & ((1 << (j - i + 1)) - 1) -fails:Integer#[] fixnum when range passed ensures n[i..] equals to (n >> i) -fails:Integer#[] fixnum when range passed moves lower boundary to the most significant bits when negative value passed -fails:Integer#[] fixnum when range passed ignores negative upper boundary -fails:Integer#[] fixnum when range passed ignores upper boundary smaller than lower boundary -fails:Integer#[] fixnum when range passed raises FloatDomainError if any boundary is infinity -fails:Integer#[] fixnum when range passed when passed (..i) returns 0 if all i bits equal 0 -fails:Integer#[] fixnum when range passed when passed (..i) raises ArgumentError if any of i bit equals 1 diff --git a/src/main/ruby/truffleruby/core/integer.rb b/src/main/ruby/truffleruby/core/integer.rb index 84e99cf478c1..caa7a40c05e3 100644 --- a/src/main/ruby/truffleruby/core/integer.rb +++ b/src/main/ruby/truffleruby/core/integer.rb @@ -59,9 +59,49 @@ def **(o) redo_coerced :**, o end - def [](index) + def [](index, len = undefined) + if index.kind_of?(Range) + handle_range(index) + else + handle_aref(index, len) + end + end + + private def handle_aref(index, len) index = Primitive.rb_to_int(index) - index < 0 ? 0 : (self >> index) & 1 + if Primitive.undefined?(len) + index < 0 ? 0 : (self >> index) & 1 + else + num = self >> index + mask = (1 << len) - 1 + + num & mask + end + end + + private def handle_range(range) + raise FloatDomainError , 'Infinity' if range.begin == Float::INFINITY || range.end == Float::INFINITY + raise FloatDomainError , '-Infinity' if range.begin == -Float::INFINITY || range.end == -Float::INFINITY + + if !Primitive.nil?(range.begin) && !Primitive.nil?(range.end) + len = range.end - range.begin + len += 1 if !range.exclude_end? + num = self >> range.begin + mask = (1 << len) - 1 + + range.end < range.begin ? num : num & mask + elsif Primitive.nil? range.end + + return self >> range.begin + else + len = range.end + len += 1 if !range.exclude_end? + mask = (1 << len) - 1 + + raise ArgumentError, 'The beginless range for Integer#[] results in infinity' if self & mask != 0 && range.end >= 0 + + 0 + end end def allbits?(mask) diff --git a/test/mri/excludes/TestInteger.rb b/test/mri/excludes/TestInteger.rb index cb20385870c9..71d3b1d31df1 100644 --- a/test/mri/excludes/TestInteger.rb +++ b/test/mri/excludes/TestInteger.rb @@ -11,5 +11,4 @@ exclude :test_floor, "needs investigation" exclude :test_pow, "needs investigation" exclude :test_truncate, "needs investigation" -exclude :test_Integer_with_invalid_exception, "needs investigation" -exclude :test_aref, "needs investigation" +exclude :test_Integer_with_invalid_exception, "needs investigation" \ No newline at end of file