[pypy-svn] r14014 - in pypy/dist/pypy: annotation rpython rpython/test translator/test

arigo at codespeak.net arigo at codespeak.net
Wed Jun 29 20:39:33 CEST 2005


Author: arigo
Date: Wed Jun 29 20:39:30 2005
New Revision: 14014

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/rpython/rclass.py
   pypy/dist/pypy/rpython/test/test_rclass.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
- the annotator assigns a slightly more precise 'classdef' in SomePBCs
  representing methods: if the method comes from a parent class but is
  read through a getattr() from an instance of a subclass, the 'classdef'
  is the subclass now.  This seems to be necessary for the rtyper.
  The PBC union of twice the same methods with different 'classdefs'
  just makes a PBC of the same method with the common 'classdef', without
  trying to be clever about moving the 'classdef' futher up to a class
  where the method is really defined.

- annotator test for the above.

- rtyper fix to handle this case (just removed a check).

- rtyper test for the above.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed Jun 29 20:39:30 2005
@@ -507,11 +507,7 @@
                     classdef2 = classdef
                     if classdef != d[x]:
                         classdef = classdef.commonbase(d[x])
-                        for cand in classdef.getmro():
-                            if x in cand.cls.__dict__.values():
-                                classdef = cand
-                                break
-                        else:
+                        if classdef is None:
                             raise UnionError(
                                 "confused pbc union trying unwarranted"
                                 "moving up of method %s from pair %s %s" %

Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Wed Jun 29 20:39:30 2005
@@ -336,7 +336,11 @@
                     continue # not matching
             d[func] = value
         if uplookup is not None:
-            d[upfunc] = uplookup
+            # when the method is found in a parent class, it get bound to the
+            # 'self' subclass.  This allows the 'func: classdef' entry of the
+            # PBC dictionary to track more precisely with which 'self' the
+            # method is called.
+            d[upfunc] = self
         elif meth:
             self.check_missing_attribute_update(name)
         if d:

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Wed Jun 29 20:39:30 2005
@@ -160,10 +160,10 @@
             count = 0
             for x, classdef in s_value.prebuiltinstances.items():
                 if isclassdef(classdef):
-                    if classdef.commonbase(self.classdef) != self.classdef:
-                        raise TyperError("methods from PBC set %r don't belong "
-                                         "in %r" % (s_value.prebuiltinstances,
-                                                    self.classdef.cls))
+                    #if classdef.commonbase(self.classdef) != self.classdef:
+                    #    raise TyperError("methods from PBC set %r don't belong "
+                    #                     "in %r" % (s_value.prebuiltinstances,
+                    #                                self.classdef.cls))
                     count += 1
                     classdef = True
                 debound[x] = classdef

Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py	Wed Jun 29 20:39:30 2005
@@ -109,3 +109,28 @@
 
     res = interpret(c, [])
     assert res is False
+
+def test_method_used_in_subclasses_only():
+    class A:
+        def meth(self):
+            return 123
+    class B(A):
+        pass
+    def f():
+        x = B()
+        return x.meth()
+    res = interpret(f, [])
+    assert res == 123
+
+def test_method_both_A_and_B():
+    class A:
+        def meth(self):
+            return 123
+    class B(A):
+        pass
+    def f():
+        a = A()
+        b = B()
+        return a.meth() + b.meth()
+    res = interpret(f, [])
+    assert res == 246

Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py	Wed Jun 29 20:39:30 2005
@@ -1361,6 +1361,25 @@
         assert isinstance(s2.dictdef.dictkey.  s_value, annmodel.SomeInteger)
         assert isinstance(s2.dictdef.dictvalue.s_value, annmodel.SomeInteger)
 
+    def test_pbc_union(self):
+        class A:
+            def meth(self):
+                return 12
+        class B(A):
+            pass
+        class C(B):
+            pass
+        def f(i):
+            if i:
+                f(0)
+                x = B()
+            else:
+                x = C()
+            return x.meth()
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s == a.bookkeeper.immutablevalue(12)
+
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list