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