[pypy-svn] r58930 - in pypy/branch/getslice/pypy: annotation annotation/test interpreter objspace objspace/flow objspace/std objspace/std/test rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator

arigo at codespeak.net arigo at codespeak.net
Fri Oct 10 19:38:46 CEST 2008


Author: arigo
Date: Fri Oct 10 19:38:43 2008
New Revision: 58930

Removed:
   pypy/branch/getslice/pypy/rpython/lltypesystem/rslice.py
   pypy/branch/getslice/pypy/rpython/ootypesystem/rslice.py
   pypy/branch/getslice/pypy/rpython/rslice.py
Modified:
   pypy/branch/getslice/pypy/annotation/annrpython.py
   pypy/branch/getslice/pypy/annotation/binaryop.py
   pypy/branch/getslice/pypy/annotation/bookkeeper.py
   pypy/branch/getslice/pypy/annotation/builtin.py
   pypy/branch/getslice/pypy/annotation/model.py
   pypy/branch/getslice/pypy/annotation/test/test_annrpython.py
   pypy/branch/getslice/pypy/annotation/unaryop.py
   pypy/branch/getslice/pypy/interpreter/baseobjspace.py
   pypy/branch/getslice/pypy/objspace/descroperation.py
   pypy/branch/getslice/pypy/objspace/flow/objspace.py
   pypy/branch/getslice/pypy/objspace/reflective.py
   pypy/branch/getslice/pypy/objspace/std/builtinshortcut.py
   pypy/branch/getslice/pypy/objspace/std/listobject.py
   pypy/branch/getslice/pypy/objspace/std/objspace.py
   pypy/branch/getslice/pypy/objspace/std/rangeobject.py
   pypy/branch/getslice/pypy/objspace/std/ropeobject.py
   pypy/branch/getslice/pypy/objspace/std/ropeunicodeobject.py
   pypy/branch/getslice/pypy/objspace/std/sliceobject.py
   pypy/branch/getslice/pypy/objspace/std/stringobject.py
   pypy/branch/getslice/pypy/objspace/std/strsliceobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_builtinshortcut.py
   pypy/branch/getslice/pypy/objspace/std/test/test_listmultiobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_listobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_rangeobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_stringobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_strsliceobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_tupleobject.py
   pypy/branch/getslice/pypy/objspace/std/test/test_unicodeobject.py
   pypy/branch/getslice/pypy/objspace/std/tupleobject.py
   pypy/branch/getslice/pypy/objspace/std/unicodeobject.py
   pypy/branch/getslice/pypy/objspace/thunk.py
   pypy/branch/getslice/pypy/rpython/lltypesystem/rlist.py
   pypy/branch/getslice/pypy/rpython/ootypesystem/rlist.py
   pypy/branch/getslice/pypy/rpython/rlist.py
   pypy/branch/getslice/pypy/rpython/rstr.py
   pypy/branch/getslice/pypy/rpython/rtuple.py
   pypy/branch/getslice/pypy/rpython/rtyper.py
   pypy/branch/getslice/pypy/rpython/test/test_rlist.py
   pypy/branch/getslice/pypy/translator/simplify.py
   pypy/branch/getslice/pypy/translator/transform.py
Log:
(antocuni, arigo)
Probably in-progress.


Modified: pypy/branch/getslice/pypy/annotation/annrpython.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/annrpython.py	(original)
+++ pypy/branch/getslice/pypy/annotation/annrpython.py	Fri Oct 10 19:38:43 2008
@@ -760,10 +760,6 @@
     def consider_op_newdict(self):
         return self.bookkeeper.newdict()
 
-    def consider_op_newslice(self, start, stop, step):
-        self.bookkeeper.count('newslice', start, stop, step)
-        return annmodel.SomeSlice(start, stop, step)
-
 
     def _registeroperations(cls, model):
         # All unary operations

Modified: pypy/branch/getslice/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/binaryop.py	(original)
+++ pypy/branch/getslice/pypy/annotation/binaryop.py	Fri Oct 10 19:38:43 2008
@@ -10,7 +10,7 @@
 from pypy.annotation.model import SomeUnicodeCodePoint
 from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
 from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator
-from pypy.annotation.model import SomePBC, SomeSlice, SomeFloat, s_None
+from pypy.annotation.model import SomePBC, SomeFloat, s_None
 from pypy.annotation.model import SomeExternalObject, SomeWeakRef
 from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
 from pypy.annotation.model import SomeSingleFloat
@@ -564,14 +564,6 @@
     delitem.can_only_throw = _can_only_throw
 
 
-class __extend__(pairtype(SomeSlice, SomeSlice)):
-
-    def union((slic1, slic2)):
-        return SomeSlice(unioncheck(slic1.start, slic2.start),
-                         unioncheck(slic1.stop, slic2.stop),
-                         unioncheck(slic1.step, slic2.step))
-
-
 class __extend__(pairtype(SomeTuple, SomeInteger)):
     
     def getitem((tup1, int2)):
@@ -585,13 +577,6 @@
             return unionof(*tup1.items)
     getitem.can_only_throw = [IndexError]
 
-class __extend__(pairtype(SomeTuple, SomeSlice)):
-
-    def getitem((tup, slic)):
-        start, stop, step = slic.constant_indices()
-        return SomeTuple(tup.items[start:stop:step])
-    getitem.can_only_throw = []
-
 
 class __extend__(pairtype(SomeList, SomeInteger)):
     
@@ -623,40 +608,6 @@
         lst1.listdef.resize()
     delitem.can_only_throw = [IndexError]
 
-def check_negative_slice(s_slice):
-    if isinstance(s_slice.start, SomeInteger) and not s_slice.start.nonneg:
-        raise TypeError("%s not proven to have non-negative start" % s_slice)
-    if isinstance(s_slice.stop, SomeInteger) and not s_slice.stop.nonneg and\
-           getattr(s_slice.stop, 'const', 0) != -1:
-        raise TypeError("%s not proven to have non-negative stop" % s_slice)
-
-class __extend__(pairtype(SomeList, SomeSlice)):
-
-    def getitem((lst, slic)):
-        check_negative_slice(slic)
-        return lst.listdef.offspring()
-    getitem.can_only_throw = []
-
-    def setitem((lst, slic), s_iterable):
-        check_negative_slice(slic)
-        # we need the same unifying effect as the extend() method for
-        # the case lst1[x:y] = lst2.
-        lst.method_extend(s_iterable)
-    setitem.can_only_throw = []
-
-    def delitem((lst1, slic)):
-        check_negative_slice(slic)
-        lst1.listdef.resize()
-    delitem.can_only_throw = []
-
-class __extend__(pairtype(SomeString, SomeSlice),
-                 pairtype(SomeUnicodeString, SomeSlice)):
-
-    def getitem((str1, slic)):
-        check_negative_slice(slic)
-        return str1.basestringclass()
-    getitem.can_only_throw = []
-
 class __extend__(pairtype(SomeString, SomeInteger)):
 
     def getitem((str1, int2)):

Modified: pypy/branch/getslice/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/getslice/pypy/annotation/bookkeeper.py	Fri Oct 10 19:38:43 2008
@@ -68,9 +68,6 @@
     def consider_generic(self, *args):
         return tuple([self.typerepr(x) for x in args])
 
-    def consider_newslice(self, s_start, s_stop, s_step):
-        return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)])
-
     def consider_list_list_eq(self, obj1, obj2):
         return obj1, obj2
 

Modified: pypy/branch/getslice/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/builtin.py	(original)
+++ pypy/branch/getslice/pypy/annotation/builtin.py	Fri Oct 10 19:38:43 2008
@@ -4,7 +4,7 @@
 
 import sys
 from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool
-from pypy.annotation.model import SomeString, SomeTuple, SomeSlice, s_Bool
+from pypy.annotation.model import SomeString, SomeTuple, s_Bool
 from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress
 from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString
 from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
@@ -249,19 +249,19 @@
     getbookkeeper().warning("ignoring apply%r" % (stuff,))
     return SomeObject()
 
-def builtin_slice(*args):
-    bk = getbookkeeper()
-    if len(args) == 1:
-        return SomeSlice(
-            bk.immutablevalue(None), args[0], bk.immutablevalue(None))
-    elif len(args) == 2:
-        return SomeSlice(
-            args[0], args[1], bk.immutablevalue(None))
-    elif len(args) == 3:
-        return SomeSlice(
-            args[0], args[1], args[2])
-    else:
-        raise Exception, "bogus call to slice()"
+##def builtin_slice(*args):
+##    bk = getbookkeeper()
+##    if len(args) == 1:
+##        return SomeSlice(
+##            bk.immutablevalue(None), args[0], bk.immutablevalue(None))
+##    elif len(args) == 2:
+##        return SomeSlice(
+##            args[0], args[1], bk.immutablevalue(None))
+##    elif len(args) == 3:
+##        return SomeSlice(
+##            args[0], args[1], args[2])
+##    else:
+##        raise Exception, "bogus call to slice()"
 
 
 def OSError_init(s_self, *args):

Modified: pypy/branch/getslice/pypy/annotation/model.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/model.py	(original)
+++ pypy/branch/getslice/pypy/annotation/model.py	Fri Oct 10 19:38:43 2008
@@ -253,25 +253,6 @@
     def can_be_none(self):
         return True
 
-class SomeSlice(SomeObject):
-    knowntype = slice
-    immutable = True
-    def __init__(self, start, stop, step):
-        self.start = start
-        self.stop = stop
-        self.step = step
-
-    def constant_indices(self):
-        if (self.start.is_immutable_constant() and
-            self.stop .is_immutable_constant() and
-            self.step .is_immutable_constant()):
-            return self.start.const, self.stop.const, self.step.const
-        else:
-            raise Exception("need constant indices for this slice")
-
-    def can_be_none(self):
-        return False
-
 class SomeTuple(SomeObject):
     "Stands for a tuple of known length."
     knowntype = tuple

Modified: pypy/branch/getslice/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/branch/getslice/pypy/annotation/test/test_annrpython.py	Fri Oct 10 19:38:43 2008
@@ -425,16 +425,6 @@
             s_meth = s_example.getattr(iv(methname))
             assert isinstance(s_constmeth, annmodel.SomeBuiltin)
 
-    def test_simple_slicing0(self):
-        a = self.RPythonAnnotator()
-        a.build_types(snippet.simple_slice, [list])
-        g = graphof(a, snippet.simple_slice)
-        for block in g.iterblocks():
-            for op in block.operations:
-                if op.opname == "newslice":
-                    assert isinstance(a.binding(op.result),
-                                      annmodel.SomeSlice)
-
     def test_simple_slicing(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.simple_slice, [list])
@@ -570,11 +560,6 @@
         s = a.build_types(operation_always_raising, [int])
         assert s == a.bookkeeper.immutablevalue(24)
 
-    def test_slice_union(self):
-        a = self.RPythonAnnotator()
-        s = a.build_types(snippet.slice_union, [int])
-        assert isinstance(s, annmodel.SomeSlice)
-
     def test_bltin_code_frame_confusion(self):
         a = self.RPythonAnnotator()
         a.build_types(snippet.bltin_code_frame_confusion,[])
@@ -3040,6 +3025,28 @@
 
         a.build_types(f, [str])
 
+    def test_setslice(self):
+        def f():
+            lst = [2, 5, 7]
+            lst[1:2] = [4]
+            return lst
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeList)
+        assert not s.listdef.listitem.resized
+
+    def test_delslice(self):
+        def f():
+            lst = [2, 5, 7]
+            del lst[1:2]
+            return lst
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeList)
+        assert s.listdef.listitem.resized
+
     def test_listitem_no_mutating(self):
         from pypy.rlib.debug import check_annotation
         called = []

Modified: pypy/branch/getslice/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/getslice/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/getslice/pypy/annotation/unaryop.py	Fri Oct 10 19:38:43 2008
@@ -24,6 +24,7 @@
                         'iter', 'next', 'invert', 'type', 'issubtype',
                         'pos', 'neg', 'nonzero', 'abs', 'hex', 'oct',
                         'ord', 'int', 'float', 'long', 'id',
+                        'getslice', 'setslice', 'delslice',
                         'neg_ovf', 'abs_ovf', 'hint', 'unicode', 'unichr'])
 
 for opname in UNARY_OPERATIONS:
@@ -274,6 +275,12 @@
             s_item.hash()    # record that we need the hash of each item
         return SomeInteger()
 
+    def getslice(tup, s_start, s_stop):
+        assert s_start.is_immutable_constant(),"tuple slicing: needs constants"
+        assert s_stop.is_immutable_constant(), "tuple slicing: needs constants"
+        items = tup.items[s_start.const:s_stop.const]
+        return SomeTuple(items)
+
 
 class __extend__(SomeList):
 
@@ -283,11 +290,9 @@
 
     def method_extend(lst, s_iterable):
         lst.listdef.resize()
-        if isinstance(s_iterable, SomeList):   # unify the two lists
-            lst.listdef.agree(s_iterable.listdef)
-        else:
-            s_iter = s_iterable.iter()
-            lst.method_append(s_iter.next())
+        if not isinstance(s_iterable, SomeList):
+            raise Exception("list.extend(x): x must be a list")
+        lst.listdef.agree(s_iterable.listdef)
 
     def method_reverse(lst):
         lst.listdef.mutate()
@@ -338,6 +343,28 @@
             lst = lst.listdef.offspring()
         return lst
 
+    def getslice(lst, s_start, s_stop):
+        check_negative_slice(s_start, s_stop)
+        return lst.listdef.offspring()
+
+    def setslice(lst, s_start, s_stop, s_iterable):
+        check_negative_slice(s_start, s_stop)
+        if not isinstance(s_iterable, SomeList):
+            raise Exception("list[start:stop] = x: x must be a list")
+        lst.listdef.agree(s_iterable.listdef)
+        # note that setslice is not allowed to resize a list in RPython
+
+    def delslice(lst, s_start, s_stop):
+        check_negative_slice(s_start, s_stop)
+        lst.listdef.resize()
+
+def check_negative_slice(s_start, s_stop):
+    if isinstance(s_start, SomeInteger) and not s_start.nonneg:
+        raise TypeError("slicing: not proven to have non-negative start")
+    if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \
+           getattr(s_stop, 'const', 0) != -1:
+        raise TypeError("slicing: not proven to have non-negative stop")
+
 
 class __extend__(SomeDict):
 
@@ -463,6 +490,10 @@
     def method_replace(str, s1, s2):
         return str.basestringclass()
 
+    def getslice(str, s_start, s_stop):
+        check_negative_slice(s_start, s_stop)
+        return str.basestringclass()
+
 class __extend__(SomeUnicodeString):
     def method_encode(uni, s_enc):
         if not s_enc.is_constant():

Modified: pypy/branch/getslice/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/getslice/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/getslice/pypy/interpreter/baseobjspace.py	Fri Oct 10 19:38:43 2008
@@ -588,17 +588,6 @@
         w_s = self.interned_strings[s] = self.wrap(s)
         return w_s
 
-    # support for the deprecated __getslice__, __setslice__, __delslice__
-    def getslice(self, w_obj, w_start, w_stop):
-        w_slice = self.newslice(w_start, w_stop, self.w_None)
-        return self.getitem(w_obj, w_slice)
-    def setslice(self, w_obj, w_start, w_stop, w_sequence):
-        w_slice = self.newslice(w_start, w_stop, self.w_None)
-        self.setitem(w_obj, w_slice, w_sequence)
-    def delslice(self, w_obj, w_start, w_stop):
-        w_slice = self.newslice(w_start, w_stop, self.w_None)
-        self.delitem(w_obj, w_slice)
-
     def interpclass_w(space, w_obj):
         """
          If w_obj is a wrapped internal interpreter class instance unwrap to it,
@@ -1032,6 +1021,9 @@
     ('getitem',         'getitem',   2, ['__getitem__']),
     ('setitem',         'setitem',   3, ['__setitem__']),
     ('delitem',         'delitem',   2, ['__delitem__']),
+    ('getslice',        'getslice',  3, ['__getslice__']),
+    ('setslice',        'setslice',  4, ['__setslice__']),
+    ('delslice',        'delslice',  3, ['__delslice__']),
     ('pos',             'pos',       1, ['__pos__']),
     ('neg',             'neg',       1, ['__neg__']),
     ('nonzero',         'truth',     1, ['__nonzero__']),

Modified: pypy/branch/getslice/pypy/objspace/descroperation.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/descroperation.py	(original)
+++ pypy/branch/getslice/pypy/objspace/descroperation.py	Fri Oct 10 19:38:43 2008
@@ -228,6 +228,30 @@
                    space.wrap("cannot delete items from object"))
         return space.get_and_call_function(w_descr, w_obj, w_key)
 
+    def getslice(space, w_obj, w_start, w_stop):
+        w_descr = space.lookup(w_obj, '__getslice__')
+        if w_descr is None:
+            w_slice = space.newslice(w_start, w_stop, space.w_None)
+            return space.getitem(w_obj, w_slice)
+        w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+        return space.get_and_call_function(w_descr, w_obj, w_start, w_stop)
+
+    def setslice(space, w_obj, w_start, w_stop, w_sequence):
+        w_descr = space.lookup(w_obj, '__setslice__')
+        if w_descr is None:
+            w_slice = space.newslice(w_start, w_stop, space.w_None)
+            return space.setitem(w_obj, w_slice, w_sequence)
+        w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+        return space.get_and_call_function(w_descr, w_obj, w_start, w_stop, w_sequence)
+
+    def delslice(space, w_obj, w_start, w_stop):
+        w_descr = space.lookup(w_obj, '__delslice__')
+        if w_descr is None:
+            w_slice = space.newslice(w_start, w_stop, space.w_None)
+            return space.delitem(w_obj, w_slice)
+        w_start, w_stop = old_slice_range(space, w_obj, w_start, w_stop)
+        return space.get_and_call_function(w_descr, w_obj, w_start, w_stop)
+
     def pow(space, w_obj1, w_obj2, w_obj3):
         w_typ1 = space.type(w_obj1)
         w_typ2 = space.type(w_obj2)
@@ -453,6 +477,35 @@
     return (space.lookup(w_obj, '__int__') is not None or
             space.lookup(w_obj, '__float__') is not None)
 
+
+
+# what is the maximum value slices can get on CPython?
+# we need to stick to that value, because fake.py etc.
+class Temp:
+    def __getslice__(self, i, j):
+        return j
+slice_max = Temp()[:]
+del Temp
+
+def old_slice_range(space, w_obj, w_start, w_stop):
+    """Only for backward compatibility for __getslice__()&co methods."""
+    if space.is_w(w_start, space.w_None):
+        w_start = space.wrap(0)
+    else:
+        w_start = space.wrap(space.getindex_w(w_start, None))
+        if space.is_true(space.lt(w_start, space.wrap(0))):
+            w_start = space.add(w_start, space.len(w_obj))
+            # NB. the language ref is inconsistent with the new-style class
+            # behavior when w_obj doesn't implement __len__(), so we just
+            # ignore this case.
+    if space.is_w(w_stop, space.w_None):
+        w_stop = space.wrap(slice_max)
+    else:
+        w_stop = space.wrap(space.getindex_w(w_stop, None))
+        if space.is_true(space.lt(w_stop, space.wrap(0))):
+            w_stop = space.add(w_stop, space.len(w_obj))
+    return w_start, w_stop
+
 # regular methods def helpers
 
 def _make_binop_impl(symbol, specialnames):
@@ -649,5 +702,3 @@
                            'ord', 'unichr', 'unicode']:
             raise Exception, "missing def for operation %s" % _name
             
-            
-

Modified: pypy/branch/getslice/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/flow/objspace.py	(original)
+++ pypy/branch/getslice/pypy/objspace/flow/objspace.py	Fri Oct 10 19:38:43 2008
@@ -103,7 +103,7 @@
             return Constant(slice(self.unwrap(w_start),
                                   self.unwrap(w_stop),
                                   self.unwrap(w_step)))
-        return self.do_operation('newslice', w_start, w_stop, w_step)
+        raise Exception("not supported in RPython: extended slicing")
 
     def wrap(self, obj):
         if isinstance(obj, (Variable, Constant)):

Modified: pypy/branch/getslice/pypy/objspace/reflective.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/reflective.py	(original)
+++ pypy/branch/getslice/pypy/objspace/reflective.py	Fri Oct 10 19:38:43 2008
@@ -89,6 +89,14 @@
                     return parentfn(w_arg1, w_arg2, w_arg3)
                 finally:
                     reset_reflective_space(space, w_old_reflectivespace)
+        elif args == 4:
+            def func(self, space, w_arg1, w_arg2, w_arg3, w_arg4):
+                w_old_reflectivespace = get_reflective_space(space)
+                set_reflectivespace(space, self.w_reflectivespace)
+                try:
+                    return parentfn(w_arg1, w_arg2, w_arg3, w_arg4)
+                finally:
+                    reset_reflective_space(space, w_old_reflectivespace)
         else:
             raise NotImplementedError
         unwrap_spec = ["self", ObjSpace] + [W_Root] * args

Modified: pypy/branch/getslice/pypy/objspace/std/builtinshortcut.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/builtinshortcut.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/builtinshortcut.py	Fri Oct 10 19:38:43 2008
@@ -32,10 +32,16 @@
 KNOWN_MISSING = ['getattr',   # mostly non-builtins or optimized by CALL_METHOD
                  'setattr', 'delattr', 'userdel',  # mostly for non-builtins
                  'get', 'set', 'delete',   # uncommon (except on functions)
-                 'delitem', 'abs', 'hex', 'oct',  # rare stuff?
+                 'getslice', 'setslice', 'delslice',  # see below
+                 'delitem',                       # rare stuff?
+                 'abs', 'hex', 'oct',             # rare stuff?
                  'pos', 'divmod', 'cmp',          # rare stuff?
                  'float', 'long', 'coerce',       # rare stuff?
                  ]
+# We cannot support {get,set,del}slice right now because
+# DescrOperation.{get,set,del}slice do a bit more work than just call
+# the special methods: they call old_slice_range().  See e.g.
+# test_builtinshortcut.AppTestString.
 
 for _name, _, _, _specialmethods in ObjSpace.MethodTable:
     if _specialmethods:

Modified: pypy/branch/getslice/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/listobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/listobject.py	Fri Oct 10 19:38:43 2008
@@ -1,7 +1,7 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.listtype import get_list_index
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 
 from pypy.objspace.std import slicetype
 from pypy.interpreter import gateway, baseobjspace
@@ -80,6 +80,21 @@
         start += step
     return w_res
 
+def getslice__List_ANY_ANY(space, w_list, w_start, w_stop):
+    length = len(w_list.wrappeditems)
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    return W_ListObject(w_list.wrappeditems[start:stop])
+
+def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_sequence):
+    length = len(w_list.wrappeditems)
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    _setitem_slice_helper(space, w_list, start, 1, stop-start, w_sequence)
+
+def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
+    length = len(w_list.wrappeditems)
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    _delitem_slice_helper(space, w_list, start, 1, stop-start)
+
 def contains__List_ANY(space, w_list, w_obj):
     # needs to be safe against eq_w() mutating the w_list behind our back
     i = 0
@@ -190,38 +205,35 @@
                              space.wrap("list deletion index out of range"))
     return space.w_None
 
+
 def delitem__List_Slice(space, w_list, w_slice):
     start, stop, step, slicelength = w_slice.indices4(space,
                                                       len(w_list.wrappeditems))
+    _delitem_slice_helper(space, w_list, start, step, slicelength)
 
+def _delitem_slice_helper(space, w_list, start, step, slicelength):
     if slicelength==0:
         return
 
     if step < 0:
         start = start + step * (slicelength-1)
         step = -step
-        # stop is invalid
         
     if step == 1:
-        _del_slice(w_list, start, start+slicelength)
+        assert start >= 0
+        assert slicelength >= 0
+        del w_list.wrappeditems[start:start+slicelength]
     else:
         items = w_list.wrappeditems
         n = len(items)
-
-        recycle = [None] * slicelength
         i = start
 
-        # keep a reference to the objects to be removed,
-        # preventing side effects during destruction
-        recycle[0] = items[i]
-
         for discard in range(1, slicelength):
             j = i+1
             i += step
             while j < i:
                 items[j-discard] = items[j]
                 j += 1
-            recycle[discard] = items[i]
 
         j = i+1
         while j < n:
@@ -229,13 +241,7 @@
             j += 1
         start = n - slicelength
         assert start >= 0 # annotator hint
-        # XXX allow negative indices in rlist
         del items[start:]
-        # now we can destruct recycle safely, regardless of
-        # side-effects to the list
-        del recycle[:]
-
-    return space.w_None
 
 def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
     idx = get_list_index(space, w_index)
@@ -246,23 +252,25 @@
                              space.wrap("list index out of range"))
     return space.w_None
 
-def setitem__List_Slice_List(space, w_list, w_slice, w_list2):
-    l = w_list2.wrappeditems
-    return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
-
 def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
-    l = space.unpackiterable(w_iterable)
-    return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
-
-def _setitem_slice_helper(space, w_list, w_slice, sequence2, len2):
     oldsize = len(w_list.wrappeditems)
     start, stop, step, slicelength = w_slice.indices4(space, oldsize)
+    _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable)
+
+def _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable):
+    if isinstance(w_iterable, W_ListObject):
+        sequence2 = w_iterable.wrappeditems
+    else:
+        sequence2 = space.unpackiterable(w_iterable)
+
     assert slicelength >= 0
     items = w_list.wrappeditems
-
+    oldsize = len(items)
+    len2 = len(sequence2)
     if step == 1:  # Support list resizing for non-extended slices
-        delta = len2 - slicelength
-        if delta >= 0:
+        delta = slicelength - len2
+        if delta < 0:
+            delta = -delta
             newsize = oldsize + delta
             # XXX support this in rlist!
             items += [None] * delta
@@ -271,9 +279,10 @@
             while i >= lim:
                 items[i] = items[i-delta]
                 i -= 1
+        elif start >= 0:
+            del items[start:start+delta]
         else:
-            # shrinking requires the careful memory management of _del_slice()
-            _del_slice(w_list, start, start-delta)
+            assert delta==0
     elif len2 != slicelength:  # No resize for extended slices
         raise OperationError(space.w_ValueError, space.wrap("attempt to "
               "assign sequence of size %d to extended slice of size %d" %
@@ -290,14 +299,13 @@
                 items[start] = sequence2[i]
                 start -= step
                 i -= 1
-            return space.w_None
+            return
         else:
             # Make a shallow copy to more easily handle the reversal case
             sequence2 = list(sequence2)
     for i in range(len2):
         items[start] = sequence2[i]
         start += step
-    return space.w_None
 
 app = gateway.applevel("""
     def listrepr(currently_in_repr, l):
@@ -350,26 +358,6 @@
     w_list.wrappeditems += space.unpackiterable(w_any)
     return space.w_None
 
-def _del_slice(w_list, ilow, ihigh):
-    """ similar to the deletion part of list_ass_slice in CPython """
-    items = w_list.wrappeditems
-    n = len(items)
-    if ilow < 0:
-        ilow = 0
-    elif ilow > n:
-        ilow = n
-    if ihigh < ilow:
-        ihigh = ilow
-    elif ihigh > n:
-        ihigh = n
-    # keep a reference to the objects to be removed,
-    # preventing side effects during destruction
-    recycle = items[ilow:ihigh]
-    del items[ilow:ihigh]
-    # now we can destruct recycle safely, regardless of
-    # side-effects to the list
-    del recycle[:]
-
 # note that the default value will come back wrapped!!!
 def list_pop__List_ANY(space, w_list, w_idx=-1):
     items = w_list.wrappeditems

Modified: pypy/branch/getslice/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/objspace.py	Fri Oct 10 19:38:43 2008
@@ -764,33 +764,6 @@
         else:
             return ObjSpace.call_method(self, w_obj, methname, *arg_w)
 
-    # support for the deprecated __getslice__, __setslice__, __delslice__
-
-    def getslice(self, w_obj, w_start, w_stop):
-        w_descr = self.lookup(w_obj, '__getslice__')
-        if w_descr is not None:
-            w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
-            return self.get_and_call_function(w_descr, w_obj, w_start, w_stop)
-        else:
-            return ObjSpace.getslice(self, w_obj, w_start, w_stop)
-
-    def setslice(self, w_obj, w_start, w_stop, w_sequence):
-        w_descr = self.lookup(w_obj, '__setslice__')
-        if w_descr is not None:
-            w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
-            self.get_and_call_function(w_descr, w_obj, w_start, w_stop,
-                                       w_sequence)
-        else:
-            ObjSpace.setslice(self, w_obj, w_start, w_stop, w_sequence)
-
-    def delslice(self, w_obj, w_start, w_stop):
-        w_descr = self.lookup(w_obj, '__delslice__')
-        if w_descr is not None:
-            w_start, w_stop = old_slice_range(self, w_obj, w_start, w_stop)
-            self.get_and_call_function(w_descr, w_obj, w_start, w_stop)
-        else:
-            ObjSpace.delslice(self, w_obj, w_start, w_stop)
-
     def raise_key_error(self, w_key):
         e = self.call_function(self.w_KeyError, w_key)
         raise OperationError(self.w_KeyError, e)
@@ -820,32 +793,3 @@
                 del mm
 
         pow.extras['defaults'] = (None,)
-
-
-# what is the maximum value slices can get on CPython?
-# we need to stick to that value, because fake.py etc.
-class Temp:
-    def __getslice__(self, i, j):
-        return j
-slice_max = Temp()[:]
-del Temp
-
-
-def old_slice_range(space, w_obj, w_start, w_stop):
-    """Only for backward compatibility for __getslice__()&co methods."""
-    if space.is_w(w_start, space.w_None):
-        w_start = space.wrap(0)
-    else:
-        w_start = space.wrap(space.getindex_w(w_start, None))
-        if space.is_true(space.lt(w_start, space.wrap(0))):
-            w_start = space.add(w_start, space.len(w_obj))
-            # NB. the language ref is inconsistent with the new-style class
-            # behavior when w_obj doesn't implement __len__(), so we just
-            # ignore this case.
-    if space.is_w(w_stop, space.w_None):
-        w_stop = space.wrap(slice_max)
-    else:
-        w_stop = space.wrap(space.getindex_w(w_stop, None))
-        if space.is_true(space.lt(w_stop, space.wrap(0))):
-            w_stop = space.add(w_stop, space.len(w_obj))
-    return w_start, w_stop

Modified: pypy/branch/getslice/pypy/objspace/std/rangeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/rangeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/rangeobject.py	Fri Oct 10 19:38:43 2008
@@ -1,7 +1,7 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std import listtype
 from pypy.objspace.std import iterobject
@@ -100,6 +100,17 @@
     rangestep = w_rangelist.step * step
     return W_RangeListObject(rangestart, rangestep, slicelength)
 
+def getslice__RangeList_ANY_ANY(space, w_rangelist, w_start, w_stop):
+    if w_rangelist.w_list is not None:
+        return space.getslice(w_rangelist.w_list, w_start, w_stop)
+    length = w_rangelist.length
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    slicelength = stop - start
+    assert slicelength >= 0
+    rangestart = w_rangelist.getitem_unchecked(start)
+    rangestep = w_rangelist.step
+    return W_RangeListObject(rangestart, rangestep, slicelength)
+
 def iter__RangeList(space, w_rangelist):
     return W_RangeIterObject(w_rangelist)
 

Modified: pypy/branch/getslice/pypy/objspace/std/ropeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/ropeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/ropeobject.py	Fri Oct 10 19:38:43 2008
@@ -2,7 +2,7 @@
 from pypy.interpreter import gateway
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.noneobject import W_NoneObject
@@ -693,6 +693,15 @@
         return W_RopeObject.EMPTY
     return W_RopeObject(rope.getslice(node, start, stop, step, sl))
 
+def getslice__Rope_ANY_ANY(space, w_str, w_start, w_stop):
+    node = w_str._node
+    length = node.length()
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    sl = stop - start
+    if sl == 0:
+        return W_RopeObject.EMPTY
+    return W_RopeObject(rope.getslice(node, start, stop, 1, sl))
+
 def mul_string_times(space, w_str, w_times):
     try:
         mul = space.getindex_w(w_times, space.w_OverflowError)

Modified: pypy/branch/getslice/pypy/objspace/std/ropeunicodeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/ropeunicodeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/ropeunicodeobject.py	Fri Oct 10 19:38:43 2008
@@ -5,7 +5,7 @@
 from pypy.objspace.std.ropeobject import W_RopeObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.rlib import rope
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
@@ -287,6 +287,15 @@
         return W_RopeUnicodeObject.EMPTY
     return W_RopeUnicodeObject(rope.getslice(node, start, stop, step, sl))
 
+def getslice__RopeUnicode_ANY_ANY(space, w_uni, w_start, w_stop):
+    node = w_uni._node
+    length = node.length()
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    sl = stop - start
+    if sl == 0:
+        return W_RopeUnicodeObject.EMPTY
+    return W_RopeUnicodeObject(rope.getslice(node, start, stop, 1, sl))
+
 def mul__RopeUnicode_ANY(space, w_uni, w_times):
     try:
         times = space.getindex_w(w_times, space.w_OverflowError)

Modified: pypy/branch/getslice/pypy/objspace/std/sliceobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/sliceobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/sliceobject.py	Fri Oct 10 19:38:43 2008
@@ -79,6 +79,19 @@
 registerimplementation(W_SliceObject)
 
 
+def normalize_simple_slice(space, length, w_start, w_stop):
+    """Helper for the {get,set,del}slice multimethod implementations."""
+    start = space.int_w(w_start)
+    stop = space.int_w(w_stop)
+    if start < 0:
+        start = 0
+    if stop > length:
+        stop = length
+    if stop < start:
+        stop = start
+    return start, stop
+
+
 repr__Slice = gateway.applevel("""
     def repr__Slice(aslice):
         return 'slice(%r, %r, %r)' % (aslice.start, aslice.stop, aslice.step)

Modified: pypy/branch/getslice/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/stringobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/stringobject.py	Fri Oct 10 19:38:43 2008
@@ -5,7 +5,7 @@
 from pypy.rlib.rarithmetic import ovfcheck, _hash_string
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.noneobject import W_NoneObject
@@ -803,6 +803,14 @@
         str = "".join([s[start + i*step] for i in range(sl)])
     return wrapstr(space, str)
 
+def getslice__String_ANY_ANY(space, w_str, w_start, w_stop):
+    s = w_str._value
+    start, stop = normalize_simple_slice(space, len(s), w_start, w_stop)
+    if start == stop:
+        return W_StringObject.EMPTY
+    else:
+        return sliced(space, s, start, stop)
+
 def mul_string_times(space, w_str, w_times):
     try:
         mul = space.getindex_w(w_times, space.w_OverflowError)

Modified: pypy/branch/getslice/pypy/objspace/std/strsliceobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/strsliceobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/strsliceobject.py	Fri Oct 10 19:38:43 2008
@@ -1,7 +1,7 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.objspace.std.unicodeobject import delegate_String2Unicode
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.inttype import wrapint
@@ -194,6 +194,18 @@
             str = "".join([s[start + i*step] for i in range(sl)])
     return wrapstr(space, str)
 
+def getslice__StringSlice_ANY_ANY(space, w_str, w_start, w_stop):
+    length = w_str.stop - w_str.start
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    sl = stop - start
+    if sl == 0:
+        return W_StringObject.EMPTY
+    else:
+        s = w_str.str
+        start = w_str.start + start
+        stop = w_str.start + stop
+        return W_StringSliceObject(s, start, stop)
+
 def len__StringSlice(space, w_str):
     return space.wrap(w_str.stop - w_str.start)
 

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_builtinshortcut.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_builtinshortcut.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_builtinshortcut.py	Fri Oct 10 19:38:43 2008
@@ -1,5 +1,6 @@
 from pypy.objspace.std.test import test_userobject
 from pypy.objspace.std.test import test_set
+from pypy.objspace.std.test import test_stringobject
 
 WITH_BUILTINSHORTCUT = {'objspace.std.builtinshortcut': True}
 
@@ -38,3 +39,8 @@
     def setup_class(cls):
         from pypy import conftest
         cls.space = conftest.gettestobjspace(**WITH_BUILTINSHORTCUT)
+
+class AppTestString(test_stringobject.AppTestStringObject):
+    def setup_class(cls):
+        from pypy import conftest
+        cls.space = conftest.gettestobjspace(**WITH_BUILTINSHORTCUT)

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_listmultiobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_listmultiobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_listmultiobject.py	Fri Oct 10 19:38:43 2008
@@ -39,6 +39,15 @@
         # These few here ^ would have failed before, but for good coverage,
         # all the list methods etc. should be tested also...
 
+    def test___getslice__(self):
+        skip("don't care for now")
+
+    def test___setslice__(self):
+        skip("don't care for now")
+        
+    def test___delslice__(self):
+        skip("don't care for now")
+
 class AppTest_ListMultiObject(BaseAppTest_ListMultiObject):
     def setup_class(cls):
         BaseAppTest_ListMultiObject.setup_class(cls)

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_listobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_listobject.py	Fri Oct 10 19:38:43 2008
@@ -754,3 +754,18 @@
             A()
             while lst:
                 keepalive.append(lst[:])
+
+    def test___getslice__(self):
+        l = [1,2,3,4]
+        res = l.__getslice__(0, 2)
+        assert res == [1, 2]
+
+    def test___setslice__(self):
+        l = [1,2,3,4]
+        l.__setslice__(0, 2, [5, 6])
+        assert l == [5, 6, 3, 4]
+
+    def test___delslice__(self):
+        l = [1,2,3,4]
+        l.__delslice__(0, 2)
+        assert l == [3, 4]

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_rangeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_rangeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_rangeobject.py	Fri Oct 10 19:38:43 2008
@@ -29,6 +29,14 @@
     def test_getitem_slice(self):
         result = []
         r = range(1, 100, 2)
+        for i in r[10:15]:
+            result.append(i)
+        assert result == [21, 23, 25, 27, 29]
+        assert self.not_forced(r)
+
+    def test_getitem_extended_slice(self):
+        result = []
+        r = range(1, 100, 2)
         for i in r[40:30:-2]:
             result.append(i)
         assert result == [81, 77, 73, 69, 65]

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_stringobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_stringobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_stringobject.py	Fri Oct 10 19:38:43 2008
@@ -714,6 +714,20 @@
                 assert x.rstrip(y) == ''
                 assert x.lstrip(y) == ''
 
+    def test_getslice(self):
+        assert "foobar".__getslice__(4, 4321) == "ar"
+        s = "abc"
+        assert s[:] == "abc"
+        assert s[1:] == "bc"
+        assert s[:2] == "ab"
+        assert s[1:2] == "b"
+        assert s[-2:] == "bc"
+        assert s[:-1] == "ab"
+        assert s[-2:2] == "b"
+        assert s[1:-1] == "b"
+        assert s[-2:-1] == "b"
+
+
 class AppTestPrebuilt(AppTestStringObject):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withprebuiltchar": True})

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_strsliceobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_strsliceobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_strsliceobject.py	Fri Oct 10 19:38:43 2008
@@ -133,3 +133,16 @@
         assert s.count("X") == 100
         assert s.count("Y") == 100
         assert self.not_forced(s)
+
+    def test_extended_slice(self):
+        import __pypy__
+        def slice1(s): return (s*3)[len(s):-len(s)]
+        s = slice1('0123456789' * 20)
+        assert len(s) == 200
+        assert self.not_forced(s)
+        t = s[::-1]
+        assert t == '9876543210' * 20
+        assert not self.not_forced(t)
+        u = s[slice(10, 20)]
+        assert self.not_forced(u)
+        assert u == '0123456789'

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_tupleobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_tupleobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_tupleobject.py	Fri Oct 10 19:38:43 2008
@@ -318,3 +318,5 @@
         assert repr(()) == '()'
         assert repr((1,2,3)) == '(1, 2, 3)'
         
+    def test_getslice(self):
+        assert ('a', 'b', 'c').__getslice__(-17, 2) == ('a', 'b')

Modified: pypy/branch/getslice/pypy/objspace/std/test/test_unicodeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/test/test_unicodeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/test/test_unicodeobject.py	Fri Oct 10 19:38:43 2008
@@ -641,3 +641,15 @@
 
         assert unicode(Y()).__class__ is X
     
+    def test_getslice(self):
+        assert u'123456'.__getslice__(1, 5) == u'2345'
+        s = u"abc"
+        assert s[:] == "abc"
+        assert s[1:] == "bc"
+        assert s[:2] == "ab"
+        assert s[1:2] == "b"
+        assert s[-2:] == "bc"
+        assert s[:-1] == "ab"
+        assert s[-2:2] == "b"
+        assert s[1:-1] == "b"
+        assert s[-2:-1] == "b"

Modified: pypy/branch/getslice/pypy/objspace/std/tupleobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/tupleobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/tupleobject.py	Fri Oct 10 19:38:43 2008
@@ -1,7 +1,7 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.inttype import wrapint
 from pypy.rlib.rarithmetic import intmask
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.interpreter import gateway
 from pypy.rlib.debug import make_sure_not_resized
 
@@ -53,6 +53,11 @@
         start += step
     return W_TupleObject(subitems)
 
+def getslice__Tuple_ANY_ANY(space, w_tuple, w_start, w_stop):
+    length = len(w_tuple.wrappeditems)
+    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
+    return W_TupleObject(w_tuple.wrappeditems[start:stop])
+
 def contains__Tuple_ANY(space, w_tuple, w_obj):
     for w_item in w_tuple.wrappeditems:
         if space.eq_w(w_item, w_obj):

Modified: pypy/branch/getslice/pypy/objspace/std/unicodeobject.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/std/unicodeobject.py	(original)
+++ pypy/branch/getslice/pypy/objspace/std/unicodeobject.py	Fri Oct 10 19:38:43 2008
@@ -3,7 +3,7 @@
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.objspace.std.ropeobject import W_RopeObject
 from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
@@ -247,6 +247,11 @@
         r = u"".join([uni[start + i*step] for i in range(sl)])
     return W_UnicodeObject(r)
 
+def getslice__Unicode_ANY_ANY(space, w_uni, w_start, w_stop):
+    uni = w_uni._value
+    start, stop = normalize_simple_slice(space, len(uni), w_start, w_stop)
+    return W_UnicodeObject(uni[start:stop])
+
 def mul__Unicode_ANY(space, w_uni, w_times):
     try:
         times = space.getindex_w(w_times, space.w_OverflowError)

Modified: pypy/branch/getslice/pypy/objspace/thunk.py
==============================================================================
--- pypy/branch/getslice/pypy/objspace/thunk.py	(original)
+++ pypy/branch/getslice/pypy/objspace/thunk.py	Fri Oct 10 19:38:43 2008
@@ -193,6 +193,13 @@
             w2 = force(space, w2)
             w3 = force(space, w3)
             return parentfn(w1, w2, w3, *extra)
+    elif nb_args == 4:
+        def proxy(w1, w2, w3, w4, *extra):
+            w1 = force(space, w1)
+            w2 = force(space, w2)
+            w3 = force(space, w3)
+            w4 = force(space, w4)
+            return parentfn(w1, w2, w3, w4, *extra)
     else:
         raise NotImplementedError("operation %r has arity %d" %
                                   (opname, nb_args))

Modified: pypy/branch/getslice/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/branch/getslice/pypy/rpython/lltypesystem/rlist.py	Fri Oct 10 19:38:43 2008
@@ -7,9 +7,6 @@
         AbstractFixedSizeListRepr, AbstractListIteratorRepr, rtype_newlist, \
         rtype_alloc_and_set, ll_setitem_nonneg, ADTIList, ADTIFixedList
 from pypy.rpython.rlist import dum_nocheck, dum_checkidx
-from pypy.rpython.lltypesystem.rslice import SliceRepr
-from pypy.rpython.lltypesystem.rslice import startstop_slice_repr, startonly_slice_repr
-from pypy.rpython.lltypesystem.rslice import minusone_slice_repr
 from pypy.rpython.lltypesystem.lltype import \
      GcForwardReference, Ptr, GcArray, GcStruct, \
      Void, Signed, malloc, typeOf, Primitive, \

Modified: pypy/branch/getslice/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/branch/getslice/pypy/rpython/ootypesystem/rlist.py	Fri Oct 10 19:38:43 2008
@@ -5,8 +5,6 @@
 from pypy.rpython.rmodel import inputconst, externalvsinternal
 from pypy.rpython.lltypesystem.lltype import Signed, Void
 from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.ootypesystem.rslice import SliceRepr, \
-     startstop_slice_repr, startonly_slice_repr, minusone_slice_repr
 from pypy.rpython.ootypesystem import rstr
 
 

Modified: pypy/branch/getslice/pypy/rpython/rlist.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/rlist.py	(original)
+++ pypy/branch/getslice/pypy/rpython/rlist.py	Fri Oct 10 19:38:43 2008
@@ -3,7 +3,6 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import Repr, IteratorRepr, IntegerRepr, inputconst
-from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython.rstr import AbstractStringRepr, AbstractCharRepr
 from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool
 from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar
@@ -403,47 +402,30 @@
         return v_lst1
 
 
-class __extend__(pairtype(AbstractBaseListRepr, AbstractSliceRepr)):
+class __extend__(AbstractBaseListRepr):
 
-    def rtype_getitem((r_lst, r_slic), hop):
-        rs = r_lst.rtyper.type_system.rslice
+    def rtype_getslice(r_lst, hop):
         cRESLIST = hop.inputconst(Void, hop.r_result.LIST)
-        if r_slic == rs.startonly_slice_repr:
-            v_lst, v_start = hop.inputargs(r_lst, rs.startonly_slice_repr)
-            return hop.gendirectcall(ll_listslice_startonly, cRESLIST, v_lst, v_start)
-        if r_slic == rs.startstop_slice_repr:
-            v_lst, v_slice = hop.inputargs(r_lst, rs.startstop_slice_repr)
-            return hop.gendirectcall(ll_listslice, cRESLIST, v_lst, v_slice)
-        if r_slic == rs.minusone_slice_repr:
-            v_lst, v_ignored = hop.inputargs(r_lst, rs.minusone_slice_repr)
-            return hop.gendirectcall(ll_listslice_minusone, cRESLIST, v_lst)
-        raise TyperError('getitem does not support slices with %r' % (r_slic,))
-
-    def rtype_setitem((r_lst, r_slic), hop):
-        #if r_slic == startonly_slice_repr:
-        #    not implemented
-        rs = r_lst.rtyper.type_system.rslice        
-        if r_slic == rs.startstop_slice_repr:
-            v_lst, v_slice, v_lst2 = hop.inputargs(r_lst, rs.startstop_slice_repr,
-                                                   hop.args_r[2])
-            hop.gendirectcall(ll_listsetslice, v_lst, v_slice, v_lst2)
-            return
-        raise TyperError('setitem does not support slices with %r' % (r_slic,))
-
-
-class __extend__(pairtype(AbstractListRepr, AbstractSliceRepr)):
-
-    def rtype_delitem((r_lst, r_slic), hop):
-        rs = r_lst.rtyper.type_system.rslice        
-        if r_slic == rs.startonly_slice_repr:
-            v_lst, v_start = hop.inputargs(r_lst, rs.startonly_slice_repr)
-            hop.gendirectcall(ll_listdelslice_startonly, v_lst, v_start)
-            return
-        if r_slic == rs.startstop_slice_repr:
-            v_lst, v_slice = hop.inputargs(r_lst, rs.startstop_slice_repr)
-            hop.gendirectcall(ll_listdelslice, v_lst, v_slice)
-            return
-        raise TyperError('delitem does not support slices with %r' % (r_slic,))
+        v_lst = hop.inputarg(r_lst, arg=0)
+        kind, vlist = hop.decompose_slice_args()
+        ll_listslice = globals()['ll_listslice_%s' % kind]
+        return hop.gendirectcall(ll_listslice, cRESLIST, v_lst, *vlist)
+
+    def rtype_setslice(r_lst, hop):
+        v_lst = hop.inputarg(r_lst, arg=0)
+        kind, vlist = hop.decompose_slice_args()
+        if kind != 'startstop':
+            raise TyperError('list.setitem does not support %r slices' % (
+                kind,))
+        v_start, v_stop = vlist
+        v_lst2 = hop.inputarg(hop.args_r[3], arg=3)
+        hop.gendirectcall(ll_listsetslice, v_lst, v_start, v_stop, v_lst2)
+
+    def rtype_delslice(r_lst, hop):
+        v_lst = hop.inputarg(r_lst, arg=0)
+        kind, vlist = hop.decompose_slice_args()
+        ll_listdelslice = globals()['ll_listdelslice_%s' % kind]
+        return hop.gendirectcall(ll_listdelslice, v_lst, *vlist)
 
 
 # ____________________________________________________________
@@ -868,9 +850,7 @@
         j += 1
     return l
 
-def ll_listslice(RESLIST, l1, slice):
-    start = slice.start
-    stop = slice.stop
+def ll_listslice_startstop(RESLIST, l1, start, stop):
     length = l1.ll_length()
     ll_assert(start >= 0, "unexpectedly negative list slice start")
     ll_assert(start <= length, "list slice start larger than list length")
@@ -909,9 +889,7 @@
             j -= 1
     l._ll_resize_le(newlength)
 
-def ll_listdelslice(l, slice):
-    start = slice.start
-    stop = slice.stop
+def ll_listdelslice_startstop(l, start, stop):
     length = l.ll_length()
     ll_assert(start >= 0, "del l[start:x] with unexpectedly negative start")
     ll_assert(start <= length, "del l[start:x] with start > len(l)")
@@ -933,12 +911,11 @@
             j -= 1
     l._ll_resize_le(newlength)
 
-def ll_listsetslice(l1, slice, l2):
+def ll_listsetslice(l1, start, stop, l2):
     count = l2.ll_length()
-    start = slice.start
     ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start")
     ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)")
-    ll_assert(count == slice.stop - start,
+    ll_assert(count == stop - start,
                  "setslice cannot resize lists in RPython")
     # XXX but it should be easy enough to support, soon
     j = start

Modified: pypy/branch/getslice/pypy/rpython/rstr.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/rstr.py	(original)
+++ pypy/branch/getslice/pypy/rpython/rstr.py	Fri Oct 10 19:38:43 2008
@@ -5,7 +5,6 @@
 from pypy.rpython.rmodel import IntegerRepr, IteratorRepr
 from pypy.rpython.rmodel import inputconst, Repr
 from pypy.rpython.rtuple import AbstractTupleRepr
-from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.lltype import Signed, Bool, Void, UniChar,\
      cast_primitive
@@ -331,22 +330,22 @@
     rtype_getitem_idx_key = rtype_getitem_idx
 
 
-class __extend__(pairtype(AbstractStringRepr, AbstractSliceRepr)):
+##class __extend__(pairtype(AbstractStringRepr, AbstractSliceRepr)):
 
-    def rtype_getitem((r_str, r_slic), hop):
-        string_repr = r_str.repr
-        rslice = hop.rtyper.type_system.rslice
-
-        if r_slic == rslice.startonly_slice_repr:
-            v_str, v_start = hop.inputargs(string_repr, rslice.startonly_slice_repr)
-            return hop.gendirectcall(r_str.ll.ll_stringslice_startonly, v_str, v_start)
-        if r_slic == rslice.startstop_slice_repr:
-            v_str, v_slice = hop.inputargs(string_repr, rslice.startstop_slice_repr)
-            return hop.gendirectcall(r_str.ll.ll_stringslice, v_str, v_slice)
-        if r_slic == rslice.minusone_slice_repr:
-            v_str, v_ignored = hop.inputargs(string_repr, rslice.minusone_slice_repr)
-            return hop.gendirectcall(r_str.ll.ll_stringslice_minusone, v_str)
-        raise TyperError(r_slic)
+##    def rtype_getitem((r_str, r_slic), hop):
+##        string_repr = r_str.repr
+##        rslice = hop.rtyper.type_system.rslice
+
+##        if r_slic == rslice.startonly_slice_repr:
+##            v_str, v_start = hop.inputargs(string_repr, rslice.startonly_slice_repr)
+##            return hop.gendirectcall(r_str.ll.ll_stringslice_startonly, v_str, v_start)
+##        if r_slic == rslice.startstop_slice_repr:
+##            v_str, v_slice = hop.inputargs(string_repr, rslice.startstop_slice_repr)
+##            return hop.gendirectcall(r_str.ll.ll_stringslice, v_str, v_slice)
+##        if r_slic == rslice.minusone_slice_repr:
+##            v_str, v_ignored = hop.inputargs(string_repr, rslice.minusone_slice_repr)
+##            return hop.gendirectcall(r_str.ll.ll_stringslice_minusone, v_str)
+##        raise TyperError(r_slic)
 
 class __extend__(pairtype(AbstractStringRepr, AbstractStringRepr)):
     def rtype_add((r_str1, r_str2), hop):

Modified: pypy/branch/getslice/pypy/rpython/rtuple.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/rtuple.py	(original)
+++ pypy/branch/getslice/pypy/rpython/rtuple.py	Fri Oct 10 19:38:43 2008
@@ -6,7 +6,6 @@
 from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
 from pypy.rpython.rmodel import IteratorRepr
 from pypy.rpython.rmodel import externalvsinternal
-from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython.lltypesystem.lltype import Void, Signed, Bool
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.unroll import unrolling_iterable
@@ -242,18 +241,18 @@
         index = v_index.value
         return r_tup.getitem(hop.llops, v_tuple, index)
 
-class __extend__(pairtype(AbstractTupleRepr, AbstractSliceRepr)):
+##class __extend__(pairtype(AbstractTupleRepr, AbstractSliceRepr)):
 
-    def rtype_getitem((r_tup, r_slice), hop):
-        v_tup = hop.inputarg(r_tup, arg=0)
-        s_slice = hop.args_s[1]
-        start, stop, step = s_slice.constant_indices()
-        indices = range(len(r_tup.items_r))[start:stop:step]
-        assert len(indices) == len(hop.r_result.items_r)
-
-        items_v = [r_tup.getitem_internal(hop.llops, v_tup, i)
-                   for i in indices]
-        return hop.r_result.newtuple(hop.llops, hop.r_result, items_v)
+##    def rtype_getitem((r_tup, r_slice), hop):
+##        v_tup = hop.inputarg(r_tup, arg=0)
+##        s_slice = hop.args_s[1]
+##        start, stop, step = s_slice.constant_indices()
+##        indices = range(len(r_tup.items_r))[start:stop:step]
+##        assert len(indices) == len(hop.r_result.items_r)
+
+##        items_v = [r_tup.getitem_internal(hop.llops, v_tup, i)
+##                   for i in indices]
+##        return hop.r_result.newtuple(hop.llops, hop.r_result, items_v)
 
 class __extend__(pairtype(AbstractTupleRepr, Repr)): 
     def rtype_contains((r_tup, r_item), hop):

Modified: pypy/branch/getslice/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/getslice/pypy/rpython/rtyper.py	Fri Oct 10 19:38:43 2008
@@ -811,6 +811,32 @@
             return # ignored for high-level ops before the last one in the block
         self.llops.llop_raising_exceptions = "removed"
 
+    def decompose_slice_args(self):
+        # Select which kind of slicing is needed.  We support:
+        #   * [start:]
+        #   * [start:stop]
+        #   * [:-1]
+        s_start = self.args_s[1]
+        s_stop = self.args_s[2]
+        if (s_start.is_constant() and s_start.const in (None, 0) and
+            s_stop.is_constant() and s_stop.const == -1):
+            return "minusone", []
+        if isinstance(s_start, annmodel.SomeInteger):
+            if not s_start.nonneg:
+                raise TyperError("slice start must be proved non-negative")
+        if isinstance(s_stop, annmodel.SomeInteger):
+            if not s_stop.nonneg:
+                raise TyperError("slice stop must be proved non-negative")
+        if s_start.is_constant() and s_start.const is None:
+            v_start = inputconst(Signed, 0)
+        else:
+            v_start = self.inputarg(Signed, arg=1)
+        if s_stop.is_constant() and s_stop.const is None:
+            return "startonly", [v_start]
+        else:
+            v_stop = self.inputarg(Signed, arg=2)
+            return "startstop", [v_start, v_stop]
+
 # ____________________________________________________________
 
 class LowLevelOpList(list):
@@ -935,7 +961,7 @@
 # and the rtyper_chooserepr() methods
 from pypy.rpython import robject
 from pypy.rpython import rint, rbool, rfloat
-from pypy.rpython import rslice, rrange
+from pypy.rpython import rrange
 from pypy.rpython import rstr, rdict, rlist
 from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase
 from pypy.rpython import rexternalobj

Modified: pypy/branch/getslice/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/getslice/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/branch/getslice/pypy/rpython/test/test_rlist.py	Fri Oct 10 19:38:43 2008
@@ -7,7 +7,6 @@
 from pypy.rpython.lltypesystem.rlist import ListRepr, FixedSizeListRepr, ll_newlist, ll_fixed_newlist
 from pypy.rpython.lltypesystem import rlist as ll_rlist
 from pypy.rpython.ootypesystem import rlist as oo_rlist
-from pypy.rpython.lltypesystem.rslice import ll_newslice
 from pypy.rpython.rint import signed_repr
 from pypy.translator.translator import TranslationContext
 from pypy.objspace.flow.model import Constant, Variable
@@ -58,8 +57,8 @@
         self.check_list(ll_listslice_startonly(LIST, l, 4), [])
         for start in range(5):
             for stop in range(start, 8):
-                s = ll_newslice(start, stop)
-                self.check_list(ll_listslice(LIST, l, s), [42, 43, 44, 45][start:stop])
+                self.check_list(ll_listslice_startstop(LIST, l, start, stop),
+                                [42, 43, 44, 45][start:stop])
 
     def test_rlist_setslice(self):
         n = 100
@@ -72,9 +71,8 @@
                     expected[i] = n
                     ll_setitem(l2, i, n)
                     n += 1
-                s = ll_newslice(start, stop)
-                l2 = ll_listslice(typeOf(l2).TO, l2, s)
-                ll_listsetslice(l1, s, l2)
+                l2 = ll_listslice_startstop(typeOf(l2).TO, l2, start, stop)
+                ll_listsetslice(l1, start, stop, l2)
                 self.check_list(l1, expected)
 
 
@@ -129,8 +127,7 @@
         for start in range(5):
             for stop in range(start, 8):
                 l = self.sample_list()
-                s = ll_newslice(start, stop)
-                ll_listdelslice(l, s)
+                ll_listdelslice_startstop(l, start, stop)
                 expected = [42, 43, 44, 45]
                 del expected[start:stop]
                 self.check_list(l, expected)
@@ -380,6 +377,25 @@
         assert res.item2 == 8
         assert res.item3 == 7
 
+    def test_delslice(self):
+        def dummyfn():
+            l = [10, 9, 8, 7]
+            del l[:2]
+            return len(l), l[0], l[1]
+        res = self.interpret(dummyfn, ())
+        assert res.item0 == 2
+        assert res.item1 == 8
+        assert res.item2 == 7
+
+        def dummyfn():
+            l = [10, 9, 8, 7]
+            del l[2:]
+            return len(l), l[0], l[1]
+        res = self.interpret(dummyfn, ())
+        assert res.item0 == 2
+        assert res.item1 == 10
+        assert res.item2 == 9
+
     def test_bltn_list(self):
         def dummyfn():
             l1 = [42]

Modified: pypy/branch/getslice/pypy/translator/simplify.py
==============================================================================
--- pypy/branch/getslice/pypy/translator/simplify.py	(original)
+++ pypy/branch/getslice/pypy/translator/simplify.py	Fri Oct 10 19:38:43 2008
@@ -483,7 +483,7 @@
 # (they have no side effects, at least in R-Python)
 CanRemove = {}
 for _op in '''
-        newtuple newlist newdict newslice is_true
+        newtuple newlist newdict is_true
         is_ id type issubtype repr str len hash getattr getitem
         pos neg nonzero abs hex oct ord invert add sub mul
         truediv floordiv div mod divmod pow lshift rshift and_ or_

Modified: pypy/branch/getslice/pypy/translator/transform.py
==============================================================================
--- pypy/branch/getslice/pypy/translator/transform.py	(original)
+++ pypy/branch/getslice/pypy/translator/transform.py	Fri Oct 10 19:38:43 2008
@@ -112,30 +112,6 @@
                                         op.result)
                 block.operations[i] = new_op
 
-# a[b:c]
-# -->
-# d = newslice(b, c, None)
-# e = getitem(a, d)
-# -->
-# e = getslice(a, b, c)
-
-##def transform_slice(self, block_subset):              -- not used any more --
-##    """Transforms a[b:c] to getslice(a, b, c)."""
-##    for block in block_subset:
-##        operations = block.operations[:]
-##        n_op = len(operations)
-##        for i in range(0, n_op-1):
-##            op1 = operations[i]
-##            op2 = operations[i+1]
-##            if (op1.opname == 'newslice' and
-##                self.gettype(op1.args[2]) is types.NoneType and
-##                op2.opname == 'getitem' and
-##                op1.result is op2.args[1]):
-##                new_op = SpaceOperation('getslice',
-##                                        (op2.args[0], op1.args[0], op1.args[1]),
-##                                        op2.result)
-##                block.operations[i+1:i+2] = [new_op]
-
 
 def transform_dead_op_vars(self, block_subset):
     # we redo the same simplification from simplify.py,



More information about the Pypy-commit mailing list