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

pedronis at codespeak.net pedronis at codespeak.net
Wed Mar 2 19:40:07 CET 2005


Author: pedronis
Date: Wed Mar  2 19:40:07 2005
New Revision: 9590

Modified:
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/test/test_model.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/translator/test/snippet.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
don't bump classdef revision number if only a fresher revision in an attribute is involved,
notice that we still reflow even in this case.

contains logic modified to let caller distinguish this situation, RevDiff (a false value)
is returned if the only reason for a false contains relationship is rev numbers.

without these changes the new test analysing make_eo would recurse infinititely.



Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Wed Mar  2 19:40:07 2005
@@ -4,7 +4,7 @@
 
 from __future__ import generators
 from types import FunctionType
-from pypy.annotation.model import SomeImpossibleValue, unionof
+from pypy.annotation.model import SomeImpossibleValue, unionof, RevDiff
 
 
 class Attribute:
@@ -118,12 +118,25 @@
     def _generalize_attr(self, attr, s_value):
         # first remove the attribute from subclasses -- including us!
         subclass_attrs = []
+        was_here = attr in self.attrs
         for subdef in self.getallsubdefs():
             if attr in subdef.attrs:
                 subclass_attrs.append(subdef.attrs[attr])
                 del subdef.attrs[attr]
-            # bump the revision number of this class and all subclasses
-            subdef.revision += 1
+
+        bump = True
+        # don't bump if the only cause is rev diff discrepancies
+        if was_here and len(subclass_attrs) == 1 and s_value is not None:
+            old_attr = subclass_attrs[0]
+            wasgeneralenough = old_attr.s_value.contains(s_value)
+            assert not wasgeneralenough
+            if wasgeneralenough is RevDiff:
+                bump = False
+
+        if bump:
+            # bump the revision number of this class and all subclasses           
+            for subdef in self.getallsubdefs():
+                subdef.revision += 1
 
         # do the generalization
         newattr = Attribute(attr, self.bookkeeper)
@@ -140,11 +153,16 @@
 
     def generalize_attr(self, attr, s_value=None):
         # if the attribute exists in a superclass, generalize there.
+        found = 0
         for clsdef in self.getmro():
             if attr in clsdef.attrs:
-                clsdef._generalize_attr(attr, s_value)
-        else:
+                if found == 0:
+                    clsdef._generalize_attr(attr, s_value)
+                found += 1
+        if found == 0:
             self._generalize_attr(attr, s_value)
+        else:
+            assert found == 1, "generalization itself should prevent this"
 
     def about_attribute(self, name):
         for cdef in self.getmro():

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed Mar  2 19:40:07 2005
@@ -39,6 +39,31 @@
 DEBUG = True    # set to False to disable recording of debugging information
 
 
+# weak false, for contains in the case of SomeInstance revision differences
+
+class _RevDiff(object):
+    def __nonzero__(self):
+        return False
+
+    def __repr__(self):
+        return "RevDiff"
+
+RevDiff = _RevDiff()
+
+# False contains_and RevDiff = False
+# RevDiff contains_and False = False
+# RevDiff contains_and True = RevDiff
+# True contains_and RevDiff = RevDiff
+
+def contains_and(*args):
+    if False in args:
+        return False
+    if RevDiff in args:
+        return RevDiff
+    assert args == (True,) * len(args)
+    return True
+    
+
 class SomeObject:
     """The set of all objects.  Each instance stands
     for an arbitrary object about which nothing is known."""
@@ -77,6 +102,7 @@
         return self.hom_contains(s_union)
 
     # default hom_contains, hom_contains can assume self.__class__ == other.__class__
+    # IMPORTANT: use contains_and or equivalent in here
     def hom_contains(self, other):
         return pair(self, other).union() == self
     
@@ -153,9 +179,9 @@
         self.step = step
 
     def hom_contains(self, other):
-        return (self.start.contains(other.start) and
-                self.stop.contains(other.stop) and
-                self.step.contains(other.step))
+        return contains_and(self.start.contains(other.start),
+                            self.stop.contains(other.stop),
+                            self.step.contains(other.step))
 
 
 class SomeTuple(SomeObject):
@@ -174,11 +200,7 @@
         other_items = other.items
         if len(self.items) != len(self.items):
             return False
-        for i1, i2 in zip(self_items, other_items):
-            if not i1.contains(i2):
-                return False
-        return True
-
+        return contains_and(*[i1.contains(i2) for i1,i2 in zip(self_items, other_items)])
 
 
 class SomeDict(SomeObject):
@@ -190,7 +212,8 @@
         self.s_value = s_value
 
     def hom_contains(self, other):
-        return self.s_key.contains(other.s_key) and self.s_value.contains(other.s_value)
+        return contains_and(self.s_key.contains(other.s_key),
+                            self.s_value.contains(other.s_value))
 
 
 class SomeIterator(SomeObject):
@@ -215,7 +238,10 @@
 
     def hom_contains(self, other):
         if self.classdef is other.classdef:
-            return self.revision >= other.revision
+            if self.revision >= other.revision:
+                return True
+            else:
+                return RevDiff
         return self.classdef.commonbase(other.classdef) is self.classdef
 
 def new_or_old_class(c):
@@ -282,7 +308,11 @@
         self.s_self = s_self
 
     def hom_contains(self, other):
-        return self.analyser == other.analyser and (not self.s_self or self.s_self.contains(other.s_self))
+        if self.analyser != other.analyser:
+            return False
+        if self.s_self is None:
+            return other.s_self is None        
+        return self.s_self.contains(other.s_self)
 
 
 class SomeImpossibleValue(SomeObject):

Modified: pypy/dist/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_model.py	(original)
+++ pypy/dist/pypy/annotation/test/test_model.py	Wed Mar  2 19:40:07 2005
@@ -31,7 +31,108 @@
                                         (s4,s4),          (s4,s6),
                                         (s5,s4), (s5,s5), (s5,s6),
                                                           (s6,s6),
-                                                          (s7,s6), (s7, s7)])
+                                                          (s7,s6), (s7,s7)])
+
+             
+def test_contains_more():
+    from pypy.annotation import bookkeeper
+    bk = bookkeeper.Bookkeeper(None)
+    class C:
+        pass
+    C_classdef = bk.getclassdef(C)
+    si1 = SomeInstance(C_classdef)
+    C_classdef.revision += 1
+    si2 = SomeInstance(C_classdef)
+
+    assert s1.contains(si1)
+    assert si1.contains(si1)
+    assert si1.contains(s6)
+
+    assert si2.contains(si1)
+    assert not si1.contains(si2)
+    assert si1.contains(si2) is RevDiff
+
+    # dicts
+
+    sd1 = SomeDict({}, SomeString(), s1)
+    sd6 = SomeDict({}, SomeString(), s6)
+    sdi1 = SomeDict({}, SomeString(), si1)
+    sdi2 = SomeDict({}, SomeString(), si2)
+    sdi3 = SomeDict({}, SomeInteger(), si1)
+
+    assert sd1.contains(sdi1)
+    assert sdi1.contains(sdi1)
+    assert sdi1.contains(sd6)
+
+    assert sdi2.contains(sdi1)
+    assert not sdi1.contains(sdi2)
+    assert sdi1.contains(sdi2) is RevDiff
+
+    assert not sdi1.contains(sdi3)
+    assert sdi1.contains(sdi3) is False
+    assert not sdi3.contains(sdi1)
+    assert sdi3.contains(sdi1) is False
+
+    sdx = SomeDict({}, si1, SomeString())
+    sdy = SomeDict({}, si2, SomeString())
+
+    assert sdy.contains(sdx)
+    assert not sdx.contains(sdy)
+    assert sdx.contains(sdy) is RevDiff
+
+    sdz = SomeDict({}, si1, SomeInteger())
+    
+    assert not sdz.contains(sdx)
+    assert not sdx.contains(sdz)
+    assert sdz.contains(sdx) is False
+    assert sdx.contains(sdz) is False
+
+    # tuples
+
+    st1 = SomeTuple((SomeString(), s1))
+    st6 = SomeTuple((SomeString(), s6))
+    sti1 = SomeTuple((SomeString(), si1))
+    sti2 = SomeTuple((SomeString(), si2))
+    sti3 = SomeTuple((SomeInteger(), si1))
+
+    assert st1.contains(sti1)
+    assert sti1.contains(sti1)
+    assert sti1.contains(st6)
+
+    assert sti2.contains(sti1)
+    assert not sti1.contains(sti2)
+    assert sti1.contains(sti2) is RevDiff
+
+    assert not sti1.contains(sti3)
+    assert sti1.contains(sti3) is False
+    assert not sti3.contains(sti1)
+    assert sti3.contains(sti1) is False
+
+    stx = SomeTuple((si1, SomeString()))
+    sty = SomeTuple((si2, SomeString()))
+
+    assert sty.contains(stx)
+    assert not stx.contains(sty)
+    assert stx.contains(sty) is RevDiff
+
+    stz = SomeTuple((si1, SomeInteger()))
+    
+    assert not stz.contains(stx)
+    assert not stx.contains(stz)
+    assert stz.contains(stx) is False
+    assert stx.contains(stz) is False
+
+    C_classdef.revision += 1
+    si3 = SomeInstance(C_classdef)
+
+    sti12 = SomeTuple((si1,si2))
+    sti23 = SomeTuple((si2,si3))
+
+    assert sti23.contains(sti12)
+    assert not sti12.contains(sti23)
+    assert sti12.contains(sti23) is RevDiff
+    
+
 
 def test_union():
     assert ([unionof(s,t) for s in slist for t in slist] ==

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Wed Mar  2 19:40:07 2005
@@ -194,6 +194,7 @@
             # if the attrdef is new, this must fail
             if attrdef.getvalue().contains(s_value):
                 return
+
             # create or update the attribute in clsdef
             clsdef.generalize_attr(attr, s_value)
             raise BlockedInference

Modified: pypy/dist/pypy/translator/test/snippet.py
==============================================================================
--- pypy/dist/pypy/translator/test/snippet.py	(original)
+++ pypy/dist/pypy/translator/test/snippet.py	Wed Mar  2 19:40:07 2005
@@ -913,3 +913,46 @@
 def propagation_of_fresh_instances_through_attrs(x):
     e = EC()
     e.enter(x)
+
+# same involving recursion
+
+
+class R:
+  def __init__(self, n):
+      if n>0:
+          self.r = R(n-1)
+      else:
+          self.r = None
+      self.n = n
+      if self.r:
+          self.m = self.r.n
+      else:
+          self.m = -1
+
+def make_r(n):
+    return R(n)
+
+class B:
+    pass
+
+class Even(B):
+    def __init__(self,n):
+        if n > 0:
+            self.x = [Odd(n-1)]
+            self.y = self.x[0].x
+        else:
+            self.x = []
+            self.y = []
+
+class Odd(B):
+    def __init__(self,n):
+        self.x = [Even(n-1)]
+        self.y = self.x[0].x
+
+def make_eo(n):
+    if n%2 == 0:
+        return Even(n)
+    else:
+        return Odd(n)
+
+

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 Mar  2 19:40:07 2005
@@ -530,7 +530,29 @@
         a = RPythonAnnotator()
         s = a.build_types(snippet.propagation_of_fresh_instances_through_attrs, [int])
         assert s is not None
+
+    def test_propagation_of_fresh_instances_through_attrs_rec_0(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.make_r, [int])
+        assert s.knowntype == snippet.R
+        Rdef = a.getuserclasses()[snippet.R]
+        assert Rdef.attrs['r'].s_value.knowntype == snippet.R
+        assert Rdef.attrs['n'].s_value.knowntype == int
+        assert Rdef.attrs['m'].s_value.knowntype == int
+    
         
+    def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.make_eo, [int])
+        assert s.knowntype == snippet.B
+        Even_def = a.getuserclasses()[snippet.Even]
+        Odd_def = a.getuserclasses()[snippet.Odd]
+        assert Even_def.attrs['x'].s_value.s_item.knowntype == snippet.Odd
+        assert Even_def.attrs['y'].s_value.s_item.knowntype == snippet.Even
+        assert Odd_def.attrs['x'].s_value.s_item.knowntype == snippet.Even
+        assert Odd_def.attrs['y'].s_value.s_item.knowntype == snippet.Odd        
+
+
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list