-
-
#
# Pyrex - Types
#
def cast_code(self, expr_code):
return "((%s)%s)" % (self.declaration_code(""), expr_code)
- def specalization_name(self):
+ def specialization_name(self):
return self.declaration_code("").replace(" ", "__")
def base_declaration_code(self, base_code, entity_code):
# is_buffer boolean Is buffer access type
# has_attributes boolean Has C dot-selectable attributes
# default_value string Initial value
- # pymemberdef_typecode string Type code for PyMemberDef struct
#
# declaration_code(entity_code,
# for_display = 0, dll_linkage = None, pyrex = 0)
is_buffer = 0
has_attributes = 0
default_value = ""
- pymemberdef_typecode = None
def resolve(self):
# If a typedef, returns the base type.
return 1
+def public_decl(base_code, dll_linkage):
+ if 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:
else:
return CTypedefType(name, base_type, cname, is_external)
+
class CTypedefType(BaseType):
#
# Pseudo-type defined with a ctypedef statement in a
self.typedef_cname = cname
self.typedef_base_type = base_type
self.typedef_is_external = is_external
- # Make typecodes in external typedefs use typesize-neutral macros
- if is_external:
- typecode = None
- if base_type.is_int:
- if base_type.signed == 0:
- typecode = "__Pyx_T_UNSIGNED_INT"
- else:
- typecode = "__Pyx_T_SIGNED_INT"
- elif base_type.is_float and not rank_to_type_name[base_type.rank] == "long double":
- typecode = "__Pyx_T_FLOATING"
- if typecode:
- self.pymemberdef_typecode = "%s(%s)" % (typecode, cname)
def resolve(self):
return self.typedef_base_type.resolve()
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.
- if self.typedef_base_type.is_ptr:
- return self.typedef_base_type.cast_code(expr_code)
+ if self.typedef_base_type.is_array:
+ base_type = self.typedef_base_type.base_type
+ return CPtrType(base_type).cast_code(expr_code)
else:
return BaseType.cast_code(self, expr_code)
def __getattr__(self, name):
return getattr(self.typedef_base_type, name)
+
class BufferType(BaseType):
#
# Delegates most attribute
def __repr__(self):
return "<BufferType %r>" % self.base
-def public_decl(base, dll_linkage):
- if dll_linkage:
- return "%s(%s)" % (dll_linkage, base)
- else:
- return base
-
+
class PyObjectType(PyrexType):
#
# Base class for all Python object types (reference-counted).
name = "object"
is_pyobject = 1
default_value = "0"
- pymemberdef_typecode = "T_OBJECT"
buffer_defaults = None
is_extern = False
is_subclassed = False
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
- return self.base_declaration_code("object", entity_code)
+ base_code = "object"
else:
- return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
+ base_code = public_decl("PyObject", dll_linkage)
+ entity_code = "*%s" % entity_code
+ return self.base_declaration_code(base_code, entity_code)
def as_pyobject(self, cname):
if (not self.is_complete()) or self.is_extension_type:
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
- return self.base_declaration_code(self.name, entity_code)
+ base_code = self.name
else:
- return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
+ base_code = public_decl("PyObject", dll_linkage)
+ entity_code = "*%s" % entity_code
+ return self.base_declaration_code(base_code, entity_code)
class PyExtensionType(PyObjectType):
# 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
+ if isinstance(src_type, PyExtensionType):
+ if src_type.base_type is not None:
+ return self.assignable_from(src_type.base_type)
+ return False
+
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
if pyrex or for_display:
- return self.base_declaration_code(self.name, entity_code)
+ base_code = self.name
else:
if self.typedef_flag:
- base_format = "%s"
+ objstruct = self.objstruct_cname
else:
- base_format = "struct %s"
- base = public_decl(base_format % self.objstruct_cname, dll_linkage)
+ objstruct = "struct %s" % self.objstruct_cname
+ base_code = public_decl(objstruct, dll_linkage)
if deref:
- return "%s %s" % (base, entity_code)
+ assert not entity_code
else:
- return "%s *%s" % (base, entity_code)
+ entity_code = "*%s" % entity_code
+ return self.base_declaration_code(base_code, entity_code)
def type_test_code(self, py_arg, notnone=False):
class CVoidType(CType):
+ #
+ # C "void" type
+ #
+
is_void = 1
def __repr__(self):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
- base = public_decl("void", dll_linkage)
- return self.base_declaration_code(base, entity_code)
+ 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
sign_words = ("unsigned ", "", "signed ")
- def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
+ def __init__(self, rank, signed = 1):
self.rank = rank
self.signed = signed
- self.pymemberdef_typecode = pymemberdef_typecode
def sign_and_name(self):
s = self.sign_words[self.signed]
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
- base = public_decl(self.sign_and_name(), dll_linkage)
- if for_display:
- base = base.replace('PY_LONG_LONG', 'long long')
- return self.base_declaration_code(base, entity_code)
+ type_name = self.sign_and_name()
+ if pyrex or for_display:
+ base_code = type_name.replace('PY_LONG_LONG', 'long long')
+ else:
+ base_code = public_decl(type_name, dll_linkage)
+ return self.base_declaration_code(base_code, entity_code)
type_conversion_predeclarations = ""
""",
impl="""
static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
- const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
- const int is_unsigned = neg_one > const_zero;
+ const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+ const int is_unsigned = const_zero < neg_one;
if (sizeof(%(type)s) == sizeof(char)) {
if (is_unsigned)
return (%(type)s)__Pyx_PyInt_AsUnsignedChar(x);
return (%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x);
else
return (%(type)s)__Pyx_PyInt_AsSignedLongLong(x);
-#if 0
- } else if (sizeof(%(type)s) > sizeof(short) &&
- sizeof(%(type)s) < sizeof(int)) { /* __int32 ILP64 ? */
- if (is_unsigned)
- return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
- else
- return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
-#endif
+ } else {
+ %(type)s val;
+ PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_VERSION_HEX < 0x03000000
+ if (likely(v) && !PyLong_Check(v)) {
+ PyObject *tmp = v;
+ v = PyNumber_Long(tmp);
+ Py_DECREF(tmp);
+ }
+ #endif
+ if (likely(v)) {
+ int one = 1; int is_little = (int)*(unsigned char *)&one;
+ unsigned char *bytes = (unsigned char *)&val;
+ int ret = _PyLong_AsByteArray((PyLongObject *)v,
+ bytes, sizeof(val),
+ is_little, !is_unsigned);
+ Py_DECREF(v);
+ if (likely(!ret))
+ return val;
+ }
+ return (%(type)s)-1;
}
- PyErr_SetString(PyExc_TypeError, "%(TypeName)s");
- return (%(type)s)-1;
}
""")
""",
impl="""
static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
- const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
- const int is_unsigned = neg_one > const_zero;
- if (sizeof(%(type)s) < sizeof(long)) {
+ const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+ const int is_unsigned = const_zero < neg_one;
+ if ((sizeof(%(type)s) == sizeof(char)) ||
+ (sizeof(%(type)s) == sizeof(short))) {
return PyInt_FromLong((long)val);
- } else if (sizeof(%(type)s) == sizeof(long)) {
+ } else if ((sizeof(%(type)s) == sizeof(int)) ||
+ (sizeof(%(type)s) == sizeof(long))) {
if (is_unsigned)
return PyLong_FromUnsignedLong((unsigned long)val);
else
return PyInt_FromLong((long)val);
- } else { /* (sizeof(%(type)s) > sizeof(long)) */
+ } else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
if (is_unsigned)
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
else
return PyLong_FromLongLong((PY_LONG_LONG)val);
+ } else {
+ int one = 1; int little = (int)*(unsigned char *)&one;
+ unsigned char *bytes = (unsigned char *)&val;
+ return _PyLong_FromByteArray(bytes, sizeof(%(type)s),
+ little, !is_unsigned);
}
}
""")
is_int = 1
typedef_flag = 0
- to_py_function = "PyInt_FromLong"
- from_py_function = "__Pyx_PyInt_AsInt"
+ to_py_function = None
+ from_py_function = None
exception_value = -1
- def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
- CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
- self.is_returncode = is_returncode
- if self.from_py_function == "__Pyx_PyInt_AsInt":
- self.from_py_function = self.get_type_conversion()
-
- def get_type_conversion(self):
- ctype = self.declaration_code('')
- bits = ctype.split(" ", 1)
- if len(bits) == 1:
- sign_word, type_name = "", bits[0]
+ def __init__(self, rank, signed = 1):
+ CNumericType.__init__(self, rank, signed)
+ if self.to_py_function is None:
+ self.to_py_function = self.get_to_py_type_conversion()
+ if self.from_py_function is None:
+ self.from_py_function = self.get_from_py_type_conversion()
+
+ def get_to_py_type_conversion(self):
+ if self.rank < list(rank_to_type_name).index('int'):
+ # This assumes sizeof(short) < sizeof(int)
+ return "PyInt_FromLong"
else:
- sign_word, type_name = bits
- type_name = type_name.replace("PY_LONG_LONG","long long")
- SignWord = sign_word.title()
- TypeName = type_name.title().replace(" ", "")
- if "Long" in TypeName:
+ # Py{Int|Long}_From[Unsigned]Long[Long]
+ Prefix = "Int"
+ SignWord = ""
+ TypeName = "Long"
+ if not self.signed:
+ Prefix = "Long"
+ SignWord = "Unsigned"
+ if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
+ Prefix = "Long"
+ TypeName = "LongLong"
+ return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)
+
+ def get_from_py_type_conversion(self):
+ type_name = rank_to_type_name[self.rank]
+ type_name = type_name.replace("PY_LONG_LONG", "long long")
+ TypeName = type_name.title().replace(" ", "")
+ SignWord = self.sign_words[self.signed].strip().title()
+ if self.rank >= list(rank_to_type_name).index('long'):
utility_code = c_long_from_py_function
else:
utility_code = c_int_from_py_function
return src_type.is_int or src_type.is_enum or src_type is error_type
-class CBIntType(CIntType):
-
- to_py_function = "__Pyx_PyBool_FromLong"
- from_py_function = "__Pyx_PyObject_IsTrue"
- exception_check = 0
-
- def __repr__(self):
- return "<CNumericType bint>"
-
-
class CAnonEnumType(CIntType):
is_enum = 1
return 'int'
-class CUIntType(CIntType):
-
- to_py_function = "PyLong_FromUnsignedLong"
- exception_value = -1
-
+class CReturnCodeType(CIntType):
-class CLongType(CIntType):
+ is_returncode = 1
- to_py_function = "PyInt_FromLong"
+class CBIntType(CIntType):
-class CULongType(CUIntType):
-
- to_py_function = "PyLong_FromUnsignedLong"
+ to_py_function = "__Pyx_PyBool_FromLong"
+ from_py_function = "__Pyx_PyObject_IsTrue"
+ exception_check = 0
+ def __repr__(self):
+ return "<CNumericType bint>"
-class CLongLongType(CIntType):
- to_py_function = "PyLong_FromLongLong"
+class CPyUnicodeIntType(CIntType):
+ # Py_UNICODE
+ # Conversion from a unicode string to Py_UNICODE at runtime is not
+ # currently supported and may never be - we only convert from and
+ # to integers here. The maximum value for a Py_UNICODE is
+ # 1114111, so PyInt_FromLong() will do just fine here.
-class CULongLongType(CUIntType):
+ to_py_function = "PyInt_FromLong"
+ from_py_function = "__Pyx_PyInt_AsPy_UNICODE"
- to_py_function = "PyLong_FromUnsignedLongLong"
+ def sign_and_name(self):
+ return "Py_UNICODE"
class CPySSizeTType(CIntType):
from_py_function = "__Pyx_PyIndex_AsSsize_t"
def sign_and_name(self):
- return rank_to_type_name[self.rank]
+ return "Py_ssize_t"
+class CSSizeTType(CIntType):
-class CSizeTType(CUIntType):
+ to_py_function = "PyInt_FromSsize_t"
+ from_py_function = "PyInt_AsSsize_t"
+
+ def sign_and_name(self):
+ return "ssize_t"
+
+class CSizeTType(CIntType):
to_py_function = "__Pyx_PyInt_FromSize_t"
from_py_function = "__Pyx_PyInt_AsSize_t"
def sign_and_name(self):
- return rank_to_type_name[self.rank]
+ return "size_t"
class CFloatType(CNumericType):
exception_value = -1
- def __init__(self, rank, pymemberdef_typecode = None, math_h_modifier = ''):
- CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
+ 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):
if real_type.is_typedef and real_type.typedef_is_external:
# The below is not actually used: Coercions are currently disabled
# so that complex types of external types can not be created
- self.funcsuffix = "_%s" % real_type.specalization_name()
+ self.funcsuffix = "_%s" % real_type.specialization_name()
elif hasattr(real_type, 'math_h_modifier'):
self.funcsuffix = real_type.math_h_modifier
else:
- self.funcsuffix = "_%s" % real_type.specalization_name()
+ 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 = {}
- self.from_parts = "%s_from_parts" % self.specalization_name()
+ self.from_parts = "%s_from_parts" % self.specialization_name()
self.default_value = "%s(0, 0)" % self.from_parts
def __eq__(self, other):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
- if for_display:
- base = public_decl(self.real_type.sign_and_name() + " complex", dll_linkage)
+ if pyrex or for_display:
+ real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
+ base_code = "%s complex" % real_code
else:
- base = public_decl(self.sign_and_name(), dll_linkage)
- return self.base_declaration_code(base, entity_code)
+ base_code = public_decl(self.sign_and_name(), dll_linkage)
+ return self.base_declaration_code(base_code, entity_code)
def sign_and_name(self):
- real_type_name = self.real_type.specalization_name()
+ real_type_name = self.real_type.specialization_name()
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):
env.use_utility_code(complex_real_imag_utility_code)
for utility_code in (complex_type_utility_code,
complex_from_parts_utility_code,
- complex_arithmatic_utility_code):
+ complex_arithmetic_utility_code):
env.use_utility_code(
utility_code.specialize(
self,
self,
real_type = self.real_type.declaration_code(''),
m = self.funcsuffix))
- self.from_py_function = "__Pyx_PyComplex_As_" + self.specalization_name()
+ self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
return True
def lookup_op(self, nargs, op):
}
""")
-complex_arithmatic_utility_code = UtilityCode(
+complex_arithmetic_utility_code = UtilityCode(
proto="""
#if CYTHON_CCOMPLEX
#define __Pyx_c_eq%(m)s(a, b) ((a)==(b))
is_null_ptr = 1
-class CReferenceType(CType):
+class CReferenceType(BaseType):
is_reference = 1
def __init__(self, base_type):
- self.base_type = base_type
+ self.ref_base_type = base_type
def __repr__(self):
- return "<CReferenceType %s>" % repr(self.base_type)
-
- def same_as_resolved_type(self, other_type):
- return other_type.is_reference and self.base_type.same_as(other_type.base_type)
+ 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,
for_display = 0, dll_linkage = None, pyrex = 0):
#print "CReferenceType.declaration_code: pointer to", self.base_type ###
- return self.base_type.declaration_code(
+ return self.ref_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
- elif other_type.is_reference and self.base_type == other_type.base_type:
- return 1
- elif other_type == self.base_type:
- return 1
- else: #for now
- return 0
-
def specialize(self, values):
- base_type = self.base_type.specialize(values)
- if base_type == self.base_type:
+ base_type = self.ref_base_type.specialize(values)
+ if base_type == self.ref_base_type:
return self
else:
return CReferenceType(base_type)
+ def __getattr__(self, name):
+ return getattr(self.ref_base_type, name)
+
+
class CFuncType(CType):
# return_type CType
# args [CFuncTypeArg]
# cname string
# type PyrexType
# pos source file position
-
+
+ # FIXME: is this the right setup? should None be allowed here?
+ not_none = False
+ or_none = False
+ accept_none = True
+
def __init__(self, name, type, pos, cname=None):
self.name = name
if cname is not None:
self.cname = Naming.var_prefix + name
self.type = type
self.pos = pos
- self.not_none = False
self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
def __repr__(self):
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
- if pyrex:
- return self.base_declaration_code(self.name, entity_code)
+ if pyrex or for_display:
+ base_code = self.name
else:
- if for_display:
- base = self.name
- elif self.typedef_flag:
- base = self.cname
+ if self.typedef_flag:
+ base_code = self.cname
else:
- base = "%s %s" % (self.kind, self.cname)
- return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
+ base_code = "%s %s" % (self.kind, self.cname)
+ base_code = public_decl(base_code, dll_linkage)
+ return self.base_declaration_code(base_code, entity_code)
def __eq__(self, other):
try:
specialized.namespace = self.namespace.specialize(values)
return specialized
- def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+ def declaration_code(self, entity_code,
+ for_display = 0, dll_linkage = None, pyrex = 0):
if self.templates:
- template_strings = [param.declaration_code('', for_display, pyrex) for param in self.templates]
- templates = "<" + ",".join(template_strings) + ">"
+ template_strings = [param.declaration_code('', for_display, None, pyrex)
+ for param in self.templates]
+ templates = "<%s>" % ",".join(template_strings)
+ if templates[-2:] == ">>":
+ templates = templates[:-2] + "> >"
else:
templates = ""
- if for_display or pyrex:
- name = self.name
+ if pyrex or for_display:
+ base_code = "%s%s" % (self.name, templates)
else:
+ base_code = "%s%s" % (self.cname, templates)
if self.namespace is not None:
- name = "%s::%s" % (self.namespace.declaration_code(''), self.cname)
- else:
- name = self.cname
- return "%s%s %s" % (name, templates, entity_code)
+ base_code = "%s::%s" % (self.namespace.declaration_code(''), base_code)
+ base_code = public_decl(base_code, dll_linkage)
+ return self.base_declaration_code(base_code, entity_code)
def is_subclass(self, other_type):
# TODO(danilo): Handle templates.
def __init__(self, name):
self.name = name
- def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+ def declaration_code(self, entity_code,
+ for_display = 0, dll_linkage = None, pyrex = 0):
if entity_code:
return self.name + " " + entity_code
else:
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
- if pyrex:
- return self.base_declaration_code(self.cname, entity_code)
+ if pyrex or for_display:
+ base_code = self.name
else:
if self.typedef_flag:
- base = self.cname
+ base_code = self.cname
else:
- base = "enum %s" % self.cname
- return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
+ base_code = "enum %s" % self.cname
+ base_code = public_decl(base_code, dll_linkage)
+ return self.base_declaration_code(base_code, entity_code)
class CStringType(object):
is_string = 1
is_unicode = 0
- to_py_function = "__Pyx_PyBytes_FromString"
- from_py_function = "__Pyx_PyBytes_AsString"
+ to_py_function = "PyBytes_FromString"
+ from_py_function = "PyBytes_AsString"
exception_value = "NULL"
def literal_code(self, value):
class CUTF8CharArrayType(CStringType, CArrayType):
# C 'char []' type.
- pymemberdef_typecode = "T_STRING_INPLACE"
is_unicode = 1
to_py_function = "PyUnicode_DecodeUTF8"
class CCharArrayType(CStringType, CArrayType):
# C 'char []' type.
- pymemberdef_typecode = "T_STRING_INPLACE"
-
def __init__(self, size):
CArrayType.__init__(self, c_char_type, size)
class CCharPtrType(CStringType, CPtrType):
# C 'char *' type.
- pymemberdef_typecode = "T_STRING"
-
def __init__(self):
CPtrType.__init__(self, c_char_type)
class CUCharPtrType(CStringType, CPtrType):
# C 'unsigned char *' type.
- pymemberdef_typecode = "T_STRING"
-
to_py_function = "__Pyx_PyBytes_FromUString"
from_py_function = "__Pyx_PyBytes_AsUString"
"short", # 1
"int", # 2
"long", # 3
- "Py_ssize_t", # 4
- "size_t", # 5
- "PY_LONG_LONG", # 6
- "float", # 7
- "double", # 8
- "long double", # 9
+ "PY_LONG_LONG", # 4
+ "float", # 5
+ "double", # 6
+ "long double", # 7
)
-py_object_type = PyObjectType()
-
-c_void_type = CVoidType()
-c_void_ptr_type = CPtrType(c_void_type)
-c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
-
-c_uchar_type = CIntType(0, 0, "T_UBYTE")
-c_ushort_type = CIntType(1, 0, "T_USHORT")
-c_uint_type = CUIntType(2, 0, "T_UINT")
-c_ulong_type = CULongType(3, 0, "T_ULONG")
-c_ulonglong_type = CULongLongType(6, 0, "T_ULONGLONG")
-
-c_char_type = CIntType(0, 1, "T_CHAR")
-c_short_type = CIntType(1, 1, "T_SHORT")
-c_int_type = CIntType(2, 1, "T_INT")
-c_long_type = CLongType(3, 1, "T_LONG")
-c_longlong_type = CLongLongType(6, 1, "T_LONGLONG")
-c_bint_type = CBIntType(2, 1, "T_INT")
-
-c_schar_type = CIntType(0, 2, "T_CHAR")
-c_sshort_type = CIntType(1, 2, "T_SHORT")
-c_sint_type = CIntType(2, 2, "T_INT")
-c_slong_type = CLongType(3, 2, "T_LONG")
-c_slonglong_type = CLongLongType(6, 2, "T_LONGLONG")
+RANK_INT = list(rank_to_type_name).index('int')
+RANK_LONG = list(rank_to_type_name).index('long')
+UNSIGNED = 0
+SIGNED = 2
-c_py_ssize_t_type = CPySSizeTType(4, 2, "T_PYSSIZET")
-c_size_t_type = CSizeTType(5, 0, "T_SIZET")
-c_float_type = CFloatType(7, "T_FLOAT", math_h_modifier='f')
-c_double_type = CFloatType(8, "T_DOUBLE")
-c_longdouble_type = CFloatType(9, math_h_modifier='l')
+py_object_type = PyObjectType()
-c_double_complex_type = CComplexType(c_double_type)
+c_void_type = CVoidType()
+
+c_uchar_type = CIntType(0, UNSIGNED)
+c_ushort_type = CIntType(1, UNSIGNED)
+c_uint_type = CIntType(2, UNSIGNED)
+c_ulong_type = CIntType(3, UNSIGNED)
+c_ulonglong_type = CIntType(4, UNSIGNED)
+
+c_char_type = CIntType(0)
+c_short_type = CIntType(1)
+c_int_type = CIntType(2)
+c_long_type = CIntType(3)
+c_longlong_type = CIntType(4)
+
+c_schar_type = CIntType(0, SIGNED)
+c_sshort_type = CIntType(1, SIGNED)
+c_sint_type = CIntType(2, SIGNED)
+c_slong_type = CIntType(3, SIGNED)
+c_slonglong_type = CIntType(4, SIGNED)
+
+c_float_type = CFloatType(5, math_h_modifier='f')
+c_double_type = CFloatType(6)
+c_longdouble_type = CFloatType(7, math_h_modifier='l')
+
+c_float_complex_type = CComplexType(c_float_type)
+c_double_complex_type = CComplexType(c_double_type)
+c_longdouble_complex_type = CComplexType(c_longdouble_type)
+
+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_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)
c_null_ptr_type = CNullPtrType(c_void_type)
+c_void_ptr_type = CPtrType(c_void_type)
+c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_char_array_type = CCharArrayType(None)
c_char_ptr_type = CCharPtrType()
c_uchar_ptr_type = CUCharPtrType()
c_utf8_char_array_type = CUTF8CharArrayType(None)
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
c_int_ptr_type = CPtrType(c_int_type)
+c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
+c_ssize_t_ptr_type = CPtrType(c_ssize_t_type)
c_size_t_ptr_type = CPtrType(c_size_t_type)
-c_returncode_type = CIntType(2, 1, "T_INT", is_returncode = 1)
-
-c_anon_enum_type = CAnonEnumType(-1, 1)
# the Py_buffer type is defined in Builtin.py
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
error_type = ErrorType()
unspecified_type = UnspecifiedType()
-sign_and_rank_to_type = {
- #(signed, rank)
- (0, 0): c_uchar_type,
- (0, 1): c_ushort_type,
- (0, 2): c_uint_type,
- (0, 3): c_ulong_type,
- (0, 6): c_ulonglong_type,
-
- (1, 0): c_char_type,
- (1, 1): c_short_type,
- (1, 2): c_int_type,
- (1, 3): c_long_type,
- (1, 6): c_longlong_type,
-
- (2, 0): c_schar_type,
- (2, 1): c_sshort_type,
- (2, 2): c_sint_type,
- (2, 3): c_slong_type,
- (2, 6): c_slonglong_type,
-
- (0, 4): c_py_ssize_t_type,
- (1, 4): c_py_ssize_t_type,
- (2, 4): c_py_ssize_t_type,
- (0, 5): c_size_t_type,
- (1, 5): c_size_t_type,
- (2, 5): c_size_t_type,
-
- (1, 7): c_float_type,
- (1, 8): c_double_type,
- (1, 9): c_longdouble_type,
-# In case we're mixing unsigned ints and floats...
- (0, 7): c_float_type,
- (0, 8): c_double_type,
- (0, 9): c_longdouble_type,
-}
-
modifiers_and_name_to_type = {
- #(signed, longness, name)
- (0, 0, "char"): c_uchar_type,
+ #(signed, longness, name) : type
+ (0, 0, "char"): c_uchar_type,
+ (1, 0, "char"): c_char_type,
+ (2, 0, "char"): c_schar_type,
+
(0, -1, "int"): c_ushort_type,
- (0, 0, "int"): c_uint_type,
- (0, 1, "int"): c_ulong_type,
- (0, 2, "int"): c_ulonglong_type,
- (1, 0, "void"): c_void_type,
- (1, 0, "char"): c_char_type,
+ (0, 0, "int"): c_uint_type,
+ (0, 1, "int"): c_ulong_type,
+ (0, 2, "int"): c_ulonglong_type,
+
(1, -1, "int"): c_short_type,
- (1, 0, "int"): c_int_type,
- (1, 1, "int"): c_long_type,
- (1, 2, "int"): c_longlong_type,
- (1, 0, "float"): c_float_type,
- (1, 0, "double"): c_double_type,
- (1, 1, "double"): c_longdouble_type,
- (1, 0, "object"): py_object_type,
- (1, 0, "bint"): c_bint_type,
- (2, 0, "char"): c_schar_type,
+ (1, 0, "int"): c_int_type,
+ (1, 1, "int"): c_long_type,
+ (1, 2, "int"): c_longlong_type,
+
(2, -1, "int"): c_sshort_type,
- (2, 0, "int"): c_sint_type,
- (2, 1, "int"): c_slong_type,
- (2, 2, "int"): c_slonglong_type,
+ (2, 0, "int"): c_sint_type,
+ (2, 1, "int"): c_slong_type,
+ (2, 2, "int"): c_slonglong_type,
- (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
- (0, 0, "size_t") : c_size_t_type,
+ (1, 0, "float"): c_float_type,
+ (1, 0, "double"): c_double_type,
+ (1, 1, "double"): c_longdouble_type,
- (1, 0, "long"): c_long_type,
- (1, 0, "short"): c_short_type,
- (1, 0, "longlong"): c_longlong_type,
- (1, 0, "bint"): c_bint_type,
-}
+ (1, 0, "complex"): c_float_complex_type,
+ (1, 0, "floatcomplex"): c_float_complex_type,
+ (1, 0, "doublecomplex"): c_double_complex_type,
+ (1, 1, "doublecomplex"): c_longdouble_complex_type,
-def is_promotion0(src_type, dst_type):
- if src_type.is_numeric and dst_type.is_numeric:
- if src_type.is_int and dst_type.is_int:
- if src_type.is_enum:
- return True
- elif src_type.signed:
- return dst_type.signed and src_type.rank <= dst_type.rank
- elif dst_type.signed: # and not src_type.signed
- src_type.rank < dst_type.rank
- else:
- return src_type.rank <= dst_type.rank
- elif src_type.is_float and dst_type.is_float:
- return src_type.rank <= dst_type.rank
- else:
- return False
- else:
- return False
+ #
+ (1, 0, "void"): c_void_type,
+
+ (1, 0, "bint"): c_bint_type,
+ (0, 0, "Py_UNICODE"): c_py_unicode_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,
+
+ (1, 0, "object"): py_object_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.
if src_type.is_numeric:
if dst_type.same_as(c_int_type):
- return src_type.is_enum or (src_type.is_int and (not src_type.signed) + src_type.rank < dst_type.rank)
+ unsigned = (not src_type.signed)
+ return (src_type.is_enum or
+ (src_type.is_int and
+ unsigned + src_type.rank < dst_type.rank))
elif dst_type.same_as(c_double_type):
return src_type.is_float and src_type.rank <= dst_type.rank
return False
if len(candidates) == 1:
return candidates[0][0]
elif len(candidates) == 0:
- if len(errors) == 1 and pos is not None:
- error(pos, errors[0][1])
+ if pos is not None:
+ if len(errors) == 1:
+ error(pos, errors[0][1])
+ else:
+ error(pos, "no suitable method found")
return None
possibilities = []
src_type = args[i].type
dst_type = func_type.args[i].type
if dst_type.assignable_from(src_type):
- if src_type == dst_type or (dst_type.is_reference and \
- src_type == dst_type.base_type) \
- or dst_type.same_as(src_type):
+ if src_type == dst_type or dst_type.same_as(src_type):
pass # score 0
elif is_promotion(src_type, dst_type):
score[2] += 1
error(pos, "no suitable method found")
return None
-
def widest_numeric_type(type1, type2):
# Given two numeric types, return the narrowest type
# encompassing both of them.
if type1 == type2:
- return type1
- if type1.is_complex:
- if type2.is_complex:
- return CComplexType(widest_numeric_type(type1.real_type, type2.real_type))
- else:
- return CComplexType(widest_numeric_type(type1.real_type, type2))
- elif type2.is_complex:
- return CComplexType(widest_numeric_type(type1, type2.real_type))
- if type1.is_enum and type2.is_enum:
- return c_int_type
- elif type1 is type2:
- return type1
- elif (type1.signed and type2.signed) or (not type1.signed and not type2.signed):
- if type2.rank > type1.rank:
- return type2
- else:
- return type1
+ widest_type = type1
+ elif type1.is_complex or type2.is_complex:
+ def real_type(ntype):
+ if ntype.is_complex:
+ return ntype.real_type
+ return ntype
+ widest_type = CComplexType(
+ widest_numeric_type(
+ real_type(type1),
+ real_type(type2)))
+ elif type1.is_enum and type2.is_enum:
+ widest_type = c_int_type
+ elif type1.rank < type2.rank:
+ widest_type = type2
+ elif type1.rank > type2.rank:
+ widest_type = type1
+ elif type1.signed < type2.signed:
+ widest_type = type1
else:
- return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
+ widest_type = type2
+ return widest_type
def spanning_type(type1, type2):
# Return a type assignable from both type1 and type2.
base = parse_basic_type(name[:-1])
if base:
return CPtrType(base)
- elif name.startswith('u'):
- return simple_c_type(0, 0, name[1:])
+ #
+ basic_type = simple_c_type(1, 0, name)
+ if basic_type:
+ return basic_type
+ #
+ signed = 1
+ longness = 0
+ if name == 'Py_UNICODE':
+ signed = 0
+ elif name == 'Py_ssize_t':
+ signed = 2
+ elif name == 'ssize_t':
+ signed = 2
+ elif name == 'size_t':
+ signed = 0
else:
- return simple_c_type(1, 0, name)
+ if name.startswith('u'):
+ name = name[1:]
+ signed = 0
+ elif (name.startswith('s') and
+ not name.startswith('short')):
+ name = name[1:]
+ signed = 2
+ longness = 0
+ while name.startswith('short'):
+ name = name.replace('short', '', 1).strip()
+ longness -= 1
+ while name.startswith('long'):
+ name = name.replace('long', '', 1).strip()
+ longness += 1
+ if longness != 0 and not name:
+ name = 'int'
+ return simple_c_type(signed, longness, name)
def c_array_type(base_type, size):
# Construct a C array type.
return error_type
else:
return CReferenceType(base_type)
-
-def Node_to_type(node, env):
- from ExprNodes import NameNode, AttributeNode, StringNode, error
- if isinstance(node, StringNode):
- node = NameNode(node.pos, name=node.value)
- if isinstance(node, NameNode) and node.name in rank_to_type_name:
- return simple_c_type(1, 0, node.name)
- elif isinstance(node, (AttributeNode, NameNode)):
- node.analyze_types(env)
- if not node.entry.is_type:
- pass
- else:
- error(node.pos, "Bad type")
def same_type(type1, type2):
return type1.same_as(type2)
type_conversion_predeclarations = """
/* Type Conversion Predeclarations */
-#if PY_MAJOR_VERSION < 3
-#define __Pyx_PyBytes_FromString PyString_FromString
-#define __Pyx_PyBytes_FromStringAndSize PyString_FromStringAndSize
-#define __Pyx_PyBytes_AsString PyString_AsString
-#else
-#define __Pyx_PyBytes_FromString PyBytes_FromString
-#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
-#define __Pyx_PyBytes_AsString PyBytes_AsString
-#endif
-
-#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s)
-#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s))
+#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
+#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s))
#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);
-#if !defined(T_PYSSIZET)
-#if PY_VERSION_HEX < 0x02050000
-#define T_PYSSIZET T_INT
-#elif !defined(T_LONGLONG)
-#define T_PYSSIZET \\
- ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \\
- ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1))
-#else
-#define T_PYSSIZET \\
- ((sizeof(Py_ssize_t) == sizeof(int)) ? T_INT : \\
- ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : \\
- ((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))
-#endif
-#endif
-
-
-#if !defined(T_ULONGLONG)
-#define __Pyx_T_UNSIGNED_INT(x) \\
- ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
- ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
- ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
- ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1))))
-#else
-#define __Pyx_T_UNSIGNED_INT(x) \\
- ((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
- ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
- ((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
- ((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \\
- ((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))))
-#endif
-#if !defined(T_LONGLONG)
-#define __Pyx_T_SIGNED_INT(x) \\
- ((sizeof(x) == sizeof(char)) ? T_BYTE : \\
- ((sizeof(x) == sizeof(short)) ? T_SHORT : \\
- ((sizeof(x) == sizeof(int)) ? T_INT : \\
- ((sizeof(x) == sizeof(long)) ? T_LONG : -1))))
-#else
-#define __Pyx_T_SIGNED_INT(x) \\
- ((sizeof(x) == sizeof(char)) ? T_BYTE : \\
- ((sizeof(x) == sizeof(short)) ? T_SHORT : \\
- ((sizeof(x) == sizeof(int)) ? T_INT : \\
- ((sizeof(x) == sizeof(long)) ? T_LONG : \\
- ((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))))
-#endif
-
-#define __Pyx_T_FLOATING(x) \\
- ((sizeof(x) == sizeof(float)) ? T_FLOAT : \\
- ((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1))
-
-#if !defined(T_SIZET)
-#if !defined(T_ULONGLONG)
-#define T_SIZET \\
- ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \\
- ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1))
-#else
-#define T_SIZET \\
- ((sizeof(size_t) == sizeof(unsigned int)) ? T_UINT : \\
- ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : \\
- ((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))
-#endif
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject*);
#endif
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
""" + type_conversion_predeclarations
+# Note: __Pyx_PyObject_IsTrue is written to minimize branching.
type_conversion_functions = """
/* Type Conversion Functions */
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
- if (x == Py_True) return 1;
- else if ((x == Py_False) | (x == Py_None)) return 0;
+ int is_true = x == Py_True;
+ if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
else return PyObject_IsTrue(x);
}
return res;
}
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject* x) {
+ long ival = __Pyx_PyInt_AsLong(x);
+ static long maxval = 0;
+ if (unlikely(!maxval))
+ maxval = (long)PyUnicode_GetMax();
+ if (unlikely(ival < 0)) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_OverflowError,
+ "can't convert negative value to Py_UNICODE");
+ return (Py_UNICODE)-1;
+ } else if (unlikely(ival > maxval)) {
+ PyErr_SetString(PyExc_OverflowError,
+ "value too large to convert to Py_UNICODE");
+ return (Py_UNICODE)-1;
+ }
+ return (Py_UNICODE)ival;
+}
+#endif
+
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
Py_ssize_t ival;
PyObject* x = PyNumber_Index(b);
""" + type_conversion_functions
-