A problem with unbound methods
Hi, I have some problems for translating calls to unbound methods. Let's show with an example: class MyClass: def __init__(self, x): self.x = x class MyDerivedClass(MyClass): def __init__(self, x): MyClass.__init__(self, x) During rtyping the field and method names are mangled, so the __init__ method became something like 'o__init____variant0': as long as I call bound methods this is not a problem because the low-level op oosend contains the right mangled name, but difficult arises when I try to call an unbound method such as the one showed above; the low-level op that I obtain is this: v9 = direct_call((<pypy.rpython.ootypesystem.ootype._static_meth object at 0xb78e51ac>), self_1, x_2) Let 'x = op.args[0].value': (Pdb) x._name 'Base.__init__' (Pdb) x.graph.name 'Base.__init__' As you can see I can read only the original unmangled name, but it is useless because I've to deal with the mangled one. I've tried to search around for a place where to read that but I couldn't find it. How can I do? thanks for the help ciao Anto
Antonio Cuni wrote:
Hi, I have some problems for translating calls to unbound methods. Let's show with an example:
class MyClass: def __init__(self, x): self.x = x
class MyDerivedClass(MyClass): def __init__(self, x): MyClass.__init__(self, x)
During rtyping the field and method names are mangled, so the __init__ method became something like 'o__init____variant0': as long as I call bound methods this is not a problem because the low-level op oosend contains the right mangled name, but difficult arises when I try to call an unbound method such as the one showed above; the low-level op that I obtain is this:
v9 = direct_call((<pypy.rpython.ootypesystem.ootype._static_meth object at 0xb78e51ac>), self_1, x_2)
Let 'x = op.args[0].value':
(Pdb) x._name 'Base.__init__' (Pdb) x.graph.name 'Base.__init__'
As you can see I can read only the original unmangled name, but it is useless because I've to deal with the mangled one. I've tried to search around for a place where to read that but I couldn't find it. How can I do?
you should not trust or use graph names in the backend, apart for givin names to things. If a function is reused in more than one class the information would not be useful (this can happen in Python/RPython). The graph would get the name based on the first class under which it was found, this may be unrelated for example for the class for self to the method name under which the graph is attached. Because there are too many variations about what is allowed in terms of supporting functions vs. just methods, calling superclass implementations of methods even when the method is overriden in a subclass etc in the targets, right now it is up to the backend to traverse and consider all classes and direct_calls and if the same graph appears both attached to a method (or methods) in a class (or classes) and in static method(s) in a direct call(s) decide what to do. This is also true in general for graphs that appear as more than on method in one place. Strategies here may vary from using a single static method (e.g. in Java) and having methods delegate to it, or if possible having just the method if the types of the first arguments in the direct call allow that approach ... regards
Hi Samuele, Samuele Pedroni wrote:
you should not trust or use graph names in the backend, apart for givin names to things. If a function is reused in more than one class the information would not be useful (this can happen in Python/RPython). The graph would get the name based on the first class under which it was found, this may be unrelated for example for the class for self to the method name under which the graph is attached.
nice to know this, I didn't know. I think I have to rethink to my approach for code generation...
Because there are too many variations about what is allowed in terms of supporting functions vs. just methods, calling superclass implementations of methods even when the method is overriden in a subclass etc in the targets, right now it is up to the backend to traverse and consider all classes and direct_calls and if the same graph appears both attached to a method (or methods) in a class (or classes) and in static method(s) in a direct call(s) decide what to do. This is also true in general for graphs that appear as more than on method in one place.
Ok, now it's clearer, thanks. So, to respond to my original question, I should create a sort of "graph database" to lookup when I need to know where have I put the code for that graph, right? Well, let's begin refactoring! :-) ciao Anto
Hi Antonio, On Thu, Apr 06, 2006 at 09:31:04PM +0200, Antonio Cuni wrote:
Ok, now it's clearer, thanks. So, to respond to my original question, I should create a sort of "graph database" to lookup when I need to know where have I put the code for that graph, right?
We could try to do this in a way that is reusable between multiple back-ends, because many OO back-ends will have a similar problem. What needs to be done is to collect all graphs and see how they are used. For each graph, it means: which regular method(s) are implemented with that graph, and which direct_calls are done to staticmethods implemented with that graph. Then we need some cases. We can be more sutble, but as a minimum we need logic like: if a graph is used only as one method, leave it alone. If it is used only as a static method, leave it alone too (and declare it as a static method somewhere). For more complicated cases, find all methods implemented with this graph, and replace each of them with a new stub graph that just contains a direct_call to the original graph as a static method. Such a transformation would "normalize" the methods in the OOClass objects (so that the approach you're currently using in CLI would continue to work for methods) and also generate a list of remaining graphs that the back-end needs to declare as static methods. A bientot, Armin.
Hi Armin, Armin Rigo wrote:
We could try to do this in a way that is reusable between multiple back-ends, because many OO back-ends will have a similar problem. What needs to be done is to collect all graphs and see how they are used. For each graph, it means: which regular method(s) are implemented with that graph, and which direct_calls are done to staticmethods implemented with that graph.
Then we need some cases. We can be more sutble, but as a minimum we need logic like: if a graph is used only as one method, leave it alone. If it is used only as a static method, leave it alone too (and declare it as a static method somewhere). For more complicated cases, find all methods implemented with this graph, and replace each of them with a new stub graph that just contains a direct_call to the original graph as a static method.
Such a transformation would "normalize" the methods in the OOClass objects (so that the approach you're currently using in CLI would continue to work for methods) and also generate a list of remaining graphs that the back-end needs to declare as static methods.
It sounds reasonable. At the moment by backend suffers just this problem: is a graph is used both as bound and unbound method it will be rendered twice. I though to resolve it in some CLI specific way, but a more general approach is better. By now the few logic I do is localized in translator/cli/database.py, but it is too CLI specific to be reusable: maybe I could try to factor out the backend-independent logic for later reuse. Another good thing to factor out could be the "pending nodes" logic: at the moment both gencli and gensqueak implements that logic independently, but it would be nice to have a reusable framework shared by gensqueak, gencli and possibly other backends. ciao Anto
participants (3)
-
Antonio Cuni
-
Armin Rigo
-
Samuele Pedroni