Author: Armin Rigo <[email protected]>
Branch: int-float-list-strategy
Changeset: r78403:cadc17f46535
Date: 2015-07-02 10:12 +0200
http://bitbucket.org/pypy/pypy/changeset/cadc17f46535/

Log:    lst = [1.2]; lst += [0]

        lst = [1.2]; lst += [0, 3.4]

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -1738,6 +1738,21 @@
     def getitems_float(self, w_list):
         return self.unerase(w_list.lstorage)
 
+
+    _base_extend_from_list = _extend_from_list
+
+    def _extend_from_list(self, w_list, w_other):
+        if (w_other.strategy is self.space.fromcache(IntegerListStrategy) or
+            w_other.strategy is self.space.fromcache(IntOrFloatListStrategy)):
+            # xxx a case that we don't optimize: [3.4].extend([9999999999999])
+            # will cause a switch to int-or-float, followed by another
+            # switch to object
+            if self.switch_to_int_or_float_strategy(w_list):
+                w_list.extend(w_other)
+                return
+        return self._base_extend_from_list(w_list, w_other)
+
+
     def _safe_find(self, w_list, obj, start, stop):
         from rpython.rlib.rfloat import isnan
         #
@@ -1766,21 +1781,24 @@
                 longlong2float.float2longlong(floatval))
         return generalized_list
 
+    def switch_to_int_or_float_strategy(self, w_list):
+        # xxx we should be able to use the same lstorage, but
+        # there is a typing issue (float vs longlong)...
+        try:
+            generalized_list = self.float_2_float_or_int(w_list)
+        except ValueError:
+            return False
+        strategy = self.space.fromcache(IntOrFloatListStrategy)
+        w_list.strategy = strategy
+        w_list.lstorage = strategy.erase(generalized_list)
+        return True
+
     def switch_to_next_strategy(self, w_list, w_sample_item):
         if type(w_sample_item) is W_IntObject:
             sample_intval = self.space.int_w(w_sample_item)
             if longlong2float.can_encode_int32(sample_intval):
-                # xxx we should be able to use the same lstorage, but
-                # there is a typing issue (float vs longlong)...
-                try:
-                    generalized_list = self.float_2_float_or_int(w_list)
-                except ValueError:
-                    pass
-                else:
+                if self.switch_to_int_or_float_strategy(w_list):
                     # yes, we can switch to IntOrFloatListStrategy
-                    strategy = self.space.fromcache(IntOrFloatListStrategy)
-                    w_list.strategy = strategy
-                    w_list.lstorage = strategy.erase(generalized_list)
                     return
         # no, fall back to ObjectListStrategy
         w_list.switch_to_object_strategy()
diff --git a/pypy/objspace/std/test/test_liststrategies.py 
b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -908,9 +908,37 @@
         assert space.unwrap(w_l1) == [0, 3.4, -2]
 
     def test_int_or_float_extend_mixed_5(self):
-        py.test.skip("XXX not implemented")
-        # lst = [1.2]; lst += [0]
-        # lst = [1.2]; lst += [0, 3.4]
+        space = self.space
+        w_l1 = W_ListObject(space, [space.wrap(-2.5)])
+        w_l2 = W_ListObject(space, [space.wrap(42)])
+        assert isinstance(w_l1.strategy, FloatListStrategy)
+        assert isinstance(w_l2.strategy, IntegerListStrategy)
+        w_l1.extend(w_l2)
+        assert isinstance(w_l1.strategy, IntOrFloatListStrategy)
+        assert space.unwrap(w_l1) == [-2.5, 42]
+
+    def test_int_or_float_extend_mixed_5_overflow(self):
+        if sys.maxint == 2147483647:
+            py.test.skip("only on 64-bit")
+        space = self.space
+        ovf1 = 2 ** 35
+        w_l1 = W_ListObject(space, [space.wrap(-2.5)])
+        w_l2 = W_ListObject(space, [space.wrap(ovf1)])
+        assert isinstance(w_l1.strategy, FloatListStrategy)
+        assert isinstance(w_l2.strategy, IntegerListStrategy)
+        w_l1.extend(w_l2)
+        assert isinstance(w_l1.strategy, ObjectListStrategy)
+        assert space.unwrap(w_l1) == [-2.5, ovf1]
+
+    def test_int_or_float_extend_mixed_6(self):
+        space = self.space
+        w_l1 = W_ListObject(space, [space.wrap(-2.5)])
+        w_l2 = W_ListObject(space, [space.wrap(3.4), space.wrap(-2)])
+        assert isinstance(w_l1.strategy, FloatListStrategy)
+        assert isinstance(w_l2.strategy, IntOrFloatListStrategy)
+        w_l1.extend(w_l2)
+        assert isinstance(w_l1.strategy, IntOrFloatListStrategy)
+        assert space.unwrap(w_l1) == [-2.5, 3.4, -2]
 
     def test_int_or_float_setslice(self):
         space = self.space
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to