[pypy-svn] r26311 - in pypy/dist/pypy/rpython/ootypesystem: . test

antocuni at codespeak.net antocuni at codespeak.net
Tue Apr 25 10:53:06 CEST 2006


Author: antocuni
Date: Tue Apr 25 10:52:59 2006
New Revision: 26311

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py
Log:
The Dict interface has been changed to support a more efficient
iteration.

The ll_get_items_iterator ADT method has been added: it returns a
DictItemsIterator that allow a pseudo-iteration over dict
items. Methods such as keys(), values(), items() and their iter*
correspondent will be implemented in term of it.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Tue Apr 25 10:52:59 2006
@@ -358,7 +358,8 @@
             "ll_set": Meth([self.KEYTYPE_T, self.VALUETYPE_T], Void),
             "ll_remove": Meth([self.KEYTYPE_T], Bool), # return False is key was not present
             "ll_contains": Meth([self.KEYTYPE_T], Bool),
-            "ll_keys": Meth([], List(self.KEYTYPE_T)),
+            "ll_keys": Meth([], List(self.KEYTYPE_T)), # deprecated
+            "ll_get_items_iterator": Meth([], DictItemsIterator(self.KEYTYPE_T, self.VALUETYPE_T)),
         })
 
         self._setup_methods(generic_types)
@@ -382,6 +383,54 @@
         VALUETYPE = self._specialize_type(self._VALUETYPE, generic_types)
         return self.__class__(KEYTYPE, VALUETYPE)
 
+class DictItemsIterator(BuiltinADTType):
+    SELFTYPE_T = object()
+    KEYTYPE_T = object()
+    VALUETYPE_T = object()
+
+    def __init__(self, KEYTYPE, VALUETYPE):
+        self._KEYTYPE = KEYTYPE
+        self._VALUETYPE = VALUETYPE
+        self._null = _null_dict_items_iterator(self)
+
+        generic_types = {
+            self.SELFTYPE_T: self,
+            self.KEYTYPE_T: KEYTYPE,
+            self.VALUETYPE_T: VALUETYPE
+            }
+
+        # some words about the interface of the iterator: we can't
+        # write the next() method directly in the backend because of
+        # two reasons:
+        #  1) tuples aren't BuiltinType, yet, so we can't make them
+        #     generic; moreover, they are constructed on-the-fly, so the
+        #     two-item tuple type that an hypotetic next() would return
+        #     isn't available at this time.
+        #  2) StopIteration is generated at translation time too, so
+        #     this would prevent backends to do a precompilation of
+        #     support code.
+
+        self._GENERIC_METHODS = frozendict({
+            "ll_go_next": Meth([], Bool), # move forward; return False is there is no more data available
+            "ll_current_key": Meth([], self.KEYTYPE_T),
+            "ll_current_value": Meth([], self.VALUETYPE_T),
+        })
+
+        self._setup_methods(generic_types)
+
+    def __str__(self):
+        return '%s%s' % (self.__class__.__name__,
+                saferecursive(str, "(...)")((self._KEYTYPE, self._VALUETYPE)))
+
+    def _get_interp_class(self):
+        return _dict_items_iterator
+
+    def _specialize(self, generic_types):
+        KEYTYPE = self._specialize_type(self._KEYTYPE, generic_types)
+        VALUETYPE = self._specialize_type(self._VALUETYPE, generic_types)
+        return self.__class__(KEYTYPE, VALUETYPE)
+    
+
 class ForwardReference(OOType):
     def become(self, real_instance):
         if not isinstance(real_instance, (Instance, BuiltinADTType)):
@@ -753,11 +802,45 @@
         keys._list = self._dict.keys()
         return keys
 
-class _null_dict(_null_mixin(_dict), _dict):
+    def ll_get_items_iterator(self):
+        # NOT_RPYTHON
+        ITER = DictItemsIterator(self._TYPE._KEYTYPE, self._TYPE._VALUETYPE)
+        return _dict_items_iterator(ITER, self._dict)
 
+class _null_dict(_null_mixin(_dict), _dict):
     def __init__(self, DICT):
         self.__dict__["_TYPE"] = DICT
 
+
+class _dict_items_iterator(_builtin_type):
+    def __init__(self, ITER, d):
+        self._TYPE = ITER
+        self._items = d.items()
+        self._index = -1
+
+    def ll_go_next(self):
+        # NOT_RPYTHON
+        self._index += 1        
+        if self._index >= len(self._items):
+            return False
+        else:
+            return True
+
+    def ll_current_key(self):
+        # NOT_RPYTHON
+        assert 0 <= self._index < len(self._items)
+        return self._items[self._index][0]
+    
+    def ll_current_value(self):
+        # NOT_RPYTHON
+        assert 0 <= self._index < len(self._items)
+        return self._items[self._index][1]
+
+class _null_dict_items_iterator(_null_mixin(_dict_items_iterator), _dict_items_iterator):
+    def __init__(self, ITER):
+        self.__dict__["_TYPE"] = ITER
+
+
 class _tuple(object):
 
     def __init__(self, TYPE):
@@ -789,6 +872,7 @@
     def __init__(self, TUPLE):
         self.__dict__["_TYPE"] = TUPLE 
 
+
 def new(TYPE):
     if isinstance(TYPE, Instance):
         return make_instance(TYPE)

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oodict.py	Tue Apr 25 10:52:59 2006
@@ -18,3 +18,15 @@
     d = new(DT)
     d.ll_set(42, 123.45)
     assert d.ll_get(42) == 123.45
+
+def test_iteritems():
+    DT = Dict(Signed, Float)
+    d = new(DT)
+    d.ll_set(42, 43.0)
+    d.ll_set(52, 53.0)
+    it = d.ll_get_items_iterator()
+    items = []
+    while it.ll_go_next():
+        items.append((it.ll_current_key(), it.ll_current_value()))
+    items.sort()
+    assert items == [(42, 43.0), (52, 53.0)]



More information about the Pypy-commit mailing list