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

Reply via email to