[pypy-commit] pypy rpython-deque: Annotation

arigo pypy.commits at gmail.com
Mon Aug 15 13:01:33 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: rpython-deque
Changeset: r86203:63bf58058a3c
Date: 2016-08-14 09:27 +0200
http://bitbucket.org/pypy/pypy/changeset/63bf58058a3c/

Log:	Annotation

diff --git a/rpython/annotator/listdef.py b/rpython/annotator/listdef.py
--- a/rpython/annotator/listdef.py
+++ b/rpython/annotator/listdef.py
@@ -12,6 +12,7 @@
 class ListItem(object):
     mutated = False    # True for lists mutated after creation
     resized = False    # True for lists resized after creation
+    deque_hinted = False # True for 'list_implemented_as_deque()'
     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
     immutable = False  # for getattr out of _immutable_fields_ = ['attr[*]']
@@ -49,6 +50,13 @@
                 raise ListChangeUnallowed("resizing list")
             self.resized = True
 
+    def deque_hint(self):
+        if not self.deque_hinted:
+            if self.dont_change_any_more:
+                raise TooLateForChange
+            self.resize()
+            self.deque_hinted = True
+
     def setrangestep(self, step):
         if step != self.range_step:
             if self.dont_change_any_more:
@@ -79,6 +87,8 @@
                 self.mutate()
             if other.resized:
                 self.resize()
+            if other.deque_hinted:
+                self.deque_hint()
             if other.range_step != self.range_step:
                 self.setrangestep(self._step_map[type(self.range_step),
                                                  type(other.range_step)])
@@ -173,9 +183,10 @@
         self.listitem.merge(newlistitem)
 
     def __repr__(self):
-        return '<[%r]%s%s%s%s>' % (self.listitem.s_value,
+        return '<[%r]%s%s%s%s%s>' % (self.listitem.s_value,
                                self.listitem.mutated and 'm' or '',
                                self.listitem.resized and 'r' or '',
+                               self.listitem.deque_hinted and 'd' or '',
                                self.listitem.immutable and 'I' or '',
                                self.listitem.must_not_resize and '!R' or '')
 
@@ -186,6 +197,10 @@
         self.listitem.mutate()
         self.listitem.resize()
 
+    def deque_hint(self):
+        self.resize()
+        self.listitem.deque_hint()
+
     def never_resize(self):
         if self.listitem.resized:
             raise ListChangeUnallowed("list already resized")
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4631,6 +4631,20 @@
         assert ('string formatting requires a constant string/unicode'
                 in str(e.value))
 
+    def test_list_implemented_as_deque(self):
+        def f(x):
+            if x > 5:
+                l = []
+            else:
+                l = []
+                objectmodel.list_implemented_as_deque(l)
+            return l
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int])
+        assert s.listdef.listitem.mutated
+        assert s.listdef.listitem.resized
+        assert s.listdef.listitem.deque_hinted
+
 
 def g(n):
     return [0, 1, 2, n]
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -431,6 +431,27 @@
         hop.exception_is_here()
         hop.gendirectcall(r_list.LIST._ll_resize_hint, v_list, v_sizehint)
 
+def list_implemented_as_deque(l):
+    """Hint that the list 'l' should use an implementation that allows
+    a "gap" at the start, which allows O(1) implementation of a few
+    operations like 'lst.insert(0, x)' and 'del lst[:n]'.
+    """
+
+class Entry(ExtRegistryEntry):
+    _about_ = list_implemented_as_deque
+
+    def compute_result_annotation(self, s_l):
+        from rpython.annotator import model as annmodel
+        if annmodel.s_None.contains(s_l):
+            return   # first argument is only None so far, but we
+                     # expect a generalization later
+        if not isinstance(s_l, annmodel.SomeList):
+            raise annmodel.AnnotatorError("Argument must be a list")
+        s_l.listdef.deque_hint()
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+
 # ____________________________________________________________
 #
 # id-like functions.  The idea is that calling hash() or id() is not


More information about the pypy-commit mailing list