PyrexTypes.py 48.7 KB
Newer Older
William Stein's avatar
William Stein committed
1 2 3 4
#
#   Pyrex - Types
#

Stefan Behnel's avatar
Stefan Behnel committed
5
from Cython.Utils import UtilityCode
6
import StringEncoding
William Stein's avatar
William Stein committed
7
import Naming
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
8
import copy
William Stein's avatar
William Stein committed
9

10
class BaseType(object):
11 12 13 14 15 16 17 18 19 20 21 22 23
    #
    #  Base class for all Pyrex types including pseudo-types.

    def cast_code(self, expr_code):
        return "((%s)%s)" % (self.declaration_code(""), expr_code)
    
    def base_declaration_code(self, base_code, entity_code):
        if entity_code:
            return "%s %s" % (base_code, entity_code)
        else:
            return base_code

class PyrexType(BaseType):
William Stein's avatar
William Stein committed
24 25 26 27 28 29 30
    #
    #  Base class for all Pyrex types.
    #
    #  is_pyobject           boolean     Is a Python object type
    #  is_extension_type     boolean     Is a Python extension type
    #  is_numeric            boolean     Is a C numeric type
    #  is_int                boolean     Is a C integer type
31
    #  is_longlong           boolean     Is a long long or unsigned long long.
William Stein's avatar
William Stein committed
32 33 34 35 36 37 38
    #  is_float              boolean     Is a C floating point type
    #  is_void               boolean     Is the C void type
    #  is_array              boolean     Is a C array type
    #  is_ptr                boolean     Is a C pointer type
    #  is_null_ptr           boolean     Is the type of NULL
    #  is_cfunction          boolean     Is a C function type
    #  is_struct_or_union    boolean     Is a C struct or union type
Robert Bradshaw's avatar
Robert Bradshaw committed
39
    #  is_struct             boolean     Is a C struct type
William Stein's avatar
William Stein committed
40
    #  is_enum               boolean     Is a C enum type
41
    #  is_typedef            boolean     Is a typedef type
William Stein's avatar
William Stein committed
42
    #  is_string             boolean     Is a C char * type
43
    #  is_unicode            boolean     Is a UTF-8 encoded C char * type
William Stein's avatar
William Stein committed
44 45
    #  is_returncode         boolean     Is used only to signal exceptions
    #  is_error              boolean     Is the dummy error type
46
    #  is_buffer             boolean     Is buffer access type
William Stein's avatar
William Stein committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    #  has_attributes        boolean     Has C dot-selectable attributes
    #  default_value         string      Initial value
    #  parsetuple_format     string      Format char for PyArg_ParseTuple
    #  pymemberdef_typecode  string      Type code for PyMemberDef struct
    #
    #  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.
    #    * If for_display, this is for reading by a human in an error
    #      message; otherwise it must be valid C code.
    #    * If dll_linkage is not None, it must be 'DL_EXPORT' or
    #      'DL_IMPORT', and will be added to the base type part of
    #      the declaration.
    #    * If pyrex = 1, this is for use in a 'cdef extern'
    #      statement of a Pyrex include file.
    #
    #  assignable_from(src_type)
    #    Tests whether a variable of this type can be
    #    assigned a value of type src_type.
    #
    #  same_as(other_type)
    #    Tests whether this type represents the same type
    #    as other_type.
    #
    #  as_argument_type():
    #    Coerces array type into pointer type for use as
    #    a formal argument type.
    #
        
    is_pyobject = 0
    is_extension_type = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
79
    is_builtin_type = 0
William Stein's avatar
William Stein committed
80 81
    is_numeric = 0
    is_int = 0
82
    is_longlong = 0
William Stein's avatar
William Stein committed
83 84 85 86 87 88 89
    is_float = 0
    is_void = 0
    is_array = 0
    is_ptr = 0
    is_null_ptr = 0
    is_cfunction = 0
    is_struct_or_union = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
90
    is_struct = 0
William Stein's avatar
William Stein committed
91
    is_enum = 0
92
    is_typedef = 0
William Stein's avatar
William Stein committed
93
    is_string = 0
94
    is_unicode = 0
William Stein's avatar
William Stein committed
95 96
    is_returncode = 0
    is_error = 0
97
    is_buffer = 0
William Stein's avatar
William Stein committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    has_attributes = 0
    default_value = ""
    parsetuple_format = ""
    pymemberdef_typecode = None
    
    def resolve(self):
        # If a typedef, returns the base type.
        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):
113
        return self.declaration_code("", for_display = 1).strip()
William Stein's avatar
William Stein committed
114 115 116 117 118
    
    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):
119
        return self == other_type or other_type is error_type
William Stein's avatar
William Stein committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    
    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.
        return 1

141 142 143 144
    def is_simple_buffer_dtype(self):
        return (self.is_int or self.is_float or self.is_pyobject or
                self.is_extension_type or self.is_ptr)

145
class CTypedefType(BaseType):
William Stein's avatar
William Stein committed
146
    #
147
    #  Pseudo-type defined with a ctypedef statement in a
William Stein's avatar
William Stein committed
148
    #  'cdef extern from' block. Delegates most attribute
149 150
    #  lookups to the base type. ANYTHING NOT DEFINED
    #  HERE IS DELEGATED!
William Stein's avatar
William Stein committed
151
    #
152 153 154 155 156
    #  qualified_name      string
    #  typedef_cname       string
    #  typedef_base_type   PyrexType
    
    is_typedef = 1
William Stein's avatar
William Stein committed
157 158 159 160 161 162 163 164 165 166
    
    def __init__(self, cname, base_type):
        self.typedef_cname = cname
        self.typedef_base_type = base_type
    
    def resolve(self):
        return self.typedef_base_type.resolve()
    
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
167 168 169 170 171 172 173 174 175 176 177 178
        name = self.declaration_name(for_display, pyrex)
        return self.base_declaration_code(name, entity_code)
    
    def declaration_name(self, for_display = 0, pyrex = 0):
        if pyrex or for_display:
            return self.qualified_name
        else:
            return self.typedef_cname
    
    def as_argument_type(self):
        return self

179 180 181 182 183 184 185 186
    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)
        else:
            return BaseType.cast_code(self, expr_code)
    
187 188
    def __repr__(self):
        return "<CTypedefType %s>" % self.typedef_cname
William Stein's avatar
William Stein committed
189 190
    
    def __str__(self):
191
        return self.declaration_name(for_display = 1)
William Stein's avatar
William Stein committed
192 193 194 195
    
    def __getattr__(self, name):
        return getattr(self.typedef_base_type, name)

196 197 198 199 200 201
class BufferType(BaseType):
    #
    #  Delegates most attribute
    #  lookups to the base type. ANYTHING NOT DEFINED
    #  HERE IS DELEGATED!
    
202 203 204 205 206 207 208
    # dtype            PyrexType
    # ndim             int
    # mode             str
    # negative_indices bool
    # cast             bool
    # is_buffer        bool
    # writable         bool
209 210

    is_buffer = 1
211
    writable = True
212
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
213 214 215
        self.base = base
        self.dtype = dtype
        self.ndim = ndim
216
        self.buffer_ptr_type = CPtrType(dtype)
217
        self.mode = mode
218
        self.negative_indices = negative_indices
219
        self.cast = cast
220
    
221 222 223
    def as_argument_type(self):
        return self

224 225 226
    def __getattr__(self, name):
        return getattr(self.base, name)

227 228 229
    def __repr__(self):
        return "<BufferType %r>" % self.base

230
    
William Stein's avatar
William Stein committed
231 232 233 234
class PyObjectType(PyrexType):
    #
    #  Base class for all Python object types (reference-counted).
    #
235
    #  buffer_defaults  dict or None     Default options for bu
William Stein's avatar
William Stein committed
236 237 238 239 240
    
    is_pyobject = 1
    default_value = "0"
    parsetuple_format = "O"
    pymemberdef_typecode = "T_OBJECT"
241
    buffer_defaults = None
William Stein's avatar
William Stein committed
242 243 244 245 246
    
    def __str__(self):
        return "Python object"
    
    def __repr__(self):
247
        return "<PyObjectType>"
William Stein's avatar
William Stein committed
248 249 250 251 252 253
    
    def assignable_from(self, src_type):
        return 1 # Conversion will be attempted
        
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
254 255
        if pyrex or for_display:
            return self.base_declaration_code("object", entity_code)
William Stein's avatar
William Stein committed
256 257 258
        else:
            return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)

259 260 261 262 263
    def as_pyobject(self, cname):
        if (not self.is_complete()) or self.is_extension_type:
            return "(PyObject *)" + cname
        else:
            return cname
William Stein's avatar
William Stein committed
264

Robert Bradshaw's avatar
Robert Bradshaw committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
class BuiltinObjectType(PyObjectType):

    is_builtin_type = 1
    has_attributes = 1
    base_type = None
    module_name = '__builtin__'

    def __init__(self, name, cname):
        self.name = name
        self.cname = cname
        self.typeptr_cname = "&" + 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 assignable_from(self, src_type):
        if isinstance(src_type, BuiltinObjectType):
            return src_type.name == self.name
        else:
            return not src_type.is_extension_type
            
    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):
304 305 306 307 308 309 310
        type_name = self.name
        if type_name == 'str':
            type_name = 'String'
        elif type_name == 'set':
            type_name = 'AnySet'
        elif type_name == 'frozenset':
            type_name = 'FrozenSet'
311
        else:
312 313
            type_name = type_name.capitalize()
        return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", Py_TYPE(%s)->tp_name), 0)' % (type_name, arg, arg, self.name, arg)
Robert Bradshaw's avatar
Robert Bradshaw committed
314

315 316 317 318 319 320 321
    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)
        else:
            return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)

Robert Bradshaw's avatar
Robert Bradshaw committed
322

William Stein's avatar
William Stein committed
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
class PyExtensionType(PyObjectType):
    #
    #  A Python extension type.
    #
    #  name             string
    #  scope            CClassScope      Attribute namespace
    #  visibility       string
    #  typedef_flag     boolean
    #  base_type        PyExtensionType or None
    #  module_name      string or None   Qualified name of defining module
    #  objstruct_cname  string           Name of PyObject struct
    #  typeobj_cname    string or None   C code fragment referring to type object
    #  typeptr_cname    string or None   Name of pointer to external type object
    #  vtabslot_cname   string           Name of C method table member
    #  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
    
    def __init__(self, name, typedef_flag, base_type):
        self.name = name
        self.scope = None
        self.typedef_flag = typedef_flag
        self.base_type = base_type
        self.module_name = None
        self.objstruct_cname = None
        self.typeobj_cname = None
        self.typeptr_cname = None
        self.vtabslot_cname = None
        self.vtabstruct_cname = None
        self.vtabptr_cname = None
        self.vtable_cname = None
    
    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 declaration_code(self, entity_code, 
380
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
381 382
        if pyrex or for_display:
            return self.base_declaration_code(self.name, entity_code)
William Stein's avatar
William Stein committed
383 384 385 386 387 388
        else:
            if self.typedef_flag:
                base_format = "%s"
            else:
                base_format = "struct %s"
            base = public_decl(base_format % self.objstruct_cname, dll_linkage)
389 390 391 392
            if deref:
                return "%s %s" % (base,  entity_code)
            else:
                return "%s *%s" % (base,  entity_code)
William Stein's avatar
William Stein committed
393

Robert Bradshaw's avatar
Robert Bradshaw committed
394 395 396
    def type_test_code(self, py_arg):
        return "__Pyx_TypeTest(%s, %s)" % (py_arg, self.typeptr_cname)
    
William Stein's avatar
William Stein committed
397 398 399 400 401 402 403
    def attributes_known(self):
        return self.scope is not None
    
    def __str__(self):
        return self.name
    
    def __repr__(self):
404 405
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
406 407 408 409 410 411 412 413 414 415 416 417
    

class CType(PyrexType):
    #
    #  Base class for all C types (non-reference-counted).
    #
    #  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
418 419
    exception_value = None
    exception_check = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
420 421 422 423

    def create_convert_utility_code(self, env):
        return True
        
424 425 426 427 428 429 430 431 432 433 434 435
    def error_condition(self, result_code):
        conds = []
        if self.is_string:
            conds.append("(!%s)" % result_code)
        elif self.exception_value is not None:
            conds.append("(%s == (%s)%s)" % (result_code, self.sign_and_name(), self.exception_value))
        if self.exception_check:
            conds.append("PyErr_Occurred()")
        if len(conds) > 0:
            return " && ".join(conds)
        else:
            return 0
William Stein's avatar
William Stein committed
436 437


438
class CVoidType(CType):
William Stein's avatar
William Stein committed
439 440 441 442 443 444 445 446
    is_void = 1
    
    def __repr__(self):
        return "<CVoidType>"
    
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        base = public_decl("void", dll_linkage)
447
        return self.base_declaration_code(base, entity_code)
William Stein's avatar
William Stein committed
448 449 450 451 452 453 454 455 456 457
    
    def is_complete(self):
        return 0


class CNumericType(CType):
    #
    #   Base class for all C numeric types.
    #
    #   rank      integer     Relative size
458
    #   signed    integer     0 = unsigned, 1 = unspecified, 2 = explicitly signed
William Stein's avatar
William Stein committed
459 460 461 462 463 464
    #
    
    is_numeric = 1
    default_value = "0"
    
    parsetuple_formats = ( # rank -> format
465 466 467
        "BHIkK?????", # unsigned
        "bhilL??fd?", # assumed signed
        "bhilL??fd?", # explicitly signed
William Stein's avatar
William Stein committed
468 469
    )
    
470 471
    sign_words = ("unsigned ", "", "signed ")
    
472
    def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
William Stein's avatar
William Stein committed
473 474 475 476 477 478 479 480
        self.rank = rank
        self.signed = signed
        ptf = self.parsetuple_formats[signed][rank]
        if ptf == '?':
            ptf = None
        self.parsetuple_format = ptf
        self.pymemberdef_typecode = pymemberdef_typecode
    
481 482 483 484 485
    def sign_and_name(self):
        s = self.sign_words[self.signed]
        n = rank_to_type_name[self.rank]
        return s + n
    
William Stein's avatar
William Stein committed
486
    def __repr__(self):
487
        return "<CNumericType %s>" % self.sign_and_name()
William Stein's avatar
William Stein committed
488 489 490
    
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
491
        base = public_decl(self.sign_and_name(), dll_linkage)
492 493
        if for_display and self.is_longlong:
            base = base.replace('PY_LONG_LONG', 'long long')
494
        return self.base_declaration_code(base,  entity_code)
495 496 497 498 499


int_conversion_list = {}
type_conversion_functions = ""
type_conversion_predeclarations = ""
William Stein's avatar
William Stein committed
500 501 502 503 504 505

class CIntType(CNumericType):
    
    is_int = 1
    typedef_flag = 0
    to_py_function = "PyInt_FromLong"
506
    from_py_function = "__pyx_PyInt_AsLong"
507
    exception_value = -1
William Stein's avatar
William Stein committed
508

509 510
    def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
        CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
William Stein's avatar
William Stein committed
511
        self.is_returncode = is_returncode
512 513 514 515 516 517 518 519
        if self.from_py_function == '__pyx_PyInt_AsLong':
            self.from_py_function = self.get_type_conversion()

    def get_type_conversion(self):
        # error on overflow
        c_type = self.sign_and_name()
        c_name = c_type.replace(' ', '_');
        func_name = "__pyx_PyInt_%s" % c_name;
Stefan Behnel's avatar
Stefan Behnel committed
520
        if func_name not in int_conversion_list:
521 522 523 524
            # no env to add utility code to
            global type_conversion_predeclarations, type_conversion_functions
            if self.signed:
                neg_test = ""
525 526
            else:
                neg_test = " || (long_val < 0)"
527 528 529 530 531
            type_conversion_predeclarations += """
static INLINE %(c_type)s %(func_name)s(PyObject* x);""" % {'c_type': c_type, 'c_name': c_name, 'func_name': func_name }
            type_conversion_functions +=  """
static INLINE %(c_type)s %(func_name)s(PyObject* x) {
    if (sizeof(%(c_type)s) < sizeof(long)) {
532 533 534
        long long_val = __pyx_PyInt_AsLong(x);
        %(c_type)s val = (%(c_type)s)long_val;
        if (unlikely((val != long_val) %(neg_test)s)) {
535 536 537
            PyErr_SetString(PyExc_OverflowError, "value too large to convert to %(c_type)s");
            return (%(c_type)s)-1;
        }
538
        return val;
539 540 541 542 543
    }
    else {
        return __pyx_PyInt_AsLong(x);
    }
}
544
""" % {'c_type': c_type, 'c_name': c_name, 'func_name': func_name, 'neg_test': neg_test }
545 546
            int_conversion_list[func_name] = True
        return func_name
547 548 549
    
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_int or src_type.is_enum or src_type is error_type
550

William Stein's avatar
William Stein committed
551

552
class CBIntType(CIntType):
Robert Bradshaw's avatar
Robert Bradshaw committed
553

554 555
    to_py_function = "__Pyx_PyBool_FromLong"
    from_py_function = "__Pyx_PyObject_IsTrue"
556
    exception_check = 0
William Stein's avatar
William Stein committed
557

558

559 560
class CAnonEnumType(CIntType):

Robert Bradshaw's avatar
Robert Bradshaw committed
561
    is_enum = 1    
562

563

William Stein's avatar
William Stein committed
564 565 566 567
class CUIntType(CIntType):

    to_py_function = "PyLong_FromUnsignedLong"
    from_py_function = "PyInt_AsUnsignedLongMask"
568
    exception_value = -1
William Stein's avatar
William Stein committed
569 570


571
class CULongType(CUIntType):
William Stein's avatar
William Stein committed
572 573 574 575 576

    to_py_function = "PyLong_FromUnsignedLong"
    from_py_function = "PyInt_AsUnsignedLongMask"


577
class CLongLongType(CIntType):
William Stein's avatar
William Stein committed
578

579
    is_longlong = 1
William Stein's avatar
William Stein committed
580
    to_py_function = "PyLong_FromLongLong"
581
    from_py_function = "__pyx_PyInt_AsLongLong"
William Stein's avatar
William Stein committed
582 583


584
class CULongLongType(CUIntType):
William Stein's avatar
William Stein committed
585

586
    is_longlong = 1
William Stein's avatar
William Stein committed
587
    to_py_function = "PyLong_FromUnsignedLongLong"
588
    from_py_function = "__pyx_PyInt_AsUnsignedLongLong"
William Stein's avatar
William Stein committed
589 590


591 592 593
class CPySSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
594
    from_py_function = "__pyx_PyIndex_AsSsize_t"
595 596


597 598 599 600 601 602
class CSizeTType(CUIntType):

    to_py_function = "__pyx_PyInt_FromSize_t"
    from_py_function = "__pyx_PyInt_AsSize_t"


William Stein's avatar
William Stein committed
603 604 605 606
class CFloatType(CNumericType):

    is_float = 1
    to_py_function = "PyFloat_FromDouble"
607
    from_py_function = "__pyx_PyFloat_AsDouble"
William Stein's avatar
William Stein committed
608
    
609 610
    def __init__(self, rank, pymemberdef_typecode = None):
        CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
William Stein's avatar
William Stein committed
611
    
612 613 614
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_numeric or src_type is error_type

William Stein's avatar
William Stein committed
615 616 617 618 619 620 621 622 623 624 625 626 627 628

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:
            self.is_string = 1
    
    def __repr__(self):
629
        return "<CArrayType %s %s>" % (self.size, repr(self.base_type))
William Stein's avatar
William Stein committed
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
    
    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, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        if self.size is not None:
            dimension_code = self.size
        else:
            dimension_code = ""
649 650
        if entity_code.startswith("*"):
            entity_code = "(%s)" % entity_code
William Stein's avatar
William Stein committed
651
        return self.base_type.declaration_code(
652
            "%s[%s]" % (entity_code, dimension_code),
William Stein's avatar
William Stein committed
653 654 655 656 657 658 659 660 661 662 663 664 665
            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
666
    default_value = "0"
William Stein's avatar
William Stein committed
667 668 669 670 671
    
    def __init__(self, base_type):
        self.base_type = base_type
    
    def __repr__(self):
672
        return "<CPtrType %s>" % repr(self.base_type)
William Stein's avatar
William Stein committed
673 674 675 676 677 678 679 680 681 682
    
    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, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        #print "CPtrType.declaration_code: pointer to", self.base_type ###
        return self.base_type.declaration_code(
683
            "*%s" % entity_code,
William Stein's avatar
William Stein committed
684 685 686 687 688
            for_display, dll_linkage, pyrex)
    
    def assignable_from_resolved_type(self, other_type):
        if other_type is error_type:
            return 1
689
        if other_type.is_null_ptr:
William Stein's avatar
William Stein committed
690
            return 1
691 692 693 694 695 696 697 698
        if self.base_type.is_cfunction:
            if other_type.is_ptr:
                other_type = other_type.base_type.resolve()
            if other_type.is_cfunction:
                return self.base_type.pointer_assignable_from_resolved_type(other_type)
            else:
                return 0
        if other_type.is_array or other_type.is_ptr:
699
            return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
700
        return 0
William Stein's avatar
William Stein committed
701 702 703 704 705 706 707 708 709 710 711 712


class CNullPtrType(CPtrType):

    is_null_ptr = 1
    

class CFuncType(CType):
    #  return_type      CType
    #  args             [CFuncTypeArg]
    #  has_varargs      boolean
    #  exception_value  string
713 714 715 716
    #  exception_check  boolean    True if PyErr_Occurred check needed
    #  calling_convention  string  Function calling convention
    #  nogil            boolean    Can be called without gil
    #  with_gil         boolean    Acquire gil around function body
William Stein's avatar
William Stein committed
717 718
    
    is_cfunction = 1
719
    original_sig = None
William Stein's avatar
William Stein committed
720
    
721 722
    def __init__(self, return_type, args, has_varargs = 0,
            exception_value = None, exception_check = 0, calling_convention = "",
723
            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0):
William Stein's avatar
William Stein committed
724 725 726
        self.return_type = return_type
        self.args = args
        self.has_varargs = has_varargs
727
        self.optional_arg_count = optional_arg_count
William Stein's avatar
William Stein committed
728 729
        self.exception_value = exception_value
        self.exception_check = exception_check
730 731
        self.calling_convention = calling_convention
        self.nogil = nogil
732
        self.with_gil = with_gil
733
        self.is_overridable = is_overridable
William Stein's avatar
William Stein committed
734 735 736 737 738
    
    def __repr__(self):
        arg_reprs = map(repr, self.args)
        if self.has_varargs:
            arg_reprs.append("...")
739
        return "<CFuncType %s %s[%s]>" % (
William Stein's avatar
William Stein committed
740
            repr(self.return_type),
741
            self.calling_convention_prefix(),
742
            ",".join(arg_reprs))
William Stein's avatar
William Stein committed
743
    
744 745 746 747 748 749 750
    def calling_convention_prefix(self):
        cc = self.calling_convention
        if cc:
            return cc + " "
        else:
            return ""
    
William Stein's avatar
William Stein committed
751 752 753 754
    def same_c_signature_as(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(
            other_type.resolve(), as_cmethod)

755
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod = 0):
756
        #print "CFuncType.same_c_signature_as_resolved_type:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
757
        #    self, other_type, "as_cmethod =", as_cmethod ###
William Stein's avatar
William Stein committed
758 759 760 761
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
762
        if self.is_overridable != other_type.is_overridable:
763
            return 0
William Stein's avatar
William Stein committed
764
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
765
        if nargs != len(other_type.args):
William Stein's avatar
William Stein committed
766 767 768 769 770 771 772 773
            return 0
        # When comparing C method signatures, the first argument
        # is exempt from compatibility checking (the proper check
        # is performed elsewhere).
        for i in range(as_cmethod, nargs):
            if not self.args[i].type.same_as(
                other_type.args[i].type):
                    return 0
Stefan Behnel's avatar
Stefan Behnel committed
774
        if self.has_varargs != other_type.has_varargs:
William Stein's avatar
William Stein committed
775
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
776
        if self.optional_arg_count != other_type.optional_arg_count:
777
            return 0
William Stein's avatar
William Stein committed
778 779
        if not self.return_type.same_as(other_type.return_type):
            return 0
780 781
        if not self.same_calling_convention_as(other_type):
            return 0
William Stein's avatar
William Stein committed
782
        return 1
783

784 785 786 787 788
    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:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
789
        #    self, other_type, "as_cmethod =", as_cmethod ###
790 791 792 793
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
794
        if not self.is_overridable and other_type.is_overridable:
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
            return 0
        nargs = len(self.args)
        if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count:
            return 0
        if self.optional_arg_count < other_type.optional_arg_count:
            return 0
        # When comparing C method signatures, the first argument
        # is exempt from compatibility checking (the proper check
        # is performed elsewhere).
        for i in range(as_cmethod, len(other_type.args)):
            if not self.args[i].type.same_as(
                other_type.args[i].type):
                    return 0
        if self.has_varargs != other_type.has_varargs:
            return 0
810
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
811 812 813
            return 0
        if not self.same_calling_convention_as(other_type):
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
814 815
        if self.nogil != other_type.nogil:
            return 0
816
        self.original_sig = other_type.original_sig or other_type
817 818 819 820 821
        if as_cmethod:
            self.args[0] = other_type.args[0]
        return 1
        
        
822 823 824 825 826 827 828 829 830
    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
        if not other_type.is_cfunction:
            return 0
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
831
        if nargs != len(other_type.args):
832 833 834 835 836 837 838
            return 0
        for i in range(as_cmethod, nargs):
            if not self.args[i].type.subtype_of_resolved_type(other_type.args[i].type):
                return 0
            else:
                self.args[i].needs_type_test = other_type.args[i].needs_type_test \
                        or not self.args[i].type.same_as(other_type.args[i].type)
Stefan Behnel's avatar
Stefan Behnel committed
839
        if self.has_varargs != other_type.has_varargs:
840
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
841
        if self.optional_arg_count != other_type.optional_arg_count:
842
            return 0
843 844 845 846
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
            return 0
        return 1

847 848 849 850
    def same_calling_convention_as(self, other):
        sc1 = self.calling_convention == '__stdcall'
        sc2 = other.calling_convention == '__stdcall'
        return sc1 == sc2
William Stein's avatar
William Stein committed
851 852 853 854 855 856 857 858 859 860 861
    
    def same_exception_signature_as(self, other_type):
        return self.same_exception_signature_as_resolved_type(
            other_type.resolve())

    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) \
862 863 864 865 866 867 868
            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)
William Stein's avatar
William Stein committed
869 870 871 872
    
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        arg_decl_list = []
873
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
William Stein's avatar
William Stein committed
874 875
            arg_decl_list.append(
                arg.type.declaration_code("", for_display, pyrex = pyrex))
876 877
        if self.is_overridable:
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
878
        if self.optional_arg_count:
879
            arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
880 881
        if self.has_varargs:
            arg_decl_list.append("...")
882
        arg_decl_code = ", ".join(arg_decl_list)
William Stein's avatar
William Stein committed
883 884
        if not arg_decl_code and not pyrex:
            arg_decl_code = "void"
885
        trailer = ""
886
        if (pyrex or for_display) and not self.return_type.is_pyobject:
William Stein's avatar
William Stein committed
887
            if self.exception_value and self.exception_check:
888
                trailer = " except? %s" % self.exception_value
William Stein's avatar
William Stein committed
889
            elif self.exception_value:
890
                trailer = " except %s" % self.exception_value
Felix Wu's avatar
Felix Wu committed
891
            elif self.exception_check == '+':
892
                trailer = " except +"
Felix Wu's avatar
Felix Wu committed
893
            else:
894 895 896
                " except *" # ignored
            if self.nogil:
                trailer += " nogil"
897 898 899 900
        cc = self.calling_convention_prefix()
        if (not entity_code and cc) or entity_code.startswith("*"):
            entity_code = "(%s%s)" % (cc, entity_code)
            cc = ""
William Stein's avatar
William Stein committed
901
        return self.return_type.declaration_code(
902
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
William Stein's avatar
William Stein committed
903
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
904
    
905 906 907
    def function_header_code(self, func_name, arg_code):
        return "%s%s(%s)" % (self.calling_convention_prefix(),
            func_name, arg_code)
William Stein's avatar
William Stein committed
908

909 910 911 912
    def signature_string(self):
        s = self.declaration_code("")
        return s

William Stein's avatar
William Stein committed
913 914 915 916 917 918 919

class CFuncTypeArg:
    #  name       string
    #  cname      string
    #  type       PyrexType
    #  pos        source file position
    
920
    def __init__(self, name, type, pos, cname=None):
William Stein's avatar
William Stein committed
921
        self.name = name
922 923 924 925
        if cname is not None:
            self.cname = cname
        else:
            self.cname = Naming.var_prefix + name
William Stein's avatar
William Stein committed
926 927
        self.type = type
        self.pos = pos
928 929
        self.not_none = False
        self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
William Stein's avatar
William Stein committed
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
    
    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)


class CStructOrUnionType(CType):
    #  name          string
    #  cname         string
    #  kind          string              "struct" or "union"
    #  scope         StructOrUnionScope, or None if incomplete
    #  typedef_flag  boolean
    
    is_struct_or_union = 1
    has_attributes = 1
    
    def __init__(self, name, kind, scope, typedef_flag, cname):
        self.name = name
        self.cname = cname
        self.kind = kind
        self.scope = scope
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
954
        self.is_struct = kind == 'struct'
Robert Bradshaw's avatar
Robert Bradshaw committed
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972
        if self.is_struct:
            self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
        self.exception_check = True
        self._convert_code = None
        
    def create_convert_utility_code(self, env):
        if env.outer_scope is None:
            return False
        if self._convert_code is None:
            import Code
            code = Code.CCodeWriter()
            header = "static PyObject* %s(%s)" % (self.to_py_function, self.declaration_code('s'))
            code.putln("%s {" % header)
            code.putln("PyObject* res;")
            code.putln("PyObject* member;")
            code.putln("res = PyDict_New(); if (res == NULL) return NULL;")
            for member in self.scope.var_entries:
                if member.type.to_py_function and member.type.create_convert_utility_code(env):
Robert Bradshaw's avatar
Robert Bradshaw committed
973 974
                    interned_name = env.get_string_const(member.name, identifier=True)
                    env.add_py_string(interned_name)
Robert Bradshaw's avatar
Robert Bradshaw committed
975 976
                    code.putln("member = %s(s.%s); if (member == NULL) goto bad;" % (
                                                member.type.to_py_function, member.cname))
Robert Bradshaw's avatar
Robert Bradshaw committed
977
                    code.putln("if (PyDict_SetItem(res, %s, member) < 0) goto bad;" % interned_name.pystring_cname)
Robert Bradshaw's avatar
Robert Bradshaw committed
978 979 980 981 982 983 984 985 986 987
                    code.putln("Py_DECREF(member);")
                else:
                    self.to_py_function = None
                    return False
            code.putln("return res;")
            code.putln("bad:")
            code.putln("Py_XDECREF(member);")
            code.putln("Py_DECREF(res);")
            code.putln("return NULL;")
            code.putln("}")
988 989 990 991 992 993
            proto = header + ";"
            # This is a bit of a hack, we need a forward declaration
            # due to the way things are ordered in the module...
            entry = env.lookup(self.name)
            if entry.visibility != 'extern':
                proto = self.declaration_code('') + ';\n' + proto
Stefan Behnel's avatar
Stefan Behnel committed
994
            self._convert_code = UtilityCode(proto=proto, impl=code.buffer.getvalue())
Robert Bradshaw's avatar
Robert Bradshaw committed
995 996 997
        
        env.use_utility_code(self._convert_code)
        return True
William Stein's avatar
William Stein committed
998 999
        
    def __repr__(self):
1000 1001
        return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
1002 1003 1004 1005

    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex:
1006
            return self.base_declaration_code(self.name, entity_code)
William Stein's avatar
William Stein committed
1007 1008 1009 1010 1011 1012 1013
        else:
            if for_display:
                base = self.name
            elif self.typedef_flag:
                base = self.cname
            else:
                base = "%s %s" % (self.kind, self.cname)
1014
            return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
William Stein's avatar
William Stein committed
1015

1016 1017 1018 1019 1020 1021 1022 1023 1024
    def __cmp__(self, other):
        try:
            if self.name == other.name:
                return 0
            else:
                return 1
        except AttributeError:
            return 1

William Stein's avatar
William Stein committed
1025 1026 1027 1028 1029 1030
    def is_complete(self):
        return self.scope is not None
    
    def attributes_known(self):
        return self.is_complete()

1031 1032 1033 1034 1035
    def can_be_complex(self):
        # Does the struct consist of exactly two floats?
        fields = self.scope.var_entries
        return len(fields) == 2 and fields[0].type.is_float and fields[1].type.is_float

William Stein's avatar
William Stein committed
1036

1037
class CEnumType(CType):
William Stein's avatar
William Stein committed
1038 1039 1040
    #  name           string
    #  cname          string or None
    #  typedef_flag   boolean
1041

William Stein's avatar
William Stein committed
1042
    is_enum = 1
1043 1044
    signed = 1
    rank = -1 # Ranks below any integer type
1045 1046
    to_py_function = "PyInt_FromLong"
    from_py_function = "PyInt_AsLong"
William Stein's avatar
William Stein committed
1047 1048 1049 1050 1051 1052 1053

    def __init__(self, name, cname, typedef_flag):
        self.name = name
        self.cname = cname
        self.values = []
        self.typedef_flag = typedef_flag
    
1054 1055 1056
    def __str__(self):
        return self.name
    
William Stein's avatar
William Stein committed
1057
    def __repr__(self):
1058 1059
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
1060 1061 1062 1063
    
    def declaration_code(self, entity_code, 
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex:
1064
            return self.base_declaration_code(self.cname, entity_code)
William Stein's avatar
William Stein committed
1065 1066 1067 1068 1069
        else:
            if self.typedef_flag:
                base = self.cname
            else:
                base = "enum %s" % self.cname
1070
            return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
William Stein's avatar
William Stein committed
1071 1072 1073 1074 1075 1076


class CStringType:
    #  Mixin class for C string types.

    is_string = 1
1077
    is_unicode = 0
William Stein's avatar
William Stein committed
1078
    
1079 1080
    to_py_function = "__Pyx_PyBytes_FromString"
    from_py_function = "__Pyx_PyBytes_AsString"
1081
    exception_value = "NULL"
William Stein's avatar
William Stein committed
1082 1083

    def literal_code(self, value):
1084
        assert isinstance(value, str)
1085
        return '"%s"' % StringEncoding.escape_byte_string(value)
1086 1087


1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
class CUTF8CharArrayType(CStringType, CArrayType):
    #  C 'char []' type.
    
    parsetuple_format = "s"
    pymemberdef_typecode = "T_STRING_INPLACE"
    is_unicode = 1
    
    to_py_function = "PyUnicode_DecodeUTF8"
    exception_value = "NULL"
    
    def __init__(self, size):
        CArrayType.__init__(self, c_char_type, size)

William Stein's avatar
William Stein committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
class CCharArrayType(CStringType, CArrayType):
    #  C 'char []' type.
    
    parsetuple_format = "s"
    pymemberdef_typecode = "T_STRING_INPLACE"
    
    def __init__(self, size):
        CArrayType.__init__(self, c_char_type, size)
    

class CCharPtrType(CStringType, CPtrType):
    # C 'char *' type.
    
    parsetuple_format = "s"
    pymemberdef_typecode = "T_STRING"
    
    def __init__(self):
        CPtrType.__init__(self, c_char_type)


Robert Bradshaw's avatar
Robert Bradshaw committed
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
class UnspecifiedType(PyrexType):
    # Used as a placeholder until the type can be determined.
        
    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
        

William Stein's avatar
William Stein committed
1132 1133 1134 1135 1136
class ErrorType(PyrexType):
    # Used to prevent propagation of error messages.
    
    is_error = 1
    exception_value = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
1137
    exception_check    = 0
William Stein's avatar
William Stein committed
1138 1139 1140
    to_py_function = "dummy"
    from_py_function = "dummy"
    
Robert Bradshaw's avatar
Robert Bradshaw committed
1141 1142 1143
    def create_convert_utility_code(self, env):
        return True
    
William Stein's avatar
William Stein committed
1144 1145 1146 1147 1148 1149
    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
1150 1151 1152
        
    def error_condition(self, result_code):
        return "dummy"
William Stein's avatar
William Stein committed
1153 1154


1155 1156 1157 1158 1159 1160 1161
rank_to_type_name = (
    "char",         # 0
    "short",        # 1
    "int",          # 2
    "long",         # 3
    "PY_LONG_LONG", # 4
    "Py_ssize_t",   # 5
1162 1163 1164 1165
    "size_t",       # 6
    "float",        # 7
    "double",       # 8
    "long double",  # 9
1166 1167
)

William Stein's avatar
William Stein committed
1168 1169 1170 1171 1172 1173
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)

1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
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(4, 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 =        CIntType(3, 1, "T_LONG")
c_longlong_type =    CLongLongType(4, 1, "T_LONGLONG")
c_bint_type =        CBIntType(2, 1, "T_INT")
1186

1187 1188 1189 1190 1191
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 =       CIntType(3, 2, "T_LONG")
c_slonglong_type =   CLongLongType(4, 2, "T_LONGLONG")
1192

1193 1194 1195 1196 1197 1198
c_py_ssize_t_type =  CPySSizeTType(5, 1)
c_size_t_type =      CSizeTType(6, 1)

c_float_type =       CFloatType(7, "T_FLOAT")
c_double_type =      CFloatType(8, "T_DOUBLE")
c_longdouble_type =  CFloatType(9)
William Stein's avatar
William Stein committed
1199 1200 1201 1202

c_null_ptr_type =     CNullPtrType(c_void_type)
c_char_array_type =   CCharArrayType(None)
c_char_ptr_type =     CCharPtrType()
1203
c_utf8_char_array_type = CUTF8CharArrayType(None)
William Stein's avatar
William Stein committed
1204 1205
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
c_int_ptr_type =      CPtrType(c_int_type)
1206 1207
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
c_size_t_ptr_type =  CPtrType(c_size_t_type)
William Stein's avatar
William Stein committed
1208 1209 1210

c_returncode_type =   CIntType(2, 1, "T_INT", is_returncode = 1)

1211 1212
c_anon_enum_type =    CAnonEnumType(-1, 1)

1213
# the Py_buffer type is defined in Builtin.py
1214 1215
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
1216

William Stein's avatar
William Stein committed
1217
error_type =    ErrorType()
Robert Bradshaw's avatar
Robert Bradshaw committed
1218
unspecified_type = UnspecifiedType()
William Stein's avatar
William Stein committed
1219 1220 1221

sign_and_rank_to_type = {
    #(signed, rank)
1222
    (0, 0): c_uchar_type, 
William Stein's avatar
William Stein committed
1223 1224
    (0, 1): c_ushort_type, 
    (0, 2): c_uint_type, 
1225 1226 1227 1228
    (0, 3): c_ulong_type,
    (0, 4): c_ulonglong_type,
    (0, 5): c_ulonglong_type, # XXX I'm not sure about this.
    
William Stein's avatar
William Stein committed
1229 1230 1231 1232 1233
    (1, 0): c_char_type, 
    (1, 1): c_short_type, 
    (1, 2): c_int_type, 
    (1, 3): c_long_type,
    (1, 4): c_longlong_type,
1234

1235 1236 1237 1238 1239
    (2, 0): c_schar_type, 
    (2, 1): c_sshort_type, 
    (2, 2): c_sint_type, 
    (2, 3): c_slong_type,
    (2, 4): c_slonglong_type,
1240 1241

    (1, 5): c_py_ssize_t_type,
1242
    (2, 5): c_py_ssize_t_type,
1243 1244 1245
    (0, 6): c_size_t_type,
    (1, 6): c_size_t_type,

1246 1247 1248
    (1, 7): c_float_type, 
    (1, 8): c_double_type,
    (1, 9): c_longdouble_type,
1249
# In case we're mixing unsigned ints and floats...
1250 1251 1252
    (0, 7): c_float_type, 
    (0, 8): c_double_type,
    (0, 9): c_longdouble_type,
William Stein's avatar
William Stein committed
1253 1254 1255 1256 1257 1258 1259
}

modifiers_and_name_to_type = {
    #(signed, longness, name)
    (0, 0, "char"): c_uchar_type, 
    (0, -1, "int"): c_ushort_type, 
    (0, 0, "int"): c_uint_type, 
1260 1261
    (0, 1, "int"): c_ulong_type,
    (0, 2, "int"): c_ulonglong_type,
William Stein's avatar
William Stein committed
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
    (1, 0, "void"): c_void_type,
    (1, 0, "char"): c_char_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,
1272
    (1, 0, "bint"): c_bint_type, 
1273 1274 1275 1276 1277
    (2, 0, "char"): c_schar_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,
1278 1279

    (1, 0, "Py_ssize_t"): c_py_ssize_t_type,
1280
    (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
1281 1282
    (0, 0, "size_t") : c_size_t_type,
    (1, 0, "size_t") : c_size_t_type,
1283 1284
    
    (1, 0, "long"): c_long_type,
1285
    (1, 0, "short"): c_short_type,
1286
    (1, 0, "longlong"): c_longlong_type,
1287
    (1, 0, "bint"): c_bint_type,
William Stein's avatar
William Stein committed
1288 1289 1290 1291 1292
}

def widest_numeric_type(type1, type2):
    # Given two numeric types, return the narrowest type
    # encompassing both of them.
1293
    if type1.is_enum and type2.is_enum:
1294 1295 1296 1297 1298 1299 1300 1301
        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
1302
    else:
1303
        return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
1304
    return widest_type
William Stein's avatar
William Stein committed
1305 1306 1307 1308 1309

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))
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
    
def parse_basic_type(name):
    base = None
    if name.startswith('p_'):
        base = parse_basic_type(name[2:])
    elif name.startswith('p'):
        base = parse_basic_type(name[1:])
    elif name.endswith('*'):
        base = parse_basic_type(name[:-1])
    if base:
        return CPtrType(base)
    elif name.startswith('u'):
        return simple_c_type(0, 0, name[1:])
    else:
        return simple_c_type(1, 0, name)
William Stein's avatar
William Stein committed
1325 1326 1327 1328 1329

def c_array_type(base_type, size):
    # Construct a C array type.
    if base_type is c_char_type:
        return CCharArrayType(size)
1330 1331
    elif base_type is error_type:
        return error_type
William Stein's avatar
William Stein committed
1332 1333 1334 1335 1336 1337 1338
    else:
        return CArrayType(base_type, size)

def c_ptr_type(base_type):
    # Construct a C pointer type.
    if base_type is c_char_type:
        return c_char_ptr_type
1339 1340
    elif base_type is error_type:
        return error_type
William Stein's avatar
William Stein committed
1341 1342
    else:
        return CPtrType(base_type)
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
        
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")
William Stein's avatar
William Stein committed
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378

def public_decl(base, dll_linkage):
    if dll_linkage:
        return "%s(%s)" % (dll_linkage, base)
    else:
        return base

def same_type(type1, type2):
    return type1.same_as(type2)
    
def assignable_from(type1, type2):
    return type1.assignable_from(type2)

def typecast(to_type, from_type, expr_code):
    #  Return expr_code cast to a C type which can be
    #  assigned to to_type, assuming its existing C type
    #  is from_type.
    if to_type is from_type or \
        (not to_type.is_pyobject and assignable_from(to_type, from_type)):
            return expr_code
    else:
        #print "typecast: to", to_type, "from", from_type ###
        return to_type.cast_code(expr_code)
1379 1380 1381 1382 1383


type_conversion_predeclarations = """
/* Type Conversion Predeclarations */

Stefan Behnel's avatar
Stefan Behnel committed
1384
#if PY_MAJOR_VERSION < 3
Robert Bradshaw's avatar
Robert Bradshaw committed
1385 1386 1387
#define __Pyx_PyBytes_FromString          PyString_FromString
#define __Pyx_PyBytes_FromStringAndSize   PyString_FromStringAndSize
#define __Pyx_PyBytes_AsString            PyString_AsString
1388
#else
Robert Bradshaw's avatar
Robert Bradshaw committed
1389 1390 1391
#define __Pyx_PyBytes_FromString          PyBytes_FromString
#define __Pyx_PyBytes_FromStringAndSize   PyBytes_FromStringAndSize
#define __Pyx_PyBytes_AsString            PyBytes_AsString
1392 1393
#endif

1394 1395 1396 1397 1398 1399
#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
static INLINE int __Pyx_PyObject_IsTrue(PyObject* x);
static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x);
static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x);
static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b);

1400 1401 1402
static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t);
static INLINE size_t __pyx_PyInt_AsSize_t(PyObject*);

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
#define __pyx_PyInt_AsLong(x) (PyInt_CheckExact(x) ? PyInt_AS_LONG(x) : PyInt_AsLong(x))
#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
""" + type_conversion_predeclarations

type_conversion_functions = """
/* Type Conversion Functions */

static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) {
  Py_ssize_t ival;
  PyObject* x = PyNumber_Index(b);
  if (!x) return -1;
  ival = PyInt_AsSsize_t(x);
  Py_DECREF(x);
  return ival;
}

1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) {
#if PY_VERSION_HEX < 0x02050000
   if (ival <= (size_t)LONG_MAX)
       return PyInt_FromLong((long)ival);
   else {
       unsigned char *bytes = (unsigned char *) &ival;
       int one = 1; int little = (int)*(unsigned char*)&one;
       return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0);
   }
#else
   return PyInt_FromSize_t(ival);
#endif
}

static INLINE size_t __pyx_PyInt_AsSize_t(PyObject* b) {
   unsigned PY_LONG_LONG val = __pyx_PyInt_AsUnsignedLongLong(b);
   if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) {
       return (size_t)-1;
   } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
       PyErr_SetString(PyExc_OverflowError, "value too large to convert to size_t");
       return (size_t)-1;
   }
   return val;
}

1444 1445
static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
   if (x == Py_True) return 1;
1446
   else if ((x == Py_False) | (x == Py_None)) return 0;
1447 1448 1449 1450
   else return PyObject_IsTrue(x);
}

static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x) {
1451
#if PY_VERSION_HEX < 0x03000000
1452 1453 1454
    if (PyInt_CheckExact(x)) {
        return PyInt_AS_LONG(x);
    }
1455 1456 1457
    else
#endif
    if (PyLong_CheckExact(x)) {
1458 1459 1460
        return PyLong_AsLongLong(x);
    }
    else {
Stefan Behnel's avatar
Stefan Behnel committed
1461
        PY_LONG_LONG val;
1462
        PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
Stefan Behnel's avatar
Stefan Behnel committed
1463
        val = __pyx_PyInt_AsLongLong(tmp);
1464 1465 1466 1467 1468 1469
        Py_DECREF(tmp);
        return val;
    }
}

static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x) {
1470
#if PY_VERSION_HEX < 0x03000000
1471 1472 1473
    if (PyInt_CheckExact(x)) {
        long val = PyInt_AS_LONG(x);
        if (unlikely(val < 0)) {
1474
            PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned long long");
1475 1476 1477 1478
            return (unsigned PY_LONG_LONG)-1;
        }
        return val;
    }
1479 1480 1481
    else
#endif
    if (PyLong_CheckExact(x)) {
1482 1483 1484
        return PyLong_AsUnsignedLongLong(x);
    }
    else {
1485
        unsigned PY_LONG_LONG val;
1486
        PyObject* tmp = PyNumber_Int(x); if (!tmp) return (PY_LONG_LONG)-1;
Stefan Behnel's avatar
Stefan Behnel committed
1487
        val = __pyx_PyInt_AsUnsignedLongLong(tmp);
1488 1489 1490 1491 1492 1493
        Py_DECREF(tmp);
        return val;
    }
}

""" + type_conversion_functions