[pypy-commit] pypy default: Added support for reversed() on lists

alex_gaynor noreply at buildbot.pypy.org
Mon Apr 29 16:52:30 CEST 2013


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r63751:0b9b94e3b630
Date: 2013-04-29 07:50 -0700
http://bitbucket.org/pypy/pypy/changeset/0b9b94e3b630/

Log:	Added support for reversed() on lists

diff --git a/rpython/annotator/builtin.py b/rpython/annotator/builtin.py
--- a/rpython/annotator/builtin.py
+++ b/rpython/annotator/builtin.py
@@ -89,9 +89,15 @@
 
 builtin_xrange = builtin_range # xxx for now allow it
 
+
 def builtin_enumerate(s_obj):
     return SomeIterator(s_obj, "enumerate")
 
+
+def builtin_reversed(s_obj):
+    return SomeIterator(s_obj, "reversed")
+
+
 def builtin_bool(s_obj):
     return s_obj.is_true()
 
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
@@ -3837,6 +3837,16 @@
         s = a.build_types(fn, [int])
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_reversed(self):
+        def fn(n):
+            for elem in reversed([1, 2, 3, 4, 5]):
+                return elem
+            return n
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(fn, [int])
+        assert isinstance(s, annmodel.SomeInteger)
+
     def test_no_attr_on_common_exception_classes(self):
         for cls in [ValueError, Exception]:
             def fn():
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -616,7 +616,10 @@
         if itr.variant == ("enumerate",):
             s_item = itr.s_container.getanyitem()
             return SomeTuple((SomeInteger(nonneg=True), s_item))
-        return itr.s_container.getanyitem(*itr.variant)
+        variant = itr.variant
+        if variant == ("reversed",):
+            variant = ()
+        return itr.s_container.getanyitem(*variant)
     next.can_only_throw = _can_only_throw
     method_next = next
 
diff --git a/rpython/rtyper/lltypesystem/rlist.py b/rpython/rtyper/lltypesystem/rlist.py
--- a/rpython/rtyper/lltypesystem/rlist.py
+++ b/rpython/rtyper/lltypesystem/rlist.py
@@ -52,8 +52,13 @@
     def get_eqfunc(self):
         return inputconst(Void, self.item_repr.get_ll_eq_function())
 
-    def make_iterator_repr(self):
-        return ListIteratorRepr(self)
+    def make_iterator_repr(self, *variant):
+        if not variant:
+            return ListIteratorRepr(self)
+        elif variant == ("reversed",):
+            return ReversedListIteratorRepr(self)
+        else:
+            raise NotImplementedError(variant)
 
     def get_itemarray_lowleveltype(self):
         ITEM = self.item_repr.lowleveltype
@@ -432,6 +437,7 @@
             self.ll_listnext = ll_listnext
         self.ll_getnextindex = ll_getnextindex
 
+
 def ll_listiter(ITERPTR, lst):
     iter = malloc(ITERPTR.TO)
     iter.list = lst
@@ -457,3 +463,30 @@
 
 def ll_getnextindex(iter):
     return iter.index
+
+
+class ReversedListIteratorRepr(AbstractListIteratorRepr):
+    def __init__(self, r_list):
+        self.r_list = r_list
+        self.lowleveltype = Ptr(GcStruct('revlistiter',
+            ('list', r_list.lowleveltype),
+            ('index', Signed),
+        ))
+        self.ll_listnext = ll_revlistnext
+        self.ll_listiter = ll_revlistiter
+
+
+def ll_revlistiter(ITERPTR, lst):
+    iter = malloc(ITERPTR.TO)
+    iter.list = lst
+    iter.index = lst.ll_length() - 1
+    return iter
+
+
+def ll_revlistnext(iter):
+    l = iter.list
+    index = iter.index
+    if index < 0:
+        raise StopIteration
+    iter.index -= 1
+    return l.ll_getitem_fast(index)
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -261,6 +261,12 @@
     hop.exception_cannot_occur()
     return hop.gendirectcall(ll_max, v1, v2)
 
+
+def rtype_builtin_reversed(hop):
+    hop.exception_cannot_occur()
+    return hop.r_result.newiter(hop)
+
+
 def ll_max(i1, i2):
     if i1 > i2:
         return i1
diff --git a/rpython/rtyper/test/test_rlist.py b/rpython/rtyper/test/test_rlist.py
--- a/rpython/rtyper/test/test_rlist.py
+++ b/rpython/rtyper/test/test_rlist.py
@@ -510,6 +510,17 @@
         res = self.interpret(dummyfn, ())
         assert res == 235
 
+    def test_reversed(self):
+        klist = [1, 2, 3]
+
+        def fn():
+            res = []
+            for elem in reversed(klist):
+                res.append(elem)
+            return res[0] * 100 + res[1] * 10 + res[2]
+        res = self.interpret(fn, [])
+        assert res == fn()
+
     def test_prebuilt_list(self):
         klist = [6, 7, 8, 9]
         def dummyfn(n):
@@ -1604,3 +1615,6 @@
 class TestOOtype(BaseTestRlist, OORtypeMixin):
     rlist = oo_rlist
     type_system = 'ootype'
+
+    def test_reversed(self):
+        py.test.skip("unsupported")


More information about the pypy-commit mailing list