[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