[pypy-svn] rev 2540 - in pypy/trunk/src/pypy/annotation: . test

arigo at codespeak.net arigo at codespeak.net
Fri Dec 19 10:54:01 CET 2003


Author: arigo
Date: Fri Dec 19 10:54:00 2003
New Revision: 2540

Modified:
   pypy/trunk/src/pypy/annotation/annset.py
   pypy/trunk/src/pypy/annotation/test/test_annset.py
Log:
Fixed merge() to deal with immutables-that-are-not-really-changed.



Modified: pypy/trunk/src/pypy/annotation/annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/annset.py	(original)
+++ pypy/trunk/src/pypy/annotation/annset.py	Fri Dec 19 10:54:00 2003
@@ -8,6 +8,10 @@
         return False
 mostgeneralvalue = MostGeneralValue()
 
+class ImpossibleValue(Exception):
+    pass
+impossiblevalue = ImpossibleValue()
+
 
 class About:
     def __init__(self):
@@ -44,8 +48,8 @@
     def leave(self):
         self.inblock = None
 
-    def isshared(self, someval1, someval2):
-        return self.about[someval1] is self.about[someval2]
+    def isshared(self, val1, val2):
+        return self.about.get(val1, val1) == self.about.get(val2, val2)
 
     def __repr__(self):     # debugging
         lines = ['=====  AnnotationSet  =====']
@@ -61,15 +65,15 @@
         return '\n'.join(lines)
 
     def get(self, predicate, subject):
-        about = self._about(subject)
-        result = about.annotations.get(predicate)
-        if result:
-            answer, dependencies = result
-            if self.inblock:
-                dependencies[self.inblock] = True
-            return answer
-        else:
-            return mostgeneralvalue
+        if subject is not mostgeneralvalue:
+            about = self._about(subject)
+            result = about.annotations.get(predicate)
+            if result:
+                answer, dependencies = result
+                if self.inblock:
+                    dependencies[self.inblock] = True
+                return answer
+        return mostgeneralvalue
 
     def _about(self, somevalue):
         try:
@@ -77,6 +81,8 @@
         except KeyError:
             if somevalue is mostgeneralvalue:
                 raise ValueError, "Unexpected mostgeneralvalue"
+            if isinstance(somevalue, ImpossibleValue):
+                raise somevalue
             about = self.about[somevalue] = About()
             about.subjects[somevalue] = True
             return about
@@ -100,8 +106,14 @@
     def merge(self, oldvalue, newvalue):
         """Update the heap to account for the merging of oldvalue and newvalue.
         Return the merged somevalue."""
+        if isinstance(newvalue, ImpossibleValue):
+            return oldvalue
+        if isinstance(oldvalue, ImpossibleValue):
+            return newvalue
         if newvalue is mostgeneralvalue or oldvalue is mostgeneralvalue:
             return mostgeneralvalue
+        if self.isshared(oldvalue, newvalue):
+            return oldvalue
 
         # build an About set that is the intersection of the two incoming ones
         about1 = self._about(oldvalue)
@@ -128,17 +140,24 @@
         # modify the annotations about it.  If one of them is mutable,
         # then we must replace its About set with 'about3'.
         invalidatedblocks = {}
-        for value, about in [(oldvalue, about1), (newvalue, about2)]:
-            if ANN.immutable not in about.annotations:
-                # find all annotations that are removed or generalized
-                for pred, (someval, deps) in about.annotations.items():
-                    if (pred not in about3.annotations or
-                        about3.annotations[pred][0] != someval):
-                        invalidatedblocks.update(deps)
+        for about in [about1, about2]:
+            # find all annotations that are removed or generalized
+            removedannotations = []
+            for pred, (someval, deps) in about.annotations.items():
+                if (pred in about3.annotations and
+                    self.isshared(about3.annotations[pred][0], someval)):
+                    continue   # unmodified annotation
+                removedannotations.append(deps)
+            # if the existing 'value' is mutable, or if nothing has been
+            # removed, then we identify (by sharing) the 'value' and the
+            # new 'about3'.
+            if not removedannotations or ANN.immutable not in about.annotations:
                 # patch 'value' to use the new 'about3'.
                 for sharedvalue in about.subjects:   # this includes 'value'
                     self.about[sharedvalue] = about3
                     about3.subjects[sharedvalue] = True
+                for deps in removedannotations:
+                    invalidatedblocks.update(deps)
 
         if not about3.subjects:
             value3 = SomeValue()

Modified: pypy/trunk/src/pypy/annotation/test/test_annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/test/test_annset.py	(original)
+++ pypy/trunk/src/pypy/annotation/test/test_annset.py	Fri Dec 19 10:54:00 2003
@@ -101,38 +101,57 @@
         self.assertSameCells(a1, c, c1, c3)
         self.assertSameSet(a1, a2)
 
-    def test_merge_immutable1(self):
+    def test_merge_same_immutables(self):
         a1 = annset(ANN.len, c1, c2,
                     ANN.immutable, c1,
                     ANN.len, c3, c2,
                     ANN.immutable, c3)
-        # (c1) inter (c3) == (some new c)
+        # (c1) inter (c3) == (c1 and c3)
         c = a1.merge(c1, c3)
-        a2 = annset(ANN.len, c1, c2,
+        self.assertSameCells(a1, c, c1, c3)
+        a2 = annset(ANN.len, c, c2,
+                    ANN.immutable, c,
+                    links=[c1,c,c3,c])
+        self.assertSameSet(a1, a2)
+
+    def test_merge_generalize_one_immutable(self):
+        a1 = annset(ANN.len, c1, c2,
                     ANN.immutable, c1,
+                    ANN.type, c1, list,
                     ANN.len, c3, c2,
                     ANN.immutable, c3,
+                    ANN.type, c2, str)
+        # (c1) inter (c3) == (c3)
+        c = a1.merge(c1, c3)
+        self.assertSameCells(a1, c, c3)
+        a2 = annset(ANN.len, c1, c2,
+                    ANN.immutable, c1,
+                    ANN.type, c1, list,
                     ANN.len, c, c2,
-                    ANN.immutable, c)
+                    ANN.immutable, c,
+                    ANN.type, c2, str,
+                    links=[c3,c])
         self.assertSameSet(a1, a2)
 
-    def test_merge_immutable2(self):
+    def test_merge_generalize_both_immutables(self):
         a1 = annset(ANN.len, c1, c2,
                     ANN.immutable, c1,
+                    ANN.type, c1, list,
                     ANN.len, c3, c2,
                     ANN.immutable, c3,
-                    ANN.type, c1, list,
+                    ANN.type, c3, tuple,
                     ANN.type, c2, str)
-        # (c1) inter (c3) == (some new c)
+        # (c1) inter (c3) == (a more general c)
         c = a1.merge(c1, c3)
         a2 = annset(ANN.len, c1, c2,
                     ANN.immutable, c1,
+                    ANN.type, c1, list,
                     ANN.len, c3, c2,
                     ANN.immutable, c3,
-                    ANN.type, c1, list,
-                    ANN.type, c2, str,
+                    ANN.type, c3, tuple,
                     ANN.len, c, c2,
-                    ANN.immutable, c)
+                    ANN.immutable, c,
+                    ANN.type, c2, str)
         self.assertSameSet(a1, a2)
 
     def test_recursive_merge(self):
@@ -151,23 +170,20 @@
         c9  = a1.merge(c1, c5)
         c10 = a1.get(ANN.tupleitem[2], c9)
         c11 = a1.get(ANN.listitems, c10)
+        self.assertSameCells(a1, c1, c5, c9)
         self.assertSameCells(a1, c2, c6, c10)
         
-        a2 = annset(ANN.tupleitem[2], c1, c2,
-                    ANN.immutable, c1,
-                    ANN.type, c3, int,
-                    ANN.immutable, c3,
-                    ANN.tupleitem[2], c5, c6,
-                    ANN.immutable, c5,
-                    ANN.type, c7, float,
-                    ANN.immutable, c7,
-
-                    ANN.tupleitem[2], c9, c10,
+        a2 = annset(ANN.tupleitem[2], c9, c10,
                     ANN.immutable, c9,
                     ANN.type, c10, list,
                     ANN.listitems, c10, c11,
                     ANN.immutable, c11,
-                    links=[c2,c10,c6,c10])
+                    # old remaining stuff
+                    ANN.type, c3, int,
+                    ANN.immutable, c3,
+                    ANN.type, c7, float,
+                    ANN.immutable, c7,
+                    links=[c1,c9, c5,c9, c2,c10, c6,c10])
         self.assertSameSet(a1, a2)
 
     def test_settype(self):


More information about the Pypy-commit mailing list