infer plain object for bytes_string[i] and str/unicode for indexed unicode/str objects
authorStefan Behnel <scoder@users.berlios.de>
Sat, 15 May 2010 13:57:56 +0000 (15:57 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 15 May 2010 13:57:56 +0000 (15:57 +0200)
Cython/Compiler/ExprNodes.py
tests/run/type_inference.pyx

index c5fe0f75730e92875f477d8c7ef93c343604e91a..b7228de058e907e48b5152e89f0feec7d3c59d94 100755 (executable)
@@ -1892,12 +1892,12 @@ class IndexNode(ExprNode):
         return self.base.type_dependencies(env)
     
     def infer_type(self, env):
-        if isinstance(self.base, StringNode): # FIXME: BytesNode?
+        if isinstance(self.base, BytesNode):
             return py_object_type
         base_type = self.base.infer_type(env)
         if base_type.is_ptr or base_type.is_array:
             return base_type.base_type
-        elif base_type is Builtin.unicode_type and self.index.infer_type(env).is_int:
+        elif base_type is unicode_type and self.index.infer_type(env).is_int:
             # Py_UNICODE will automatically coerce to a unicode string
             # if required, so this is safe. We only infer Py_UNICODE
             # when the index is a C integer type. Otherwise, we may
@@ -1906,6 +1906,9 @@ class IndexNode(ExprNode):
             # to receive it, throw it away, and potentially rebuild it
             # on a subsequent PyObject coercion.
             return PyrexTypes.c_py_unicode_type
+        elif base_type in (str_type, unicode_type):
+            # these types will always return themselves on Python indexing
+            return base_type
         else:
             # TODO: Handle buffers (hopefully without too much redundancy).
             return py_object_type
index 0abc0526b2fb6672b073de2136c16754b8a7d1a0..960210753a33aabd528e2f3c2f33947b787a438c 100644 (file)
@@ -71,6 +71,27 @@ def slicing():
     t1 = t[1:2]
     assert typeof(t1) == "tuple object", typeof(t1)
 
+def indexing():
+    """
+    >>> indexing()
+    """
+    b = b"abc"
+    assert typeof(b) == "char *", typeof(b)
+    b1 = b[1]
+    assert typeof(b1) == "char", typeof(b1)  # FIXME: bytes object ??
+    u = u"xyz"
+    assert typeof(u) == "unicode object", typeof(u)
+    u1 = u[1]
+    assert typeof(u1) == "Py_UNICODE", typeof(u1)
+    L = [1,2,3]
+    assert typeof(L) == "list object", typeof(L)
+    L1 = L[1]
+    assert typeof(L1) == "Python object", typeof(L1)
+    t = (4,5,6)
+    assert typeof(t) == "tuple object", typeof(t)
+    t1 = t[1]
+    assert typeof(t1) == "Python object", typeof(t1)
+
 def multiple_assignments():
     """
     >>> multiple_assignments()
@@ -197,6 +218,15 @@ def loop_over_charptr():
         pass
     return typeof(c)
 
+def loop_over_bytes_literal():
+    """
+    >>> print( loop_over_bytes_literal() )
+    Python object
+    """
+    for c in b'abcdefg':
+        pass
+    return typeof(c)
+
 def loop_over_bytes():
     """
     >>> print( loop_over_bytes() )
@@ -207,6 +237,16 @@ def loop_over_bytes():
         pass
     return typeof(c)
 
+def loop_over_str():
+    """
+    >>> print( loop_over_str() )
+    str object
+    """
+    cdef str string = 'abcdefg'
+    for c in string:
+        pass
+    return typeof(c)
+
 def loop_over_unicode():
     """
     >>> print( loop_over_unicode() )