-
Notifications
You must be signed in to change notification settings - Fork 79
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
dialects: (builtin) Fix documentation for parsing of bools, and add conversion to Python bool #3689
base: main
Are you sure you want to change the base?
dialects: (builtin) Fix documentation for parsing of bools, and add conversion to Python bool #3689
Conversation
…he integer values of booleans. Added `to_bool` to IntegerAttr (xdslproject#3684)
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3689 +/- ##
==========================================
+ Coverage 91.30% 91.31% +0.01%
==========================================
Files 466 467 +1
Lines 58357 58493 +136
Branches 5624 5640 +16
==========================================
+ Hits 53280 53411 +131
- Misses 3628 3632 +4
- Partials 1449 1450 +1 ☔ View full report in Codecov by Sentry. |
xdsl/dialects/builtin.py
Outdated
def to_bool(self) -> bool: | ||
# Do assertion, yes, no? | ||
assert self.type == i1 | ||
return bool(self.value.data) |
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.
def to_bool(self) -> bool: | |
# Do assertion, yes, no? | |
assert self.type == i1 | |
return bool(self.value.data) | |
def __bool__(self) -> bool: | |
"""Returns True if value is non-zero.""" | |
return bool(self.value.data) |
tests/dialects/test_builtin.py
Outdated
with pytest.raises(AssertionError): | ||
IntegerAttr(1, i8).to_bool() | ||
|
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.
Yeah I don't think we need to be this strict, I'm happy to follow C/Python's truthiness as being non-zero.
Why not |
Huh, I didn't think about that. Could that mess with checks where one checks if an optional attribute/property is present? E.g.:
I think a saw a few of those checks. 🤔 |
This is an antipattern and should never be used, for precisely this reason :) I would like to move towards more functions using attributes for calculations instead of python integers, and this is a valid use for them, I would argue that we want this functionality for them also. I would recommend making the change, and then waiting for @math-fehr and @alexarice's reviews before merging. |
A test failed because there was such an if. This could potentially break a lot of code of people who use xDSL. |
Whether or not it is an antipattern, I feel that we have used conversion to bool in place of "is not None" in a lot of places and I'm not sure there's a good way to find all the places. |
I would personally not overload bool, and would probably name the function |
def __bool__(self) -> bool: | ||
"""Returns True if value is non-zero.""" | ||
return bool(self.data) | ||
|
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.
would be good to add unit tests for this for good measure
@alexarice I've been pretty consistent in my PR reviews to discourage this approach, and I feel that we're actually in a good place here, modulo the two uses of it in csl. @math-fehr, why not? I don't see why we shouldn't be able to use integer attrs as idiomatic Python integers, whether it's IntAttr or IntegerAttr. |
My memory is that we've changed a few |
If I had anything to do with it it would have been the other way around, which is hopefully why all the tests pass with this change. |
One thing you might want to consider when going with if bool_attr is True:
# Do stuff or if bool_attr is False:
# Do stuff You could argue that this code is simply wrong but it's a code a beginner might write (or someone who likes to make things very explicit). Basically the programmers would have to know when they can use a IntegerAttr like a bool and in what situations they shouldn't. Now, whether you really want to cater to beginner programmers is another question. As another side note: What about adding a function |
Pyright should flag that as the types have no overlap, so I don't think it's a significant concern. |
I'm not sure that it would be a good idea to add that helper, it's not really shorter or easier to understand than |
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.
Some small comments. If we're happy that we won't be introducing bugs, I'm happy with using __bool__
(and don't think we should have a helper for is not None
though I can only see references to that in the discussion and not the code)
|
||
|
||
def test_IntegerAttr___bool__(): | ||
assert not IntegerAttr.from_bool(False) |
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.
assert not IntegerAttr.from_bool(False) | |
assert not BoolAttr.from_bool(False) |
Super nit and probably doesn't really matter
|
||
def test_IntegerAttr___bool__(): | ||
assert not IntegerAttr.from_bool(False) | ||
assert IntegerAttr.from_bool(True) |
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.
assert IntegerAttr.from_bool(True) | |
assert BoolAttr.from_bool(True) |
@@ -45,7 +45,7 @@ def parse_optional_integer( | |||
""" | |||
Parse an (possible negative) integer. The integer can either be | |||
decimal or hexadecimal. | |||
Optionally allow parsing of 'true' or 'false' into 1 and 0. | |||
Optionally allow parsing of 'true' or 'false' into -1 and 0. |
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.
This does not agree with the implementation below
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 does though
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.
Ah actually not 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.
You're right, all of the functions with the changed documentation here return the 1/0 values, it's only when creating the attribute that the value is different. This should be reflected in documentation for the attribute, not the parser.
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.
Yes, I did not put a comment on the doc change for the attribute
@@ -78,7 +78,7 @@ def parse_integer( | |||
""" | |||
Parse an (possible negative) integer. The integer can | |||
either be decimal or hexadecimal. | |||
Optionally allow parsing of 'true' or 'false' into 1 and 0. | |||
Optionally allow parsing of 'true' or 'false' into -1 and 0. |
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.
Same here
@@ -121,7 +121,7 @@ def parse_optional_number( | |||
) -> int | float | None: | |||
""" | |||
Parse a (possibly negative) integer or float literal, if present. | |||
Can optionally parse 'true' or 'false' into 1 and 0. | |||
Can optionally parse 'true' or 'false' into -1 and 0. |
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.
Same here
@@ -149,7 +149,7 @@ def parse_number( | |||
) -> int | float: | |||
""" | |||
Parse a (possibly negative) integer or float literal. | |||
Can optionally parse 'true' or 'false' into 1 and 0. | |||
Can optionally parse 'true' or 'false' into -1 and 0. |
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.
and here
Updated documentation in attribute_parser and base_parser regarding the integer values of bools.
Added
to_bool
to IntegerAttrSee issue #3684