[pypy-svn] r17433 - in pypy/dist/pypy: annotation rpython rpython/test

arigo at codespeak.net arigo at codespeak.net
Fri Sep 9 21:49:27 CEST 2005


Author: arigo
Date: Fri Sep  9 21:49:25 2005
New Revision: 17433

Modified:
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/rdict.py
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/rrange.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/rtuple.py
   pypy/dist/pypy/rpython/test/test_rdict.py
Log:
Support for the iterkeys(), itervalues() and iteritems() methods on RPython
dicts.  All three kinds of iterators are implementated with the same
SomeIterator and StrDictIteratorRepr classes, using a 'variant' field to
distinguish (and the dummy function trick in rdict.py to get the
specialization).

All xxxIteratorRepr classes now inherit from a common IteratorRepr, which
implements the common functionality of returning the iterator itself when the
'iter' operation is applied.



Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Fri Sep  9 21:49:25 2005
@@ -266,7 +266,8 @@
 class SomeIterator(SomeObject):
     "Stands for an iterator returning objects from a given container."
     knowntype = type(iter([]))  # arbitrarily chose seqiter as the type
-    def __init__(self, s_container):
+    def __init__(self, s_container, *variant):
+        self.variant = variant
         self.s_container = s_container
 
     def can_be_none(self):

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Fri Sep  9 21:49:25 2005
@@ -277,8 +277,16 @@
         return SomeIterator(dct)
     iter.can_only_throw = []
 
-    def getanyitem(dct):
-        return dct.dictdef.read_key()
+    def getanyitem(dct, variant='keys'):
+        if variant == 'keys':
+            return dct.dictdef.read_key()
+        elif variant == 'values':
+            return dct.dictdef.read_value()
+        elif variant == 'items':
+            return SomeTuple((dct.dictdef.read_key(),
+                              dct.dictdef.read_value()))
+        else:
+            raise ValueError
 
     def method_get(dct, key, dfl):
         dct.dictdef.generalize_key(key)
@@ -301,6 +309,15 @@
         return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(),
                                                   dct.dictdef.read_value())))
 
+    def method_iterkeys(dct):
+        return SomeIterator(dct, 'keys')
+
+    def method_itervalues(dct):
+        return SomeIterator(dct, 'values')
+
+    def method_iteritems(dct):
+        return SomeIterator(dct, 'items')
+
     def method_clear(dct):
         pass
 
@@ -374,7 +391,7 @@
     iter.can_only_throw = []
 
     def next(itr):
-        return itr.s_container.getanyitem()
+        return itr.s_container.getanyitem(*itr.variant)
 
 
 class __extend__(SomeInstance):

Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py	(original)
+++ pypy/dist/pypy/rpython/rdict.py	Fri Sep  9 21:49:25 2005
@@ -111,8 +111,8 @@
         v_dict, = hop.inputargs(self)
         return hop.gendirectcall(ll_strdict_is_true, v_dict)
 
-    def make_iterator_repr(self):
-        return StrDictIteratorRepr(self)
+    def make_iterator_repr(self, *variant):
+        return StrDictIteratorRepr(self, *variant)
 
     def rtype_method_get(self, hop):
         v_dict, v_key, v_default = hop.inputargs(self, rstr.string_repr,
@@ -147,6 +147,18 @@
     def rtype_method_items(self, hop):
         return self._rtype_method_kvi(hop, dum_items)
 
+    def rtype_method_iterkeys(self, hop):
+        hop.exception_cannot_occur()
+        return StrDictIteratorRepr(self, "keys").newiter(hop)
+
+    def rtype_method_itervalues(self, hop):
+        hop.exception_cannot_occur()
+        return StrDictIteratorRepr(self, "values").newiter(hop)
+
+    def rtype_method_iteritems(self, hop):
+        hop.exception_cannot_occur()
+        return StrDictIteratorRepr(self, "items").newiter(hop)
+
     def rtype_method_clear(self, hop):
         v_dict, = hop.inputargs(self)
         hop.exception_cannot_occur()
@@ -200,6 +212,12 @@
 #  get flowed and annotated, mostly with SomePtr.
 
 deleted_entry_marker = lltype.malloc(rstr.STR, 0, immortal=True)
+def dum_keys(): pass
+def dum_values(): pass
+def dum_items():pass
+dum_variant = {"keys":   dum_keys,
+               "values": dum_values,
+               "items":  dum_items}
 
 def ll_strdict_len(d):
     return d.num_items 
@@ -328,10 +346,11 @@
 #
 #  Iteration.
 
-class StrDictIteratorRepr(rmodel.Repr):
+class StrDictIteratorRepr(rmodel.IteratorRepr):
 
-    def __init__(self, r_dict):
+    def __init__(self, r_dict, variant="keys"):
         self.r_dict = r_dict
+        self.variant = variant
         self.lowleveltype = lltype.Ptr(lltype.GcStruct('strdictiter',
                                          ('dict', r_dict.lowleveltype),
                                          ('index', lltype.Signed)))
@@ -343,9 +362,12 @@
 
     def rtype_next(self, hop):
         v_iter, = hop.inputargs(self)
+        r_list = hop.r_result
+        v_func = hop.inputconst(lltype.Void, dum_variant[self.variant])
+        c1 = hop.inputconst(lltype.Void, r_list.lowleveltype)
         hop.has_implicit_exception(StopIteration) # record that we know about it
         hop.exception_is_here()
-        return hop.gendirectcall(ll_strdictnext, v_iter)
+        return hop.gendirectcall(ll_strdictnext, v_iter, v_func, c1)
 
 def ll_strdictiter(ITERPTR, d):
     iter = lltype.malloc(ITERPTR.TO)
@@ -353,16 +375,25 @@
     iter.index = 0
     return iter
 
-def ll_strdictnext(iter):
+def ll_strdictnext(iter, func, RETURNTYPE):
     entries = iter.dict.entries
     index = iter.index
     entries_len = len(entries)
     while index < entries_len:
-        key = entries[index].key
+        entry = entries[index]
+        key = entry.key
         index = index + 1
         if key and key != deleted_entry_marker:
             iter.index = index
-            return key
+            if func is dum_items:
+                r = lltype.malloc(RETURNTYPE.TO)
+                r.item0 = key
+                r.item1 = entry.value
+                return r
+            elif func is dum_keys:
+                return key
+            elif func is dum_values:
+                return entry.value
     iter.index = index
     raise StopIteration
 
@@ -410,10 +441,6 @@
             ll_strdict_setitem(dic1, entry.key, entry.value)
         i += 1
 
-def dum_keys(): pass
-def dum_values(): pass
-def dum_items():pass
-
 # this is an implementation of keys(), values() and items()
 # in a single function.
 # note that by specialization on func, three different

Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Fri Sep  9 21:49:25 2005
@@ -2,6 +2,7 @@
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst
+from pypy.rpython.rmodel import IteratorRepr
 from pypy.rpython import rrange
 from pypy.rpython.rslice import SliceRepr
 from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
@@ -806,7 +807,7 @@
 #
 #  Iteration.
 
-class ListIteratorRepr(Repr):
+class ListIteratorRepr(IteratorRepr):
 
     def __init__(self, r_list):
         self.r_list = r_list

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Fri Sep  9 21:49:25 2005
@@ -149,16 +149,24 @@
         r_iter = self.make_iterator_repr()
         return r_iter.newiter(hop)
 
-    def make_iterator_repr(self):
+    def make_iterator_repr(self, *variant):
         raise TyperError("%s is not iterable" % (self,))
 
+class IteratorRepr(Repr):
+    """Base class of Reprs of any kind of iterator."""
+
+    def rtype_iter(self, hop):    #   iter(iter(x))  <==>  iter(x)
+        v_iter, = hop.inputargs(self)
+        return v_iter
+
+
 class __extend__(annmodel.SomeIterator):
     # NOTE: SomeIterator is for iterators over any container, not just list
     def rtyper_makerepr(self, rtyper):
         r_container = rtyper.getrepr(self.s_container)
-        return r_container.make_iterator_repr()
+        return r_container.make_iterator_repr(*self.variant)
     def rtyper_makekey(self):
-        return self.__class__, self.s_container.rtyper_makekey()
+        return self.__class__, self.s_container.rtyper_makekey(), self.variant
 
 class __extend__(annmodel.SomeImpossibleValue):
     def rtyper_makerepr(self, rtyper):

Modified: pypy/dist/pypy/rpython/rrange.py
==============================================================================
--- pypy/dist/pypy/rpython/rrange.py	(original)
+++ pypy/dist/pypy/rpython/rrange.py	Fri Sep  9 21:49:25 2005
@@ -1,6 +1,6 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, IteratorRepr
 from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void
 from pypy.objspace.flow.model import Constant
 
@@ -118,7 +118,7 @@
 #
 #  Iteration.
 
-class RangeIteratorRepr(Repr):
+class RangeIteratorRepr(IteratorRepr):
     lowleveltype = Ptr(RANGEITER)
 
     def __init__(self, r_rng):

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Fri Sep  9 21:49:25 2005
@@ -1,7 +1,7 @@
 from weakref import WeakValueDictionary
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, IteratorRepr
 from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst, UniCharRepr
 from pypy.rpython.rarithmetic import intmask, _hash_string
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
@@ -994,7 +994,7 @@
 #
 #  Iteration.
 
-class StringIteratorRepr(Repr):
+class StringIteratorRepr(IteratorRepr):
     lowleveltype = Ptr(GcStruct('stringiter',
                                 ('string', string_repr.lowleveltype),
                                 ('index', Signed)))

Modified: pypy/dist/pypy/rpython/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/rtuple.py	(original)
+++ pypy/dist/pypy/rpython/rtuple.py	Fri Sep  9 21:49:25 2005
@@ -2,6 +2,7 @@
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst
+from pypy.rpython.rmodel import IteratorRepr
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed, malloc
 from pypy.rpython.lltype import typeOf, nullptr
@@ -183,7 +184,7 @@
 #
 #  Iteration.
 
-class Length1TupleIteratorRepr(Repr):
+class Length1TupleIteratorRepr(IteratorRepr):
 
     def __init__(self, r_tuple):
         self.r_tuple = r_tuple

Modified: pypy/dist/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rdict.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rdict.py	Fri Sep  9 21:49:25 2005
@@ -163,6 +163,23 @@
     res = interpret(func, [6, 7])
     assert res == 42
 
+def test_dict_itermethods():
+    def func():
+        d = {}
+        d['hello'] = 6
+        d['world'] = 7
+        k1 = k2 = k3 = 1
+        for key in d.iterkeys():
+            k1 = k1 * d[key]
+        for value in d.itervalues():
+            k2 = k2 * value
+        for key, value in d.iteritems():
+            assert d[key] == value
+            k3 = k3 * value
+        return k1 + k2 + k3
+    res = interpret(func, [])
+    assert res == 42 + 42 + 42
+
 def test_two_dicts_with_different_value_types():
     def func(i):
         d1 = {}



More information about the Pypy-commit mailing list