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

arigo at codespeak.net arigo at codespeak.net
Wed May 3 11:02:50 CEST 2006


Author: arigo
Date: Wed May  3 11:02:48 2006
New Revision: 26714

Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/lltypesystem/rdict.py
   pypy/dist/pypy/rpython/test/test_remptydict.py
Log:
(pedronis, arigo)  Support for iterating over empty lists and dicts.


Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Wed May  3 11:02:48 2006
@@ -488,11 +488,12 @@
                 exits = [link for link in block.exits
                               if link.exitcase is not None]
 
-            elif e.op.opname in ('simple_call', 'call_args'):
+            elif e.op.opname in ('simple_call', 'call_args', 'next'):
                 # XXX warning, keep the name of the call operations in sync
                 # with the flow object space.  These are the operations for
                 # which it is fine to always raise an exception.  We then
                 # swallow the BlockedInference and that's it.
+                # About 'next': see test_annotate_iter_empty_container().
                 return
 
             else:

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Wed May  3 11:02:48 2006
@@ -1975,6 +1975,23 @@
         assert s.__class__ == annmodel.SomeObject
         assert s.knowntype == type
 
+    def test_annotate_iter_empty_container(self):
+        def f():
+            n = 0
+            d = {}
+            for x in []:                n += x
+            for y in d:                 n += y
+            for z in d.iterkeys():      n += z
+            for s in d.itervalues():    n += s
+            for t, u in d.items():      n += t * u
+            for t, u in d.iteritems():  n += t * u
+            return n
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert s.is_constant()
+        assert s.const == 0
+
 def g(n):
     return [0,1,2,n]
 

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Wed May  3 11:02:48 2006
@@ -7,7 +7,7 @@
      SomeDict, SomeUnicodeCodePoint, SomeTuple, SomeImpossibleValue, \
      SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \
      SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
-     SomeCTypesObject,\
+     SomeCTypesObject, s_ImpossibleValue, \
      unionof, set, missing_operation, add_knowntypedata
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation import builtin
@@ -317,8 +317,13 @@
         elif variant == 'values':
             return dct.dictdef.read_value()
         elif variant == 'items':
-            return SomeTuple((dct.dictdef.read_key(),
-                              dct.dictdef.read_value()))
+            s_key   = dct.dictdef.read_key()
+            s_value = dct.dictdef.read_value()
+            if (isinstance(s_key, SomeImpossibleValue) or
+                isinstance(s_value, SomeImpossibleValue)):
+                return s_ImpossibleValue
+            else:
+                return SomeTuple((s_key, s_value))
         else:
             raise ValueError
 
@@ -342,8 +347,7 @@
         return getbookkeeper().newlist(dct.dictdef.read_value())
 
     def method_items(dct):
-        return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(),
-                                                  dct.dictdef.read_value())))
+        return getbookkeeper().newlist(dct.getanyitem('items'))
 
     def method_iterkeys(dct):
         return SomeIterator(dct, 'keys')
@@ -388,7 +392,7 @@
     def method_join(str, s_list):
         getbookkeeper().count("str_join", str)
         s_item = s_list.listdef.read_item()
-        if s_item == SomeImpossibleValue():
+        if isinstance(s_item, SomeImpossibleValue):
             return immutablevalue("")
         return SomeString()
 

Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rdict.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rdict.py	Wed May  3 11:02:48 2006
@@ -614,7 +614,9 @@
             index = index + 1
             if entry.valid():
                 iter.index = index
-                if func is dum_items:
+                if RETURNTYPE is lltype.Void:
+                    return None
+                elif func is dum_items:
                     r = lltype.malloc(RETURNTYPE.TO)
                     r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
                     r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
@@ -707,15 +709,16 @@
         entry = entries[i]
         if entry.valid():
             ELEM = lltype.typeOf(items).TO.OF
-            if func is dum_items:
-                r = lltype.malloc(ELEM.TO)
-                r.item0 = recast(ELEM.TO.item0, entry.key)
-                r.item1 = recast(ELEM.TO.item1, entry.value)
-                items[p] = r
-            elif func is dum_keys:
-                items[p] = recast(ELEM, entry.key)
-            elif func is dum_values:
-                items[p] = recast(ELEM, entry.value)
+            if ELEM is not lltype.Void:
+                if func is dum_items:
+                    r = lltype.malloc(ELEM.TO)
+                    r.item0 = recast(ELEM.TO.item0, entry.key)
+                    r.item1 = recast(ELEM.TO.item1, entry.value)
+                    items[p] = r
+                elif func is dum_keys:
+                    items[p] = recast(ELEM, entry.key)
+                elif func is dum_values:
+                    items[p] = recast(ELEM, entry.value)
             p += 1
         i += 1
     return res

Modified: pypy/dist/pypy/rpython/test/test_remptydict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_remptydict.py	(original)
+++ pypy/dist/pypy/rpython/test/test_remptydict.py	Wed May  3 11:02:48 2006
@@ -11,3 +11,17 @@
         return bool(a.d1) or bool(a.d2)
     res = interpret(func, [])
     assert res is False
+
+def test_iterate_over_empty_dict():
+    def f():
+        n = 0
+        d = {}
+        for x in []:                n += x
+        for y in d:                 n += y
+        for z in d.iterkeys():      n += z
+        for s in d.itervalues():    n += s
+        for t, u in d.items():      n += t * u
+        for t, u in d.iteritems():  n += t * u
+        return n
+    res = interpret(f, [])
+    assert res == 0



More information about the Pypy-commit mailing list