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

pedronis at codespeak.net pedronis at codespeak.net
Thu Mar 3 16:52:33 CET 2005


Author: pedronis
Date: Thu Mar  3 16:52:33 2005
New Revision: 9603

Modified:
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/translator/test/snippet.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
use structural comparison to decide when not to bump rev numbers.





Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Thu Mar  3 16:52:33 2005
@@ -6,6 +6,7 @@
 from types import FunctionType
 from pypy.annotation.model import SomeImpossibleValue, unionof, RevDiff
 
+notyet = object()
 
 class Attribute:
     # readonly-ness
@@ -20,8 +21,11 @@
         self.s_value = SomeImpossibleValue()
         self.readonly = True
 
+        self.flat = notyet
+
     def getvalue(self):
         while self.sources:
+            self.flat = notyet
             source, classdef = self.sources.popitem()
             s_value = self.bookkeeper.immutablevalue(
                 source.__dict__[self.name])
@@ -35,6 +39,13 @@
         self.sources.update(other.sources)
         self.s_value = unionof(self.s_value, other.s_value)
         self.readonly = self.readonly and other.readonly
+        self.flat = notyet
+
+    def structure(self):
+        s_value = self.getvalue()
+        if self.flat is notyet:
+            self.flat = s_value.structure()
+        return self.flat
 
 
 class ClassDef:
@@ -125,13 +136,19 @@
                 del subdef.attrs[attr]
 
         bump = True
+        attach_flat = None
         # 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
+                s_value_struct = s_value.structure()
+                if not old_attr.flat is notyet:
+                    old_attr_struct = old_attr.structure()
+                    if s_value_struct == old_attr_struct:
+                        bump = False
+                attach_flat = s_value_struct
 
         if bump:
             # bump the revision number of this class and all subclasses           
@@ -147,6 +164,9 @@
             newattr.merge(subattr)
         self.attrs[attr] = newattr
 
+        if attach_flat is not None:
+            newattr.flat = attach_flat
+
         # reflow from all factories
         for position in self.getallinstantiations():
             self.bookkeeper.annotator.reflowfromposition(position)

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Thu Mar  3 16:52:33 2005
@@ -134,6 +134,23 @@
     del set_caused_by_merge
 
 
+    # structural expansion
+
+    def structure(self, memo=None):
+        if self.is_constant():
+            return self.const
+        if memo is None:
+            memo = {}
+        return self._structure(memo)
+
+    def _structure(self, memo):
+        return self
+
+class struct(tuple):
+    def __new__(cls, *args):
+        return tuple.__new__(cls,args)
+
+
 class SomeInteger(SomeObject):
     "Stands for an object which is known to be an integer."
     knowntype = int
@@ -170,6 +187,9 @@
     def hom_contains(self, other):
         return self.s_item.contains(other.s_item)
 
+    def _structure(self, memo):
+        return struct(list, self.s_item.structure(memo))
+
 
 class SomeSlice(SomeObject):
     knowntype = slice
@@ -183,6 +203,14 @@
                             self.stop.contains(other.stop),
                             self.step.contains(other.step))
 
+    def _structure(self, memo):
+        return struct(slice,
+                      self.start.structure(memo),
+                      self.stop.structure(memo),
+                      self.step.structure(memo),
+                      )
+                
+
 
 class SomeTuple(SomeObject):
     "Stands for a tuple of known length."
@@ -202,6 +230,10 @@
             return False
         return contains_and(*[i1.contains(i2) for i1,i2 in zip(self_items, other_items)])
 
+    def _structure(self, memo):
+        return struct(tuple,*[ i.structure(memo) for i in self.items])
+                      
+
 
 class SomeDict(SomeObject):
     "Stands for a dict."
@@ -216,6 +248,12 @@
                             self.s_value.contains(other.s_value))
 
 
+    def _structure(self, memo):
+        return struct(dict,
+                      self.s_key.structure(memo),
+                      self.s_value.structure(memo))
+                      
+
 class SomeIterator(SomeObject):
     "Stands for an iterator returning objects of a known type."
     knowntype = type(iter([]))  # arbitrarily chose seqiter as the type
@@ -225,6 +263,10 @@
     def hom_contains(self, other):
         return self.s_item.contains(other.s_item)
 
+    def _structure(self, memo):
+        return struct(iter,
+                      self.s_item.structure(memo))
+
 class SomeInstance(SomeObject):
     "Stands for an instance of a (user-defined) class."
     def __init__(self, classdef):
@@ -244,6 +286,27 @@
                 return RevDiff
         return self.classdef.commonbase(other.classdef) is self.classdef
 
+    def _classdef_structure(self, classdef, memo):
+        if classdef is None:
+            return None
+        if classdef in memo or classdef.cls.__module__ == '__builtin__':
+            return struct(classdef)
+        attr_names = classdef.attrs.keys()
+        attr_names.sort()
+        attrs = classdef.attrs
+        parts = [classdef]
+        memo[classdef] = None
+        parts.append(self._classdef_structure(classdef.basedef, memo))
+        for name in attr_names:
+            a = attrs[name]
+            parts.append((name, a.getvalue().structure(memo)))
+        strct = struct(*parts)
+        return strct
+         
+    def _structure(self, memo): # xxx try later an approach that can cache classef expansions
+        return self._classdef_structure(self.classdef, memo)
+
+
 def new_or_old_class(c):
     if hasattr(c, '__class__'):
         return c.__class__
@@ -314,6 +377,15 @@
             return other.s_self is None        
         return self.s_self.contains(other.s_self)
 
+    def _structure(self, memo):
+        if self.s_self:
+            return struct(len,
+                          self.analyser,
+                          self.s_self.structure(memo))
+        else:
+            return struct(len,
+                          self.analyser)
+                     
 
 class SomeImpossibleValue(SomeObject):
     """The empty set.  Instances are placeholders for objects that

Modified: pypy/dist/pypy/translator/test/snippet.py
==============================================================================
--- pypy/dist/pypy/translator/test/snippet.py	(original)
+++ pypy/dist/pypy/translator/test/snippet.py	Thu Mar  3 16:52:33 2005
@@ -956,3 +956,32 @@
         return Odd(n)
 
 
+# shows that we care about the expanded structure in front of changes to attributes involving only
+# instances rev numbers
+
+class Box:
+ pass
+
+class Box2:
+  pass
+
+class Box3(Box2):
+  pass
+
+def flow_rev_numbers(n):
+  bx3 = Box3()
+  bx3.x = 1
+  bx = Box()
+  bx.bx3 = bx3
+  if n >0:
+     z =  bx.bx3.x
+     if n >0:
+        bx2 = Box2()
+        bx2.x = 3
+     return z
+  raise Exception
+
+
+
+
+

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	Thu Mar  3 16:52:33 2005
@@ -552,6 +552,11 @@
         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 test_flow_rev_numbers(self):
+        a = RPythonAnnotator()
+        s = a.build_types(snippet.flow_rev_numbers, [])
+        assert s.knowntype == int
+        assert not s.is_constant() # !
 
 
 def g(n):



More information about the Pypy-commit mailing list