slicing a builtin type will return the same type
authorStefan Behnel <scoder@users.berlios.de>
Mon, 4 May 2009 11:58:06 +0000 (13:58 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Mon, 4 May 2009 11:58:06 +0000 (13:58 +0200)
Cython/Compiler/Builtin.py
Cython/Compiler/ExprNodes.py
tests/run/typed_slice.pyx [new file with mode: 0644]

index e72a1df8621cc539b924b5da3b0dda0c83f9f0bb..12823aa9af20a2633a8ee3e24ea04ff2e7576e9e 100644 (file)
@@ -368,12 +368,13 @@ def init_builtins():
     init_builtin_funcs()
     init_builtin_types()
     init_builtin_structs()
-    global list_type, tuple_type, dict_type, set_type, unicode_type, type_type
+    global list_type, tuple_type, dict_type, set_type, bytes_type, unicode_type, type_type
     type_type  = builtin_scope.lookup('type').type
     list_type  = builtin_scope.lookup('list').type
     tuple_type = builtin_scope.lookup('tuple').type
     dict_type  = builtin_scope.lookup('dict').type
     set_type   = builtin_scope.lookup('set').type
+    bytes_type = builtin_scope.lookup('bytes').type
     unicode_type = builtin_scope.lookup('unicode').type
 
 init_builtins()
index c1bc8ea4bc5509c46bb2d27a7de458a4b2769651..f248af97e56eb85467e298d3ba9ca20567ba91ba 100644 (file)
@@ -13,7 +13,7 @@ import Nodes
 from Nodes import Node
 import PyrexTypes
 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
-from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type
+from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_type
 import Builtin
 import Symtab
 import Options
@@ -1998,6 +1998,11 @@ class SliceIndexNode(ExprNode):
     
     def analyse_target_declaration(self, env):
         pass
+    
+    def analyse_target_types(self, env):
+        self.analyse_types(env)
+        # when assigning, we must accept any Python type
+        self.type = py_object_type
 
     def analyse_types(self, env):
         self.base.analyse_types(env)
@@ -2005,16 +2010,20 @@ class SliceIndexNode(ExprNode):
             self.start.analyse_types(env)
         if self.stop:
             self.stop.analyse_types(env)
-        if self.base.type.is_string:
-            self.type = py_object_type
-        elif self.base.type.is_array or self.base.type.is_ptr:
+        base_type = self.base.type
+        if base_type.is_string:
+            self.type = bytes_type
+        elif base_type.is_array or base_type.is_ptr:
             # we need a ptr type here instead of an array type, as
             # array types can result in invalid type casts in the C
             # code
-            self.type = PyrexTypes.CPtrType(self.base.type.base_type)
+            self.type = PyrexTypes.CPtrType(base_type.base_type)
         else:
             self.base = self.base.coerce_to_pyobject(env)
             self.type = py_object_type
+        if base_type.is_builtin_type:
+            # slicing builtin types returns something of the same type
+            self.type = base_type
         c_int = PyrexTypes.c_py_ssize_t_type
         if self.start:
             self.start = self.start.coerce_to(c_int, env)
diff --git a/tests/run/typed_slice.pyx b/tests/run/typed_slice.pyx
new file mode 100644 (file)
index 0000000..3b5b04b
--- /dev/null
@@ -0,0 +1,62 @@
+__doc__ = u"""
+    >>> l = [1,2,3,4]
+
+    >>> slice_list(l)
+    [2, 3]
+    >>> slice_tuple(tuple(l))
+    (2, 3)
+
+    >>> l2 = l[:]
+    >>> slice_list_assign_list(l2)
+    [1, 1, 2, 3, 4, 4]
+
+    >>> l2 = l[:]
+    >>> slice_list_assign_tuple(l2)
+    [1, 1, 2, 3, 4, 4]
+
+    >>> l2 = l[:]
+    >>> slice_list_assign(l2, (1,2,3,4))
+    [1, 1, 2, 3, 4, 4]
+
+    >>> l2 = l[:]
+    >>> slice_list_assign(l2, dict(zip(l,l)))
+    [1, 1, 2, 3, 4, 4]
+
+    >>> slice_charp('abcdefg')
+    'bc'
+    >>> slice_charp_repeat('abcdefg')
+    'cd'
+"""
+
+def slice_list(list l):
+    return l[1:3]
+
+def slice_list_copy(list l):
+    cdef list retlist = l[1:3]
+    return retlist
+
+def slice_tuple(tuple t):
+    return t[1:3]
+
+def slice_list_assign_list(list l):
+    l[1:3] = [1,2,3,4]
+    return l
+
+def slice_list_assign_tuple(list l):
+    l[1:3] = (1,2,3,4)
+    return l
+
+def slice_list_assign(list l, value):
+    l[1:3] = value
+    return l
+
+
+def slice_charp(str py_string):
+    cdef char* s = py_string
+    return s[1:3]
+
+def slice_charp_repeat(str py_string):
+    cdef char* s = py_string
+    cdef str slice_val = s[1:6]
+    s = slice_val
+    return s[1:3]