-
Notifications
You must be signed in to change notification settings - Fork 193
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
force logical operator expr which in if-orelse stmt
to boolean
#1812
base: master
Are you sure you want to change the base?
Conversation
Thanks for the patch. I like the approach, but there are a few things to change to make your code more robust 👍
What I propose:
Does that sounds valid to you? |
@serge-sans-paille thanks for your review !
I will fix it soon
This transformation
sorry! It's buggy, flag
Do you mean convert explicit expression def foo():
flag = bool(x and y) # => flag = bool(x) and bool(y) Is it necessary to infer an def foo():
flag = x and y # flag should be converted to flag = bool(x) and bool(y) to avoid compile error
if flag:
do_something()
return 0 |
If I'm not mistaken your code will choke on something like
where I suggest to transform the above in
Then optimize it into
note: it's important to use an explicit path to
Does that make more sense now? |
I got it. Redefinition of # expand bool into logical stmt
bool(x and y) # => bool(x) and bool(y)
# combine continuous bool call
bool(bool(bool(x))) # => bool(x) |
I wrote special case like |
pm.apply(ExpandBuiltins, node) | ||
pm.apply(ExpandBooleanOperator, node) |
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 think these two (expand and combine) should be in the optimization pipeline, not in the transformation pipeline
def __init__(self): | ||
super(ExpandBooleanOperator, self).__init__() | ||
self._bool_call = False | ||
self._is_logical = 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.
note: You should set self.update =True
when you make any change to the AST.
|
||
def __init__(self): | ||
super(ExpandBooleanOperator, self).__init__() | ||
self._bool_call = 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.
Use stateful transformation like you do makes the code harder to follow. I think you could (non recursively) detect if a call is a call to builtin.bool, then swicth on the argument: if it's a BoolOp
node just distribute builtins.bool
over the arguments.
But maybe I'm missing something?
return self._is_logical and self._bool_call | ||
|
||
|
||
class CombineBoolCall(Transformation): |
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 should be a pattern in optimizations/pattern_transform.py
@wcsjtu any news on thatone? I like the way this PR is going, happy to provide help if needed |
I' m learning your code these day. I found its hard to pass information between def visit_AugAssign(self, node):
self.in_augassign = True
self.generic_visit(node)
self.in_augassign = False
|
type of logical operator stmt in python, such as
a and b
,a or b
is ambiguous. For exampleIn current implementation of
pythonic::builtins::pythran::and_
,when
a == "1"
, variableb
will be converted totypes::str tmp_str_b
implicitly viathen converted
bool tmp_bool_b
viawhich always
tmp_bool_b === true
。so, exprif "1" and False
in python isif False
, in c++ isif (true)
This pull request force
expr
in 'if-orelse' stmt tobool(expr)
to avoid implicit type coversion inpythonic::builtins::pythran::and_
here is the test code