-
Notifications
You must be signed in to change notification settings - Fork 185
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
Ruby 2.7: Better support of Integer#[] with range arguments #2182
Ruby 2.7: Better support of Integer#[] with range arguments #2182
Conversation
Hello Igor Victor, thanks for contributing a PR to our project! We use the Oracle Contributor Agreement to make the copyright of contributions clear. We don't have a record of you having signed this yet, based on your email address gogainda -(at)- yandex -(dot)- ru. You can sign it at that link. If you think you've already signed it, please comment below and we'll check. |
80bbe8d
to
f77f2a2
Compare
Hello Igor Novokshonov, thanks for contributing a PR to our project! We use the Oracle Contributor Agreement to make the copyright of contributions clear. We don't have a record of you having signed this yet, based on your email address gogainda -(at)- yandex -(dot)- ru. You can sign it at that link. If you think you've already signed it, please comment below and we'll check. |
@@ -38,6 +38,7 @@ | |||
Object.deprecate_constant :Fixnum, :Bignum | |||
|
|||
class Integer < Numeric | |||
FIXNUM_MAX = 0x3fffffff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eregon not sure that it's safe to hardcode this value, but I did't find better solution, mb you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems odd to me we even need this value to implement Integer#[], do you know which arguments return it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Translating C code from MRI to Ruby leads to rather unreadable Ruby code, as you can see.
Could you try to write an implementation based on the specs/tests and not based on what MRI does in C code?
I think that would be a lot more readable.
I think you could use Primitive.range_normalized_start_length(range, self.bit_length)
to convert all kind of ranges to a [start, length]
pair, so there is no need to deal with various begin/endless Ranges explicitly.
Igor Novokshonov has signed the Oracle Contributor Agreement (based on email address gogainda -(at)- yandex -(dot)- ru) so can contribute to this repository. |
I rewrote the logic as you suggested, but not quite happy with results. |
I'm not sure to follow, do you have an example where it behaves differently on MRI? |
this implementation works as per element_reference_tags test, but some of the mri tests are still failing, this is why I reverted "exclude :test_aref, "needs investigation", specifically my impl is not correctly handling ranges starting with negative values. Should I try to come up with solution which will fix element_reference_tags and ruby mri tests? |
Yes, we should try to make it correct.
Yeah we call them "specs" and "MRI tests". |
@eregon all tests should be passing now. Additionally, I removed one misleading test case from specs |
@@ -38,6 +38,7 @@ | |||
Object.deprecate_constant :Fixnum, :Bignum | |||
|
|||
class Integer < Numeric | |||
FIXNUM_MAX = 0x3fffffff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this anymore.
if range.exclude_end? | ||
(1 << idx) - 1 | ||
else | ||
(1 << (idx +1)) - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ 1
end | ||
end | ||
|
||
private def validate_range(index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you inline this method?
raise FloatDomainError , '-Infinity' if index.begin == -Float::INFINITY || index.end == -Float::INFINITY | ||
end | ||
|
||
private def mask(range, idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move this logic in the two callers, and e.g. do len += 1 unless range.exclude_end?
so then it's just (1 << len) - 1
?
end | ||
end | ||
|
||
private def handle_aref(index, len) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have extra methods on Integer
, even if private
.
We should move them to class methods on a new Truffle::IntegerOperations
module.
I can do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I addressed all the comments apart from this one, not sure what I can do here. More general question, trying to avoid creating extra private methods is dictated by how truffleruby treats such code or it's code style preference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because a Ruby program might notice this, e.g. some Ruby program would defined a public Integer#handle_aref
, then it could conflict. It's also visible via private_methods
, send
, etc.
@eregon anything else I should do here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great now, thank you for the PR!
end | ||
end | ||
|
||
private def handle_aref(index, len) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because a Ruby program might notice this, e.g. some Ruby program would defined a public Integer#handle_aref
, then it could conflict. It's also visible via private_methods
, send
, etc.
@eregon do I need to squash it? btw, I forgot to add a change log |
#2182) PullRequest: truffleruby/2274
It's merged now, so it can't be squashed, but I think that's OK because the commits only touched that area of the code. Could you make a PR to add the ChangeLog entry? |
@gogainda Actually I'll make a PR adding the ChangeLog entry, I'm already doing another PR touching the ChangeLog anyway. |
Related to #2004
Implementing https://bugs.ruby-lang.org/issues/8842
This PR is basically translation of this commit to Ruby language
The only test which is not passing for Integer#[] is
which I am not sure how to fix currently (corrected: fixed)
Ruby code is not very idiomatic right now, but I will work on it later. As of now I will focus on review comments if any:)