Author: Alex Gaynor <alex.gay...@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") _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit