[pypy-svn] r78958 - in pypy/branch/rlist-jit/pypy/annotation: . test

arigo at codespeak.net arigo at codespeak.net
Wed Nov 10 13:24:57 CET 2010


Author: arigo
Date: Wed Nov 10 13:24:55 2010
New Revision: 78958

Modified:
   pypy/branch/rlist-jit/pypy/annotation/description.py
   pypy/branch/rlist-jit/pypy/annotation/listdef.py
   pypy/branch/rlist-jit/pypy/annotation/test/test_annrpython.py
Log:
* Merge r78957 from branch/fast-forward.

* Mark the 'x.list' marked as _immutable_fields_=['list[*]']
  with never_mutate(), to make sure.



Modified: pypy/branch/rlist-jit/pypy/annotation/description.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/annotation/description.py	(original)
+++ pypy/branch/rlist-jit/pypy/annotation/description.py	Wed Nov 10 13:24:55 2010
@@ -647,7 +647,9 @@
         while cdesc is not None:
             if '_immutable_fields_' in cdesc.classdict:
                 if search in cdesc.classdict['_immutable_fields_'].value:
-                    return s_result.listdef.offspring()
+                    s_copy = s_result.listdef.offspring()
+                    s_copy.listdef.never_mutate()
+                    return s_copy
             cdesc = cdesc.basedesc
         return s_result     # common case
 

Modified: pypy/branch/rlist-jit/pypy/annotation/listdef.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/annotation/listdef.py	(original)
+++ pypy/branch/rlist-jit/pypy/annotation/listdef.py	Wed Nov 10 13:24:55 2010
@@ -6,11 +6,16 @@
 class TooLateForChange(Exception):
     pass
 
+class ListChangeUnallowed(Exception):
+    pass
+
 class ListItem(object):
     mutated = False    # True for lists mutated after creation
     resized = False    # True for lists resized after creation
     range_step = None  # the step -- only for lists only created by a range()
     dont_change_any_more = False   # set to True when too late for changes
+    must_not_mutate = False   # make_sure_not_modified()
+    must_not_resize = False   # make_sure_not_resized()
 
     # what to do if range_step is different in merge.
     # - if one is a list (range_step is None), unify to a list.
@@ -26,7 +31,6 @@
         self.bookkeeper = bookkeeper
         self.itemof = {}  # set of all ListDefs using this ListItem
         self.read_locations = {}
-        self.dont_resize = False
         if bookkeeper is None:
             self.dont_change_any_more = True
 
@@ -34,12 +38,16 @@
         if not self.mutated:
             if self.dont_change_any_more:
                 raise TooLateForChange
+            if self.must_not_mutate:
+                raise ListChangeUnallowed("mutating list")
             self.mutated = True
 
     def resize(self):
         if not self.resized:
-            if self.dont_change_any_more or self.dont_resize:
+            if self.dont_change_any_more:
                 raise TooLateForChange
+            if self.must_not_resize:
+                raise ListChangeUnallowed("resizing list")
             self.resized = True
 
     def setrangestep(self, step):
@@ -63,11 +71,16 @@
                     # things more general
                     self, other = other, self
 
-            if other.dont_resize:
-                if self.resized:                    
-                    raise TooLateForChange()
-                self.dont_resize = True
-            if other.mutated: self.mutate()
+            if other.must_not_mutate:
+                if self.mutated:
+                    raise ListChangeUnallowed("list merge with a mutated")
+                self.must_not_mutate = True
+            if other.must_not_resize:
+                if self.resized:
+                    raise ListChangeUnallowed("list merge with a resized")
+                self.must_not_resize = True
+            if other.mutated:
+                self.mutate()
             if other.resized:
                 self.resize()
             if other.range_step != self.range_step:
@@ -189,13 +202,14 @@
 
     def never_resize(self):
         if self.listitem.resized:
-            raise TooLateForChange()
-        self.listitem.dont_resize = True
+            raise ListChangeUnallowed("list already resized")
+        self.listitem.must_not_resize = True
 
     def never_mutate(self):
-        if self.listitem.resized or self.listitem.mutated:
-            raise TooLateForChange()
-        self.listitem.dont_change_any_more = True
+        self.never_resize()
+        if self.listitem.mutated:
+            raise ListChangeUnallowed("list already mutated")
+        self.listitem.must_not_mutate = True
 
 MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
 

Modified: pypy/branch/rlist-jit/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/rlist-jit/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/rlist-jit/pypy/annotation/test/test_annrpython.py	Wed Nov 10 13:24:55 2010
@@ -10,7 +10,7 @@
 from pypy.translator.translator import graphof as tgraphof
 from pypy.annotation import policy
 from pypy.annotation import specialize
-from pypy.annotation.listdef import ListDef, TooLateForChange
+from pypy.annotation.listdef import ListDef, ListChangeUnallowed
 from pypy.annotation.dictdef import DictDef
 from pypy.objspace.flow.model import *
 from pypy.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
@@ -3206,7 +3206,7 @@
             l.append(4)
 
         a = self.RPythonAnnotator()
-        py.test.raises(TooLateForChange, a.build_types, g, [])
+        py.test.raises(ListChangeUnallowed, a.build_types, g, [])
         assert called
 
     def test_listitem_no_mutating2(self):
@@ -3229,7 +3229,7 @@
 
         a = self.RPythonAnnotator()
         a.translator.config.translation.list_comprehension_operations = True
-        py.test.raises(TooLateForChange, a.build_types, fn, [int])
+        py.test.raises(ListChangeUnallowed, a.build_types, fn, [int])
 
     def test_listitem_never_resize(self):
         from pypy.rlib.debug import check_annotation
@@ -3243,7 +3243,7 @@
             check_annotation(l, checker)
 
         a = self.RPythonAnnotator()
-        py.test.raises(TooLateForChange, a.build_types, f, [])
+        py.test.raises(ListChangeUnallowed, a.build_types, f, [])
 
 
     def test_len_of_empty_list(self):
@@ -3357,6 +3357,38 @@
         # not a constant: both __enter__ and __exit__ have been annotated
         assert not s.is_constant()
 
+    def test_make_sure_not_modified(self):
+        from pypy.rlib.debug import make_sure_not_modified
+
+        def pycode(consts):
+            make_sure_not_modified(consts)
+        def build1():
+            return pycode(consts=[1])
+        def build2():
+            return pycode(consts=[0])
+        def fn():
+            build1()
+            build2()
+
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.list_comprehension_operations = True
+        a.build_types(fn, [])
+        # assert did not raise ListChangeUnallowed
+
+    def test_return_immutable_list(self):
+        class A:
+            _immutable_fields_ = 'lst[*]'
+        def f(n):
+            a = A()
+            l1 = [n]
+            l1.append(n+1)
+            a.lst = l1
+            return a.lst
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s.listdef.listitem.must_not_mutate
+
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list