PyrexTypes.py 132 KB
Newer Older
William Stein's avatar
William Stein committed
1
#
2
#   Cython/Python language types
William Stein's avatar
William Stein committed
3 4
#

5
from Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
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
9
from Errors import error
William Stein's avatar
William Stein committed
10

11
class BaseType(object):
12
    #
13
    #  Base class for all Cython types including pseudo-types.
14

15 16 17
    # List of attribute names of any subtypes
    subtypes = []

18 19 20
    def can_coerce_to_pyobject(self, env):
        return False

21 22
    def cast_code(self, expr_code):
        return "((%s)%s)" % (self.declaration_code(""), expr_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
23

Craig Citro's avatar
Craig Citro committed
24
    def specialization_name(self):
25 26 27
        # This is not entirely robust.
        safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'
        all = []
28
        for c in self.declaration_code("").replace("unsigned ", "unsigned_").replace("long long", "long_long").replace(" ", "__"):
29 30 31 32 33
            if c in safe:
                all.append(c)
            else:
                all.append('_%x_' % ord(c))
        return ''.join(all)
Robert Bradshaw's avatar
Robert Bradshaw committed
34

35 36 37 38 39 40
    def base_declaration_code(self, base_code, entity_code):
        if entity_code:
            return "%s %s" % (base_code, entity_code)
        else:
            return base_code

41 42 43 44 45 46 47
    def __deepcopy__(self, memo):
        """
        Types never need to be copied, if we do copy, Unfortunate Things
        Will Happen!
        """
        return self

Mark Florisson's avatar
Mark Florisson committed
48 49 50
    def get_fused_types(self, result=None, seen=None, subtypes=None):
        subtypes = subtypes or self.subtypes
        if subtypes:
51 52
            if result is None:
                result = []
53
                seen = set()
54

Mark Florisson's avatar
Mark Florisson committed
55
            for attr in subtypes:
56
                list_or_subtype = getattr(self, attr)
57 58 59 60 61 62
                if list_or_subtype:
                    if isinstance(list_or_subtype, BaseType):
                        list_or_subtype.get_fused_types(result, seen)
                    else:
                        for subtype in list_or_subtype:
                            subtype.get_fused_types(result, seen)
63 64 65 66 67

            return result

        return None

Mark Florisson's avatar
Mark Florisson committed
68 69 70 71 72 73
    def specialize_fused(self, env):
        if env.fused_to_specific:
            return self.specialize(env.fused_to_specific)

        return self

74 75 76 77 78 79 80 81
    def _get_fused_types(self):
        """
        Add this indirection for the is_fused property to allow overriding
        get_fused_types in subclasses.
        """
        return self.get_fused_types()

    is_fused = property(_get_fused_types, doc="Whether this type or any of its "
82 83
                                             "subtypes is a fused type")

84 85 86 87
    def __lt__(self, other):
        """
        For sorting. The sorting order should correspond to the preference of
        conversion from Python types.
88 89 90

        Override to provide something sensible. This is only implemented so that
        python 3 doesn't trip
91
        """
92
        return id(type(self)) < id(type(other))
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    def py_type_name(self):
        """
        Return the name of the Python type that can coerce to this type.
        """

    def typeof_name(self):
        """
        Return the string with which fused python functions can be indexed.
        """
        if self.is_builtin_type or self.py_type_name() == 'object':
            index_name = self.py_type_name()
        else:
            index_name = str(self)

        return index_name

Mark Florisson's avatar
Mark Florisson committed
110 111 112 113 114 115 116 117
    def check_for_null_code(self, cname):
        """
        Return the code for a NULL-check in case an UnboundLocalError should
        be raised if an entry of this type is referenced before assignment.
        Returns None if no check should be performed.
        """
        return None

118
    def invalid_value(self):
119
        """
120 121
        Returns the most invalid value an object of this type can assume as a
        C expression string. Returns None if no such value exists.
122 123
        """

Mark Florisson's avatar
merge  
Mark Florisson committed
124

125
class PyrexType(BaseType):
William Stein's avatar
William Stein committed
126
    #
127
    #  Base class for all Cython types
William Stein's avatar
William Stein committed
128 129 130
    #
    #  is_pyobject           boolean     Is a Python object type
    #  is_extension_type     boolean     Is a Python extension type
131
    #  is_final_type         boolean     Is a final extension type
William Stein's avatar
William Stein committed
132 133 134
    #  is_numeric            boolean     Is a C numeric type
    #  is_int                boolean     Is a C integer type
    #  is_float              boolean     Is a C floating point type
135
    #  is_complex            boolean     Is a C complex type
William Stein's avatar
William Stein committed
136 137 138 139
    #  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
Danilo Freitas's avatar
Danilo Freitas committed
140
    #  is_reference          boolean     Is a C reference type
Robert Bradshaw's avatar
Robert Bradshaw committed
141
    #  is_const              boolean     Is a C const type.
William Stein's avatar
William Stein committed
142 143
    #  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
144
    #  is_struct             boolean     Is a C struct type
William Stein's avatar
William Stein committed
145
    #  is_enum               boolean     Is a C enum type
146
    #  is_typedef            boolean     Is a typedef type
William Stein's avatar
William Stein committed
147
    #  is_string             boolean     Is a C char * type
148
    #  is_cpp_string         boolean     Is a C++ std::string type
Stefan Behnel's avatar
Stefan Behnel committed
149
    #  is_unicode_char       boolean     Is either Py_UCS4 or Py_UNICODE
William Stein's avatar
William Stein committed
150 151
    #  is_returncode         boolean     Is used only to signal exceptions
    #  is_error              boolean     Is the dummy error type
152
    #  is_buffer             boolean     Is buffer access type
William Stein's avatar
William Stein committed
153 154
    #  has_attributes        boolean     Has C dot-selectable attributes
    #  default_value         string      Initial value
155
    #  entry                 Entry       The Entry for this type
William Stein's avatar
William Stein committed
156
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
157
    #  declaration_code(entity_code,
William Stein's avatar
William Stein committed
158 159 160 161 162 163 164 165 166
    #      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'
167
    #      statement of a Cython include file.
William Stein's avatar
William Stein committed
168 169 170 171 172 173 174 175 176 177
    #
    #  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():
178
    #    Coerces array and C function types into pointer type for use as
William Stein's avatar
William Stein committed
179 180
    #    a formal argument type.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
181

William Stein's avatar
William Stein committed
182
    is_pyobject = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
183
    is_unspecified = 0
William Stein's avatar
William Stein committed
184
    is_extension_type = 0
185
    is_final_type = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
186
    is_builtin_type = 0
William Stein's avatar
William Stein committed
187 188 189
    is_numeric = 0
    is_int = 0
    is_float = 0
190
    is_complex = 0
William Stein's avatar
William Stein committed
191 192 193 194
    is_void = 0
    is_array = 0
    is_ptr = 0
    is_null_ptr = 0
195
    is_reference = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
196
    is_const = 0
William Stein's avatar
William Stein committed
197 198
    is_cfunction = 0
    is_struct_or_union = 0
199
    is_cpp_class = 0
200
    is_cpp_string = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
201
    is_struct = 0
William Stein's avatar
William Stein committed
202
    is_enum = 0
203
    is_typedef = 0
William Stein's avatar
William Stein committed
204
    is_string = 0
Stefan Behnel's avatar
Stefan Behnel committed
205
    is_unicode_char = 0
William Stein's avatar
William Stein committed
206 207
    is_returncode = 0
    is_error = 0
208
    is_buffer = 0
209
    is_memoryviewslice = 0
William Stein's avatar
William Stein committed
210 211
    has_attributes = 0
    default_value = ""
Robert Bradshaw's avatar
Robert Bradshaw committed
212

William Stein's avatar
William Stein committed
213 214 215
    def resolve(self):
        # If a typedef, returns the base type.
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
216

217
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
218
        # TODO(danilo): Override wherever it makes sense.
219
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
220

William Stein's avatar
William Stein committed
221 222 223 224
    def literal_code(self, value):
        # Returns a C code fragment representing a literal
        # value of this type.
        return str(value)
Robert Bradshaw's avatar
Robert Bradshaw committed
225

William Stein's avatar
William Stein committed
226
    def __str__(self):
227
        return self.declaration_code("", for_display = 1).strip()
Robert Bradshaw's avatar
Robert Bradshaw committed
228

William Stein's avatar
William Stein committed
229 230
    def same_as(self, other_type, **kwds):
        return self.same_as_resolved_type(other_type.resolve(), **kwds)
Robert Bradshaw's avatar
Robert Bradshaw committed
231

William Stein's avatar
William Stein committed
232
    def same_as_resolved_type(self, other_type):
233
        return self == other_type or other_type is error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
234

William Stein's avatar
William Stein committed
235 236
    def subtype_of(self, other_type):
        return self.subtype_of_resolved_type(other_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
237

William Stein's avatar
William Stein committed
238 239
    def subtype_of_resolved_type(self, other_type):
        return self.same_as(other_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
240

William Stein's avatar
William Stein committed
241 242
    def assignable_from(self, src_type):
        return self.assignable_from_resolved_type(src_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
243

William Stein's avatar
William Stein committed
244 245
    def assignable_from_resolved_type(self, src_type):
        return self.same_as(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
246

William Stein's avatar
William Stein committed
247 248
    def as_argument_type(self):
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
249

William Stein's avatar
William Stein committed
250 251 252 253 254
    def is_complete(self):
        # A type is incomplete if it is an unsized array,
        # a struct whose attributes are not defined, etc.
        return 1

255
    def is_simple_buffer_dtype(self):
256
        return (self.is_int or self.is_float or self.is_complex or self.is_pyobject or
257 258
                self.is_extension_type or self.is_ptr)

259 260 261 262 263 264
    def struct_nesting_depth(self):
        # Returns the number levels of nested structs. This is
        # used for constructing a stack for walking the run-time
        # type information of the struct.
        return 1

265 266
    def global_init_code(self, entry, code):
        # abstract
267
        pass
268

269 270
    def needs_nonecheck(self):
        return 0
271 272


273 274 275 276 277
def public_decl(base_code, dll_linkage):
    if dll_linkage:
        return "%s(%s)" % (dll_linkage, base_code)
    else:
        return base_code
Robert Bradshaw's avatar
Robert Bradshaw committed
278

279
def create_typedef_type(name, base_type, cname, is_external=0):
280 281
    is_fused = base_type.is_fused
    if base_type.is_complex or is_fused:
282
        if is_external:
283 284 285 286 287 288 289
            if is_fused:
                msg = "Fused"
            else:
                msg = "Complex"

            raise ValueError("%s external typedefs not supported" % msg)

290 291
        return base_type
    else:
292
        return CTypedefType(name, base_type, cname, is_external)
293

294

295
class CTypedefType(BaseType):
William Stein's avatar
William Stein committed
296
    #
297
    #  Pseudo-type defined with a ctypedef statement in a
William Stein's avatar
William Stein committed
298
    #  'cdef extern from' block. Delegates most attribute
299 300
    #  lookups to the base type. ANYTHING NOT DEFINED
    #  HERE IS DELEGATED!
William Stein's avatar
William Stein committed
301
    #
302
    #  qualified_name      string
303
    #  typedef_name        string
304 305
    #  typedef_cname       string
    #  typedef_base_type   PyrexType
306
    #  typedef_is_external bool
Robert Bradshaw's avatar
Robert Bradshaw committed
307

308
    is_typedef = 1
309
    typedef_is_external = 0
310 311 312

    to_py_utility_code = None
    from_py_utility_code = None
313 314

    subtypes = ['typedef_base_type']
Robert Bradshaw's avatar
Robert Bradshaw committed
315

316
    def __init__(self, name, base_type, cname, is_external=0):
317
        assert not base_type.is_complex
318
        self.typedef_name = name
William Stein's avatar
William Stein committed
319 320
        self.typedef_cname = cname
        self.typedef_base_type = base_type
321
        self.typedef_is_external = is_external
Robert Bradshaw's avatar
Robert Bradshaw committed
322

323 324 325
    def invalid_value(self):
        return self.typedef_base_type.invalid_value()

William Stein's avatar
William Stein committed
326 327
    def resolve(self):
        return self.typedef_base_type.resolve()
Robert Bradshaw's avatar
Robert Bradshaw committed
328 329

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
330
            for_display = 0, dll_linkage = None, pyrex = 0):
331
        if pyrex or for_display:
332
            base_code = self.typedef_name
333
        else:
334
            base_code = public_decl(self.typedef_cname, dll_linkage)
335
        return self.base_declaration_code(base_code, entity_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
336

337 338 339
    def as_argument_type(self):
        return self

340 341
    def cast_code(self, expr_code):
        # If self is really an array (rather than pointer), we can't cast.
Robert Bradshaw's avatar
Robert Bradshaw committed
342
        # For example, the gmp mpz_t.
343 344 345
        if self.typedef_base_type.is_array:
            base_type = self.typedef_base_type.base_type
            return CPtrType(base_type).cast_code(expr_code)
346 347
        else:
            return BaseType.cast_code(self, expr_code)
348

349 350
    def __repr__(self):
        return "<CTypedefType %s>" % self.typedef_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
351

William Stein's avatar
William Stein committed
352
    def __str__(self):
353
        return self.typedef_name
354 355 356

    def _create_utility_code(self, template_utility_code,
                             template_function_name):
357
        type_name = self.typedef_cname.replace(" ","_").replace("::","__")
358 359 360 361 362 363 364 365 366 367
        utility_code = template_utility_code.specialize(
            type     = self.typedef_cname,
            TypeName = type_name)
        function_name = template_function_name % type_name
        return utility_code, function_name

    def create_to_py_utility_code(self, env):
        if self.typedef_is_external:
            if not self.to_py_utility_code:
                base_type = self.typedef_base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
368 369 370
                if type(base_type) is CIntType:
                    # Various subclasses have special methods
                    # that should be inherited.
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
                    self.to_py_utility_code, self.to_py_function = \
                        self._create_utility_code(c_typedef_int_to_py_function,
                                                  '__Pyx_PyInt_to_py_%s')
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
                    pass
            if self.to_py_utility_code:
                env.use_utility_code(self.to_py_utility_code)
                return True
        # delegation
        return self.typedef_base_type.create_to_py_utility_code(env)

    def create_from_py_utility_code(self, env):
        if self.typedef_is_external:
            if not self.from_py_utility_code:
                base_type = self.typedef_base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
389 390 391
                if type(base_type) is CIntType:
                    # Various subclasses have special methods
                    # that should be inherited.
392 393 394 395 396 397 398 399 400 401 402 403 404
                    self.from_py_utility_code, self.from_py_function = \
                        self._create_utility_code(c_typedef_int_from_py_function,
                                                  '__Pyx_PyInt_from_py_%s')
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
            if self.from_py_utility_code:
                env.use_utility_code(self.from_py_utility_code)
                return True
        # delegation
        return self.typedef_base_type.create_from_py_utility_code(env)

405
    def overflow_check_binop(self, binop, env, const_rhs=False):
406 407 408
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
        type = self.declaration_code("")
        name = self.specialization_name()
409
        if binop == "lshift":
410 411 412
            env.use_utility_code(TempitaUtilityCode.load(
                "LeftShift", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
413 414 415 416
        else:
            if const_rhs:
                binop += "_const"
            _load_overflow_base(env)
417 418 419 420 421 422
            env.use_utility_code(TempitaUtilityCode.load(
                "SizeCheck", "Overflow.c",
                context={'TYPE': type, 'NAME': name}))
            env.use_utility_code(TempitaUtilityCode.load(
                "Binop", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
423 424
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

425 426 427 428 429 430 431 432 433 434 435
    def error_condition(self, result_code):
        if self.typedef_is_external:
            if self.exception_value:
                condition = "(%s == (%s)%s)" % (
                    result_code, self.typedef_cname, self.exception_value)
                if self.exception_check:
                    condition += " && PyErr_Occurred()"
                return condition
        # delegation
        return self.typedef_base_type.error_condition(result_code)

William Stein's avatar
William Stein committed
436 437 438
    def __getattr__(self, name):
        return getattr(self.typedef_base_type, name)

439 440
    def py_type_name(self):
        return self.typedef_base_type.py_type_name()
441

442

443
class MemoryViewSliceType(PyrexType):
444

445
    is_memoryviewslice = 1
Kurt Smith's avatar
Kurt Smith committed
446

447 448 449
    has_attributes = 1
    scope = None

Stefan Behnel's avatar
Stefan Behnel committed
450
    # These are special cased in Defnode
451 452 453 454
    from_py_function = None
    to_py_function = None

    exception_value = None
455
    exception_check = True
456

457 458
    subtypes = ['dtype']

459
    def __init__(self, base_dtype, axes):
Stefan Behnel's avatar
Stefan Behnel committed
460
        """
461
        MemoryViewSliceType(base, axes)
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

        Base is the C base type; axes is a list of (access, packing) strings,
        where access is one of 'full', 'direct' or 'ptr' and packing is one of
        'contig', 'strided' or 'follow'.  There is one (access, packing) tuple
        for each dimension.

        the access specifiers determine whether the array data contains
        pointers that need to be dereferenced along that axis when
        retrieving/setting:

        'direct' -- No pointers stored in this dimension.
        'ptr' -- Pointer stored in this dimension.
        'full' -- Check along this dimension, don't assume either.

        the packing specifiers specify how the array elements are layed-out
        in memory.

        'contig' -- The data are contiguous in memory along this dimension.
                At most one dimension may be specified as 'contig'.
        'strided' -- The data aren't contiguous along this dimenison.
        'follow' -- Used for C/Fortran contiguous arrays, a 'follow' dimension
            has its stride automatically computed from extents of the other
            dimensions to ensure C or Fortran memory layout.

        C-contiguous memory has 'direct' as the access spec, 'contig' as the
        *last* axis' packing spec and 'follow' for all other packing specs.

        Fortran-contiguous memory has 'direct' as the access spec, 'contig' as
        the *first* axis' packing spec and 'follow' for all other packing
        specs.
Stefan Behnel's avatar
Stefan Behnel committed
492
        """
493
        import MemoryView
494

Kurt Smith's avatar
Kurt Smith committed
495
        self.dtype = base_dtype
496
        self.axes = axes
497
        self.ndim = len(axes)
498
        self.flags = MemoryView.get_buf_flags(self.axes)
499

500 501 502
        self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes)
        assert not (self.is_c_contig and self.is_f_contig)

503
        self.mode = MemoryView.get_mode(axes)
504
        self.writable_needed = False
505

506 507
        if not self.dtype.is_fused:
            self.dtype_name = MemoryView.mangle_dtype_name(self.dtype)
508

509 510 511 512 513 514
    def same_as_resolved_type(self, other_type):
        return ((other_type.is_memoryviewslice and
            self.dtype.same_as(other_type.dtype) and
            self.axes == other_type.axes) or
            other_type is error_type)

515 516 517
    def needs_nonecheck(self):
        return True

Kurt Smith's avatar
Kurt Smith committed
518
    def is_complete(self):
519
        # incomplete since the underlying struct doesn't have a cython.memoryview object.
Kurt Smith's avatar
Kurt Smith committed
520 521 522 523
        return 0

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
524 525 526 527 528
        # XXX: we put these guards in for now...
        assert not pyrex
        assert not dll_linkage
        import MemoryView
        return self.base_declaration_code(
529
                MemoryView.memviewslice_cname,
530
                entity_code)
Kurt Smith's avatar
Kurt Smith committed
531

532 533
    def attributes_known(self):
        if self.scope is None:
534
            import Symtab
535

536 537
            self.scope = scope = Symtab.CClassScope(
                    'mvs_class_'+self.specialization_suffix(),
538 539
                    None,
                    visibility='extern')
540 541

            scope.parent_type = self
542
            scope.directives = {}
543

544 545 546 547 548
            scope.declare_var('_data', c_char_ptr_type, None,
                              cname='data', is_cdef=1)

        return True

549
    def declare_attribute(self, attribute, env, pos):
550 551 552
        import MemoryView, Options

        scope = self.scope
553

554
        if attribute == 'shape':
555 556
            scope.declare_var('shape',
                    c_array_type(c_py_ssize_t_type,
557 558
                                 Options.buffer_max_dims),
                    pos,
559 560 561
                    cname='shape',
                    is_cdef=1)

562
        elif attribute == 'strides':
563 564
            scope.declare_var('strides',
                    c_array_type(c_py_ssize_t_type,
565 566
                                 Options.buffer_max_dims),
                    pos,
567 568 569
                    cname='strides',
                    is_cdef=1)

570
        elif attribute == 'suboffsets':
571 572
            scope.declare_var('suboffsets',
                    c_array_type(c_py_ssize_t_type,
573 574
                                 Options.buffer_max_dims),
                    pos,
575 576 577
                    cname='suboffsets',
                    is_cdef=1)

578
        elif attribute in ("copy", "copy_fortran"):
579
            ndim = len(self.axes)
580

581 582
            to_axes_c = [('direct', 'contig')]
            to_axes_f = [('direct', 'contig')]
583
            if ndim - 1:
584 585
                to_axes_c = [('direct', 'follow')]*(ndim-1) + to_axes_c
                to_axes_f = to_axes_f + [('direct', 'follow')]*(ndim-1)
586

587 588
            to_memview_c = MemoryViewSliceType(self.dtype, to_axes_c)
            to_memview_f = MemoryViewSliceType(self.dtype, to_axes_f)
589

590 591
            for to_memview, cython_name in [(to_memview_c, "copy"),
                                            (to_memview_f, "copy_fortran")]:
592
                entry = scope.declare_cfunction(cython_name,
593 594 595 596
                            CFuncType(self, [CFuncTypeArg("memviewslice", self, None)]),
                            pos=pos,
                            defining=1,
                            cname=MemoryView.copy_c_or_fortran_cname(to_memview))
597

598 599
                #entry.utility_code_definition = \
                env.use_utility_code(MemoryView.get_copy_new_utility(pos, self, to_memview))
600

601 602
            MemoryView.use_cython_array_utility_code(env)

603
        elif attribute in ("is_c_contig", "is_f_contig"):
604
            # is_c_contig and is_f_contig functions
605
            for (c_or_f, cython_name) in (('c', 'is_c_contig'), ('f', 'is_f_contig')):
606

607
                is_contig_name = \
608
                        MemoryView.get_is_contig_func_name(c_or_f, self.ndim)
609

Mark Florisson's avatar
Mark Florisson committed
610
                cfunctype = CFuncType(
611
                        return_type=c_bint_type,
Mark Florisson's avatar
Mark Florisson committed
612 613 614 615
                        args=[CFuncTypeArg("memviewslice", self, None)],
                        exception_value="-1",
                )

616
                entry = scope.declare_cfunction(cython_name,
Mark Florisson's avatar
Mark Florisson committed
617
                            cfunctype,
618 619 620
                            pos=pos,
                            defining=1,
                            cname=is_contig_name)
621

622 623
                entry.utility_code_definition = MemoryView.get_is_contig_utility(
                                            attribute == 'is_c_contig', self.ndim)
624

625
        return True
626 627

    def specialization_suffix(self):
628
        return "%s_%s" % (self.axes_to_name(), self.dtype_name)
629

630 631 632
    def can_coerce_to_pyobject(self, env):
        return True

Mark Florisson's avatar
Mark Florisson committed
633 634 635
    def check_for_null_code(self, cname):
        return cname + '.memview'

636
    def create_from_py_utility_code(self, env):
637
        import MemoryView, Buffer
638 639 640 641 642

        # We don't have 'code', so use a LazyUtilityCode with a callback.
        def lazy_utility_callback(code):
            context['dtype_typeinfo'] = Buffer.get_type_information_cname(
                                                          code, self.dtype)
643 644
            return TempitaUtilityCode.load(
                        "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
645 646 647 648 649 650 651 652 653 654 655 656

        env.use_utility_code(Buffer.acquire_utility_code)
        env.use_utility_code(MemoryView.memviewslice_init_code)
        env.use_utility_code(LazyUtilityCode(lazy_utility_callback))

        if self.is_c_contig:
            c_or_f_flag = "__Pyx_IS_C_CONTIG"
        elif self.is_f_contig:
            c_or_f_flag = "__Pyx_IS_F_CONTIG"
        else:
            c_or_f_flag = "0"

657 658
        suffix = self.specialization_suffix()
        funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
659 660 661

        context = dict(
            MemoryView.context,
662
            buf_flag = self.flags,
663
            ndim = self.ndim,
664
            axes_specs = ', '.join(self.axes_to_code()),
665 666 667 668 669 670 671 672 673
            dtype_typedecl = self.dtype.declaration_code(""),
            struct_nesting_depth = self.dtype.struct_nesting_depth(),
            c_or_f_flag = c_or_f_flag,
            funcname = funcname,
        )

        self.from_py_function = funcname
        return True

674 675 676
    def create_to_py_utility_code(self, env):
        return True

677 678 679 680 681
    def get_to_py_function(self, env, obj):
        to_py_func, from_py_func = self.dtype_object_conversion_funcs(env)
        to_py_func = "(PyObject *(*)(char *)) " + to_py_func
        from_py_func = "(int (*)(char *, PyObject *)) " + from_py_func

682 683
        tup = (obj.result(), self.ndim, to_py_func, from_py_func,
               self.dtype.is_pyobject)
684
        return "__pyx_memoryview_fromslice(%s, %s, %s, %s, %d);" % tup
685 686 687 688 689 690 691 692 693 694 695 696 697

    def dtype_object_conversion_funcs(self, env):
        get_function = "__pyx_memview_get_%s" % self.dtype_name
        set_function = "__pyx_memview_set_%s" % self.dtype_name

        context = dict(
            get_function = get_function,
            set_function = set_function,
        )

        if self.dtype.is_pyobject:
            utility_name = "MemviewObjectToObject"
        else:
Mark Florisson's avatar
Mark Florisson committed
698 699 700
            to_py = self.dtype.create_to_py_utility_code(env)
            from_py = self.dtype.create_from_py_utility_code(env)
            if not (to_py or from_py):
701 702
                return "NULL", "NULL"

Mark Florisson's avatar
Mark Florisson committed
703 704 705 706 707 708
            if not self.dtype.to_py_function:
                get_function = "NULL"

            if not self.dtype.from_py_function:
                set_function = "NULL"

709 710 711 712 713 714 715 716 717 718
            utility_name = "MemviewDtypeToObject"
            error_condition = (self.dtype.error_condition('value') or
                               'PyErr_Occurred()')
            context.update(
                to_py_function = self.dtype.to_py_function,
                from_py_function = self.dtype.from_py_function,
                dtype = self.dtype.declaration_code(""),
                error_condition = error_condition,
            )

719
        utility = TempitaUtilityCode.load(
720 721 722
                        utility_name, "MemoryView_C.c", context=context)
        env.use_utility_code(utility)
        return get_function, set_function
723

724
    def axes_to_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
725
        """Return a list of code constants for each axis"""
726 727 728 729
        import MemoryView
        d = MemoryView._spec_to_const
        return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]

730
    def axes_to_name(self):
Stefan Behnel's avatar
Stefan Behnel committed
731
        """Return an abbreviated name for our axes"""
732 733 734 735 736 737 738
        import MemoryView
        d = MemoryView._spec_to_abbrev
        return "".join(["%s%s" % (d[a], d[p]) for a, p in self.axes])

    def error_condition(self, result_code):
        return "!%s.memview" % result_code

739 740 741 742
    def __str__(self):
        import MemoryView

        axes_code_list = []
743
        for idx, (access, packing) in enumerate(self.axes):
744 745 746 747
            flag = MemoryView.get_memoryview_flag(access, packing)
            if flag == "strided":
                axes_code_list.append(":")
            else:
748
                if flag == 'contiguous':
Mark Florisson's avatar
Mark Florisson committed
749
                    have_follow = [p for a, p in self.axes[idx - 1:idx + 2]
750 751 752 753
                                         if p == 'follow']
                    if have_follow or self.ndim == 1:
                        flag = '1'

754 755 756 757 758 759 760 761 762
                axes_code_list.append("::" + flag)

        if self.dtype.is_pyobject:
            dtype_name = self.dtype.name
        else:
            dtype_name = self.dtype

        return "%s[%s]" % (dtype_name, ", ".join(axes_code_list))

763
    def specialize(self, values):
Stefan Behnel's avatar
Stefan Behnel committed
764
        """This does not validate the base type!!"""
765 766 767 768
        dtype = self.dtype.specialize(values)
        if dtype is not self.dtype:
            return MemoryViewSliceType(dtype, self.axes)

769 770
        return self

771 772
    def cast_code(self, expr_code):
        return expr_code
773

774

775 776 777 778 779
class BufferType(BaseType):
    #
    #  Delegates most attribute
    #  lookups to the base type. ANYTHING NOT DEFINED
    #  HERE IS DELEGATED!
Robert Bradshaw's avatar
Robert Bradshaw committed
780

781 782 783 784 785 786 787
    # dtype            PyrexType
    # ndim             int
    # mode             str
    # negative_indices bool
    # cast             bool
    # is_buffer        bool
    # writable         bool
788 789

    is_buffer = 1
790
    writable = True
791 792 793

    subtypes = ['dtype']

794
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
795 796 797
        self.base = base
        self.dtype = dtype
        self.ndim = ndim
798
        self.buffer_ptr_type = CPtrType(dtype)
799
        self.mode = mode
800
        self.negative_indices = negative_indices
801
        self.cast = cast
Robert Bradshaw's avatar
Robert Bradshaw committed
802

803 804 805
    def as_argument_type(self):
        return self

Mark Florisson's avatar
Mark Florisson committed
806 807 808 809 810 811 812
    def specialize(self, values):
        dtype = self.dtype.specialize(values)
        if dtype is not self.dtype:
            return BufferType(self.base, dtype, self.ndim, self.mode,
                              self.negative_indices, self.cast)
        return self

813 814 815
    def __getattr__(self, name):
        return getattr(self.base, name)

816 817 818
    def __repr__(self):
        return "<BufferType %r>" % self.base

819
    def __str__(self):
820
        # avoid ', ', as fused functions split the signature string on ', '
821
        cast_str = ''
822 823
        if self.cast:
            cast_str = ',cast=True'
824

825
        return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
826
                                      cast_str)
827

828
    def assignable_from(self, other_type):
829 830 831
        if other_type.is_buffer:
            return (self.same_as(other_type, compare_base=False) and
                    self.base.assignable_from(other_type.base))
832

833 834 835 836 837 838 839
        return self.base.assignable_from(other_type)

    def same_as(self, other_type, compare_base=True):
        if not other_type.is_buffer:
            return other_type.same_as(self.base)

        return (self.dtype.same_as(other_type.dtype) and
840 841
                self.ndim == other_type.ndim and
                self.mode == other_type.mode and
842 843
                self.cast == other_type.cast and
                (not compare_base or self.base.same_as(other_type.base)))
844

845

William Stein's avatar
William Stein committed
846 847 848 849
class PyObjectType(PyrexType):
    #
    #  Base class for all Python object types (reference-counted).
    #
850
    #  buffer_defaults  dict or None     Default options for bu
851 852

    name = "object"
William Stein's avatar
William Stein committed
853 854
    is_pyobject = 1
    default_value = "0"
855
    buffer_defaults = None
856 857
    is_extern = False
    is_subclassed = False
858

William Stein's avatar
William Stein committed
859 860
    def __str__(self):
        return "Python object"
Robert Bradshaw's avatar
Robert Bradshaw committed
861

William Stein's avatar
William Stein committed
862
    def __repr__(self):
863
        return "<PyObjectType>"
864 865 866 867

    def can_coerce_to_pyobject(self, env):
        return True

868
    def default_coerced_ctype(self):
Stefan Behnel's avatar
Stefan Behnel committed
869
        """The default C type that this Python type coerces to, or None."""
870 871
        return None

William Stein's avatar
William Stein committed
872
    def assignable_from(self, src_type):
873 874
        # except for pointers, conversion will be attempted
        return not src_type.is_ptr or src_type.is_string
Robert Bradshaw's avatar
Robert Bradshaw committed
875 876

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
877
            for_display = 0, dll_linkage = None, pyrex = 0):
878
        if pyrex or for_display:
879
            base_code = "object"
William Stein's avatar
William Stein committed
880
        else:
881 882 883
            base_code = public_decl("PyObject", dll_linkage)
            entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
884

885 886 887 888 889
    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
890

891 892 893 894 895 896 897 898 899 900
    def py_type_name(self):
        return "object"

    def __lt__(self, other):
        """
        Make sure we sort highest, as instance checking on py_type_name
        ('object') is always true
        """
        return False

901 902 903
    def global_init_code(self, entry, code):
        code.put_init_var_to_py_none(entry, nanny=False)

Mark Florisson's avatar
Mark Florisson committed
904 905 906
    def check_for_null_code(self, cname):
        return cname

907

Robert Bradshaw's avatar
Robert Bradshaw committed
908
class BuiltinObjectType(PyObjectType):
909
    #  objstruct_cname  string           Name of PyObject struct
Robert Bradshaw's avatar
Robert Bradshaw committed
910 911 912 913 914 915

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

916 917 918 919 920 921 922
    # fields that let it look like an extension type
    vtabslot_cname = None
    vtabstruct_cname = None
    vtabptr_cname = None
    typedef_flag = True
    is_external = True

923
    def __init__(self, name, cname, objstruct_cname=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
924 925
        self.name = name
        self.cname = cname
926
        self.typeptr_cname = "(&%s)" % cname
927
        self.objstruct_cname = objstruct_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
928

Robert Bradshaw's avatar
Robert Bradshaw committed
929 930 931 932
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
933

Robert Bradshaw's avatar
Robert Bradshaw committed
934 935
    def __str__(self):
        return "%s object" % self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
936

Robert Bradshaw's avatar
Robert Bradshaw committed
937 938
    def __repr__(self):
        return "<%s>"% self.cname
939 940 941 942 943 944 945 946 947 948

    def default_coerced_ctype(self):
        if self.name == 'bytes':
            return c_char_ptr_type
        elif self.name == 'bool':
            return c_bint_type
        elif self.name == 'float':
            return c_double_type
        return None

Robert Bradshaw's avatar
Robert Bradshaw committed
949 950
    def assignable_from(self, src_type):
        if isinstance(src_type, BuiltinObjectType):
951
            return src_type.name == self.name
952
        elif src_type.is_extension_type:
953 954 955 956 957
            # FIXME: This is an ugly special case that we currently
            # keep supporting.  It allows users to specify builtin
            # types as external extension types, while keeping them
            # compatible with the real builtin types.  We already
            # generate a warning for it.  Big TODO: remove!
958 959
            return (src_type.module_name == '__builtin__' and
                    src_type.name == self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
960
        else:
961
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
962

Robert Bradshaw's avatar
Robert Bradshaw committed
963 964
    def typeobj_is_available(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
965

Robert Bradshaw's avatar
Robert Bradshaw committed
966 967
    def attributes_known(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
968

Robert Bradshaw's avatar
Robert Bradshaw committed
969
    def subtype_of(self, type):
970
        return type.is_pyobject and type.assignable_from(self)
971 972

    def type_check_function(self, exact=True):
973 974
        type_name = self.name
        if type_name == 'str':
975
            type_check = 'PyString_Check'
976
        elif type_name == 'frozenset':
977
            type_check = 'PyFrozenSet_Check'
978
        else:
979
            type_check = 'Py%s_Check' % type_name.capitalize()
Stefan Behnel's avatar
Stefan Behnel committed
980
        if exact and type_name not in ('bool', 'slice'):
981 982 983 984 985
            type_check += 'Exact'
        return type_check

    def isinstance_code(self, arg):
        return '%s(%s)' % (self.type_check_function(exact=False), arg)
986

987 988
    def type_test_code(self, arg, notnone=False):
        type_check = self.type_check_function(exact=True)
989 990
        check = 'likely(%s(%s))' % (type_check, arg)
        if not notnone:
Stefan Behnel's avatar
Stefan Behnel committed
991
            check += '||((%s) == Py_None)' % arg
992 993
        error = '(PyErr_Format(PyExc_TypeError, "Expected %s, got %%.200s", Py_TYPE(%s)->tp_name), 0)' % (self.name, arg)
        return check + '||' + error
Robert Bradshaw's avatar
Robert Bradshaw committed
994

Robert Bradshaw's avatar
Robert Bradshaw committed
995
    def declaration_code(self, entity_code,
996 997
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
998
            base_code = self.name
999
        else:
1000 1001 1002
            base_code = public_decl("PyObject", dll_linkage)
            entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
1003

1004 1005 1006 1007 1008
    def cast_code(self, expr_code, to_object_struct = False):
        return "((%s*)%s)" % (
            to_object_struct and self.objstruct_cname or "PyObject", # self.objstruct_cname may be None
            expr_code)

1009 1010 1011 1012
    def py_type_name(self):
        return self.name


Robert Bradshaw's avatar
Robert Bradshaw committed
1013

William Stein's avatar
William Stein committed
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
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
1025
    #  objtypedef_cname string           Name of PyObject struct typedef
William Stein's avatar
William Stein committed
1026 1027 1028 1029 1030 1031
    #  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
Robert Bradshaw's avatar
Robert Bradshaw committed
1032

William Stein's avatar
William Stein committed
1033 1034
    is_extension_type = 1
    has_attributes = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1035

1036 1037 1038
    def needs_nonecheck(self):
        return True

1039
    objtypedef_cname = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1040

1041
    def __init__(self, name, typedef_flag, base_type, is_external=0):
William Stein's avatar
William Stein committed
1042 1043 1044
        self.name = name
        self.scope = None
        self.typedef_flag = typedef_flag
1045 1046
        if base_type is not None:
            base_type.is_subclassed = True
William Stein's avatar
William Stein committed
1047 1048 1049 1050 1051 1052 1053 1054 1055
        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
1056
        self.is_external = is_external
Robert Bradshaw's avatar
Robert Bradshaw committed
1057

William Stein's avatar
William Stein committed
1058 1059 1060 1061
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1062

William Stein's avatar
William Stein committed
1063
    def subtype_of_resolved_type(self, other_type):
Stefan Behnel's avatar
Stefan Behnel committed
1064
        if other_type.is_extension_type or other_type.is_builtin_type:
William Stein's avatar
William Stein committed
1065 1066 1067 1068
            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
Robert Bradshaw's avatar
Robert Bradshaw committed
1069

William Stein's avatar
William Stein committed
1070 1071 1072
    def typeobj_is_available(self):
        # Do we have a pointer to the type object?
        return self.typeptr_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
1073

William Stein's avatar
William Stein committed
1074 1075 1076 1077
    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
Robert Bradshaw's avatar
Robert Bradshaw committed
1078

1079 1080 1081 1082 1083 1084
    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)
1085 1086 1087 1088 1089 1090 1091 1092
        if isinstance(src_type, BuiltinObjectType):
            # FIXME: This is an ugly special case that we currently
            # keep supporting.  It allows users to specify builtin
            # types as external extension types, while keeping them
            # compatible with the real builtin types.  We already
            # generate a warning for it.  Big TODO: remove!
            return (self.module_name == '__builtin__' and
                    self.name == src_type.name)
1093 1094
        return False

Robert Bradshaw's avatar
Robert Bradshaw committed
1095
    def declaration_code(self, entity_code,
1096
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
1097
        if pyrex or for_display:
1098
            base_code = self.name
William Stein's avatar
William Stein committed
1099 1100
        else:
            if self.typedef_flag:
1101
                objstruct = self.objstruct_cname
William Stein's avatar
William Stein committed
1102
            else:
1103
                objstruct = "struct %s" % self.objstruct_cname
1104
            base_code = public_decl(objstruct, dll_linkage)
1105
            if deref:
1106
                assert not entity_code
1107
            else:
1108 1109
                entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
1110

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
    def type_test_code(self, py_arg, notnone=False):

        none_check = "((%s) == Py_None)" % py_arg
        type_check = "likely(__Pyx_TypeTest(%s, %s))" % (
            py_arg, self.typeptr_cname)
        if notnone:
            return type_check
        else:
            return "likely(%s || %s)" % (none_check, type_check)

William Stein's avatar
William Stein committed
1121 1122
    def attributes_known(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1123

William Stein's avatar
William Stein committed
1124 1125
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1126

William Stein's avatar
William Stein committed
1127
    def __repr__(self):
1128 1129
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
1130

1131 1132 1133 1134 1135 1136
    def py_type_name(self):
        if not self.module_name:
            return self.name

        return "__import__(%r, None, None, ['']).%s" % (self.module_name,
                                                        self.name)
William Stein's avatar
William Stein committed
1137 1138 1139 1140 1141 1142 1143 1144

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
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1145

William Stein's avatar
William Stein committed
1146 1147
    to_py_function = None
    from_py_function = None
1148 1149
    exception_value = None
    exception_check = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1150

1151
    def create_to_py_utility_code(self, env):
1152
        return self.to_py_function is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1153

1154
    def create_from_py_utility_code(self, env):
1155
        return self.from_py_function is not None
1156 1157 1158 1159

    def can_coerce_to_pyobject(self, env):
        return self.create_to_py_utility_code(env)

1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
    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
1172 1173


Robert Bradshaw's avatar
Robert Bradshaw committed
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
class CConstType(BaseType):

    is_const = 1
    
    def __init__(self, const_base_type):
        self.const_base_type = const_base_type
        if const_base_type.has_attributes and const_base_type.scope is not None:
            import Symtab
            self.scope = Symtab.CConstScope(const_base_type.scope)

    def __repr__(self):
        return "<CConstType %s>" % repr(self.const_base_type)

    def __str__(self):
        return self.declaration_code("", for_display=1)

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
        return self.const_base_type.declaration_code("const %s" % entity_code, for_display, dll_linkage, pyrex)

    def specialize(self, values):
        base_type = self.const_base_type.specialize(values)
        if base_type == self.const_base_type:
            return self
        else:
Stefan Behnel's avatar
Stefan Behnel committed
1199
            return CConstType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209

    def create_to_py_utility_code(self, env):
        if self.const_base_type.create_to_py_utility_code(env):
            self.to_py_function = self.const_base_type.to_py_function
            return True

    def __getattr__(self, name):
        return getattr(self.const_base_type, name)


1210
class FusedType(CType):
1211 1212 1213 1214 1215 1216 1217
    """
    Represents a Fused Type. All it needs to do is keep track of the types
    it aggregates, as it will be replaced with its specific version wherever
    needed.

    See http://wiki.cython.org/enhancements/fusedtypes

1218
    types           [PyrexType]             is the list of types to be fused
1219 1220 1221 1222
    name            str                     the name of the ctypedef
    """

    is_fused = 1
1223
    exception_check = 0
1224

1225
    def __init__(self, types, name=None):
1226
        self.types = types
1227
        self.name = name
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250

    def declaration_code(self, entity_code, for_display = 0,
                         dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
            return self.name

        raise Exception("This may never happen, please report a bug")

    def __repr__(self):
        return 'FusedType(name=%r)' % self.name

    def specialize(self, values):
        return values[self]

    def get_fused_types(self, result=None, seen=None):
        if result is None:
            return [self]

        if self not in seen:
            result.append(self)
            seen.add(self)


1251
class CVoidType(CType):
1252 1253 1254 1255
    #
    #   C "void" type
    #

William Stein's avatar
William Stein committed
1256
    is_void = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1257

William Stein's avatar
William Stein committed
1258 1259
    def __repr__(self):
        return "<CVoidType>"
Robert Bradshaw's avatar
Robert Bradshaw committed
1260 1261

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1262
            for_display = 0, dll_linkage = None, pyrex = 0):
1263 1264 1265 1266 1267
        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)
Robert Bradshaw's avatar
Robert Bradshaw committed
1268

William Stein's avatar
William Stein committed
1269 1270 1271
    def is_complete(self):
        return 0

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
class InvisibleVoidType(CVoidType):
    #
    #   For use with C++ constructors and destructors return types.
    #   Acts like void, but does not print out a declaration.
    #
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
            base_code = "[void]"
        else:
            base_code = public_decl("", dll_linkage)
        return self.base_declaration_code(base_code, entity_code)

William Stein's avatar
William Stein committed
1285 1286 1287 1288 1289 1290

class CNumericType(CType):
    #
    #   Base class for all C numeric types.
    #
    #   rank      integer     Relative size
1291
    #   signed    integer     0 = unsigned, 1 = unspecified, 2 = explicitly signed
William Stein's avatar
William Stein committed
1292
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
1293

William Stein's avatar
William Stein committed
1294 1295
    is_numeric = 1
    default_value = "0"
1296 1297
    has_attributes = True
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1298

1299
    sign_words = ("unsigned ", "", "signed ")
Robert Bradshaw's avatar
Robert Bradshaw committed
1300

1301
    def __init__(self, rank, signed = 1):
William Stein's avatar
William Stein committed
1302 1303
        self.rank = rank
        self.signed = signed
Robert Bradshaw's avatar
Robert Bradshaw committed
1304

1305 1306 1307 1308
    def sign_and_name(self):
        s = self.sign_words[self.signed]
        n = rank_to_type_name[self.rank]
        return s + n
Robert Bradshaw's avatar
Robert Bradshaw committed
1309

William Stein's avatar
William Stein committed
1310
    def __repr__(self):
1311
        return "<CNumericType %s>" % self.sign_and_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1312 1313

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1314
            for_display = 0, dll_linkage = None, pyrex = 0):
1315 1316 1317 1318 1319 1320
        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)
Robert Bradshaw's avatar
Robert Bradshaw committed
1321

1322 1323 1324 1325 1326 1327 1328 1329 1330
    def attributes_known(self):
        if self.scope is None:
            import Symtab
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
            scope.directives = {}
Stefan Behnel's avatar
Stefan Behnel committed
1331
            scope.declare_cfunction(
1332
                    "conjugate",
1333
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1334 1335 1336 1337
                    pos=None,
                    defining=1,
                    cname=" ")
        return True
1338

1339
    def __lt__(self, other):
Stefan Behnel's avatar
Stefan Behnel committed
1340
        """Sort based on rank, preferring signed over unsigned"""
1341 1342 1343
        if other.is_numeric:
            return self.rank > other.rank and self.signed >= other.signed

1344 1345
        # Prefer numeric types over others
        return True
1346 1347 1348 1349 1350

    def py_type_name(self):
        if self.rank <= 4:
            return "(int, long)"
        return "float"
1351

1352 1353
c_int_from_py_function = UtilityCode(
proto="""
1354
static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
1355 1356
""",
impl="""
1357
static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
Robert Bradshaw's avatar
Robert Bradshaw committed
1358 1359
    const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
    const int is_unsigned = neg_one > const_zero;
1360 1361 1362
    if (sizeof(%(type)s) < sizeof(long)) {
        long val = __Pyx_PyInt_AsLong(x);
        if (unlikely(val != (long)(%(type)s)val)) {
1363
            if (!unlikely(val == -1 && PyErr_Occurred())) {
1364
                PyErr_SetString(PyExc_OverflowError,
1365
                    (is_unsigned && unlikely(val < 0)) ?
1366 1367
                    "can't convert negative value to %(type)s" :
                    "value too large to convert to %(type)s");
1368
            }
1369 1370 1371 1372 1373 1374
            return (%(type)s)-1;
        }
        return (%(type)s)val;
    }
    return (%(type)s)__Pyx_PyInt_As%(SignWord)sLong(x);
}
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1375
""") #fool emacs: '
1376 1377 1378

c_long_from_py_function = UtilityCode(
proto="""
1379
static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
1380 1381
""",
impl="""
1382
static CYTHON_INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
Robert Bradshaw's avatar
Robert Bradshaw committed
1383 1384
    const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
    const int is_unsigned = neg_one > const_zero;
1385
#if PY_VERSION_HEX < 0x03000000
1386 1387
    if (likely(PyInt_Check(x))) {
        long val = PyInt_AS_LONG(x);
1388
        if (is_unsigned && unlikely(val < 0)) {
1389 1390 1391 1392
            PyErr_SetString(PyExc_OverflowError,
                            "can't convert negative value to %(type)s");
            return (%(type)s)-1;
        }
1393 1394 1395
        return (%(type)s)val;
    } else
#endif
1396
    if (likely(PyLong_Check(x))) {
1397 1398 1399 1400 1401 1402
        if (is_unsigned) {
            if (unlikely(Py_SIZE(x) < 0)) {
                PyErr_SetString(PyExc_OverflowError,
                                "can't convert negative value to %(type)s");
                return (%(type)s)-1;
            }
Lisandro Dalcin's avatar
Lisandro Dalcin committed
1403
            return (%(type)s)PyLong_AsUnsigned%(TypeName)s(x);
1404
        } else {
Lisandro Dalcin's avatar
Lisandro Dalcin committed
1405
            return (%(type)s)PyLong_As%(TypeName)s(x);
1406
        }
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
    } else {
        %(type)s val;
        PyObject *tmp = __Pyx_PyNumber_Int(x);
        if (!tmp) return (%(type)s)-1;
        val = __Pyx_PyInt_As%(SignWord)s%(TypeName)s(tmp);
        Py_DECREF(tmp);
        return val;
    }
}
""")

1418 1419
c_typedef_int_from_py_function = UtilityCode(
proto="""
1420
static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject *);
1421 1422
""",
impl="""
1423
static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
1424 1425
    const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
    const int is_unsigned = const_zero < neg_one;
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
    if (sizeof(%(type)s) == sizeof(char)) {
        if (is_unsigned)
            return (%(type)s)__Pyx_PyInt_AsUnsignedChar(x);
        else
            return (%(type)s)__Pyx_PyInt_AsSignedChar(x);
    } else if (sizeof(%(type)s) == sizeof(short)) {
        if (is_unsigned)
            return (%(type)s)__Pyx_PyInt_AsUnsignedShort(x);
        else
            return (%(type)s)__Pyx_PyInt_AsSignedShort(x);
    } else if (sizeof(%(type)s) == sizeof(int)) {
        if (is_unsigned)
            return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
        else
            return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
    } else if (sizeof(%(type)s) == sizeof(long)) {
        if (is_unsigned)
            return (%(type)s)__Pyx_PyInt_AsUnsignedLong(x);
        else
            return (%(type)s)__Pyx_PyInt_AsSignedLong(x);
    } else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
        if (is_unsigned)
            return (%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x);
        else
            return (%(type)s)__Pyx_PyInt_AsSignedLongLong(x);
1451
    }  else {
1452 1453 1454 1455
        #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
        PyErr_SetString(PyExc_RuntimeError,
                        "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
        #else
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
        %(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;
        }
1475
        #endif
1476
        return (%(type)s)-1;
1477
    }
1478 1479
}
""")
1480

1481 1482
c_typedef_int_to_py_function = UtilityCode(
proto="""
1483
static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s);
1484 1485
""",
impl="""
1486
static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
1487 1488 1489 1490
    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))) {
1491
        return PyInt_FromLong((long)val);
1492 1493
    } else if ((sizeof(%(type)s) == sizeof(int)) ||
               (sizeof(%(type)s) == sizeof(long))) {
1494 1495 1496 1497
        if (is_unsigned)
            return PyLong_FromUnsignedLong((unsigned long)val);
        else
            return PyInt_FromLong((long)val);
1498
    } else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
1499 1500 1501 1502
        if (is_unsigned)
            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
        else
            return PyLong_FromLongLong((PY_LONG_LONG)val);
1503 1504 1505
    } else {
        int one = 1; int little = (int)*(unsigned char *)&one;
        unsigned char *bytes = (unsigned char *)&val;
Robert Bradshaw's avatar
Robert Bradshaw committed
1506
        return _PyLong_FromByteArray(bytes, sizeof(%(type)s),
1507
                                     little, !is_unsigned);
1508
    }
1509 1510
}
""")
William Stein's avatar
William Stein committed
1511 1512

class CIntType(CNumericType):
1513

William Stein's avatar
William Stein committed
1514 1515
    is_int = 1
    typedef_flag = 0
1516 1517
    to_py_function = None
    from_py_function = None
1518
    exception_value = -1
William Stein's avatar
William Stein committed
1519

1520
    def __init__(self, rank, signed = 1):
1521
        CNumericType.__init__(self, rank, signed)
1522 1523 1524 1525 1526 1527
        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):
1528
        if self.rank < list(rank_to_type_name).index('int'):
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
            # This assumes sizeof(short) < sizeof(int)
            return "PyInt_FromLong"
        else:
            # Py{Int|Long}_From[Unsigned]Long[Long]
            Prefix = "Int"
            SignWord = ""
            TypeName = "Long"
            if not self.signed:
                Prefix = "Long"
                SignWord = "Unsigned"
1539
            if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
1540 1541 1542 1543 1544
                Prefix = "Long"
                TypeName = "LongLong"
            return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)

    def get_from_py_type_conversion(self):
1545 1546 1547 1548
        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()
1549
        if self.rank >= list(rank_to_type_name).index('long'):
1550 1551 1552 1553 1554
            utility_code = c_long_from_py_function
        else:
            utility_code = c_int_from_py_function
        utility_code.specialize(self,
                                SignWord=SignWord,
1555
                                TypeName=TypeName)
1556
        func_name = "__Pyx_PyInt_As%s%s" % (SignWord, TypeName)
1557
        return func_name
1558

1559 1560
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_int or src_type.is_enum or src_type is error_type
1561

1562
    def invalid_value(self):
1563
        if rank_to_type_name[int(self.rank)] == 'char':
1564 1565 1566 1567 1568
            return "'?'"
        else:
            # We do not really know the size of the type, so return
            # a 32-bit literal and rely on casting to final type. It will
            # be negative for signed ints, which is good.
1569
            return "0xbad0bad0"
William Stein's avatar
William Stein committed
1570

1571
    def overflow_check_binop(self, binop, env, const_rhs=False):
1572 1573 1574
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
        type = self.declaration_code("")
        name = self.specialization_name()
1575
        if binop == "lshift":
1576 1577
            env.use_utility_code(TempitaUtilityCode.load(
                "LeftShift", "Overflow.c",
1578
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
1579
        else:
1580 1581 1582
            if const_rhs:
                binop += "_const"
            if type in ('int', 'long', 'long long'):
1583 1584 1585
                env.use_utility_code(TempitaUtilityCode.load(
                    "BaseCaseSigned", "Overflow.c",
                    context={'INT': type, 'NAME': name}))
1586
            elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1587 1588 1589
                env.use_utility_code(TempitaUtilityCode.load(
                    "BaseCaseUnsigned", "Overflow.c",
                    context={'UINT': type, 'NAME': name}))
1590 1591 1592 1593 1594
            elif self.rank <= 1:
                # sizeof(short) < sizeof(int)
                return "__Pyx_%s_%s_no_overflow" % (binop, name)
            else:
                _load_overflow_base(env)
1595 1596 1597 1598 1599 1600
                env.use_utility_code(TempitaUtilityCode.load(
                    "SizeCheck", "Overflow.c",
                    context={'TYPE': type, 'NAME': name}))
                env.use_utility_code(TempitaUtilityCode.load(
                    "Binop", "Overflow.c",
                    context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
1601 1602 1603 1604 1605
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

def _load_overflow_base(env):
    env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
    for type in ('int', 'long', 'long long'):
1606 1607 1608
        env.use_utility_code(TempitaUtilityCode.load(
            "BaseCaseSigned", "Overflow.c",
            context={'INT': type, 'NAME': type.replace(' ', '_')}))
1609
    for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1610 1611 1612
        env.use_utility_code(TempitaUtilityCode.load(
            "BaseCaseUnsigned", "Overflow.c",
            context={'UINT': type, 'NAME': type.replace(' ', '_')}))
1613 1614


1615 1616
class CAnonEnumType(CIntType):

1617 1618 1619 1620
    is_enum = 1

    def sign_and_name(self):
        return 'int'
1621

1622

1623 1624
class CReturnCodeType(CIntType):

1625 1626
    to_py_function = "__Pyx_Owned_Py_None"

1627 1628
    is_returncode = 1

1629

1630 1631 1632 1633
class CBIntType(CIntType):

    to_py_function = "__Pyx_PyBool_FromLong"
    from_py_function = "__Pyx_PyObject_IsTrue"
Robert Bradshaw's avatar
Robert Bradshaw committed
1634
    exception_check = 1 # for C++ bool
1635 1636 1637 1638

    def __repr__(self):
        return "<CNumericType bint>"

1639 1640 1641
    def __str__(self):
        return 'bint'

1642 1643 1644
    def py_type_name(self):
        return "bool"

1645

Stefan Behnel's avatar
Stefan Behnel committed
1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
class CPyUCS4IntType(CIntType):
    # Py_UCS4

    is_unicode_char = True

    # Py_UCS4 coerces from and to single character unicode strings (or
    # at most two characters on 16bit Unicode builds), but we also
    # allow Python integers as input.  The value range for Py_UCS4
    # is 0..1114111, which is checked when converting from an integer
    # value.

    to_py_function = "PyUnicode_FromOrdinal"
    from_py_function = "__Pyx_PyObject_AsPy_UCS4"

    def create_from_py_utility_code(self, env):
1661
        env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c"))
Stefan Behnel's avatar
Stefan Behnel committed
1662 1663 1664 1665 1666 1667
        return True

    def sign_and_name(self):
        return "Py_UCS4"


1668 1669 1670
class CPyUnicodeIntType(CIntType):
    # Py_UNICODE

Stefan Behnel's avatar
Stefan Behnel committed
1671 1672
    is_unicode_char = True

1673 1674 1675 1676
    # Py_UNICODE coerces from and to single character unicode strings,
    # but we also allow Python integers as input.  The value range for
    # Py_UNICODE is 0..1114111, which is checked when converting from
    # an integer value.
1677

1678 1679 1680 1681
    to_py_function = "PyUnicode_FromOrdinal"
    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"

    def create_from_py_utility_code(self, env):
1682
        env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c"))
1683
        return True
1684 1685 1686 1687 1688

    def sign_and_name(self):
        return "Py_UNICODE"


1689 1690 1691 1692 1693 1694 1695 1696
class CPyHashTType(CIntType):

    to_py_function = "__Pyx_PyInt_FromHash_t"
    from_py_function = "__Pyx_PyInt_AsHash_t"

    def sign_and_name(self):
        return "Py_hash_t"

1697 1698 1699
class CPySSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
1700
    from_py_function = "__Pyx_PyIndex_AsSsize_t"
1701

1702
    def sign_and_name(self):
1703
        return "Py_ssize_t"
1704

1705 1706 1707 1708 1709 1710
class CSSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
    from_py_function = "PyInt_AsSsize_t"

    def sign_and_name(self):
1711
        return "Py_ssize_t"
1712

1713
class CSizeTType(CIntType):
1714

1715 1716
    to_py_function = "__Pyx_PyInt_FromSize_t"
    from_py_function = "__Pyx_PyInt_AsSize_t"
1717

1718
    def sign_and_name(self):
1719
        return "size_t"
1720

1721

William Stein's avatar
William Stein committed
1722 1723 1724 1725
class CFloatType(CNumericType):

    is_float = 1
    to_py_function = "PyFloat_FromDouble"
1726
    from_py_function = "__pyx_PyFloat_AsDouble"
1727 1728

    exception_value = -1
Robert Bradshaw's avatar
Robert Bradshaw committed
1729

1730 1731
    def __init__(self, rank, math_h_modifier = ''):
        CNumericType.__init__(self, rank, 1)
1732
        self.math_h_modifier = math_h_modifier
1733 1734
        if rank == RANK_FLOAT:
            self.from_py_function = "__pyx_PyFloat_AsFloat"
Robert Bradshaw's avatar
Robert Bradshaw committed
1735

1736
    def assignable_from_resolved_type(self, src_type):
1737 1738
        return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type

1739 1740
    def invalid_value(self):
        return Naming.PYX_NAN
1741

1742
class CComplexType(CNumericType):
Robert Bradshaw's avatar
Robert Bradshaw committed
1743

1744
    is_complex = 1
1745
    to_py_function = "__pyx_PyComplex_FromComplex"
1746 1747
    has_attributes = 1
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1748

1749
    def __init__(self, real_type):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1750 1751 1752 1753 1754
        while real_type.is_typedef and not real_type.typedef_is_external:
            real_type = real_type.typedef_base_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
Craig Citro's avatar
Craig Citro committed
1755
            self.funcsuffix = "_%s" % real_type.specialization_name()
1756
        elif hasattr(real_type, 'math_h_modifier'):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1757
            self.funcsuffix = real_type.math_h_modifier
1758
        else:
Craig Citro's avatar
Craig Citro committed
1759
            self.funcsuffix = "_%s" % real_type.specialization_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1760

1761 1762
        self.real_type = real_type
        CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
1763
        self.binops = {}
Craig Citro's avatar
Craig Citro committed
1764
        self.from_parts = "%s_from_parts" % self.specialization_name()
1765
        self.default_value = "%s(0, 0)" % self.from_parts
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1766

1767
    def __eq__(self, other):
1768
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
1769
            return self.real_type == other.real_type
1770
        else:
1771
            return False
Robert Bradshaw's avatar
Robert Bradshaw committed
1772

1773 1774 1775 1776 1777
    def __ne__(self, other):
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
            return self.real_type != other.real_type
        else:
            return True
1778 1779 1780 1781 1782 1783 1784 1785 1786

    def __lt__(self, other):
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
            return self.real_type < other.real_type
        else:
            # this is arbitrary, but it makes sure we always have
            # *some* kind of order
            return False

1787 1788
    def __hash__(self):
        return ~hash(self.real_type)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1789

Robert Bradshaw's avatar
Robert Bradshaw committed
1790
    def declaration_code(self, entity_code,
1791
            for_display = 0, dll_linkage = None, pyrex = 0):
1792 1793 1794
        if pyrex or for_display:
            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
            base_code = "%s complex" % real_code
1795
        else:
1796 1797
            base_code = public_decl(self.sign_and_name(), dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
1798

1799
    def sign_and_name(self):
Craig Citro's avatar
Craig Citro committed
1800
        real_type_name = self.real_type.specialization_name()
1801
        real_type_name = real_type_name.replace('long__double','long_double')
1802
        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
1803
        return Naming.type_prefix + real_type_name + "_complex"
Robert Bradshaw's avatar
Robert Bradshaw committed
1804

1805 1806
    def assignable_from(self, src_type):
        # Temporary hack/feature disabling, see #441
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1807 1808 1809
        if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
            and src_type.typedef_is_external):
             return False
1810 1811
        else:
            return super(CComplexType, self).assignable_from(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1812

1813 1814
    def assignable_from_resolved_type(self, src_type):
        return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1815
                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
1816
                    or src_type is error_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1817

1818 1819 1820
    def attributes_known(self):
        if self.scope is None:
            import Symtab
1821 1822 1823 1824 1825
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
1826
            scope.directives = {}
1827 1828
            scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True)
            scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True)
Stefan Behnel's avatar
Stefan Behnel committed
1829
            scope.declare_cfunction(
1830
                    "conjugate",
1831
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1832 1833
                    pos=None,
                    defining=1,
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1834
                    cname="__Pyx_c_conj%s" % self.funcsuffix)
1835

1836
        return True
1837

1838
    def create_declaration_utility_code(self, env):
1839 1840
        # This must always be run, because a single CComplexType instance can be shared
        # across multiple compilations (the one created in the module scope)
1841 1842 1843 1844
        env.use_utility_code(complex_header_utility_code)
        env.use_utility_code(complex_real_imag_utility_code)
        for utility_code in (complex_type_utility_code,
                             complex_from_parts_utility_code,
Craig Citro's avatar
Craig Citro committed
1845
                             complex_arithmetic_utility_code):
1846 1847
            env.use_utility_code(
                utility_code.specialize(
Robert Bradshaw's avatar
Robert Bradshaw committed
1848
                    self,
1849
                    real_type = self.real_type.declaration_code(''),
Robert Bradshaw's avatar
Robert Bradshaw committed
1850 1851
                    m = self.funcsuffix,
                    is_float = self.real_type.is_float))
1852 1853 1854 1855 1856
        return True

    def create_to_py_utility_code(self, env):
        env.use_utility_code(complex_real_imag_utility_code)
        env.use_utility_code(complex_to_py_utility_code)
1857 1858 1859 1860
        return True

    def create_from_py_utility_code(self, env):
        self.real_type.create_from_py_utility_code(env)
1861 1862 1863 1864 1865

        for utility_code in (complex_from_parts_utility_code,
                             complex_from_py_utility_code):
            env.use_utility_code(
                utility_code.specialize(
Robert Bradshaw's avatar
Robert Bradshaw committed
1866
                    self,
1867
                    real_type = self.real_type.declaration_code(''),
Robert Bradshaw's avatar
Robert Bradshaw committed
1868 1869
                    m = self.funcsuffix,
                    is_float = self.real_type.is_float))
Craig Citro's avatar
Craig Citro committed
1870
        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
1871
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1872

1873
    def lookup_op(self, nargs, op):
1874
        try:
1875
            return self.binops[nargs, op]
1876
        except KeyError:
1877 1878 1879
            pass
        try:
            op_name = complex_ops[nargs, op]
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1880
            self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
1881 1882 1883 1884 1885 1886
            return func_name
        except KeyError:
            return None

    def unary_op(self, op):
        return self.lookup_op(1, op)
Robert Bradshaw's avatar
Robert Bradshaw committed
1887

1888 1889
    def binary_op(self, op):
        return self.lookup_op(2, op)
Robert Bradshaw's avatar
Robert Bradshaw committed
1890

1891 1892 1893
    def py_type_name(self):
        return "complex"

1894 1895 1896
    def cast_code(self, expr_code):
        return expr_code

1897 1898 1899
complex_ops = {
    (1, '-'): 'neg',
    (1, 'zero'): 'is_zero',
1900 1901 1902 1903
    (2, '+'): 'sum',
    (2, '-'): 'diff',
    (2, '*'): 'prod',
    (2, '/'): 'quot',
1904 1905
    (2, '=='): 'eq',
}
1906

1907
complex_header_utility_code = UtilityCode(
1908
proto_block='h_code',
1909
proto="""
1910 1911 1912 1913 1914 1915 1916 1917
#if !defined(CYTHON_CCOMPLEX)
  #if defined(__cplusplus)
    #define CYTHON_CCOMPLEX 1
  #elif defined(_Complex_I)
    #define CYTHON_CCOMPLEX 1
  #else
    #define CYTHON_CCOMPLEX 0
  #endif
1918 1919
#endif

1920 1921 1922 1923 1924 1925 1926
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    #include <complex>
  #else
    #include <complex.h>
  #endif
#endif
Robert Bradshaw's avatar
Robert Bradshaw committed
1927 1928 1929 1930 1931

#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
  #undef _Complex_I
  #define _Complex_I 1.0fj
#endif
1932 1933
""")

1934
complex_real_imag_utility_code = UtilityCode(
1935
proto="""
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    #define __Pyx_CREAL(z) ((z).real())
    #define __Pyx_CIMAG(z) ((z).imag())
  #else
    #define __Pyx_CREAL(z) (__real__(z))
    #define __Pyx_CIMAG(z) (__imag__(z))
  #endif
#else
    #define __Pyx_CREAL(z) ((z).real)
    #define __Pyx_CIMAG(z) ((z).imag)
#endif
1948 1949 1950 1951 1952 1953 1954 1955

#if defined(_WIN32) && defined(__cplusplus) && CYTHON_CCOMPLEX
    #define __Pyx_SET_CREAL(z,x) ((z).real(x))
    #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
#else
    #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x)
    #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y)
#endif
1956 1957
""")

1958
complex_type_utility_code = UtilityCode(
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1959
proto_block='complex_type_declarations',
1960
proto="""
1961 1962 1963 1964
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    typedef ::std::complex< %(real_type)s > %(type_name)s;
  #else
1965
    typedef %(real_type)s _Complex %(type_name)s;
1966 1967 1968 1969 1970 1971 1972
  #endif
#else
    typedef struct { %(real_type)s real, imag; } %(type_name)s;
#endif
""")

complex_from_parts_utility_code = UtilityCode(
1973
proto_block='utility_code_proto',
1974
proto="""
1975
static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s, %(real_type)s);
1976 1977 1978 1979
""",
impl="""
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
1980
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
1981 1982 1983
      return ::std::complex< %(real_type)s >(x, y);
    }
  #else
1984
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
1985 1986
      return x + y*(%(type)s)_Complex_I;
    }
1987
  #endif
1988
#else
1989
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
1990
      %(type)s z;
Robert Bradshaw's avatar
Robert Bradshaw committed
1991 1992 1993
      z.real = x;
      z.imag = y;
      return z;
1994
    }
1995 1996
#endif
""")
1997

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011
complex_to_py_utility_code = UtilityCode(
proto="""
#define __pyx_PyComplex_FromComplex(z) \\
        PyComplex_FromDoubles((double)__Pyx_CREAL(z), \\
                              (double)__Pyx_CIMAG(z))
""")

complex_from_py_utility_code = UtilityCode(
proto="""
static %(type)s __Pyx_PyComplex_As_%(type_name)s(PyObject*);
""",
impl="""
static %(type)s __Pyx_PyComplex_As_%(type_name)s(PyObject* o) {
    Py_complex cval;
2012
#if CYTHON_COMPILING_IN_CPYTHON
2013 2014 2015
    if (PyComplex_CheckExact(o))
        cval = ((PyComplexObject *)o)->cval;
    else
2016
#endif
2017 2018 2019 2020 2021 2022
        cval = PyComplex_AsCComplex(o);
    return %(type_name)s_from_parts(
               (%(real_type)s)cval.real,
               (%(real_type)s)cval.imag);
}
""")
2023

Craig Citro's avatar
Craig Citro committed
2024
complex_arithmetic_utility_code = UtilityCode(
2025 2026 2027 2028 2029 2030 2031 2032 2033
proto="""
#if CYTHON_CCOMPLEX
    #define __Pyx_c_eq%(m)s(a, b)   ((a)==(b))
    #define __Pyx_c_sum%(m)s(a, b)  ((a)+(b))
    #define __Pyx_c_diff%(m)s(a, b) ((a)-(b))
    #define __Pyx_c_prod%(m)s(a, b) ((a)*(b))
    #define __Pyx_c_quot%(m)s(a, b) ((a)/(b))
    #define __Pyx_c_neg%(m)s(a)     (-(a))
  #ifdef __cplusplus
2034
    #define __Pyx_c_is_zero%(m)s(z) ((z)==(%(real_type)s)0)
2035
    #define __Pyx_c_conj%(m)s(z)    (::std::conj(z))
Robert Bradshaw's avatar
Robert Bradshaw committed
2036 2037 2038 2039
    #if %(is_float)s
        #define __Pyx_c_abs%(m)s(z)     (::std::abs(z))
        #define __Pyx_c_pow%(m)s(a, b)  (::std::pow(a, b))
    #endif
2040 2041 2042
  #else
    #define __Pyx_c_is_zero%(m)s(z) ((z)==0)
    #define __Pyx_c_conj%(m)s(z)    (conj%(m)s(z))
Robert Bradshaw's avatar
Robert Bradshaw committed
2043 2044 2045 2046
    #if %(is_float)s
        #define __Pyx_c_abs%(m)s(z)     (cabs%(m)s(z))
        #define __Pyx_c_pow%(m)s(a, b)  (cpow%(m)s(a, b))
    #endif
2047 2048
 #endif
#else
2049 2050 2051 2052 2053 2054 2055 2056
    static CYTHON_INLINE int __Pyx_c_eq%(m)s(%(type)s, %(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_sum%(m)s(%(type)s, %(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_diff%(m)s(%(type)s, %(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_prod%(m)s(%(type)s, %(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_quot%(m)s(%(type)s, %(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_neg%(m)s(%(type)s);
    static CYTHON_INLINE int __Pyx_c_is_zero%(m)s(%(type)s);
    static CYTHON_INLINE %(type)s __Pyx_c_conj%(m)s(%(type)s);
Robert Bradshaw's avatar
Robert Bradshaw committed
2057 2058 2059 2060
    #if %(is_float)s
        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s);
        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s, %(type)s);
    #endif
2061 2062 2063 2064 2065
#endif
""",
impl="""
#if CYTHON_CCOMPLEX
#else
2066
    static CYTHON_INLINE int __Pyx_c_eq%(m)s(%(type)s a, %(type)s b) {
2067 2068
       return (a.real == b.real) && (a.imag == b.imag);
    }
2069
    static CYTHON_INLINE %(type)s __Pyx_c_sum%(m)s(%(type)s a, %(type)s b) {
2070 2071 2072 2073 2074
        %(type)s z;
        z.real = a.real + b.real;
        z.imag = a.imag + b.imag;
        return z;
    }
2075
    static CYTHON_INLINE %(type)s __Pyx_c_diff%(m)s(%(type)s a, %(type)s b) {
2076 2077 2078 2079 2080
        %(type)s z;
        z.real = a.real - b.real;
        z.imag = a.imag - b.imag;
        return z;
    }
2081
    static CYTHON_INLINE %(type)s __Pyx_c_prod%(m)s(%(type)s a, %(type)s b) {
2082 2083 2084 2085 2086
        %(type)s z;
        z.real = a.real * b.real - a.imag * b.imag;
        z.imag = a.real * b.imag + a.imag * b.real;
        return z;
    }
2087
    static CYTHON_INLINE %(type)s __Pyx_c_quot%(m)s(%(type)s a, %(type)s b) {
2088
        %(type)s z;
2089
        %(real_type)s denom = b.real * b.real + b.imag * b.imag;
2090 2091 2092 2093
        z.real = (a.real * b.real + a.imag * b.imag) / denom;
        z.imag = (a.imag * b.real - a.real * b.imag) / denom;
        return z;
    }
2094
    static CYTHON_INLINE %(type)s __Pyx_c_neg%(m)s(%(type)s a) {
2095 2096 2097 2098 2099
        %(type)s z;
        z.real = -a.real;
        z.imag = -a.imag;
        return z;
    }
2100
    static CYTHON_INLINE int __Pyx_c_is_zero%(m)s(%(type)s a) {
2101 2102
       return (a.real == 0) && (a.imag == 0);
    }
2103
    static CYTHON_INLINE %(type)s __Pyx_c_conj%(m)s(%(type)s a) {
2104 2105 2106 2107 2108
        %(type)s z;
        z.real =  a.real;
        z.imag = -a.imag;
        return z;
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
2109 2110
    #if %(is_float)s
        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
2111
          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
Robert Bradshaw's avatar
Robert Bradshaw committed
2112
            return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
2113 2114
          #else
            return hypot%(m)s(z.real, z.imag);
Robert Bradshaw's avatar
Robert Bradshaw committed
2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
          #endif
        }
        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s a, %(type)s b) {
            %(type)s z;
            %(real_type)s r, lnr, theta, z_r, z_theta;
            if (b.imag == 0 && b.real == (int)b.real) {
                if (b.real < 0) {
                    %(real_type)s denom = a.real * a.real + a.imag * a.imag;
                    a.real = a.real / denom;
                    a.imag = -a.imag / denom;
                    b.real = -b.real;
                }
                switch ((int)b.real) {
                    case 0:
                        z.real = 1;
                        z.imag = 0;
                        return z;
                    case 1:
                        return a;
                    case 2:
                        z = __Pyx_c_prod%(m)s(a, a);
                        return __Pyx_c_prod%(m)s(a, a);
                    case 3:
                        z = __Pyx_c_prod%(m)s(a, a);
                        return __Pyx_c_prod%(m)s(z, a);
                    case 4:
                        z = __Pyx_c_prod%(m)s(a, a);
                        return __Pyx_c_prod%(m)s(z, z);
                }
            }
            if (a.imag == 0) {
                if (a.real == 0) {
                    return a;
                }
                r = a.real;
                theta = 0;
            } else {
                r = __Pyx_c_abs%(m)s(a);
                theta = atan2%(m)s(a.imag, a.real);
            }
            lnr = log%(m)s(r);
            z_r = exp%(m)s(lnr * b.real - theta * b.imag);
            z_theta = theta * b.real + lnr * b.imag;
            z.real = z_r * cos%(m)s(z_theta);
            z.imag = z_r * sin%(m)s(z_theta);
            return z;
        }
    #endif
2163
#endif
2164
""")
2165

2166 2167 2168 2169
class CPointerBaseType(CType):
    # common base type for pointer/array types
    #
    #  base_type     CType              Reference type
2170 2171 2172

    subtypes = ['base_type']

2173
    def __init__(self, base_type):
William Stein's avatar
William Stein committed
2174
        self.base_type = base_type
2175 2176 2177 2178
        for char_type in (c_char_type, c_uchar_type, c_schar_type):
            if base_type.same_as(char_type):
                self.is_string = 1
                break
Robert Bradshaw's avatar
Robert Bradshaw committed
2179

2180
        if self.is_string and not base_type.is_error:
2181
            if base_type.signed:
2182
                self.to_py_function = "__Pyx_PyObject_FromString"
2183
                if self.is_ptr:
2184
                    self.from_py_function = "__Pyx_PyObject_AsString"
2185
            else:
2186
                self.to_py_function = "__Pyx_PyObject_FromUString"
2187
                if self.is_ptr:
2188
                    self.from_py_function = "__Pyx_PyObject_AsUString"
2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212
            self.exception_value = "NULL"

    def py_type_name(self):
        if self.is_string:
            return "bytes"
        else:
            return super(CPointerBaseType, self).py_type_name()

    def literal_code(self, value):
        if self.is_string:
            assert isinstance(value, str)
            return '"%s"' % StringEncoding.escape_byte_string(value)


class CArrayType(CPointerBaseType):
    #  base_type     CType              Element type
    #  size          integer or None    Number of elements

    is_array = 1

    def __init__(self, base_type, size):
        super(CArrayType, self).__init__(base_type)
        self.size = size

2213
    def __eq__(self, other):
2214 2215
        if isinstance(other, CType) and other.is_array and self.size == other.size:
            return self.base_type.same_as(other.base_type)
2216 2217
        return False

2218 2219 2220
    def __hash__(self):
        return hash(self.base_type) + 28 # arbitrarily chosen offset

William Stein's avatar
William Stein committed
2221
    def __repr__(self):
2222
        return "<CArrayType %s %s>" % (self.size, repr(self.base_type))
Robert Bradshaw's avatar
Robert Bradshaw committed
2223

William Stein's avatar
William Stein committed
2224 2225 2226 2227
    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)
Robert Bradshaw's avatar
Robert Bradshaw committed
2228

William Stein's avatar
William Stein committed
2229 2230 2231
    def assignable_from_resolved_type(self, src_type):
        # Can't assign to a variable of an array type
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2232

William Stein's avatar
William Stein committed
2233 2234 2235
    def element_ptr_type(self):
        return c_ptr_type(self.base_type)

Robert Bradshaw's avatar
Robert Bradshaw committed
2236
    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2237 2238 2239 2240 2241
            for_display = 0, dll_linkage = None, pyrex = 0):
        if self.size is not None:
            dimension_code = self.size
        else:
            dimension_code = ""
2242 2243
        if entity_code.startswith("*"):
            entity_code = "(%s)" % entity_code
William Stein's avatar
William Stein committed
2244
        return self.base_type.declaration_code(
2245
            "%s[%s]" % (entity_code, dimension_code),
William Stein's avatar
William Stein committed
2246
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2247

William Stein's avatar
William Stein committed
2248 2249
    def as_argument_type(self):
        return c_ptr_type(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2250

William Stein's avatar
William Stein committed
2251 2252 2253 2254
    def is_complete(self):
        return self.size is not None


2255 2256
class CPtrType(CPointerBaseType):
    #  base_type     CType              Reference type
Robert Bradshaw's avatar
Robert Bradshaw committed
2257

William Stein's avatar
William Stein committed
2258
    is_ptr = 1
2259
    default_value = "0"
2260

2261 2262 2263
    def __hash__(self):
        return hash(self.base_type) + 27 # arbitrarily chosen offset

2264 2265 2266 2267 2268
    def __eq__(self, other):
        if isinstance(other, CType) and other.is_ptr:
            return self.base_type.same_as(other.base_type)
        return False

William Stein's avatar
William Stein committed
2269
    def __repr__(self):
2270
        return "<CPtrType %s>" % repr(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2271

William Stein's avatar
William Stein committed
2272 2273 2274 2275
    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)
Robert Bradshaw's avatar
Robert Bradshaw committed
2276 2277

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2278 2279 2280
            for_display = 0, dll_linkage = None, pyrex = 0):
        #print "CPtrType.declaration_code: pointer to", self.base_type ###
        return self.base_type.declaration_code(
2281
            "*%s" % entity_code,
William Stein's avatar
William Stein committed
2282
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2283

William Stein's avatar
William Stein committed
2284 2285 2286
    def assignable_from_resolved_type(self, other_type):
        if other_type is error_type:
            return 1
2287
        if other_type.is_null_ptr:
William Stein's avatar
William Stein committed
2288
            return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2289 2290
        if self.base_type.is_const:
            self = CPtrType(self.base_type.const_base_type)
2291 2292 2293 2294 2295 2296 2297
        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
Robert Bradshaw's avatar
Robert Bradshaw committed
2298
        if (self.base_type.is_cpp_class and other_type.is_ptr
2299 2300
                and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)):
            return 1
2301
        if other_type.is_array or other_type.is_ptr:
2302
            return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
2303
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2304

2305 2306 2307 2308 2309 2310
    def specialize(self, values):
        base_type = self.base_type.specialize(values)
        if base_type == self.base_type:
            return self
        else:
            return CPtrType(base_type)
William Stein's avatar
William Stein committed
2311

2312 2313
    def invalid_value(self):
        return "1"
William Stein's avatar
William Stein committed
2314

2315 2316
    def find_cpp_operation_type(self, operator, operand_type=None):
        if self.base_type.is_cpp_class:
Stefan Behnel's avatar
Stefan Behnel committed
2317
            return self.base_type.find_cpp_operation_type(operator, operand_type)
2318 2319
        return None

William Stein's avatar
William Stein committed
2320 2321 2322
class CNullPtrType(CPtrType):

    is_null_ptr = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2323

William Stein's avatar
William Stein committed
2324

Robert Bradshaw's avatar
Robert Bradshaw committed
2325
class CReferenceType(BaseType):
Danilo Freitas's avatar
Danilo Freitas committed
2326 2327 2328 2329

    is_reference = 1

    def __init__(self, base_type):
Robert Bradshaw's avatar
Robert Bradshaw committed
2330
        self.ref_base_type = base_type
Danilo Freitas's avatar
Danilo Freitas committed
2331 2332

    def __repr__(self):
Robert Bradshaw's avatar
Robert Bradshaw committed
2333
        return "<CReferenceType %s>" % repr(self.ref_base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2334

Robert Bradshaw's avatar
Robert Bradshaw committed
2335 2336
    def __str__(self):
        return "%s &" % self.ref_base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2337

Robert Bradshaw's avatar
Robert Bradshaw committed
2338
    def declaration_code(self, entity_code,
Danilo Freitas's avatar
Danilo Freitas committed
2339
            for_display = 0, dll_linkage = None, pyrex = 0):
2340
        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
Robert Bradshaw's avatar
Robert Bradshaw committed
2341
        return self.ref_base_type.declaration_code(
Danilo Freitas's avatar
Danilo Freitas committed
2342 2343
            "&%s" % entity_code,
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2344

Danilo Freitas's avatar
Danilo Freitas committed
2345
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
2346 2347
        base_type = self.ref_base_type.specialize(values)
        if base_type == self.ref_base_type:
Danilo Freitas's avatar
Danilo Freitas committed
2348 2349 2350 2351
            return self
        else:
            return CReferenceType(base_type)

Robert Bradshaw's avatar
Robert Bradshaw committed
2352 2353 2354 2355
    def __getattr__(self, name):
        return getattr(self.ref_base_type, name)


William Stein's avatar
William Stein committed
2356 2357 2358 2359 2360
class CFuncType(CType):
    #  return_type      CType
    #  args             [CFuncTypeArg]
    #  has_varargs      boolean
    #  exception_value  string
2361 2362 2363 2364
    #  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
Danilo Freitas's avatar
Danilo Freitas committed
2365
    #  templates        [string] or None
2366
    #  cached_specialized_types [CFuncType]   cached specialized versions of the CFuncType if defined in a pxd
Mark Florisson's avatar
Mark Florisson committed
2367 2368
    #  from_fused       boolean    Indicates whether this is a specialized
    #                              C function
2369 2370
    #  is_strict_signature boolean  function refuses to accept coerced arguments
    #                               (used for optimisation overrides)
Robert Bradshaw's avatar
Robert Bradshaw committed
2371
    #  is_const_method  boolean
Robert Bradshaw's avatar
Robert Bradshaw committed
2372

William Stein's avatar
William Stein committed
2373
    is_cfunction = 1
2374
    original_sig = None
2375
    cached_specialized_types = None
Mark Florisson's avatar
Mark Florisson committed
2376
    from_fused = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2377
    is_const_method = False
2378 2379 2380

    subtypes = ['return_type', 'args']

2381 2382
    def __init__(self, return_type, args, has_varargs = 0,
            exception_value = None, exception_check = 0, calling_convention = "",
Danilo Freitas's avatar
Danilo Freitas committed
2383
            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
2384
            templates = None, is_strict_signature = False):
William Stein's avatar
William Stein committed
2385 2386 2387
        self.return_type = return_type
        self.args = args
        self.has_varargs = has_varargs
2388
        self.optional_arg_count = optional_arg_count
William Stein's avatar
William Stein committed
2389 2390
        self.exception_value = exception_value
        self.exception_check = exception_check
2391 2392
        self.calling_convention = calling_convention
        self.nogil = nogil
2393
        self.with_gil = with_gil
2394
        self.is_overridable = is_overridable
Danilo Freitas's avatar
Danilo Freitas committed
2395
        self.templates = templates
2396
        self.is_strict_signature = is_strict_signature
2397

William Stein's avatar
William Stein committed
2398 2399 2400 2401
    def __repr__(self):
        arg_reprs = map(repr, self.args)
        if self.has_varargs:
            arg_reprs.append("...")
2402 2403 2404 2405 2406 2407 2408
        if self.exception_value:
            except_clause = " %r" % self.exception_value
        else:
            except_clause = ""
        if self.exception_check:
            except_clause += "?"
        return "<CFuncType %s %s[%s]%s>" % (
William Stein's avatar
William Stein committed
2409
            repr(self.return_type),
2410
            self.calling_convention_prefix(),
2411 2412
            ",".join(arg_reprs),
            except_clause)
Robert Bradshaw's avatar
Robert Bradshaw committed
2413

2414 2415 2416 2417 2418 2419
    def calling_convention_prefix(self):
        cc = self.calling_convention
        if cc:
            return cc + " "
        else:
            return ""
Robert Bradshaw's avatar
Robert Bradshaw committed
2420

2421 2422 2423
    def as_argument_type(self):
        return c_ptr_type(self)

William Stein's avatar
William Stein committed
2424 2425 2426 2427
    def same_c_signature_as(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(
            other_type.resolve(), as_cmethod)

2428
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod = 0):
2429
        #print "CFuncType.same_c_signature_as_resolved_type:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
2430
        #    self, other_type, "as_cmethod =", as_cmethod ###
William Stein's avatar
William Stein committed
2431 2432 2433 2434
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2435
        if self.is_overridable != other_type.is_overridable:
2436
            return 0
William Stein's avatar
William Stein committed
2437
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
2438
        if nargs != len(other_type.args):
William Stein's avatar
William Stein committed
2439 2440 2441 2442 2443 2444 2445 2446
            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
2447
        if self.has_varargs != other_type.has_varargs:
William Stein's avatar
William Stein committed
2448
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2449
        if self.optional_arg_count != other_type.optional_arg_count:
2450
            return 0
William Stein's avatar
William Stein committed
2451 2452
        if not self.return_type.same_as(other_type.return_type):
            return 0
2453 2454
        if not self.same_calling_convention_as(other_type):
            return 0
William Stein's avatar
William Stein committed
2455
        return 1
2456

2457 2458
    def compatible_signature_with(self, other_type, as_cmethod = 0):
        return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
Robert Bradshaw's avatar
Robert Bradshaw committed
2459

2460 2461
    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
2462
        #    self, other_type, "as_cmethod =", as_cmethod ###
2463 2464 2465 2466
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2467
        if not self.is_overridable and other_type.is_overridable:
2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482
            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
2483
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
2484 2485 2486
            return 0
        if not self.same_calling_convention_as(other_type):
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2487 2488
        if self.nogil != other_type.nogil:
            return 0
2489
        self.original_sig = other_type.original_sig or other_type
2490 2491 2492
        if as_cmethod:
            self.args[0] = other_type.args[0]
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2493 2494


2495 2496
    def narrower_c_signature_than(self, other_type, as_cmethod = 0):
        return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
Robert Bradshaw's avatar
Robert Bradshaw committed
2497

2498 2499 2500 2501 2502 2503
    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
2504
        if nargs != len(other_type.args):
2505 2506 2507 2508 2509 2510 2511
            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
2512
        if self.has_varargs != other_type.has_varargs:
2513
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2514
        if self.optional_arg_count != other_type.optional_arg_count:
2515
            return 0
2516 2517 2518 2519
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
            return 0
        return 1

2520
    def same_calling_convention_as(self, other):
2521 2522 2523 2524 2525 2526 2527 2528 2529
        ## XXX Under discussion ...
        ## callspec_words = ("__stdcall", "__cdecl", "__fastcall")
        ## cs1 = self.calling_convention
        ## cs2 = other.calling_convention
        ## if (cs1 in callspec_words or
        ##     cs2 in callspec_words):
        ##     return cs1 == cs2
        ## else:
        ##     return True
2530 2531 2532
        sc1 = self.calling_convention == '__stdcall'
        sc2 = other.calling_convention == '__stdcall'
        return sc1 == sc2
Robert Bradshaw's avatar
Robert Bradshaw committed
2533

William Stein's avatar
William Stein committed
2534 2535 2536 2537 2538 2539 2540
    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
Robert Bradshaw's avatar
Robert Bradshaw committed
2541

William Stein's avatar
William Stein committed
2542 2543
    def same_as_resolved_type(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(other_type, as_cmethod) \
2544 2545
            and self.same_exception_signature_as_resolved_type(other_type) \
            and self.nogil == other_type.nogil
Robert Bradshaw's avatar
Robert Bradshaw committed
2546

2547 2548 2549 2550
    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)
Robert Bradshaw's avatar
Robert Bradshaw committed
2551 2552

    def declaration_code(self, entity_code,
2553 2554
                         for_display = 0, dll_linkage = None, pyrex = 0,
                         with_calling_convention = 1):
William Stein's avatar
William Stein committed
2555
        arg_decl_list = []
2556
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
William Stein's avatar
William Stein committed
2557 2558
            arg_decl_list.append(
                arg.type.declaration_code("", for_display, pyrex = pyrex))
2559 2560
        if self.is_overridable:
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
2561
        if self.optional_arg_count:
2562
            arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
2563 2564
        if self.has_varargs:
            arg_decl_list.append("...")
2565
        arg_decl_code = ", ".join(arg_decl_list)
William Stein's avatar
William Stein committed
2566 2567
        if not arg_decl_code and not pyrex:
            arg_decl_code = "void"
2568
        trailer = ""
2569
        if (pyrex or for_display) and not self.return_type.is_pyobject:
William Stein's avatar
William Stein committed
2570
            if self.exception_value and self.exception_check:
2571
                trailer = " except? %s" % self.exception_value
William Stein's avatar
William Stein committed
2572
            elif self.exception_value:
2573
                trailer = " except %s" % self.exception_value
Felix Wu's avatar
Felix Wu committed
2574
            elif self.exception_check == '+':
2575
                trailer = " except +"
Felix Wu's avatar
Felix Wu committed
2576
            else:
2577 2578 2579
                " except *" # ignored
            if self.nogil:
                trailer += " nogil"
2580 2581 2582 2583 2584 2585 2586
        if not with_calling_convention:
            cc = ''
        else:
            cc = self.calling_convention_prefix()
            if (not entity_code and cc) or entity_code.startswith("*"):
                entity_code = "(%s%s)" % (cc, entity_code)
                cc = ""
Robert Bradshaw's avatar
Robert Bradshaw committed
2587 2588
        if self.is_const_method:
            trailer += " const"
William Stein's avatar
William Stein committed
2589
        return self.return_type.declaration_code(
2590
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
William Stein's avatar
William Stein committed
2591
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2592

2593
    def function_header_code(self, func_name, arg_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2594 2595 2596 2597 2598 2599
        if self.is_const_method:
            trailer = " const"
        else:
            trailer = ""
        return "%s%s(%s)%s" % (self.calling_convention_prefix(),
            func_name, arg_code, trailer)
William Stein's avatar
William Stein committed
2600

2601 2602 2603 2604
    def signature_string(self):
        s = self.declaration_code("")
        return s

2605 2606 2607
    def signature_cast_string(self):
        s = self.declaration_code("(*)", with_calling_convention=False)
        return '(%s)' % s
Robert Bradshaw's avatar
Robert Bradshaw committed
2608

Robert Bradshaw's avatar
Robert Bradshaw committed
2609 2610 2611 2612 2613
    def specialize(self, values):
        if self.templates is None:
            new_templates = None
        else:
            new_templates = [v.specialize(values) for v in self.templates]
2614

Mark Florisson's avatar
Mark Florisson committed
2615 2616
        result = CFuncType(self.return_type.specialize(values),
                           [arg.specialize(values) for arg in self.args],
2617
                           has_varargs = self.has_varargs,
Mark Florisson's avatar
Mark Florisson committed
2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628
                           exception_value = self.exception_value,
                           exception_check = self.exception_check,
                           calling_convention = self.calling_convention,
                           nogil = self.nogil,
                           with_gil = self.with_gil,
                           is_overridable = self.is_overridable,
                           optional_arg_count = self.optional_arg_count,
                           templates = new_templates)

        result.from_fused = self.is_fused
        return result
Robert Bradshaw's avatar
Robert Bradshaw committed
2629

2630 2631
    def opt_arg_cname(self, arg_name):
        return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
2632

2633 2634 2635 2636
    # Methods that deal with Fused Types
    # All but map_with_specific_entries should be called only on functions
    # with fused types (and not on their corresponding specific versions).

2637
    def get_all_specialized_permutations(self, fused_types=None):
2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
        """
        Permute all the types. For every specific instance of a fused type, we
        want all other specific instances of all other fused types.

        It returns an iterable of two-tuples of the cname that should prefix
        the cname of the function, and a dict mapping any fused types to their
        respective specific types.
        """
        assert self.is_fused

        if fused_types is None:
            fused_types = self.get_fused_types()

2651
        return get_all_specialized_permutations(fused_types)
2652

2653
    def get_all_specialized_function_types(self):
2654 2655 2656 2657 2658
        """
        Get all the specific function types of this one.
        """
        assert self.is_fused

2659 2660 2661 2662 2663
        if self.entry.fused_cfunction:
            return [n.type for n in self.entry.fused_cfunction.nodes]
        elif self.cached_specialized_types is not None:
            return self.cached_specialized_types

Mark Florisson's avatar
Mark Florisson committed
2664 2665 2666
        cfunc_entries = self.entry.scope.cfunc_entries
        cfunc_entries.remove(self.entry)

2667
        result = []
2668
        permutations = self.get_all_specialized_permutations()
2669

2670 2671 2672
        for cname, fused_to_specific in permutations:
            new_func_type = self.entry.type.specialize(fused_to_specific)

2673 2674 2675 2676
            if self.optional_arg_count:
                # Remember, this method is set by CFuncDeclaratorNode
                self.declare_opt_arg_struct(new_func_type, cname)

2677
            new_entry = copy.deepcopy(self.entry)
Mark Florisson's avatar
Mark Florisson committed
2678
            new_func_type.specialize_entry(new_entry, cname)
2679

2680
            new_entry.type = new_func_type
2681
            new_func_type.entry = new_entry
2682 2683
            result.append(new_func_type)

Mark Florisson's avatar
Mark Florisson committed
2684 2685
            cfunc_entries.append(new_entry)

2686 2687
        self.cached_specialized_types = result

2688
        return result
2689

Mark Florisson's avatar
Mark Florisson committed
2690
    def get_fused_types(self, result=None, seen=None, subtypes=None):
Stefan Behnel's avatar
Stefan Behnel committed
2691
        """Return fused types in the order they appear as parameter types"""
Mark Florisson's avatar
Mark Florisson committed
2692 2693
        return super(CFuncType, self).get_fused_types(result, seen,
                                                      subtypes=['args'])
2694

Mark Florisson's avatar
Mark Florisson committed
2695 2696
    def specialize_entry(self, entry, cname):
        assert not self.is_fused
2697
        specialize_entry(entry, cname)
Mark Florisson's avatar
Mark Florisson committed
2698 2699


2700 2701 2702 2703
def specialize_entry(entry, cname):
    """
    Specialize an entry of a copied fused function or method
    """
2704
    entry.is_fused_specialized = True
2705
    entry.name = get_fused_cname(cname, entry.name)
Mark Florisson's avatar
Mark Florisson committed
2706

2707 2708 2709 2710 2711 2712 2713
    if entry.is_cmethod:
        entry.cname = entry.name
        if entry.is_inherited:
            entry.cname = StringEncoding.EncodedString(
                    "%s.%s" % (Naming.obj_base_cname, entry.cname))
    else:
        entry.cname = get_fused_cname(cname, entry.cname)
2714

2715 2716
    if entry.func_cname:
        entry.func_cname = get_fused_cname(cname, entry.func_cname)
2717 2718 2719 2720 2721

def get_fused_cname(fused_cname, orig_cname):
    """
    Given the fused cname id and an original cname, return a specialized cname
    """
Mark Florisson's avatar
Mark Florisson committed
2722
    assert fused_cname and orig_cname
2723 2724
    return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix,
                                                    fused_cname, orig_cname))
2725

2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739
def unique(somelist):
    seen = set()
    result = []
    for obj in somelist:
        if obj not in seen:
            result.append(obj)
            seen.add(obj)

    return result

def get_all_specialized_permutations(fused_types):
    return _get_all_specialized_permutations(unique(fused_types))

def _get_all_specialized_permutations(fused_types, id="", f2s=()):
2740
    fused_type, = fused_types[0].get_fused_types()
2741 2742
    result = []

2743
    for newid, specific_type in enumerate(fused_type.types):
2744 2745 2746 2747
        # f2s = dict(f2s, **{ fused_type: specific_type })
        f2s = dict(f2s)
        f2s.update({ fused_type: specific_type })

2748 2749 2750
        if id:
            cname = '%s_%s' % (id, newid)
        else:
2751
            cname = str(newid)
2752 2753

        if len(fused_types) > 1:
2754
            result.extend(_get_all_specialized_permutations(
2755 2756 2757 2758 2759 2760
                                            fused_types[1:], cname, f2s))
        else:
            result.append((cname, f2s))

    return result

2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785
def specialization_signature_string(fused_compound_type, fused_to_specific):
    """
    Return the signature for a specialization of a fused type. e.g.

        floating[:] ->
            'float' or 'double'

        cdef fused ft:
            float[:]
            double[:]

        ft ->
            'float[:]' or 'double[:]'

        integral func(floating) ->
            'int (*func)(float)' or ...
    """
    fused_types = fused_compound_type.get_fused_types()
    if len(fused_types) == 1:
        fused_type = fused_types[0]
    else:
        fused_type = fused_compound_type

    return fused_type.specialize(fused_to_specific).typeof_name()

2786 2787 2788 2789 2790
def get_specialized_types(type):
    """
    Return a list of specialized types sorted in reverse order in accordance
    with their preference in runtime fused-type dispatch
    """
2791 2792
    assert type.is_fused

2793
    if isinstance(type, FusedType):
2794
        result = type.types
2795 2796
        for specialized_type in result:
            specialized_type.specialization_string = specialized_type.typeof_name()
2797 2798
    else:
        result = []
2799
        for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
2800 2801 2802 2803
            specialized_type = type.specialize(f2s)
            specialized_type.specialization_string = (
                            specialization_signature_string(type, f2s))
            result.append(specialized_type)
2804

2805
    return sorted(result)
2806

William Stein's avatar
William Stein committed
2807

2808
class CFuncTypeArg(BaseType):
William Stein's avatar
William Stein committed
2809 2810 2811 2812
    #  name       string
    #  cname      string
    #  type       PyrexType
    #  pos        source file position
2813 2814 2815 2816 2817

    # FIXME: is this the right setup? should None be allowed here?
    not_none = False
    or_none = False
    accept_none = True
Stefan Behnel's avatar
Stefan Behnel committed
2818
    accept_builtin_subtypes = False
2819

2820 2821
    subtypes = ['type']

2822
    def __init__(self, name, type, pos, cname=None):
William Stein's avatar
William Stein committed
2823
        self.name = name
2824 2825 2826 2827
        if cname is not None:
            self.cname = cname
        else:
            self.cname = Naming.var_prefix + name
William Stein's avatar
William Stein committed
2828 2829
        self.type = type
        self.pos = pos
2830
        self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
Robert Bradshaw's avatar
Robert Bradshaw committed
2831

William Stein's avatar
William Stein committed
2832 2833
    def __repr__(self):
        return "%s:%s" % (self.name, repr(self.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
2834

William Stein's avatar
William Stein committed
2835 2836
    def declaration_code(self, for_display = 0):
        return self.type.declaration_code(self.cname, for_display)
Robert Bradshaw's avatar
Robert Bradshaw committed
2837

Robert Bradshaw's avatar
Robert Bradshaw committed
2838 2839
    def specialize(self, values):
        return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
William Stein's avatar
William Stein committed
2840

Mark Florisson's avatar
Mark Florisson committed
2841
class ToPyStructUtilityCode(object):
2842 2843 2844

    requires = None

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2845 2846
    def __init__(self, type, forward_decl):
        self.type = type
Mark Florisson's avatar
Mark Florisson committed
2847 2848
        self.header = "static PyObject* %s(%s)" % (type.to_py_function,
                                                   type.declaration_code('s'))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2849 2850 2851
        self.forward_decl = forward_decl

    def __eq__(self, other):
Mark Florisson's avatar
Mark Florisson committed
2852 2853
        return isinstance(other, ToPyStructUtilityCode) and self.header == other.header

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2854 2855
    def __hash__(self):
        return hash(self.header)
Robert Bradshaw's avatar
Robert Bradshaw committed
2856

2857 2858
    def get_tree(self):
        pass
Vitja Makarov's avatar
Vitja Makarov committed
2859

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2860 2861 2862
    def put_code(self, output):
        code = output['utility_code_def']
        proto = output['utility_code_proto']
Robert Bradshaw's avatar
Robert Bradshaw committed
2863

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885
        code.putln("%s {" % self.header)
        code.putln("PyObject* res;")
        code.putln("PyObject* member;")
        code.putln("res = PyDict_New(); if (res == NULL) return NULL;")
        for member in self.type.scope.var_entries:
            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
            code.putln("member = %s(s.%s); if (member == NULL) goto bad;" % (
                member.type.to_py_function, member.cname))
            code.putln("if (PyDict_SetItem(res, %s, member) < 0) goto bad;" % nameconst_cname)
            code.putln("Py_DECREF(member);")
        code.putln("return res;")
        code.putln("bad:")
        code.putln("Py_XDECREF(member);")
        code.putln("Py_DECREF(res);")
        code.putln("return NULL;")
        code.putln("}")

        # This is a bit of a hack, we need a forward declaration
        # due to the way things are ordered in the module...
        if self.forward_decl:
            proto.putln(self.type.declaration_code('') + ';')
        proto.putln(self.header + ";")
Robert Bradshaw's avatar
Robert Bradshaw committed
2886

2887 2888
    def inject_tree_and_scope_into(self, module_node):
        pass
Vitja Makarov's avatar
Vitja Makarov committed
2889

William Stein's avatar
William Stein committed
2890 2891 2892 2893 2894 2895 2896

class CStructOrUnionType(CType):
    #  name          string
    #  cname         string
    #  kind          string              "struct" or "union"
    #  scope         StructOrUnionScope, or None if incomplete
    #  typedef_flag  boolean
2897
    #  packed        boolean
Robert Bradshaw's avatar
Robert Bradshaw committed
2898

2899
    # entry          Entry
Robert Bradshaw's avatar
Robert Bradshaw committed
2900

William Stein's avatar
William Stein committed
2901 2902
    is_struct_or_union = 1
    has_attributes = 1
Mark Florisson's avatar
Mark Florisson committed
2903
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
2904

2905
    def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
William Stein's avatar
William Stein committed
2906 2907 2908 2909 2910
        self.name = name
        self.cname = cname
        self.kind = kind
        self.scope = scope
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
2911
        self.is_struct = kind == 'struct'
Robert Bradshaw's avatar
Robert Bradshaw committed
2912 2913
        if self.is_struct:
            self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
Mark Florisson's avatar
Mark Florisson committed
2914
            self.from_py_function = "%s_from_py_%s" % (Naming.convert_func_prefix, self.cname)
Robert Bradshaw's avatar
Robert Bradshaw committed
2915
        self.exception_check = True
Mark Florisson's avatar
Mark Florisson committed
2916 2917
        self._convert_to_py_code = None
        self._convert_from_py_code = None
2918
        self.packed = packed
Robert Bradshaw's avatar
Robert Bradshaw committed
2919

2920
    def create_to_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2921 2922
        if env.outer_scope is None:
            return False
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2923

2924
        if self._convert_to_py_code is False: return None # tri-state-ish
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2925

Mark Florisson's avatar
Mark Florisson committed
2926
        if self._convert_to_py_code is None:
Robert Bradshaw's avatar
Robert Bradshaw committed
2927
            for member in self.scope.var_entries:
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2928
                if not member.type.to_py_function or not member.type.create_to_py_utility_code(env):
Robert Bradshaw's avatar
Robert Bradshaw committed
2929
                    self.to_py_function = None
Mark Florisson's avatar
Mark Florisson committed
2930
                    self._convert_to_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2931
                    return False
2932
            forward_decl = (self.entry.visibility != 'extern')
Mark Florisson's avatar
Mark Florisson committed
2933
            self._convert_to_py_code = ToPyStructUtilityCode(self, forward_decl)
Robert Bradshaw's avatar
Robert Bradshaw committed
2934

Mark Florisson's avatar
Mark Florisson committed
2935 2936 2937 2938 2939 2940 2941
        env.use_utility_code(self._convert_to_py_code)
        return True

    def create_from_py_utility_code(self, env):
        if env.outer_scope is None:
            return False

2942
        if self._convert_from_py_code is False: return None # tri-state-ish
Mark Florisson's avatar
Mark Florisson committed
2943 2944 2945 2946 2947 2948 2949

        if self._convert_from_py_code is None:
            for member in self.scope.var_entries:
                if (not member.type.from_py_function or not
                        member.type.create_from_py_utility_code(env)):
                    self.from_py_function = None
                    self._convert_from_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2950
                    return False
Mark Florisson's avatar
Mark Florisson committed
2951 2952 2953 2954 2955 2956

            context = dict(
                struct_type_decl = self.declaration_code(""),
                var_entries = self.scope.var_entries,
                funcname = self.from_py_function,
            )
2957 2958
            self._convert_from_py_code = TempitaUtilityCode.load(
                      "FromPyStructUtility", "TypeConversion.c", context=context)
Mark Florisson's avatar
Mark Florisson committed
2959 2960

        env.use_utility_code(self._convert_from_py_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
2961
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
2962

William Stein's avatar
William Stein committed
2963
    def __repr__(self):
2964 2965
        return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
2966

Robert Bradshaw's avatar
Robert Bradshaw committed
2967
    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2968
            for_display = 0, dll_linkage = None, pyrex = 0):
2969 2970
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
2971
        else:
2972 2973
            if self.typedef_flag:
                base_code = self.cname
William Stein's avatar
William Stein committed
2974
            else:
2975 2976 2977
                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)
William Stein's avatar
William Stein committed
2978

2979
    def __eq__(self, other):
2980
        try:
Stefan Behnel's avatar
Stefan Behnel committed
2981 2982
            return (isinstance(other, CStructOrUnionType) and
                    self.name == other.name)
2983
        except AttributeError:
2984 2985 2986 2987 2988 2989 2990 2991 2992
            return False

    def __lt__(self, other):
        try:
            return self.name < other.name
        except AttributeError:
            # this is arbitrary, but it makes sure we always have
            # *some* kind of order
            return False
2993

Stefan Behnel's avatar
Stefan Behnel committed
2994
    def __hash__(self):
2995
        return hash(self.cname) ^ hash(self.kind)
Stefan Behnel's avatar
Stefan Behnel committed
2996

William Stein's avatar
William Stein committed
2997 2998
    def is_complete(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
2999

William Stein's avatar
William Stein committed
3000 3001 3002
    def attributes_known(self):
        return self.is_complete()

3003
    def can_be_complex(self):
3004
        # Does the struct consist of exactly two identical floats?
3005
        fields = self.scope.var_entries
3006 3007 3008 3009 3010
        if len(fields) != 2: return False
        a, b = fields
        return (a.type.is_float and b.type.is_float and
                a.type.declaration_code("") ==
                b.type.declaration_code(""))
3011

3012 3013 3014 3015
    def struct_nesting_depth(self):
        child_depths = [x.type.struct_nesting_depth()
                        for x in self.scope.var_entries]
        return max(child_depths) + 1
William Stein's avatar
William Stein committed
3016

3017 3018 3019 3020 3021
    def cast_code(self, expr_code):
        if self.is_struct:
            return expr_code
        return super(CStructOrUnionType, self).cast_code(expr_code)

3022

Robert Bradshaw's avatar
Robert Bradshaw committed
3023
builtin_cpp_conversions = ("std::string", "std::vector", "std::list", "std::set", "std::map", "std::pair")
3024

3025 3026 3027 3028
class CppClassType(CType):
    #  name          string
    #  cname         string
    #  scope         CppClassScope
Danilo Freitas's avatar
Danilo Freitas committed
3029
    #  templates     [string] or None
Robert Bradshaw's avatar
Robert Bradshaw committed
3030

3031 3032
    is_cpp_class = 1
    has_attributes = 1
3033
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3034
    namespace = None
3035 3036 3037 3038 3039
    
    # For struct-like declaration.
    kind = "struct"
    packed = False
    typedef_flag = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3040

3041 3042
    subtypes = ['templates']

3043
    def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None):
3044 3045 3046
        self.name = name
        self.cname = cname
        self.scope = scope
DaniloFreitas's avatar
DaniloFreitas committed
3047
        self.base_classes = base_classes
DaniloFreitas's avatar
DaniloFreitas committed
3048
        self.operators = []
Danilo Freitas's avatar
Danilo Freitas committed
3049
        self.templates = templates
3050
        self.template_type = template_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3051
        self.specializations = {}
3052
        self.is_cpp_string = cname == 'std::string'
3053

3054 3055 3056 3057 3058 3059 3060
    def use_conversion_utility(self, from_or_to):
        pass
    
    def create_from_py_utility_code(self, env):
        if self.from_py_function is not None:
            return True
        if self.cname in builtin_cpp_conversions:
3061
            X = "XYZABC"
3062
            tags = []
3063
            declarations = ["cdef extern from *:"]
3064
            for ix, T in enumerate(self.templates or []):
3065
                if T.is_pyobject or not T.create_from_py_utility_code(env):
3066 3067
                    return False
                tags.append(T.specialization_name())
3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
                if T.exception_value is not None:
                    except_clause = T.exception_value
                    if T.exception_check:
                        except_clause = "? %s" % except_clause
                    declarations.append(
                        "    ctypedef %s %s '%s'" % (
                             T.declaration_code("", for_display=True), X[ix], T.declaration_code("")))
                else:
                    except_clause = "*"
                    declarations.append(
                        "    ctypedef struct %s '%s':\n        pass" % (
                             X[ix], T.declaration_code("")))
                declarations.append(
                    "    cdef %s %s_from_py '%s' (object) except %s" % (
                         X[ix], X[ix], T.from_py_function, except_clause))
3083
            cls = self.cname[5:]
3084 3085 3086 3087 3088
            cname = '__pyx_convert_%s_from_py_%s' % (cls, '____'.join(tags))
            context = {
                'template_type_declarations': '\n'.join(declarations),
                'cname': cname
            }
3089 3090 3091 3092 3093 3094 3095 3096 3097
            from UtilityCode import CythonUtilityCode
            env.use_utility_code(CythonUtilityCode.load(cls + ".from_py", "CppConvert.pyx", context=context))
            self.from_py_function = cname
            return True
    
    def create_to_py_utility_code(self, env):
        if self.to_py_function is not None:
            return True
        if self.cname in builtin_cpp_conversions:
3098
            X = "XYZABC"
3099
            tags = []
3100
            declarations = ["cdef extern from *:"]
3101 3102 3103 3104
            for ix, T in enumerate(self.templates or []):
                if not T.create_to_py_utility_code(env):
                    return False
                tags.append(T.specialization_name())
3105 3106 3107 3108 3109 3110
                declarations.append(
                    "    ctypedef struct %s '%s':\n        pass" % (
                         X[ix], T.declaration_code("")))
                declarations.append(
                    "    cdef object %s_to_py '%s' (%s)" % (
                         X[ix], T.to_py_function, X[ix]))
3111 3112
            cls = self.cname[5:]
            cname = "__pyx_convert_%s_to_py_%s" % (cls, "____".join(tags))
3113 3114 3115 3116
            context = {
                'template_type_declarations': '\n'.join(declarations),
                'cname': cname
            }
3117 3118 3119 3120 3121
            from UtilityCode import CythonUtilityCode
            env.use_utility_code(CythonUtilityCode.load(cls + ".to_py", "CppConvert.pyx", context=context))
            self.to_py_function = cname
            return True

3122
    def specialize_here(self, pos, template_values = None):
3123
        if self.templates is None:
Stefan Behnel's avatar
Stefan Behnel committed
3124 3125
            error(pos, "'%s' type is not a template" % self)
            return error_type
3126
        if len(self.templates) != len(template_values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3127
            error(pos, "%s templated type receives %d arguments, got %d" %
3128 3129
                  (self.name, len(self.templates), len(template_values)))
            return error_type
3130
        return self.specialize(dict(zip(self.templates, template_values)))
Robert Bradshaw's avatar
Robert Bradshaw committed
3131

3132
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3133
        if not self.templates and not self.namespace:
3134
            return self
Robert Bradshaw's avatar
Robert Bradshaw committed
3135 3136
        if self.templates is None:
            self.templates = []
Robert Bradshaw's avatar
Robert Bradshaw committed
3137 3138 3139
        key = tuple(values.items())
        if key in self.specializations:
            return self.specializations[key]
3140
        template_values = [t.specialize(values) for t in self.templates]
Robert Bradshaw's avatar
Robert Bradshaw committed
3141
        specialized = self.specializations[key] = \
3142
            CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3143 3144
        # Need to do these *after* self.specializations[key] is set
        # to avoid infinite recursion on circular references.
3145
        specialized.base_classes = [b.specialize(values) for b in self.base_classes]
Robert Bradshaw's avatar
Robert Bradshaw committed
3146
        specialized.scope = self.scope.specialize(values)
Robert Bradshaw's avatar
Robert Bradshaw committed
3147 3148
        if self.namespace is not None:
            specialized.namespace = self.namespace.specialize(values)
Robert Bradshaw's avatar
Robert Bradshaw committed
3149
        return specialized
3150

3151 3152
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
Danilo Freitas's avatar
Danilo Freitas committed
3153
        if self.templates:
3154 3155
            template_strings = [param.declaration_code('', for_display, None, pyrex)
                                for param in self.templates]
3156 3157 3158 3159 3160
            if for_display:
                brackets = "[%s]"
            else:
                brackets = "<%s>"
            templates = brackets % ",".join(template_strings)
3161 3162
            if templates[-2:] == ">>":
                templates = templates[:-2] + "> >"
3163 3164
        else:
            templates = ""
3165 3166
        if pyrex or for_display:
            base_code = "%s%s" % (self.name, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3167
        else:
3168
            base_code = "%s%s" % (self.cname, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3169
            if self.namespace is not None:
3170 3171 3172
                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)
3173 3174

    def is_subclass(self, other_type):
3175 3176
        if self.same_as_resolved_type(other_type):
            return 1
3177 3178 3179
        for base_class in self.base_classes:
            if base_class.is_subclass(other_type):
                return 1
3180
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3181

3182 3183 3184 3185
    def same_as_resolved_type(self, other_type):
        if other_type.is_cpp_class:
            if self == other_type:
                return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3186 3187
            elif (self.cname == other_type.cname and
                  self.template_type and other_type.template_type):
3188 3189
                if self.templates == other_type.templates:
                    return 1
3190
                for t1, t2 in zip(self.templates, other_type.templates):
3191 3192 3193 3194
                    if not t1.same_as_resolved_type(t2):
                        return 0
                return 1
        return 0
3195

3196 3197
    def assignable_from_resolved_type(self, other_type):
        # TODO: handle operator=(...) here?
3198 3199
        if other_type is error_type:
            return True
3200
        return other_type.is_cpp_class and other_type.is_subclass(self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3201

Robert Bradshaw's avatar
Robert Bradshaw committed
3202 3203 3204
    def attributes_known(self):
        return self.scope is not None

3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217
    def find_cpp_operation_type(self, operator, operand_type=None):
        operands = [self]
        if operand_type is not None:
            operands.append(operand_type)
        # pos == None => no errors
        operator_entry = self.scope.lookup_operator_for_types(None, operator, operands)
        if not operator_entry:
            return None
        func_type = operator_entry.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        return func_type.return_type

3218 3219 3220 3221 3222
    def check_nullary_constructor(self, pos, msg="stack allocated"):
        constructor = self.scope.lookup(u'<init>')
        if constructor is not None and best_match([], constructor.all_alternatives()) is None:
            error(pos, "C++ class must have a nullary constructor to be %s" % msg)

3223

3224
class TemplatePlaceholderType(CType):
Robert Bradshaw's avatar
Robert Bradshaw committed
3225

Danilo Freitas's avatar
Danilo Freitas committed
3226 3227
    def __init__(self, name):
        self.name = name
Robert Bradshaw's avatar
Robert Bradshaw committed
3228 3229

    def declaration_code(self, entity_code,
3230
            for_display = 0, dll_linkage = None, pyrex = 0):
3231 3232 3233 3234
        if entity_code:
            return self.name + " " + entity_code
        else:
            return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3235

3236 3237 3238 3239 3240 3241 3242 3243
    def specialize(self, values):
        if self in values:
            return values[self]
        else:
            return self

    def same_as_resolved_type(self, other_type):
        if isinstance(other_type, TemplatePlaceholderType):
3244
            return self.name == other_type.name
3245 3246
        else:
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3247

3248 3249
    def __hash__(self):
        return hash(self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
3250

3251 3252 3253 3254 3255
    def __cmp__(self, other):
        if isinstance(other, TemplatePlaceholderType):
            return cmp(self.name, other.name)
        else:
            return cmp(type(self), type(other))
Danilo Freitas's avatar
Danilo Freitas committed
3256

Robert Bradshaw's avatar
Robert Bradshaw committed
3257 3258 3259 3260 3261 3262
    def __eq__(self, other):
        if isinstance(other, TemplatePlaceholderType):
            return self.name == other.name
        else:
            return False

3263
class CEnumType(CType):
William Stein's avatar
William Stein committed
3264 3265 3266
    #  name           string
    #  cname          string or None
    #  typedef_flag   boolean
3267

William Stein's avatar
William Stein committed
3268
    is_enum = 1
3269 3270
    signed = 1
    rank = -1 # Ranks below any integer type
3271 3272
    to_py_function = "PyInt_FromLong"
    from_py_function = "PyInt_AsLong"
William Stein's avatar
William Stein committed
3273 3274 3275 3276 3277 3278

    def __init__(self, name, cname, typedef_flag):
        self.name = name
        self.cname = cname
        self.values = []
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
3279

3280 3281
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3282

William Stein's avatar
William Stein committed
3283
    def __repr__(self):
3284 3285
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
3286 3287

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
3288
            for_display = 0, dll_linkage = None, pyrex = 0):
3289 3290
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3291 3292
        else:
            if self.typedef_flag:
3293
                base_code = self.cname
William Stein's avatar
William Stein committed
3294
            else:
3295 3296 3297
                base_code = "enum %s" % self.cname
            base_code = public_decl(base_code, dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
3298

Robert Bradshaw's avatar
Robert Bradshaw committed
3299 3300
class UnspecifiedType(PyrexType):
    # Used as a placeholder until the type can be determined.
Robert Bradshaw's avatar
Robert Bradshaw committed
3301

Robert Bradshaw's avatar
Robert Bradshaw committed
3302
    is_unspecified = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3303 3304

    def declaration_code(self, entity_code,
Robert Bradshaw's avatar
Robert Bradshaw committed
3305 3306
            for_display = 0, dll_linkage = None, pyrex = 0):
        return "<unspecified>"
Robert Bradshaw's avatar
Robert Bradshaw committed
3307

Robert Bradshaw's avatar
Robert Bradshaw committed
3308 3309
    def same_as_resolved_type(self, other_type):
        return False
Robert Bradshaw's avatar
Robert Bradshaw committed
3310

Robert Bradshaw's avatar
Robert Bradshaw committed
3311

William Stein's avatar
William Stein committed
3312 3313
class ErrorType(PyrexType):
    # Used to prevent propagation of error messages.
Robert Bradshaw's avatar
Robert Bradshaw committed
3314

William Stein's avatar
William Stein committed
3315 3316
    is_error = 1
    exception_value = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
3317
    exception_check    = 0
William Stein's avatar
William Stein committed
3318 3319
    to_py_function = "dummy"
    from_py_function = "dummy"
Robert Bradshaw's avatar
Robert Bradshaw committed
3320

3321 3322
    def create_to_py_utility_code(self, env):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3323

3324
    def create_from_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3325
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3326 3327

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
3328 3329
            for_display = 0, dll_linkage = None, pyrex = 0):
        return "<error>"
Robert Bradshaw's avatar
Robert Bradshaw committed
3330

William Stein's avatar
William Stein committed
3331 3332
    def same_as_resolved_type(self, other_type):
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3333

3334 3335
    def error_condition(self, result_code):
        return "dummy"
William Stein's avatar
William Stein committed
3336 3337


3338 3339 3340
rank_to_type_name = (
    "char",         # 0
    "short",        # 1
3341 3342 3343 3344 3345 3346
    "int",          # 2
    "long",         # 3
    "PY_LONG_LONG", # 4
    "float",        # 5
    "double",       # 6
    "long double",  # 7
3347 3348
)

3349 3350 3351 3352
_rank_to_type_name = list(rank_to_type_name)
RANK_INT  = _rank_to_type_name.index('int')
RANK_LONG = _rank_to_type_name.index('long')
RANK_FLOAT = _rank_to_type_name.index('float')
3353 3354 3355
UNSIGNED = 0
SIGNED = 2

3356 3357
error_type =    ErrorType()
unspecified_type = UnspecifiedType()
3358

William Stein's avatar
William Stein committed
3359 3360
py_object_type = PyObjectType()

3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
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)
William Stein's avatar
William Stein committed
3374

3375 3376 3377 3378 3379 3380 3381 3382 3383
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')
William Stein's avatar
William Stein committed
3384

3385 3386 3387
c_float_complex_type =      CComplexType(c_float_type)
c_double_complex_type =     CComplexType(c_double_type)
c_longdouble_complex_type = CComplexType(c_longdouble_type)
3388

3389 3390 3391 3392
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)
Stefan Behnel's avatar
Stefan Behnel committed
3393
c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
3394
c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
3395 3396 3397 3398
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)

William Stein's avatar
William Stein committed
3399
c_null_ptr_type =     CNullPtrType(c_void_type)
3400 3401
c_void_ptr_type =     CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
3402 3403
c_char_ptr_type =     CPtrType(c_char_type)
c_uchar_ptr_type =    CPtrType(c_uchar_type)
William Stein's avatar
William Stein committed
3404 3405
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
c_int_ptr_type =      CPtrType(c_int_type)
Stefan Behnel's avatar
Stefan Behnel committed
3406
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
3407
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
3408
c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
3409
c_size_t_ptr_type =  CPtrType(c_size_t_type)
William Stein's avatar
William Stein committed
3410

3411

3412
# the Py_buffer type is defined in Builtin.py
3413 3414
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
3415

3416 3417 3418
# Not sure whether the unsigned versions and 'long long' should be in there
# long long requires C99 and might be slow, and would always get preferred
# when specialization happens through calling and not indexing
3419 3420
cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type],
                             name="integral")
3421 3422
# Omitting long double as it might be slow
cy_floating_type = FusedType([c_float_type, c_double_type], name="floating")
3423 3424 3425 3426
cy_numeric_type = FusedType([c_short_type,
                             c_int_type,
                             c_long_type,
                             c_float_type,
3427
                             c_double_type,
3428
                             c_float_complex_type,
3429 3430
                             c_double_complex_type], name="numeric")

3431 3432 3433 3434 3435 3436 3437 3438
# buffer-related structs
c_buf_diminfo_type =  CStructOrUnionType("__Pyx_Buf_DimInfo", "struct",
                                      None, 1, "__Pyx_Buf_DimInfo")
c_pyx_buffer_type = CStructOrUnionType("__Pyx_Buffer", "struct", None, 1, "__Pyx_Buffer")
c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type)
c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct",
                                      None, 1, "__Pyx_LocalBuf_ND")

3439 3440
cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
                                      None, 0, "__pyx_memoryview_obj")
3441

3442
cython_memoryview_ptr_type = CPtrType(cython_memoryview_type)
3443

3444 3445
memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
                                          None, 1, "__Pyx_memviewslice")
3446

William Stein's avatar
William Stein committed
3447
modifiers_and_name_to_type = {
3448 3449 3450 3451 3452
    #(signed, longness, name) : type
    (0,  0, "char"): c_uchar_type,
    (1,  0, "char"): c_char_type,
    (2,  0, "char"): c_schar_type,

3453
    (0, -1, "int"): c_ushort_type,
3454 3455 3456 3457
    (0,  0, "int"): c_uint_type,
    (0,  1, "int"): c_ulong_type,
    (0,  2, "int"): c_ulonglong_type,

3458
    (1, -1, "int"): c_short_type,
3459 3460 3461 3462
    (1,  0, "int"): c_int_type,
    (1,  1, "int"): c_long_type,
    (1,  2, "int"): c_longlong_type,

3463
    (2, -1, "int"): c_sshort_type,
3464 3465 3466 3467 3468 3469 3470
    (2,  0, "int"): c_sint_type,
    (2,  1, "int"): c_slong_type,
    (2,  2, "int"): c_slonglong_type,

    (1,  0, "float"):  c_float_type,
    (1,  0, "double"): c_double_type,
    (1,  1, "double"): c_longdouble_type,
3471

3472
    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
3473 3474 3475 3476 3477 3478
    (1,  0, "floatcomplex"):  c_float_complex_type,
    (1,  0, "doublecomplex"): c_double_complex_type,
    (1,  1, "doublecomplex"): c_longdouble_complex_type,

    #
    (1,  0, "void"): c_void_type,
3479 3480 3481

    (1,  0, "bint"):       c_bint_type,
    (0,  0, "Py_UNICODE"): c_py_unicode_type,
Stefan Behnel's avatar
Stefan Behnel committed
3482
    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
3483
    (2,  0, "Py_hash_t"):  c_py_hash_t_type,
3484 3485 3486 3487
    (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,

3488
    (1,  0, "object"): py_object_type,
William Stein's avatar
William Stein committed
3489 3490
}

3491 3492
def is_promotion(src_type, dst_type):
    # It's hard to find a hard definition of promotion, but empirical
Robert Bradshaw's avatar
Robert Bradshaw committed
3493
    # evidence suggests that the below is all that's allowed.
3494 3495
    if src_type.is_numeric:
        if dst_type.same_as(c_int_type):
3496 3497 3498 3499
            unsigned = (not src_type.signed)
            return (src_type.is_enum or
                    (src_type.is_int and
                     unsigned + src_type.rank < dst_type.rank))
3500 3501 3502 3503
        elif dst_type.same_as(c_double_type):
            return src_type.is_float and src_type.rank <= dst_type.rank
    return False

3504
def best_match(args, functions, pos=None, env=None):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
3505
    """
3506 3507 3508 3509 3510 3511 3512 3513 3514 3515
    Given a list args of arguments and a list of functions, choose one
    to call which seems to be the "best" fit for this list of arguments.
    This function is used, e.g., when deciding which overloaded method
    to dispatch for C++ classes.

    We first eliminate functions based on arity, and if only one
    function has the correct arity, we return it. Otherwise, we weight
    functions based on how much work must be done to convert the
    arguments, with the following priorities:
      * identical types or pointers to identical types
Robert Bradshaw's avatar
Robert Bradshaw committed
3516
      * promotions
3517 3518 3519 3520 3521 3522 3523 3524
      * non-Python types
    That is, we prefer functions where no arguments need converted,
    and failing that, functions where only promotions are required, and
    so on.

    If no function is deemed a good fit, or if two or more functions have
    the same weight, we return None (as there is no best match). If pos
    is not None, we also generate an error.
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
3525
    """
Robert Bradshaw's avatar
Robert Bradshaw committed
3526
    # TODO: args should be a list of types, not a list of Nodes.
3527
    actual_nargs = len(args)
3528 3529 3530

    candidates = []
    errors = []
3531
    for func in functions:
3532
        error_mesg = ""
3533 3534 3535
        func_type = func.type
        if func_type.is_ptr:
            func_type = func_type.base_type
3536 3537
        # Check function type
        if not func_type.is_cfunction:
3538
            if not func_type.is_error and pos is not None:
3539 3540 3541
                error_mesg = "Calling non-function type '%s'" % func_type
            errors.append((func, error_mesg))
            continue
3542 3543 3544
        # Check no. of args
        max_nargs = len(func_type.args)
        min_nargs = max_nargs - func_type.optional_arg_count
3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557
        if actual_nargs < min_nargs or \
            (not func_type.has_varargs and actual_nargs > max_nargs):
            if max_nargs == min_nargs and not func_type.has_varargs:
                expectation = max_nargs
            elif actual_nargs < min_nargs:
                expectation = "at least %s" % min_nargs
            else:
                expectation = "at most %s" % max_nargs
            error_mesg = "Call with wrong number of arguments (expected %s, got %s)" \
                         % (expectation, actual_nargs)
            errors.append((func, error_mesg))
            continue
        candidates.append((func, func_type))
Robert Bradshaw's avatar
Robert Bradshaw committed
3558

3559 3560
    # Optimize the most common case of no overloading...
    if len(candidates) == 1:
3561
        return candidates[0][0]
3562
    elif len(candidates) == 0:
3563
        if pos is not None:
3564 3565 3566
            func, errmsg = errors[0]
            if len(errors) == 1 or [1 for func, e in errors if e == errmsg]:
                error(pos, errmsg)
3567 3568
            else:
                error(pos, "no suitable method found")
3569
        return None
Robert Bradshaw's avatar
Robert Bradshaw committed
3570

3571 3572
    possibilities = []
    bad_types = []
3573
    needed_coercions = {}
Mark Florisson's avatar
merge  
Mark Florisson committed
3574

3575
    for index, (func, func_type) in enumerate(candidates):
3576
        score = [0,0,0,0]
3577
        for i in range(min(len(args), len(func_type.args))):
3578 3579
            src_type = args[i].type
            dst_type = func_type.args[i].type
3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600

            assignable = dst_type.assignable_from(src_type)

            # Now take care of normal string literals. So when you call a cdef
            # function that takes a char *, the coercion will mean that the
            # type will simply become bytes. We need to do this coercion
            # manually for overloaded and fused functions
            if not assignable and src_type.is_pyobject:
                if (src_type.is_builtin_type and src_type.name == 'str' and
                        dst_type.resolve() is c_char_ptr_type):
                    c_src_type = c_char_ptr_type
                else:
                    c_src_type = src_type.default_coerced_ctype()

                if c_src_type:
                    assignable = dst_type.assignable_from(c_src_type)
                    if assignable:
                        src_type = c_src_type
                        needed_coercions[func] = i, dst_type

            if assignable:
Robert Bradshaw's avatar
Robert Bradshaw committed
3601
                if src_type == dst_type or dst_type.same_as(src_type):
3602
                    pass # score 0
3603 3604
                elif func_type.is_strict_signature:
                    break # exact match requested but not found
3605 3606
                elif is_promotion(src_type, dst_type):
                    score[2] += 1
3607 3608
                elif ((src_type.is_int and dst_type.is_int) or
                      (src_type.is_float and dst_type.is_float)):
Mark Florisson's avatar
Mark Florisson committed
3609
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
3610
                                    (src_type.rank + (not src_type.signed))) + 1
3611 3612 3613 3614 3615
                elif not src_type.is_pyobject:
                    score[1] += 1
                else:
                    score[0] += 1
            else:
3616 3617 3618
                error_mesg = "Invalid conversion from '%s' to '%s'"%(src_type,
                                                                     dst_type)
                bad_types.append((func, error_mesg))
3619 3620
                break
        else:
3621
            possibilities.append((score, index, func)) # so we can sort it
3622

3623
    if possibilities:
3624
        possibilities.sort()
3625 3626 3627 3628 3629 3630 3631
        if len(possibilities) > 1:
            score1 = possibilities[0][0]
            score2 = possibilities[1][0]
            if score1 == score2:
                if pos is not None:
                    error(pos, "ambiguous overloaded method")
                return None
3632

Mark Florisson's avatar
merge  
Mark Florisson committed
3633
        function = possibilities[0][-1]
3634 3635 3636 3637 3638 3639 3640

        if function in needed_coercions and env:
            arg_i, coerce_to_type = needed_coercions[function]
            args[arg_i] = args[arg_i].coerce_to(coerce_to_type, env)

        return function

3641
    if pos is not None:
3642 3643
        if len(bad_types) == 1:
            error(pos, bad_types[0][1])
3644
        else:
3645
            error(pos, "no suitable method found")
3646

3647 3648
    return None

William Stein's avatar
William Stein committed
3649 3650 3651
def widest_numeric_type(type1, type2):
    # Given two numeric types, return the narrowest type
    # encompassing both of them.
3652
    if type1 == type2:
3653 3654 3655 3656 3657 3658 3659 3660
        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(
Robert Bradshaw's avatar
Robert Bradshaw committed
3661
                real_type(type1),
3662 3663 3664 3665 3666 3667 3668 3669 3670
                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
3671
    else:
3672 3673
        widest_type = type2
    return widest_type
William Stein's avatar
William Stein committed
3674

3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687
def independent_spanning_type(type1, type2):
    # Return a type assignable independently from both type1 and
    # type2, but do not require any interoperability between the two.
    # For example, in "True * 2", it is safe to assume an integer
    # result type (so spanning_type() will do the right thing),
    # whereas "x = True or 2" must evaluate to a type that can hold
    # both a boolean value and an integer, so this function works
    # better.
    if type1 == type2:
        return type1
    elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric):
        # special case: if one of the results is a bint and the other
        # is another C integer, we must prevent returning a numeric
Craig Citro's avatar
Craig Citro committed
3688
        # type so that we do not lose the ability to coerce to a
3689
        # Python bool if we have to.
Robert Bradshaw's avatar
Robert Bradshaw committed
3690
        return py_object_type
3691 3692
    span_type = _spanning_type(type1, type2)
    if span_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
3693
        return error_type
3694 3695 3696 3697 3698 3699 3700 3701
    return span_type

def spanning_type(type1, type2):
    # Return a type assignable from both type1 and type2, or
    # py_object_type if no better type is found.  Assumes that the
    # code that calls this will try a coercion afterwards, which will
    # fail if the types cannot actually coerce to a py_object_type.
    if type1 == type2:
Robert Bradshaw's avatar
Robert Bradshaw committed
3702
        return type1
3703 3704
    elif type1 is py_object_type or type2 is py_object_type:
        return py_object_type
3705 3706 3707
    elif type1 is c_py_unicode_type or type2 is c_py_unicode_type:
        # Py_UNICODE behaves more like a string than an int
        return py_object_type
3708 3709 3710 3711 3712 3713 3714
    span_type = _spanning_type(type1, type2)
    if span_type is None:
        return py_object_type
    return span_type

def _spanning_type(type1, type2):
    if type1.is_numeric and type2.is_numeric:
Robert Bradshaw's avatar
Robert Bradshaw committed
3715
        return widest_numeric_type(type1, type2)
3716 3717 3718 3719
    elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
        return widest_numeric_type(c_double_type, type2)
    elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
        return widest_numeric_type(type1, c_double_type)
3720
    elif type1.is_extension_type and type2.is_extension_type:
3721 3722 3723
        return widest_extension_type(type1, type2)
    elif type1.is_pyobject or type2.is_pyobject:
        return py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3724
    elif type1.assignable_from(type2):
3725 3726 3727
        if type1.is_extension_type and type1.typeobj_is_imported():
            # external types are unsafe, so we use PyObject instead
            return py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3728
        return type1
3729
    elif type2.assignable_from(type1):
3730 3731 3732
        if type2.is_extension_type and type2.typeobj_is_imported():
            # external types are unsafe, so we use PyObject instead
            return py_object_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3733 3734
        return type2
    else:
3735 3736 3737 3738
        return None

def widest_extension_type(type1, type2):
    if type1.typeobj_is_imported() or type2.typeobj_is_imported():
Robert Bradshaw's avatar
Robert Bradshaw committed
3739
        return py_object_type
3740 3741 3742 3743 3744 3745 3746 3747 3748
    while True:
        if type1.subtype_of(type2):
            return type2
        elif type2.subtype_of(type1):
            return type1
        type1, type2 = type1.base_type, type2.base_type
        if type1 is None or type2 is None:
            return py_object_type

William Stein's avatar
William Stein committed
3749 3750 3751 3752
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))
Robert Bradshaw's avatar
Robert Bradshaw committed
3753

3754 3755 3756 3757 3758 3759 3760 3761 3762 3763
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)
3764 3765 3766 3767 3768 3769 3770
    #
    basic_type = simple_c_type(1, 0, name)
    if basic_type:
        return basic_type
    #
    signed = 1
    longness = 0
3771 3772
    if name == 'Py_UNICODE':
        signed = 0
Stefan Behnel's avatar
Stefan Behnel committed
3773 3774
    elif name == 'Py_UCS4':
        signed = 0
3775 3776
    elif name == 'Py_hash_t':
        signed = 2
3777 3778 3779
    elif name == 'Py_ssize_t':
        signed = 2
    elif name == 'ssize_t':
3780 3781 3782
        signed = 2
    elif name == 'size_t':
        signed = 0
3783
    else:
3784 3785 3786
        if name.startswith('u'):
            name = name[1:]
            signed = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3787
        elif (name.startswith('s') and
3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
              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)
William Stein's avatar
William Stein committed
3801 3802 3803

def c_array_type(base_type, size):
    # Construct a C array type.
3804
    if base_type is error_type:
3805
        return error_type
William Stein's avatar
William Stein committed
3806 3807 3808 3809 3810
    else:
        return CArrayType(base_type, size)

def c_ptr_type(base_type):
    # Construct a C pointer type.
3811
    if base_type is error_type:
3812
        return error_type
William Stein's avatar
William Stein committed
3813 3814 3815
    else:
        return CPtrType(base_type)

Danilo Freitas's avatar
Danilo Freitas committed
3816 3817
def c_ref_type(base_type):
    # Construct a C reference type
3818
    if base_type is error_type:
Danilo Freitas's avatar
Danilo Freitas committed
3819 3820 3821
        return error_type
    else:
        return CReferenceType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3822 3823 3824 3825 3826 3827 3828

def c_const_type(base_type):
    # Construct a C const type.
    if base_type is error_type:
        return error_type
    else:
        return CConstType(base_type)
William Stein's avatar
William Stein committed
3829 3830 3831

def same_type(type1, type2):
    return type1.same_as(type2)
Robert Bradshaw's avatar
Robert Bradshaw committed
3832

William Stein's avatar
William Stein committed
3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845
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)