Author: Armin Rigo <[email protected]>
Branch: all_ordered_dicts
Changeset: r75302:fc9fe2200019
Date: 2015-01-12 12:12 +0100
http://bitbucket.org/pypy/pypy/changeset/fc9fe2200019/

Log:    Add reversed_dict() in RPython

diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -753,6 +753,14 @@
         dict._prepare_dict_update(n_elements)
         # ^^ call an extra method that doesn't exist before translation
 
[email protected]_location()
+def reversed_dict(d):
+    """Equivalent to reversed(ordered_dict), but works also for
+    regular dicts."""
+    if not we_are_translated() and type(d) is dict:
+        d = list(d)
+    return reversed(d)
+
 
 # ____________________________________________________________
 
diff --git a/rpython/rlib/test/test_objectmodel.py 
b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -341,6 +341,21 @@
         res = self.interpret(g, [3])
         assert res == 42     # "did not crash"
 
+    def test_reversed_dict(self):
+        d1 = {2:3, 4:5, 6:7}
+        def g():
+            n1 = 0
+            for key in d1:
+                n1 = n1 * 10 + key
+            n2 = 0
+            for key in reversed_dict(d1):
+                n2 = n2 * 10 + key
+            return n1 * 10000 + n2
+        got = str(g())
+        assert len(got) == 7 and got[3] == '0' and got[:3] == got[6:3:-1]
+        got = str(self.interpret(g, []))
+        assert len(got) == 7 and got[3] == '0' and got[:3] == got[6:3:-1]
+
     def test_compute_hash(self):
         class Foo(object):
             pass
diff --git a/rpython/rtyper/lltypesystem/rordereddict.py 
b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -988,8 +988,12 @@
         self.r_dict = r_dict
         self.variant = variant
         self.lowleveltype = get_ll_dictiter(r_dict.lowleveltype)
-        self.ll_dictiter = ll_dictiter
-        self._ll_dictnext = _ll_dictnext
+        if variant == 'reversed':
+            self.ll_dictiter = ll_dictiter_reversed
+            self._ll_dictnext = _ll_dictnext_reversed
+        else:
+            self.ll_dictiter = ll_dictiter
+            self._ll_dictnext = _ll_dictnext
 
 
 def ll_dictiter(ITERPTR, d):
@@ -1019,6 +1023,26 @@
         iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
     raise StopIteration
 
+def ll_dictiter_reversed(ITERPTR, d):
+    iter = lltype.malloc(ITERPTR.TO)
+    iter.dict = d
+    iter.index = d.num_ever_used_items
+    return iter
+
+def _ll_dictnext_reversed(iter):
+    dict = iter.dict
+    if dict:
+        entries = dict.entries
+        index = iter.index - 1
+        while index >= 0:
+            if entries.valid(index):
+                iter.index = index
+                return index
+            index = index - 1
+        # clear the reference to the dict and prevent restarts
+        iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
+    raise StopIteration
+
 # _____________________________________________________________
 # methods
 
diff --git a/rpython/rtyper/rdict.py b/rpython/rtyper/rdict.py
--- a/rpython/rtyper/rdict.py
+++ b/rpython/rtyper/rdict.py
@@ -98,12 +98,12 @@
             c_key = hop.inputconst(lltype.Void, 'key')
             v_key = hop.genop('getinteriorfield', [v_entries, v_index, c_key],
                               resulttype=KEY)
-        if variant != 'keys':
+        if variant != 'keys' and variant != 'reversed':
             VALUE = ENTRIES.TO.OF.value
             c_value = hop.inputconst(lltype.Void, 'value')
             v_value = hop.genop('getinteriorfield', 
[v_entries,v_index,c_value],
                                 resulttype=VALUE)
-        if variant == 'keys':
+        if variant == 'keys' or variant == 'reversed':
             return self.r_dict.recast_key(hop.llops, v_key)
         elif variant == 'values':
             return self.r_dict.recast_value(hop.llops, v_value)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to