Author: Maciej Fijalkowski <[email protected]>
Branch: rdict-experiments-2
Changeset: r59815:1b1d4733a1fd
Date: 2013-01-06 20:51 +0200
http://bitbucket.org/pypy/pypy/changeset/1b1d4733a1fd/
Log: fix iterators
diff --git a/pypy/rpython/lltypesystem/rdict.py
b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -637,14 +637,17 @@
#
# Iteration.
+def get_ll_dictiter(DICT):
+ return lltype.Ptr(lltype.GcStruct('dictiter',
+ ('dict', DICT),
+ ('index', lltype.Signed)))
+
class DictIteratorRepr(AbstractDictIteratorRepr):
def __init__(self, r_dict, variant="keys"):
self.r_dict = r_dict
self.variant = variant
- self.lowleveltype = lltype.Ptr(lltype.GcStruct('dictiter',
- ('dict', r_dict.lowleveltype),
- ('index', lltype.Signed)))
+ self.lowleveltype = get_ll_dictiter(r_dict.lowleveltype)
self.ll_dictiter = ll_dictiter
self.ll_dictnext = ll_dictnext_group[variant]
@@ -664,30 +667,23 @@
def ll_dictnext(RETURNTYPE, iter):
# note that RETURNTYPE is None for keys and values
dict = iter.dict
- if dict:
- entries = dict.entries
- index = iter.index
- entries_len = len(entries)
- while index < entries_len:
- entry = entries[index]
- is_valid = entries.valid(index)
- index = index + 1
- if is_valid:
- iter.index = index
- if RETURNTYPE is lltype.Void:
- return None
- elif kind == 'items':
- r = lltype.malloc(RETURNTYPE.TO)
- r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
- r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
- return r
- elif kind == 'keys':
- return entry.key
- elif kind == 'values':
- return entry.value
+ if not dict or iter.index >= dict.num_items:
# clear the reference to the dict and prevent restarts
iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
- raise StopIteration
+ raise StopIteration
+ entry = dict.entries[iter.index]
+ iter.index += 1
+ if RETURNTYPE is lltype.Void:
+ return None
+ elif kind == 'items':
+ r = lltype.malloc(RETURNTYPE.TO)
+ r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
+ r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
+ return r
+ elif kind == 'keys':
+ return entry.key
+ elif kind == 'values':
+ return entry.value
return ll_dictnext
ll_dictnext_group = {'keys' : _make_ll_dictnext('keys'),
diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -77,6 +77,20 @@
for item in ['a', 'b', 'c', 'd', 'e', 'f']:
assert rdict.ll_dict_getitem(ll_d, llstr(item)) == ord(item) -
ord('a') + 1
+ def test_dict_iteration(self):
+ DICT = self._get_str_dict()
+ ll_d = rdict.ll_newdict(DICT)
+ rdict.ll_dict_setitem(ll_d, llstr("k"), 1)
+ rdict.ll_dict_setitem(ll_d, llstr("j"), 2)
+ ITER = rdict.get_ll_dictiter(lltype.Ptr(DICT))
+ ll_iter = rdict.ll_dictiter(ITER, ll_d)
+ ll_iterkeys = rdict.ll_dictnext_group['keys']
+ next = ll_iterkeys(lltype.Signed, ll_iter)
+ assert hlstr(next) == "k"
+ next = ll_iterkeys(lltype.Signed, ll_iter)
+ assert hlstr(next) == "j"
+ py.test.raises(StopIteration, ll_iterkeys, lltype.Signed, ll_iter)
+
class BaseTestRdict(BaseRtypingTest):
def test_dict_creation(self):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit