remove trailing whitespace
[cython.git] / Cython / Compiler / PyrexTypes.py
index e21e2558623d612167ffa6da655ca97bb0e1a600..2dce098f6333b7caa05276a8bd987b3487b8acc1 100755 (executable)
@@ -17,10 +17,10 @@ class BaseType(object):
 
     def cast_code(self, expr_code):
         return "((%s)%s)" % (self.declaration_code(""), expr_code)
-    
+
     def specialization_name(self):
         return self.declaration_code("").replace(" ", "__")
-    
+
     def base_declaration_code(self, base_code, entity_code):
         if entity_code:
             return "%s %s" % (base_code, entity_code)
@@ -49,13 +49,14 @@ class PyrexType(BaseType):
     #  is_typedef            boolean     Is a typedef type
     #  is_string             boolean     Is a C char * type
     #  is_unicode            boolean     Is a UTF-8 encoded C char * type
+    #  is_unicode_char       boolean     Is either Py_UCS4 or Py_UNICODE
     #  is_returncode         boolean     Is used only to signal exceptions
     #  is_error              boolean     Is the dummy error type
     #  is_buffer             boolean     Is buffer access type
     #  has_attributes        boolean     Has C dot-selectable attributes
     #  default_value         string      Initial value
     #
-    #  declaration_code(entity_code, 
+    #  declaration_code(entity_code,
     #      for_display = 0, dll_linkage = None, pyrex = 0)
     #    Returns a code fragment for the declaration of an entity
     #    of this type, given a code fragment for the entity.
@@ -79,7 +80,7 @@ class PyrexType(BaseType):
     #    Coerces array type into pointer type for use as
     #    a formal argument type.
     #
-        
+
     is_pyobject = 0
     is_unspecified = 0
     is_extension_type = 0
@@ -101,49 +102,50 @@ class PyrexType(BaseType):
     is_typedef = 0
     is_string = 0
     is_unicode = 0
+    is_unicode_char = 0
     is_returncode = 0
     is_error = 0
     is_buffer = 0
     has_attributes = 0
     default_value = ""
-    
+
     def resolve(self):
         # If a typedef, returns the base type.
         return self
-    
+
     def specialize(self, values):
         # TODO(danilo): Override wherever it makes sense.
         return self
-    
+
     def literal_code(self, value):
         # Returns a C code fragment representing a literal
         # value of this type.
         return str(value)
-    
+
     def __str__(self):
         return self.declaration_code("", for_display = 1).strip()
-    
+
     def same_as(self, other_type, **kwds):
         return self.same_as_resolved_type(other_type.resolve(), **kwds)
-    
+
     def same_as_resolved_type(self, other_type):
         return self == other_type or other_type is error_type
-    
+
     def subtype_of(self, other_type):
         return self.subtype_of_resolved_type(other_type.resolve())
-    
+
     def subtype_of_resolved_type(self, other_type):
         return self.same_as(other_type)
-    
+
     def assignable_from(self, src_type):
         return self.assignable_from_resolved_type(src_type.resolve())
-    
+
     def assignable_from_resolved_type(self, src_type):
         return self.same_as(src_type)
-    
+
     def as_argument_type(self):
         return self
-    
+
     def is_complete(self):
         # A type is incomplete if it is an unsized array,
         # a struct whose attributes are not defined, etc.
@@ -165,7 +167,7 @@ def public_decl(base_code, dll_linkage):
         return "%s(%s)" % (dll_linkage, base_code)
     else:
         return base_code
-    
+
 def create_typedef_type(name, base_type, cname, is_external=0):
     if base_type.is_complex:
         if is_external:
@@ -187,38 +189,38 @@ class CTypedefType(BaseType):
     #  typedef_cname       string
     #  typedef_base_type   PyrexType
     #  typedef_is_external bool
-    
+
     is_typedef = 1
     typedef_is_external = 0
 
     to_py_utility_code = None
     from_py_utility_code = None
-    
-    
+
+
     def __init__(self, name, base_type, cname, is_external=0):
         assert not base_type.is_complex
         self.typedef_name = name
         self.typedef_cname = cname
         self.typedef_base_type = base_type
         self.typedef_is_external = is_external
-    
+
     def resolve(self):
         return self.typedef_base_type.resolve()
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = self.typedef_name
         else:
             base_code = public_decl(self.typedef_cname, dll_linkage)
         return self.base_declaration_code(base_code, entity_code)
-    
+
     def as_argument_type(self):
         return self
 
     def cast_code(self, expr_code):
         # If self is really an array (rather than pointer), we can't cast.
-        # For example, the gmp mpz_t. 
+        # For example, the gmp mpz_t.
         if self.typedef_base_type.is_array:
             base_type = self.typedef_base_type.base_type
             return CPtrType(base_type).cast_code(expr_code)
@@ -227,13 +229,13 @@ class CTypedefType(BaseType):
 
     def __repr__(self):
         return "<CTypedefType %s>" % self.typedef_cname
-    
+
     def __str__(self):
         return self.typedef_name
 
     def _create_utility_code(self, template_utility_code,
                              template_function_name):
-        type_name = self.typedef_cname.replace(" ","_")
+        type_name = self.typedef_cname.replace(" ","_").replace("::","__")
         utility_code = template_utility_code.specialize(
             type     = self.typedef_cname,
             TypeName = type_name)
@@ -244,7 +246,9 @@ class CTypedefType(BaseType):
         if self.typedef_is_external:
             if not self.to_py_utility_code:
                 base_type = self.typedef_base_type
-                if base_type.is_int:
+                if type(base_type) is CIntType:
+                    # Various subclasses have special methods
+                    # that should be inherited.
                     self.to_py_utility_code, self.to_py_function = \
                         self._create_utility_code(c_typedef_int_to_py_function,
                                                   '__Pyx_PyInt_to_py_%s')
@@ -263,7 +267,9 @@ class CTypedefType(BaseType):
         if self.typedef_is_external:
             if not self.from_py_utility_code:
                 base_type = self.typedef_base_type
-                if base_type.is_int:
+                if type(base_type) is CIntType:
+                    # Various subclasses have special methods
+                    # that should be inherited.
                     self.from_py_utility_code, self.from_py_function = \
                         self._create_utility_code(c_typedef_int_from_py_function,
                                                   '__Pyx_PyInt_from_py_%s')
@@ -297,7 +303,7 @@ class BufferType(BaseType):
     #  Delegates most attribute
     #  lookups to the base type. ANYTHING NOT DEFINED
     #  HERE IS DELEGATED!
-    
+
     # dtype            PyrexType
     # ndim             int
     # mode             str
@@ -316,7 +322,7 @@ class BufferType(BaseType):
         self.mode = mode
         self.negative_indices = negative_indices
         self.cast = cast
-    
+
     def as_argument_type(self):
         return self
 
@@ -339,21 +345,25 @@ class PyObjectType(PyrexType):
     buffer_defaults = None
     is_extern = False
     is_subclassed = False
-    
+
     def __str__(self):
         return "Python object"
-    
+
     def __repr__(self):
         return "<PyObjectType>"
 
     def can_coerce_to_pyobject(self, env):
         return True
 
+    def default_coerced_ctype(self):
+        "The default C type that this Python type coerces to, or None."
+        return None
+
     def assignable_from(self, src_type):
         # except for pointers, conversion will be attempted
         return not src_type.is_ptr or src_type.is_string
-        
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = "object"
@@ -369,74 +379,88 @@ class PyObjectType(PyrexType):
             return cname
 
 class BuiltinObjectType(PyObjectType):
+    #  objstruct_cname  string           Name of PyObject struct
 
     is_builtin_type = 1
     has_attributes = 1
     base_type = None
     module_name = '__builtin__'
 
-    alternative_name = None # used for str/bytes duality
+    # fields that let it look like an extension type
+    vtabslot_cname = None
+    vtabstruct_cname = None
+    vtabptr_cname = None
+    typedef_flag = True
+    is_external = True
 
-    def __init__(self, name, cname):
+    def __init__(self, name, cname, objstruct_cname=None):
         self.name = name
-        if name == 'str':
-            self.alternative_name = 'bytes'
-        elif name == 'bytes':
-            self.alternative_name = 'str'
         self.cname = cname
-        self.typeptr_cname = "&" + cname
-                                 
+        self.typeptr_cname = "(&%s)" % cname
+        self.objstruct_cname = objstruct_cname
+
     def set_scope(self, scope):
         self.scope = scope
         if scope:
             scope.parent_type = self
-        
+
     def __str__(self):
         return "%s object" % self.name
-    
+
     def __repr__(self):
         return "<%s>"% self.cname
-        
+
+    def default_coerced_ctype(self):
+        if self.name == 'bytes':
+            return c_char_ptr_type
+        elif self.name == 'bool':
+            return c_bint_type
+        elif self.name == 'float':
+            return c_double_type
+        return None
+
     def assignable_from(self, src_type):
         if isinstance(src_type, BuiltinObjectType):
-            return src_type.name == self.name or (
-                src_type.name == self.alternative_name and
-                src_type.name is not None)
+            return src_type.name == self.name
         elif src_type.is_extension_type:
             return (src_type.module_name == '__builtin__' and
                     src_type.name == self.name)
         else:
             return True
-            
+
     def typeobj_is_available(self):
         return True
-        
+
     def attributes_known(self):
         return True
-        
+
     def subtype_of(self, type):
         return type.is_pyobject and self.assignable_from(type)
-        
-    def type_test_code(self, arg, notnone=False):
+
+    def type_check_function(self, exact=True):
         type_name = self.name
         if type_name == 'str':
-            type_check = 'PyString_CheckExact'
-        elif type_name == 'set':
-            type_check = 'PyAnySet_CheckExact'
+            type_check = 'PyString_Check'
         elif type_name == 'frozenset':
-            type_check = 'PyFrozenSet_CheckExact'
-        elif type_name == 'bool':
-            type_check = 'PyBool_Check'
+            type_check = 'PyFrozenSet_Check'
         else:
-            type_check = 'Py%s_CheckExact' % type_name.capitalize()
+            type_check = 'Py%s_Check' % type_name.capitalize()
+        if exact and type_name not in ('bool', 'slice'):
+            type_check += 'Exact'
+        return type_check
+
+    def isinstance_code(self, arg):
+        return '%s(%s)' % (self.type_check_function(exact=False), arg)
 
+    def type_test_code(self, arg, notnone=False):
+        type_check = self.type_check_function(exact=True)
         check = 'likely(%s(%s))' % (type_check, arg)
         if not notnone:
             check = check + ('||((%s) == Py_None)' % arg)
         error = '(PyErr_Format(PyExc_TypeError, "Expected %s, got %%.200s", Py_TYPE(%s)->tp_name), 0)' % (self.name, arg)
         return check + '||' + error
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = self.name
@@ -445,6 +469,11 @@ class BuiltinObjectType(PyObjectType):
             entity_code = "*%s" % entity_code
         return self.base_declaration_code(base_code, entity_code)
 
+    def cast_code(self, expr_code, to_object_struct = False):
+        return "((%s*)%s)" % (
+            to_object_struct and self.objstruct_cname or "PyObject", # self.objstruct_cname may be None
+            expr_code)
+
 
 class PyExtensionType(PyObjectType):
     #
@@ -464,12 +493,12 @@ class PyExtensionType(PyObjectType):
     #  vtabstruct_cname string           Name of C method table struct
     #  vtabptr_cname    string           Name of pointer to C method table
     #  vtable_cname     string           Name of C method table definition
-    
+
     is_extension_type = 1
     has_attributes = 1
-    
+
     objtypedef_cname = None
-    
+
     def __init__(self, name, typedef_flag, base_type, is_external=0):
         self.name = name
         self.scope = None
@@ -486,28 +515,28 @@ class PyExtensionType(PyObjectType):
         self.vtabptr_cname = None
         self.vtable_cname = None
         self.is_external = is_external
-    
+
     def set_scope(self, scope):
         self.scope = scope
         if scope:
             scope.parent_type = self
-    
+
     def subtype_of_resolved_type(self, other_type):
         if other_type.is_extension_type:
             return self is other_type or (
                 self.base_type and self.base_type.subtype_of(other_type))
         else:
             return other_type is py_object_type
-    
+
     def typeobj_is_available(self):
         # Do we have a pointer to the type object?
         return self.typeptr_cname
-    
+
     def typeobj_is_imported(self):
         # If we don't know the C name of the type object but we do
         # know which module it's defined in, it will be imported.
         return self.typeobj_cname is None and self.module_name is not None
-    
+
     def assignable_from(self, src_type):
         if self == src_type:
             return True
@@ -516,7 +545,7 @@ class PyExtensionType(PyObjectType):
                 return self.assignable_from(src_type.base_type)
         return False
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
         if pyrex or for_display:
             base_code = self.name
@@ -544,14 +573,14 @@ class PyExtensionType(PyObjectType):
 
     def attributes_known(self):
         return self.scope is not None
-    
+
     def __str__(self):
         return self.name
-    
+
     def __repr__(self):
         return "<PyExtensionType %s%s>" % (self.scope.class_name,
             ("", " typedef")[self.typedef_flag])
-    
+
 
 class CType(PyrexType):
     #
@@ -560,7 +589,7 @@ class CType(PyrexType):
     #  to_py_function     string     C function for converting to Python object
     #  from_py_function   string     C function for constructing from Python object
     #
-    
+
     to_py_function = None
     from_py_function = None
     exception_value = None
@@ -568,7 +597,7 @@ class CType(PyrexType):
 
     def create_to_py_utility_code(self, env):
         return self.to_py_function is not None
-        
+
     def create_from_py_utility_code(self, env):
         return self.from_py_function is not None
 
@@ -595,18 +624,18 @@ class CVoidType(CType):
     #
 
     is_void = 1
-    
+
     def __repr__(self):
         return "<CVoidType>"
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = "void"
         else:
             base_code = public_decl("void", dll_linkage)
         return self.base_declaration_code(base_code, entity_code)
-    
+
     def is_complete(self):
         return 0
 
@@ -618,25 +647,27 @@ class CNumericType(CType):
     #   rank      integer     Relative size
     #   signed    integer     0 = unsigned, 1 = unspecified, 2 = explicitly signed
     #
-    
+
     is_numeric = 1
     default_value = "0"
-    
+    has_attributes = True
+    scope = None
+
     sign_words = ("unsigned ", "", "signed ")
-    
+
     def __init__(self, rank, signed = 1):
         self.rank = rank
         self.signed = signed
-    
+
     def sign_and_name(self):
         s = self.sign_words[self.signed]
         n = rank_to_type_name[self.rank]
         return s + n
-    
+
     def __repr__(self):
         return "<CNumericType %s>" % self.sign_and_name()
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         type_name = self.sign_and_name()
         if pyrex or for_display:
@@ -645,6 +676,23 @@ class CNumericType(CType):
             base_code = public_decl(type_name, dll_linkage)
         return self.base_declaration_code(base_code, entity_code)
 
+    def attributes_known(self):
+        if self.scope is None:
+            import Symtab
+            self.scope = scope = Symtab.CClassScope(
+                    '',
+                    None,
+                    visibility="extern")
+            scope.parent_type = self
+            scope.directives = {}
+            entry = scope.declare_cfunction(
+                    "conjugate",
+                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
+                    pos=None,
+                    defining=1,
+                    cname=" ")
+        return True
+
 
 type_conversion_predeclarations = ""
 type_conversion_functions = ""
@@ -798,7 +846,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
     } else {
         int one = 1; int little = (int)*(unsigned char *)&one;
         unsigned char *bytes = (unsigned char *)&val;
-        return _PyLong_FromByteArray(bytes, sizeof(%(type)s), 
+        return _PyLong_FromByteArray(bytes, sizeof(%(type)s),
                                      little, !is_unsigned);
     }
 }
@@ -865,6 +913,8 @@ class CAnonEnumType(CIntType):
 
 class CReturnCodeType(CIntType):
 
+    to_py_function = "__Pyx_Owned_Py_None"
+
     is_returncode = 1
 
 
@@ -872,15 +922,90 @@ class CBIntType(CIntType):
 
     to_py_function = "__Pyx_PyBool_FromLong"
     from_py_function = "__Pyx_PyObject_IsTrue"
-    exception_check = 0
+    exception_check = 1 # for C++ bool
 
     def __repr__(self):
         return "<CNumericType bint>"
 
+    def __str__(self):
+        return 'bint'
+
+
+class CPyUCS4IntType(CIntType):
+    # Py_UCS4
+
+    is_unicode_char = True
+
+    # Py_UCS4 coerces from and to single character unicode strings (or
+    # at most two characters on 16bit Unicode builds), but we also
+    # allow Python integers as input.  The value range for Py_UCS4
+    # is 0..1114111, which is checked when converting from an integer
+    # value.
+
+    to_py_function = "PyUnicode_FromOrdinal"
+    from_py_function = "__Pyx_PyObject_AsPy_UCS4"
+
+    def create_from_py_utility_code(self, env):
+        env.use_utility_code(pyobject_as_py_ucs4_utility_code)
+        return True
+
+    def sign_and_name(self):
+        return "Py_UCS4"
+
+
+pyobject_as_py_ucs4_utility_code = UtilityCode(
+proto='''
+static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject*);
+''',
+impl='''
+static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
+   long ival;
+   if (PyUnicode_Check(x)) {
+       if (likely(PyUnicode_GET_SIZE(x) == 1)) {
+           return PyUnicode_AS_UNICODE(x)[0];
+       }
+       #if Py_UNICODE_SIZE == 2
+       else if (PyUnicode_GET_SIZE(x) == 2) {
+           Py_UCS4 high_val = PyUnicode_AS_UNICODE(x)[0];
+           if (high_val >= 0xD800 && high_val <= 0xDBFF) {
+               Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
+               if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
+                   return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
+               }
+           }
+       }
+       #endif
+       PyErr_Format(PyExc_ValueError,
+           "only single character unicode strings can be converted to Py_UCS4, got length "
+           #if PY_VERSION_HEX < 0x02050000
+           "%d",
+           #else
+           "%zd",
+           #endif
+           PyUnicode_GET_SIZE(x));
+       return (Py_UCS4)-1;
+   }
+   ival = __Pyx_PyInt_AsLong(x);
+   if (unlikely(ival < 0)) {
+       if (!PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "cannot convert negative value to Py_UCS4");
+       return (Py_UCS4)-1;
+   } else if (unlikely(ival > 1114111)) {
+       PyErr_SetString(PyExc_OverflowError,
+                       "value too large to convert to Py_UCS4");
+       return (Py_UCS4)-1;
+   }
+   return (Py_UCS4)ival;
+}
+''')
+
 
 class CPyUnicodeIntType(CIntType):
     # Py_UNICODE
 
+    is_unicode_char = True
+
     # Py_UNICODE coerces from and to single character unicode strings,
     # but we also allow Python integers as input.  The value range for
     # Py_UNICODE is 0..1114111, which is checked when converting from
@@ -936,6 +1061,14 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
 ''')
 
 
+class CPyHashTType(CIntType):
+
+    to_py_function = "__Pyx_PyInt_FromHash_t"
+    from_py_function = "__Pyx_PyInt_AsHash_t"
+
+    def sign_and_name(self):
+        return "Py_hash_t"
+
 class CPySSizeTType(CIntType):
 
     to_py_function = "PyInt_FromSsize_t"
@@ -950,7 +1083,7 @@ class CSSizeTType(CIntType):
     from_py_function = "PyInt_AsSsize_t"
 
     def sign_and_name(self):
-        return "ssize_t"
+        return "Py_ssize_t"
 
 class CSizeTType(CIntType):
 
@@ -968,22 +1101,22 @@ class CFloatType(CNumericType):
     from_py_function = "__pyx_PyFloat_AsDouble"
 
     exception_value = -1
-    
+
     def __init__(self, rank, math_h_modifier = ''):
         CNumericType.__init__(self, rank, 1)
         self.math_h_modifier = math_h_modifier
-    
+
     def assignable_from_resolved_type(self, src_type):
         return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type
 
 
 class CComplexType(CNumericType):
-    
+
     is_complex = 1
     to_py_function = "__pyx_PyComplex_FromComplex"
     has_attributes = 1
     scope = None
-    
+
     def __init__(self, real_type):
         while real_type.is_typedef and not real_type.typedef_is_external:
             real_type = real_type.typedef_base_type
@@ -995,7 +1128,7 @@ class CComplexType(CNumericType):
             self.funcsuffix = real_type.math_h_modifier
         else:
             self.funcsuffix = "_%s" % real_type.specialization_name()
-    
+
         self.real_type = real_type
         CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
         self.binops = {}
@@ -1007,7 +1140,7 @@ class CComplexType(CNumericType):
             return self.real_type == other.real_type
         else:
             return False
-    
+
     def __ne__(self, other):
         if isinstance(self, CComplexType) and isinstance(other, CComplexType):
             return self.real_type != other.real_type
@@ -1025,7 +1158,7 @@ class CComplexType(CNumericType):
     def __hash__(self):
         return ~hash(self.real_type)
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
@@ -1039,7 +1172,7 @@ class CComplexType(CNumericType):
         real_type_name = real_type_name.replace('long__double','long_double')
         real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
         return Naming.type_prefix + real_type_name + "_complex"
-    
+
     def assignable_from(self, src_type):
         # Temporary hack/feature disabling, see #441
         if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
@@ -1047,12 +1180,12 @@ class CComplexType(CNumericType):
              return False
         else:
             return super(CComplexType, self).assignable_from(src_type)
-        
+
     def assignable_from_resolved_type(self, src_type):
         return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type)
-                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type) 
+                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
                     or src_type is error_type)
-                    
+
     def attributes_known(self):
         if self.scope is None:
             import Symtab
@@ -1061,11 +1194,12 @@ class CComplexType(CNumericType):
                     None,
                     visibility="extern")
             scope.parent_type = self
-            scope.declare_var("real", self.real_type, None, "real", is_cdef=True)
-            scope.declare_var("imag", self.real_type, None, "imag", is_cdef=True)
+            scope.directives = {}
+            scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True)
+            scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True)
             entry = scope.declare_cfunction(
                     "conjugate",
-                    CFuncType(self, [CFuncTypeArg("self", self, None)]),
+                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
                     pos=None,
                     defining=1,
                     cname="__Pyx_c_conj%s" % self.funcsuffix)
@@ -1082,9 +1216,10 @@ class CComplexType(CNumericType):
                              complex_arithmetic_utility_code):
             env.use_utility_code(
                 utility_code.specialize(
-                    self, 
+                    self,
                     real_type = self.real_type.declaration_code(''),
-                    m = self.funcsuffix))
+                    m = self.funcsuffix,
+                    is_float = self.real_type.is_float))
         return True
 
     def create_to_py_utility_code(self, env):
@@ -1099,12 +1234,13 @@ class CComplexType(CNumericType):
                              complex_from_py_utility_code):
             env.use_utility_code(
                 utility_code.specialize(
-                    self, 
+                    self,
                     real_type = self.real_type.declaration_code(''),
-                    m = self.funcsuffix))
+                    m = self.funcsuffix,
+                    is_float = self.real_type.is_float))
         self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
         return True
-    
+
     def lookup_op(self, nargs, op):
         try:
             return self.binops[nargs, op]
@@ -1119,10 +1255,10 @@ class CComplexType(CNumericType):
 
     def unary_op(self, op):
         return self.lookup_op(1, op)
-        
+
     def binary_op(self, op):
         return self.lookup_op(2, op)
-        
+
 complex_ops = {
     (1, '-'): 'neg',
     (1, 'zero'): 'is_zero',
@@ -1260,11 +1396,17 @@ proto="""
   #ifdef __cplusplus
     #define __Pyx_c_is_zero%(m)s(z) ((z)==(%(real_type)s)0)
     #define __Pyx_c_conj%(m)s(z)    (::std::conj(z))
-    /*#define __Pyx_c_abs%(m)s(z)     (::std::abs(z))*/
+    #if %(is_float)s
+        #define __Pyx_c_abs%(m)s(z)     (::std::abs(z))
+        #define __Pyx_c_pow%(m)s(a, b)  (::std::pow(a, b))
+    #endif
   #else
     #define __Pyx_c_is_zero%(m)s(z) ((z)==0)
     #define __Pyx_c_conj%(m)s(z)    (conj%(m)s(z))
-    /*#define __Pyx_c_abs%(m)s(z)     (cabs%(m)s(z))*/
+    #if %(is_float)s
+        #define __Pyx_c_abs%(m)s(z)     (cabs%(m)s(z))
+        #define __Pyx_c_pow%(m)s(a, b)  (cpow%(m)s(a, b))
+    #endif
  #endif
 #else
     static CYTHON_INLINE int __Pyx_c_eq%(m)s(%(type)s, %(type)s);
@@ -1275,7 +1417,10 @@ proto="""
     static CYTHON_INLINE %(type)s __Pyx_c_neg%(m)s(%(type)s);
     static CYTHON_INLINE int __Pyx_c_is_zero%(m)s(%(type)s);
     static CYTHON_INLINE %(type)s __Pyx_c_conj%(m)s(%(type)s);
-    /*static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s);*/
+    #if %(is_float)s
+        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s);
+        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s, %(type)s);
+    #endif
 #endif
 """,
 impl="""
@@ -1324,46 +1469,91 @@ impl="""
         z.imag = -a.imag;
         return z;
     }
-/*
-    static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
-#if HAVE_HYPOT
-        return hypot%(m)s(z.real, z.imag);
-#else
-        return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
-#endif
-    }
-*/
+    #if %(is_float)s
+        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
+          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
+            return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
+          #else
+            return hypot%(m)s(z.real, z.imag);
+          #endif
+        }
+        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s a, %(type)s b) {
+            %(type)s z;
+            %(real_type)s r, lnr, theta, z_r, z_theta;
+            if (b.imag == 0 && b.real == (int)b.real) {
+                if (b.real < 0) {
+                    %(real_type)s denom = a.real * a.real + a.imag * a.imag;
+                    a.real = a.real / denom;
+                    a.imag = -a.imag / denom;
+                    b.real = -b.real;
+                }
+                switch ((int)b.real) {
+                    case 0:
+                        z.real = 1;
+                        z.imag = 0;
+                        return z;
+                    case 1:
+                        return a;
+                    case 2:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(a, a);
+                    case 3:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(z, a);
+                    case 4:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(z, z);
+                }
+            }
+            if (a.imag == 0) {
+                if (a.real == 0) {
+                    return a;
+                }
+                r = a.real;
+                theta = 0;
+            } else {
+                r = __Pyx_c_abs%(m)s(a);
+                theta = atan2%(m)s(a.imag, a.real);
+            }
+            lnr = log%(m)s(r);
+            z_r = exp%(m)s(lnr * b.real - theta * b.imag);
+            z_theta = theta * b.real + lnr * b.imag;
+            z.real = z_r * cos%(m)s(z_theta);
+            z.imag = z_r * sin%(m)s(z_theta);
+            return z;
+        }
+    #endif
 #endif
 """)
 
 class CArrayType(CType):
     #  base_type     CType              Element type
     #  size          integer or None    Number of elements
-    
+
     is_array = 1
-    
+
     def __init__(self, base_type, size):
         self.base_type = base_type
         self.size = size
-        if base_type is c_char_type:
+        if base_type in (c_char_type, c_uchar_type, c_schar_type):
             self.is_string = 1
-    
+
     def __repr__(self):
         return "<CArrayType %s %s>" % (self.size, repr(self.base_type))
-    
+
     def same_as_resolved_type(self, other_type):
         return ((other_type.is_array and
             self.base_type.same_as(other_type.base_type))
                 or other_type is error_type)
-    
+
     def assignable_from_resolved_type(self, src_type):
         # Can't assign to a variable of an array type
         return 0
-    
+
     def element_ptr_type(self):
         return c_ptr_type(self.base_type)
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if self.size is not None:
             dimension_code = self.size
@@ -1374,38 +1564,38 @@ class CArrayType(CType):
         return self.base_type.declaration_code(
             "%s[%s]" % (entity_code, dimension_code),
             for_display, dll_linkage, pyrex)
-    
+
     def as_argument_type(self):
         return c_ptr_type(self.base_type)
-    
+
     def is_complete(self):
         return self.size is not None
 
 
 class CPtrType(CType):
     #  base_type     CType    Referenced type
-    
+
     is_ptr = 1
     default_value = "0"
-    
+
     def __init__(self, base_type):
         self.base_type = base_type
-    
+
     def __repr__(self):
         return "<CPtrType %s>" % repr(self.base_type)
-    
+
     def same_as_resolved_type(self, other_type):
         return ((other_type.is_ptr and
             self.base_type.same_as(other_type.base_type))
                 or other_type is error_type)
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         #print "CPtrType.declaration_code: pointer to", self.base_type ###
         return self.base_type.declaration_code(
             "*%s" % entity_code,
             for_display, dll_linkage, pyrex)
-    
+
     def assignable_from_resolved_type(self, other_type):
         if other_type is error_type:
             return 1
@@ -1418,13 +1608,13 @@ class CPtrType(CType):
                 return self.base_type.pointer_assignable_from_resolved_type(other_type)
             else:
                 return 0
-        if (self.base_type.is_cpp_class and other_type.is_ptr 
+        if (self.base_type.is_cpp_class and other_type.is_ptr
                 and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)):
             return 1
         if other_type.is_array or other_type.is_ptr:
             return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
         return 0
-    
+
     def specialize(self, values):
         base_type = self.base_type.specialize(values)
         if base_type == self.base_type:
@@ -1436,7 +1626,7 @@ class CPtrType(CType):
 class CNullPtrType(CPtrType):
 
     is_null_ptr = 1
-    
+
 
 class CReferenceType(BaseType):
 
@@ -1447,20 +1637,20 @@ class CReferenceType(BaseType):
 
     def __repr__(self):
         return "<CReferenceType %s>" % repr(self.ref_base_type)
-    
+
     def __str__(self):
         return "%s &" % self.ref_base_type
 
     def as_argument_type(self):
         return self
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         #print "CReferenceType.declaration_code: pointer to", self.base_type ###
         return self.ref_base_type.declaration_code(
             "&%s" % entity_code,
             for_display, dll_linkage, pyrex)
-    
+
     def specialize(self, values):
         base_type = self.ref_base_type.specialize(values)
         if base_type == self.ref_base_type:
@@ -1482,10 +1672,10 @@ class CFuncType(CType):
     #  nogil            boolean    Can be called without gil
     #  with_gil         boolean    Acquire gil around function body
     #  templates        [string] or None
-    
+
     is_cfunction = 1
     original_sig = None
-    
+
     def __init__(self, return_type, args, has_varargs = 0,
             exception_value = None, exception_check = 0, calling_convention = "",
             nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
@@ -1501,7 +1691,7 @@ class CFuncType(CType):
         self.with_gil = with_gil
         self.is_overridable = is_overridable
         self.templates = templates
-    
+
     def __repr__(self):
         arg_reprs = map(repr, self.args)
         if self.has_varargs:
@@ -1517,14 +1707,14 @@ class CFuncType(CType):
             self.calling_convention_prefix(),
             ",".join(arg_reprs),
             except_clause)
-    
+
     def calling_convention_prefix(self):
         cc = self.calling_convention
         if cc:
             return cc + " "
         else:
             return ""
-    
+
     def same_c_signature_as(self, other_type, as_cmethod = 0):
         return self.same_c_signature_as_resolved_type(
             other_type.resolve(), as_cmethod)
@@ -1560,7 +1750,7 @@ class CFuncType(CType):
 
     def compatible_signature_with(self, other_type, as_cmethod = 0):
         return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
-    
+
     def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
         #print "CFuncType.same_c_signature_as_resolved_type:", \
         #    self, other_type, "as_cmethod =", as_cmethod ###
@@ -1594,11 +1784,11 @@ class CFuncType(CType):
         if as_cmethod:
             self.args[0] = other_type.args[0]
         return 1
-        
-        
+
+
     def narrower_c_signature_than(self, other_type, as_cmethod = 0):
         return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
-        
+
     def narrower_c_signature_than_resolved_type(self, other_type, as_cmethod):
         if other_type is error_type:
             return 1
@@ -1634,7 +1824,7 @@ class CFuncType(CType):
         sc1 = self.calling_convention == '__stdcall'
         sc2 = other.calling_convention == '__stdcall'
         return sc1 == sc2
-    
+
     def same_exception_signature_as(self, other_type):
         return self.same_exception_signature_as_resolved_type(
             other_type.resolve())
@@ -1642,18 +1832,18 @@ class CFuncType(CType):
     def same_exception_signature_as_resolved_type(self, other_type):
         return self.exception_value == other_type.exception_value \
             and self.exception_check == other_type.exception_check
-    
+
     def same_as_resolved_type(self, other_type, as_cmethod = 0):
         return self.same_c_signature_as_resolved_type(other_type, as_cmethod) \
             and self.same_exception_signature_as_resolved_type(other_type) \
             and self.nogil == other_type.nogil
-    
+
     def pointer_assignable_from_resolved_type(self, other_type):
         return self.same_c_signature_as_resolved_type(other_type) \
             and self.same_exception_signature_as_resolved_type(other_type) \
             and not (self.nogil and not other_type.nogil)
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
                          for_display = 0, dll_linkage = None, pyrex = 0,
                          with_calling_convention = 1):
         arg_decl_list = []
@@ -1691,7 +1881,7 @@ class CFuncType(CType):
         return self.return_type.declaration_code(
             "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
             for_display, dll_linkage, pyrex)
-    
+
     def function_header_code(self, func_name, arg_code):
         return "%s%s(%s)" % (self.calling_convention_prefix(),
             func_name, arg_code)
@@ -1703,7 +1893,7 @@ class CFuncType(CType):
     def signature_cast_string(self):
         s = self.declaration_code("(*)", with_calling_convention=False)
         return '(%s)' % s
-    
+
     def specialize(self, values):
         if self.templates is None:
             new_templates = None
@@ -1720,7 +1910,7 @@ class CFuncType(CType):
                              is_overridable = self.is_overridable,
                              optional_arg_count = self.optional_arg_count,
                              templates = new_templates)
-    
+
     def opt_arg_cname(self, arg_name):
         return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
 
@@ -1745,13 +1935,13 @@ class CFuncTypeArg(object):
         self.type = type
         self.pos = pos
         self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
-    
+
     def __repr__(self):
         return "%s:%s" % (self.name, repr(self.type))
-    
+
     def declaration_code(self, for_display = 0):
         return self.type.declaration_code(self.cname, for_display)
-    
+
     def specialize(self, values):
         return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
 
@@ -1765,11 +1955,11 @@ class StructUtilityCode(object):
         return isinstance(other, StructUtilityCode) and self.header == other.header
     def __hash__(self):
         return hash(self.header)
-    
+
     def put_code(self, output):
         code = output['utility_code_def']
         proto = output['utility_code_proto']
-        
+
         code.putln("%s {" % self.header)
         code.putln("PyObject* res;")
         code.putln("PyObject* member;")
@@ -1792,7 +1982,7 @@ class StructUtilityCode(object):
         if self.forward_decl:
             proto.putln(self.type.declaration_code('') + ';')
         proto.putln(self.header + ";")
-        
+
 
 class CStructOrUnionType(CType):
     #  name          string
@@ -1801,12 +1991,12 @@ class CStructOrUnionType(CType):
     #  scope         StructOrUnionScope, or None if incomplete
     #  typedef_flag  boolean
     #  packed        boolean
-    
+
     # entry          Entry
-    
+
     is_struct_or_union = 1
     has_attributes = 1
-    
+
     def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
         self.name = name
         self.cname = cname
@@ -1819,7 +2009,7 @@ class CStructOrUnionType(CType):
         self.exception_check = True
         self._convert_code = None
         self.packed = packed
-        
+
     def create_to_py_utility_code(self, env):
         if env.outer_scope is None:
             return False
@@ -1834,15 +2024,15 @@ class CStructOrUnionType(CType):
                     return False
             forward_decl = (self.entry.visibility != 'extern')
             self._convert_code = StructUtilityCode(self, forward_decl)
-        
+
         env.use_utility_code(self._convert_code)
         return True
-        
+
     def __repr__(self):
         return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
             ("", " typedef")[self.typedef_flag])
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = self.name
@@ -1874,7 +2064,7 @@ class CStructOrUnionType(CType):
 
     def is_complete(self):
         return self.scope is not None
-    
+
     def attributes_known(self):
         return self.is_complete()
 
@@ -1897,12 +2087,12 @@ class CppClassType(CType):
     #  cname         string
     #  scope         CppClassScope
     #  templates     [string] or None
-    
+
     is_cpp_class = 1
     has_attributes = 1
     exception_check = True
     namespace = None
-    
+
     def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None):
         self.name = name
         self.cname = cname
@@ -1918,11 +2108,11 @@ class CppClassType(CType):
             error(pos, "'%s' type is not a template" % self);
             return PyrexTypes.error_type
         if len(self.templates) != len(template_values):
-            error(pos, "%s templated type receives %d arguments, got %d" % 
+            error(pos, "%s templated type receives %d arguments, got %d" %
                   (self.name, len(self.templates), len(template_values)))
             return error_type
         return self.specialize(dict(zip(self.templates, template_values)))
-    
+
     def specialize(self, values):
         if not self.templates and not self.namespace:
             return self
@@ -1969,7 +2159,7 @@ class CppClassType(CType):
             if base_class.is_subclass(other_type):
                 return 1
         return 0
-    
+
     def same_as_resolved_type(self, other_type):
         if other_type.is_cpp_class:
             if self == other_type:
@@ -1988,23 +2178,23 @@ class CppClassType(CType):
         if other_type is error_type:
             return True
         return other_type.is_cpp_class and other_type.is_subclass(self)
-    
+
     def attributes_known(self):
         return self.scope is not None
 
 
 class TemplatePlaceholderType(CType):
-    
+
     def __init__(self, name):
         self.name = name
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if entity_code:
             return self.name + " " + entity_code
         else:
             return self.name
-    
+
     def specialize(self, values):
         if self in values:
             return values[self]
@@ -2016,10 +2206,10 @@ class TemplatePlaceholderType(CType):
             return self.name == other_type.name
         else:
             return 0
-        
+
     def __hash__(self):
         return hash(self.name)
-    
+
     def __cmp__(self, other):
         if isinstance(other, TemplatePlaceholderType):
             return cmp(self.name, other.name)
@@ -2042,15 +2232,15 @@ class CEnumType(CType):
         self.cname = cname
         self.values = []
         self.typedef_flag = typedef_flag
-    
+
     def __str__(self):
         return self.name
-    
+
     def __repr__(self):
         return "<CEnumType %s %s%s>" % (self.name, self.cname,
             ("", " typedef")[self.typedef_flag])
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = self.name
@@ -2068,7 +2258,7 @@ class CStringType(object):
 
     is_string = 1
     is_unicode = 0
-    
+
     to_py_function = "PyBytes_FromString"
     from_py_function = "PyBytes_AsString"
     exception_value = "NULL"
@@ -2080,32 +2270,32 @@ class CStringType(object):
 
 class CUTF8CharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
-    
+
     is_unicode = 1
-    
+
     to_py_function = "PyUnicode_DecodeUTF8"
     exception_value = "NULL"
-    
+
     def __init__(self, size):
         CArrayType.__init__(self, c_char_type, size)
 
 class CCharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
-    
+
     def __init__(self, size):
         CArrayType.__init__(self, c_char_type, size)
-    
+
 
 class CCharPtrType(CStringType, CPtrType):
     # C 'char *' type.
-    
+
     def __init__(self):
         CPtrType.__init__(self, c_char_type)
 
 
 class CUCharPtrType(CStringType, CPtrType):
     # C 'unsigned char *' type.
-    
+
     to_py_function = "__Pyx_PyBytes_FromUString"
     from_py_function = "__Pyx_PyBytes_AsUString"
 
@@ -2115,39 +2305,39 @@ class CUCharPtrType(CStringType, CPtrType):
 
 class UnspecifiedType(PyrexType):
     # Used as a placeholder until the type can be determined.
-    
+
     is_unspecified = 1
-        
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         return "<unspecified>"
-    
+
     def same_as_resolved_type(self, other_type):
         return False
-        
+
 
 class ErrorType(PyrexType):
     # Used to prevent propagation of error messages.
-    
+
     is_error = 1
     exception_value = "0"
     exception_check    = 0
     to_py_function = "dummy"
     from_py_function = "dummy"
-    
+
     def create_to_py_utility_code(self, env):
         return True
-    
+
     def create_from_py_utility_code(self, env):
         return True
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         return "<error>"
-    
+
     def same_as_resolved_type(self, other_type):
         return 1
-        
+
     def error_condition(self, result_code):
         return "dummy"
 
@@ -2203,6 +2393,8 @@ c_anon_enum_type =   CAnonEnumType(-1)
 c_returncode_type =  CReturnCodeType(RANK_INT)
 c_bint_type =        CBIntType(RANK_INT)
 c_py_unicode_type =  CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
+c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
+c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
 c_py_ssize_t_type =  CPySSizeTType(RANK_LONG+0.5, SIGNED)
 c_ssize_t_type =     CSSizeTType(RANK_LONG+0.5, SIGNED)
 c_size_t_type =      CSizeTType(RANK_LONG+0.5, UNSIGNED)
@@ -2254,7 +2446,7 @@ modifiers_and_name_to_type = {
     (1,  0, "double"): c_double_type,
     (1,  1, "double"): c_longdouble_type,
 
-    (1,  0, "complex"):  c_float_complex_type,
+    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
     (1,  0, "floatcomplex"):  c_float_complex_type,
     (1,  0, "doublecomplex"): c_double_complex_type,
     (1,  1, "doublecomplex"): c_longdouble_complex_type,
@@ -2264,6 +2456,8 @@ modifiers_and_name_to_type = {
 
     (1,  0, "bint"):       c_bint_type,
     (0,  0, "Py_UNICODE"): c_py_unicode_type,
+    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
+    (2,  0, "Py_hash_t"):  c_py_hash_t_type,
     (2,  0, "Py_ssize_t"): c_py_ssize_t_type,
     (2,  0, "ssize_t") :   c_ssize_t_type,
     (0,  0, "size_t") :    c_size_t_type,
@@ -2273,7 +2467,7 @@ modifiers_and_name_to_type = {
 
 def is_promotion(src_type, dst_type):
     # It's hard to find a hard definition of promotion, but empirical
-    # evidence suggests that the below is all that's allowed. 
+    # evidence suggests that the below is all that's allowed.
     if src_type.is_numeric:
         if dst_type.same_as(c_int_type):
             unsigned = (not src_type.signed)
@@ -2296,7 +2490,7 @@ def best_match(args, functions, pos=None):
     functions based on how much work must be done to convert the
     arguments, with the following priorities:
       * identical types or pointers to identical types
-      * promotions 
+      * promotions
       * non-Python types
     That is, we prefer functions where no arguments need converted,
     and failing that, functions where only promotions are required, and
@@ -2306,7 +2500,7 @@ def best_match(args, functions, pos=None):
     the same weight, we return None (as there is no best match). If pos
     is not None, we also generate an error.
     """
-    # TODO: args should be a list of types, not a list of Nodes. 
+    # TODO: args should be a list of types, not a list of Nodes.
     actual_nargs = len(args)
 
     candidates = []
@@ -2338,7 +2532,7 @@ def best_match(args, functions, pos=None):
             errors.append((func, error_mesg))
             continue
         candidates.append((func, func_type))
-        
+
     # Optimize the most common case of no overloading...
     if len(candidates) == 1:
         return candidates[0][0]
@@ -2349,7 +2543,7 @@ def best_match(args, functions, pos=None):
             else:
                 error(pos, "no suitable method found")
         return None
-        
+
     possibilities = []
     bad_types = []
     for func, func_type in candidates:
@@ -2399,7 +2593,7 @@ def widest_numeric_type(type1, type2):
             return ntype
         widest_type = CComplexType(
             widest_numeric_type(
-                real_type(type1), 
+                real_type(type1),
                 real_type(type2)))
     elif type1.is_enum and type2.is_enum:
         widest_type = c_int_type
@@ -2413,31 +2607,55 @@ def widest_numeric_type(type1, type2):
         widest_type = type2
     return widest_type
 
-def spanning_type(type1, type2):
-    # Return a type assignable from both type1 and type2.
-    if type1 is py_object_type or type2 is py_object_type:
+def independent_spanning_type(type1, type2):
+    # Return a type assignable independently from both type1 and
+    # type2, but do not require any interoperability between the two.
+    # For example, in "True * 2", it is safe to assume an integer
+    # result type (so spanning_type() will do the right thing),
+    # whereas "x = True or 2" must evaluate to a type that can hold
+    # both a boolean value and an integer, so this function works
+    # better.
+    if type1 == type2:
+        return type1
+    elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric):
+        # special case: if one of the results is a bint and the other
+        # is another C integer, we must prevent returning a numeric
+        # type so that we do not lose the ability to coerce to a
+        # Python bool if we have to.
         return py_object_type
-    elif type1 == type2:
+    span_type = _spanning_type(type1, type2)
+    if span_type is None:
+        return error_type
+    return span_type
+
+def spanning_type(type1, type2):
+    # Return a type assignable from both type1 and type2, or
+    # py_object_type if no better type is found.  Assumes that the
+    # code that calls this will try a coercion afterwards, which will
+    # fail if the types cannot actually coerce to a py_object_type.
+    if type1 == type2:
         return type1
-    elif type1.is_numeric and type2.is_numeric:
+    elif type1 is py_object_type or type2 is py_object_type:
+        return py_object_type
+    elif type1 is c_py_unicode_type or type2 is c_py_unicode_type:
+        # Py_UNICODE behaves more like a string than an int
+        return py_object_type
+    span_type = _spanning_type(type1, type2)
+    if span_type is None:
+        return py_object_type
+    return span_type
+
+def _spanning_type(type1, type2):
+    if type1.is_numeric and type2.is_numeric:
         return widest_numeric_type(type1, type2)
     elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
         return widest_numeric_type(c_double_type, type2)
     elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
         return widest_numeric_type(type1, c_double_type)
-    elif type1.is_pyobject ^ type2.is_pyobject:
-        return py_object_type
     elif type1.is_extension_type and type2.is_extension_type:
-        if type1.typeobj_is_imported() or type2.typeobj_is_imported():
-            return py_object_type
-        while True:
-            if type1.subtype_of(type2):
-                return type2
-            elif type2.subtype_of(type1):
-                return type1
-            type1, type2 = type1.base_type, type2.base_type
-            if type1 is None or type2 is None:
-                return py_object_type
+        return widest_extension_type(type1, type2)
+    elif type1.is_pyobject or type2.is_pyobject:
+        return py_object_type
     elif type1.assignable_from(type2):
         if type1.is_extension_type and type1.typeobj_is_imported():
             # external types are unsafe, so we use PyObject instead
@@ -2449,13 +2667,25 @@ def spanning_type(type1, type2):
             return py_object_type
         return type2
     else:
+        return None
+
+def widest_extension_type(type1, type2):
+    if type1.typeobj_is_imported() or type2.typeobj_is_imported():
         return py_object_type
-    
+    while True:
+        if type1.subtype_of(type2):
+            return type2
+        elif type2.subtype_of(type1):
+            return type1
+        type1, type2 = type1.base_type, type2.base_type
+        if type1 is None or type2 is None:
+            return py_object_type
+
 def simple_c_type(signed, longness, name):
     # Find type descriptor for simple type given name and modifiers.
     # Returns None if arguments don't make sense.
     return modifiers_and_name_to_type.get((signed, longness, name))
-    
+
 def parse_basic_type(name):
     base = None
     if name.startswith('p_'):
@@ -2475,6 +2705,10 @@ def parse_basic_type(name):
     longness = 0
     if name == 'Py_UNICODE':
         signed = 0
+    elif name == 'Py_UCS4':
+        signed = 0
+    elif name == 'Py_hash_t':
+        signed = 2
     elif name == 'Py_ssize_t':
         signed = 2
     elif name == 'ssize_t':
@@ -2485,7 +2719,7 @@ def parse_basic_type(name):
         if name.startswith('u'):
             name = name[1:]
             signed = 0
-        elif (name.startswith('s') and 
+        elif (name.startswith('s') and
               not name.startswith('short')):
             name = name[1:]
             signed = 2
@@ -2529,7 +2763,7 @@ def c_ref_type(base_type):
 
 def same_type(type1, type2):
     return type1.same_as(type2)
-    
+
 def assignable_from(type1, type2):
     return type1.assignable_from(type2)
 
@@ -2551,6 +2785,7 @@ type_conversion_predeclarations = """
 #define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
 #define __Pyx_PyBytes_AsUString(s)   ((unsigned char*) PyBytes_AsString(s))
 
+#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
 #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);