1. Pypy
  2. Untitled project
  3. pypy

Commits

Armin Rigo  committed 50f5c28

(antocuni, arigo)
Probably in-progress.

  • Participants
  • Parent commits 1c2dc14
  • Branches getslice

Comments (0)

Files changed (43)

File pypy/annotation/annrpython.py

View file
     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

File pypy/annotation/binaryop.py

View file
 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
     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)):
             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)):
     
         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)):

File pypy/annotation/bookkeeper.py

View file
     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
 

File pypy/annotation/builtin.py

View file
 
 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
     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):

File pypy/annotation/model.py

View file
     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

File pypy/annotation/test/test_annrpython.py

View file
             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])
         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,[])
 
         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 = []

File pypy/annotation/unaryop.py

View file
                         '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:
             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):
 
 
     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()
             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):
 
     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():

File pypy/interpreter/baseobjspace.py

View file
         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,
     ('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__']),

File pypy/objspace/descroperation.py

View file
                    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)
     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):
                            'ord', 'unichr', 'unicode']:
             raise Exception, "missing def for operation %s" % _name
             
-            
-

File pypy/objspace/flow/objspace.py

View file
             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)):

File pypy/objspace/reflective.py

View file
                     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

File pypy/objspace/std/builtinshortcut.py

View file
 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:

File pypy/objspace/std/listobject.py

View file
 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
         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
                              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:
             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)
                              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
             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" %
                 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):
     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

File pypy/objspace/std/objspace.py

View file
         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)
                 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

File pypy/objspace/std/rangeobject.py

View file
 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
     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)
 

File pypy/objspace/std/ropeobject.py

View file
 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
         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)

File pypy/objspace/std/ropeunicodeobject.py

View file
 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
         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)

File pypy/objspace/std/sliceobject.py

View file
 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)

File pypy/objspace/std/stringobject.py

View file
 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
         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)

File pypy/objspace/std/strsliceobject.py

View file
 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
             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)
 

File pypy/objspace/std/test/test_builtinshortcut.py

View file
 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}
 
     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)

File pypy/objspace/std/test/test_listmultiobject.py

View file
         # 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)

File pypy/objspace/std/test/test_listobject.py

View file
             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]

File pypy/objspace/std/test/test_rangeobject.py

View file
     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]

File pypy/objspace/std/test/test_stringobject.py

View file
                 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})

File pypy/objspace/std/test/test_strsliceobject.py

View file
         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'

File pypy/objspace/std/test/test_tupleobject.py

View file
         assert repr(()) == '()'
         assert repr((1,2,3)) == '(1, 2, 3)'
         
+    def test_getslice(self):
+        assert ('a', 'b', 'c').__getslice__(-17, 2) == ('a', 'b')

File pypy/objspace/std/test/test_unicodeobject.py

View file
 
         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"

File pypy/objspace/std/tupleobject.py

View file
 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
 
         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):

File pypy/objspace/std/unicodeobject.py

View file
 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
         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)

File pypy/objspace/thunk.py

View file
             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))

File pypy/rpython/lltypesystem/rlist.py

View file
         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, \

File pypy/rpython/lltypesystem/rslice.py

-from pypy.rpython.rslice import AbstractSliceRepr
-from pypy.rpython.lltypesystem.lltype import \
-     GcStruct, Signed, Ptr, Void, malloc, PyObject, nullptr
-from pypy.tool.pairtype import pairtype
-from pypy.rpython.robject import PyObjRepr, pyobj_repr
-from pypy.rpython.rmodel import inputconst, PyObjPtr, IntegerRepr
-
-# ____________________________________________________________
-#
-#  Concrete implementation of RPython slice objects:
-#
-#  - if stop is None, use only a Signed
-#  - if stop is not None:
-#
-#      struct slice {
-#          Signed start;
-#          Signed stop;
-#          //     step is always 1
-#      }
-
-SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed),
-                 hints = {'immutable': True})
-
-class SliceRepr(AbstractSliceRepr):
-    pass
-
-startstop_slice_repr = SliceRepr()
-startstop_slice_repr.lowleveltype = Ptr(SLICE)
-startonly_slice_repr = SliceRepr()
-startonly_slice_repr.lowleveltype = Signed
-minusone_slice_repr = SliceRepr()
-minusone_slice_repr.lowleveltype = Void    # only for [:-1]
-
-# ____________________________________________________________
-
-def ll_newslice(start, stop):
-    s = malloc(SLICE)
-    s.start = start
-    s.stop = stop
-    return s
-
-# ____________________________________________________________
-#
-# limited support for casting into PyObject
-
-# stuff like this should go into one file maybe
-
-class __extend__(pairtype(SliceRepr, PyObjRepr)):
-    def convert_from_to((r_from, r_to), v, llops):
-        null = inputconst(Ptr(PyObject), nullptr(PyObject))
-        def pyint(v):
-            return llops.gencapicall('PyInt_FromLong', [v], resulttype=r_to)
-        v_step = v_start = v_stop = null
-        if r_from.lowleveltype is Signed:
-            v_start = pyint(v)
-        elif r_from.lowleveltype is Void:
-            v_stop = inputconst(r_to, -1)
-        else:
-            v_start = pyint(llops.genop('getfield', [v, inputconst(Void, 'start')],
-                            resulttype=Signed))
-            v_stop = pyint(llops.genop('getfield', [v, inputconst(Void, 'stop')],
-                           resulttype=Signed))
-        return llops.gencapicall('PySlice_New',
-                                 [v_start, v_stop, v_step],
-                                 resulttype = pyobj_repr)

File pypy/rpython/ootypesystem/rlist.py

View file
 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
 
 

File pypy/rpython/ootypesystem/rslice.py

-from pypy.rpython.rslice import AbstractSliceRepr
-from pypy.rpython.lltypesystem.lltype import Void, Signed
-from pypy.rpython.ootypesystem import ootype
-
-SLICE = ootype.Instance('Slice', ootype.ROOT, {'start': Signed, 'stop': Signed})
-
-class SliceRepr(AbstractSliceRepr):
-    pass
-
-startstop_slice_repr = SliceRepr()
-startstop_slice_repr.lowleveltype = SLICE
-startonly_slice_repr = SliceRepr()
-startonly_slice_repr.lowleveltype = Signed
-minusone_slice_repr = SliceRepr()
-minusone_slice_repr.lowleveltype = Void    # only for [:-1]
-
-# ____________________________________________________________
-
-def ll_newslice(start, stop):
-    s = ootype.new(SLICE)
-    s.start = start
-    s.stop = stop
-    return s
-

File pypy/rpython/rlist.py

View file
 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
         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,))
+        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_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,))
+    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)
 
-
-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,))
+    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)
 
 
 # ____________________________________________________________
         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")
             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)")
             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

File pypy/rpython/rslice.py

-from pypy.rpython.rmodel import Repr
-from pypy.rpython.lltypesystem.lltype import Signed, Void
-from pypy.objspace.flow.model import Constant
-from pypy.annotation import model as annmodel
-from pypy.rpython.error import TyperError
-
-class AbstractSliceRepr(Repr):
-    pass
-
-
-def select_slice_repr(self):
-    # Select which one of the three prebuilt reprs to use.
-    # Return a name.
-    if not self.step.is_constant() or self.step.const not in (None, 1):
-        raise TyperError("only supports slices with step 1")
-    if (self.start.is_constant() and self.start.const in (None, 0) and
-        self.stop.is_constant() and self.stop.const == -1):
-        return "minusone_slice_repr"    # [:-1]
-    if isinstance(self.start, annmodel.SomeInteger):
-        if not self.start.nonneg:
-            raise TyperError("slice start must be proved non-negative")
-    if isinstance(self.stop, annmodel.SomeInteger):
-        if not self.stop.nonneg:
-            raise TyperError("slice stop must be proved non-negative")
-    if self.stop.is_constant() and self.stop.const is None:
-        return "startonly_slice_repr"
-    else:
-        return "startstop_slice_repr"
-
-class __extend__(annmodel.SomeSlice):
-    def rtyper_makerepr(self, rtyper):
-        return getattr(rtyper.type_system.rslice, select_slice_repr(self))
-        
-    def rtyper_makekey(self):
-        return self.__class__, select_slice_repr(self)
-
-
-def rtype_newslice(hop):
-    sig = []
-    for s in hop.args_s:
-        if s.is_constant() and s.const is None:
-            sig.append(Void)
-        else:
-            sig.append(Signed)
-    v_start, v_stop, v_step = hop.inputargs(*sig)
-    assert isinstance(v_step, Constant) and v_step.value in (None, 1)
-    if isinstance(v_start, Constant) and v_start.value is None:
-        v_start = hop.inputconst(Signed, 0)
-    if (isinstance(v_start, Constant) and v_start.value == 0 and
-        isinstance(v_stop, Constant) and v_stop.value == -1):
-        # [:-1] slice
-        return hop.inputconst(Void, slice(None,-1))
-    if isinstance(v_stop, Constant) and v_stop.value is None:
-        # start-only slice
-        # NB. cannot just return v_start in case it is a constant
-        return hop.genop('same_as', [v_start],
-            resulttype=hop.rtyper.type_system.rslice.startonly_slice_repr)
-    else:
-        # start-stop slice
-        return hop.gendirectcall(hop.rtyper.type_system.rslice.ll_newslice,
-                                 v_start, v_stop)

File pypy/rpython/rstr.py

View file
 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
     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
+##    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)
+##        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):

File pypy/rpython/rtuple.py

View file
 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
         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)
+##    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)
+##        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):

File pypy/rpython/rtyper.py

View file
             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):
 # 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

File pypy/rpython/test/test_rlist.py

View file
 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
         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
                     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)
 
 
         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)
         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]

File pypy/translator/simplify.py

View file
 # (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_

File pypy/translator/transform.py

View file
                                         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,