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
Avoid using strings for exception_value of func_type #5710
Avoid using strings for exception_value of func_type #5710
Conversation
The main advantage is that we don't end up hugely sensitive to the exact string representation of a particular number. Fixes cython#5709
Cython/Compiler/ExprNodes.py
Outdated
@staticmethod | ||
def make_specific_const_node(pos, value, type): |
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 can probably build this automatically from the subclasses of ConstNode
and their types. That reduces the chance of forgetting to update this method. You forgot str_type
, at least.
https://stackoverflow.com/questions/3862310/how-to-find-all-the-subclasses-of-a-class-given-its-name
I think a less redundant name would be ConstNode.for_type()
.
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.
StringNode
is a subclass of PyConstNode
rather than ConstNode
so wouldn't be caught by the subclasses check. I also think it's difficult to do while still supporting Python 2.
I've changed the name 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.
I also think it's difficult to do while still supporting Python 2.
We are looking at the Cython literal type here, right? Not the Python object type? Then it's easy to do because we see these types in the source code.
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 more meant the __subclasses__
mechanism that is used by the stack overflow page that you linked doesn't exist in Python 2, so it's difficult to get a list of all the subclasses of ConstNode
Cython/Compiler/Nodes.py
Outdated
self.exception_value.calculate_constant_result() | ||
exc_val = self.exception_value.constant_result | ||
from .ExprNodes import constant_value_not_set | ||
if exc_val is None or exc_val is constant_value_not_set: |
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.
Isn't this something that ConstNode
could do? That would avoid the local import. Something like ExprNode.as_exception_value()
, where the default implementation would call error()
and subclasses could override it.
We should also make sure that this works for enum values etc., anything that is usable as exception value.
Cython/Compiler/Nodes.py
Outdated
self.exception_value = ConstNode( | ||
self.pos, value=return_type.exception_value, type=return_type) | ||
self.exception_value = ConstNode.for_type( | ||
self.pos, value=str(return_type.exception_value), type=return_type) | ||
if self.exception_value: |
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 changed this to is (not) None
in other places, so here as well? I still see a couple of other places where we use a plain if … self.exception_value …:
, e.g. in the error check just a bit up.
if self.exception_value: | |
if self.exception_value is not None: |
Cython/Compiler/ExprNodes.py
Outdated
@@ -1311,6 +1330,29 @@ def calculate_result_code(self): | |||
def generate_result_code(self, code): | |||
pass | |||
|
|||
@staticmethod | |||
def for_type(pos, value, type): |
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.
Might be worth adding a constant_result
as well, while we're at 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.
I'm slightly unclear what this means.
I'll add calculate_constant_result()
to the value before returning it, but it's possible I've missed the point 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.
I meant to set the attribute (explicitly) when creating the node instance. Calling calculate_constant_result()
is allowed to fail, so we should not use it outside of the ConstantFolding
transform.
You could pass the constant_result
also as an optional argument into this method, so that callers can decide if and how to calculate it. Default should probably be constant_value_not_set
. Or calculate it here based on the type and value.
This is similar to Parsing.wrap_compile_time_constant()
, BTW, although that has a slightly different focus. I'm not implying that there is room for reuse, though…
Cython/Compiler/ExprNodes.py
Outdated
result = None | ||
with local_errors(ignore=True): | ||
result = self.compile_time_value(env) | ||
if isinstance(result, Symtab.Entry): | ||
result = result.cname |
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.
compile_time_value()
is used at parse time, which is long over here. This is called during the analysis phase. It seems better to use self.entry
and the constant result value.
Isn't the constant result calculated already at this point?
|
Cython/Compiler/ExprNodes.py
Outdated
@@ -1311,6 +1330,29 @@ def calculate_result_code(self): | |||
def generate_result_code(self, code): | |||
pass | |||
|
|||
@staticmethod | |||
def for_type(pos, value, type): |
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 meant to set the attribute (explicitly) when creating the node instance. Calling calculate_constant_result()
is allowed to fail, so we should not use it outside of the ConstantFolding
transform.
You could pass the constant_result
also as an optional argument into this method, so that callers can decide if and how to calculate it. Default should probably be constant_value_not_set
. Or calculate it here based on the type and value.
This is similar to Parsing.wrap_compile_time_constant()
, BTW, although that has a slightly different focus. I'm not implying that there is room for reuse, though…
Co-authored-by: scoder <stefan_ml@behnel.de>
The main advantage is that we don't end up hugely sensitive to the exact string representation of a particular number.
Fixes #5709