PyrexTypes.py 158 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 6
from __future__ import absolute_import

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
7
import copy
8
import re
9

10 11 12 13 14
try:
    reduce
except NameError:
    from functools import reduce

15 16 17 18
from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
from . import StringEncoding
from . import Naming

root's avatar
root committed
19
from .Errors import error
20

William Stein's avatar
William Stein committed
21

22
class BaseType(object):
23
    #
24
    #  Base class for all Cython types including pseudo-types.
25

26 27
    # List of attribute names of any subtypes
    subtypes = []
28
    _empty_declaration = None
29

30 31 32
    def can_coerce_to_pyobject(self, env):
        return False

33
    def cast_code(self, expr_code):
34 35 36 37 38 39
        return "((%s)%s)" % (self.empty_declaration_code(), expr_code)

    def empty_declaration_code(self):
        if self._empty_declaration is None:
            self._empty_declaration = self.declaration_code('')
        return self._empty_declaration
Robert Bradshaw's avatar
Robert Bradshaw committed
40

Craig Citro's avatar
Craig Citro committed
41
    def specialization_name(self):
42 43 44
        # This is not entirely robust.
        safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'
        all = []
45
        for c in self.empty_declaration_code().replace("unsigned ", "unsigned_").replace("long long", "long_long").replace(" ", "__"):
46 47 48 49 50
            if c in safe:
                all.append(c)
            else:
                all.append('_%x_' % ord(c))
        return ''.join(all)
Robert Bradshaw's avatar
Robert Bradshaw committed
51

52 53 54 55 56 57
    def base_declaration_code(self, base_code, entity_code):
        if entity_code:
            return "%s %s" % (base_code, entity_code)
        else:
            return base_code

58 59 60 61 62 63 64
    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
65 66
    def get_fused_types(self, result=None, seen=None, subtypes=None):
        subtypes = subtypes or self.subtypes
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        if not subtypes:
            return None

        if result is None:
            result = []
            seen = set()

        for attr in subtypes:
            list_or_subtype = getattr(self, attr)
            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)

        return result
84

Mark Florisson's avatar
Mark Florisson committed
85 86 87 88 89 90
    def specialize_fused(self, env):
        if env.fused_to_specific:
            return self.specialize(env.fused_to_specific)

        return self

91 92
    @property
    def is_fused(self):
93
        """
94
        Whether this type or any of its subtypes is a fused type
95
        """
96 97
        # Add this indirection for the is_fused property to allow overriding
        # get_fused_types in subclasses.
98 99
        return self.get_fused_types()

Robert Bradshaw's avatar
Robert Bradshaw committed
100 101 102 103 104 105 106 107 108 109 110 111
    def deduce_template_params(self, actual):
        """
        Deduce any template params in this (argument) type given the actual
        argument type.

        http://en.cppreference.com/w/cpp/language/function_template#Template_argument_deduction
        """
        if self == actual:
            return {}
        else:
            return None

112 113 114 115
    def __lt__(self, other):
        """
        For sorting. The sorting order should correspond to the preference of
        conversion from Python types.
116 117 118

        Override to provide something sensible. This is only implemented so that
        python 3 doesn't trip
119
        """
120
        return id(type(self)) < id(type(other))
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137

    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
138 139 140 141 142 143 144 145
    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

146
    def invalid_value(self):
147
        """
148 149
        Returns the most invalid value an object of this type can assume as a
        C expression string. Returns None if no such value exists.
150 151
        """

Mark Florisson's avatar
merge  
Mark Florisson committed
152

153
class PyrexType(BaseType):
William Stein's avatar
William Stein committed
154
    #
155
    #  Base class for all Cython types
William Stein's avatar
William Stein committed
156 157 158
    #
    #  is_pyobject           boolean     Is a Python object type
    #  is_extension_type     boolean     Is a Python extension type
159
    #  is_final_type         boolean     Is a final extension type
William Stein's avatar
William Stein committed
160 161 162
    #  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
163
    #  is_complex            boolean     Is a C complex type
William Stein's avatar
William Stein committed
164 165 166 167
    #  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
168
    #  is_reference          boolean     Is a C reference type
Robert Bradshaw's avatar
Robert Bradshaw committed
169
    #  is_const              boolean     Is a C const type.
William Stein's avatar
William Stein committed
170 171
    #  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
172
    #  is_struct             boolean     Is a C struct type
William Stein's avatar
William Stein committed
173
    #  is_enum               boolean     Is a C enum type
174
    #  is_typedef            boolean     Is a typedef type
William Stein's avatar
William Stein committed
175
    #  is_string             boolean     Is a C char * type
176
    #  is_pyunicode_ptr      boolean     Is a C PyUNICODE * type
177
    #  is_cpp_string         boolean     Is a C++ std::string type
Stefan Behnel's avatar
Stefan Behnel committed
178
    #  is_unicode_char       boolean     Is either Py_UCS4 or Py_UNICODE
William Stein's avatar
William Stein committed
179 180
    #  is_returncode         boolean     Is used only to signal exceptions
    #  is_error              boolean     Is the dummy error type
181
    #  is_buffer             boolean     Is buffer access type
William Stein's avatar
William Stein committed
182 183
    #  has_attributes        boolean     Has C dot-selectable attributes
    #  default_value         string      Initial value
184
    #  entry                 Entry       The Entry for this type
William Stein's avatar
William Stein committed
185
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
186
    #  declaration_code(entity_code,
William Stein's avatar
William Stein committed
187 188 189 190 191 192 193 194 195
    #      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'
196
    #      statement of a Cython include file.
William Stein's avatar
William Stein committed
197 198 199 200 201 202 203 204 205 206
    #
    #  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():
207
    #    Coerces array and C function types into pointer type for use as
William Stein's avatar
William Stein committed
208 209
    #    a formal argument type.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
210

William Stein's avatar
William Stein committed
211
    is_pyobject = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
212
    is_unspecified = 0
William Stein's avatar
William Stein committed
213
    is_extension_type = 0
214
    is_final_type = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
215
    is_builtin_type = 0
William Stein's avatar
William Stein committed
216 217 218
    is_numeric = 0
    is_int = 0
    is_float = 0
219
    is_complex = 0
William Stein's avatar
William Stein committed
220 221 222 223
    is_void = 0
    is_array = 0
    is_ptr = 0
    is_null_ptr = 0
224
    is_reference = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
225
    is_const = 0
William Stein's avatar
William Stein committed
226 227
    is_cfunction = 0
    is_struct_or_union = 0
228
    is_cpp_class = 0
229
    is_cpp_string = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
230
    is_struct = 0
William Stein's avatar
William Stein committed
231
    is_enum = 0
232
    is_typedef = 0
William Stein's avatar
William Stein committed
233
    is_string = 0
234
    is_pyunicode_ptr = 0
Stefan Behnel's avatar
Stefan Behnel committed
235
    is_unicode_char = 0
William Stein's avatar
William Stein committed
236 237
    is_returncode = 0
    is_error = 0
238
    is_buffer = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
239
    is_ctuple = 0
240
    is_memoryviewslice = 0
William Stein's avatar
William Stein committed
241 242
    has_attributes = 0
    default_value = ""
Robert Bradshaw's avatar
Robert Bradshaw committed
243

William Stein's avatar
William Stein committed
244 245 246
    def resolve(self):
        # If a typedef, returns the base type.
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
247

248
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
249
        # TODO(danilo): Override wherever it makes sense.
250
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
251

William Stein's avatar
William Stein committed
252 253 254 255
    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
256

William Stein's avatar
William Stein committed
257
    def __str__(self):
258
        return self.declaration_code("", for_display = 1).strip()
Robert Bradshaw's avatar
Robert Bradshaw committed
259

William Stein's avatar
William Stein committed
260 261
    def same_as(self, other_type, **kwds):
        return self.same_as_resolved_type(other_type.resolve(), **kwds)
Robert Bradshaw's avatar
Robert Bradshaw committed
262

William Stein's avatar
William Stein committed
263
    def same_as_resolved_type(self, other_type):
264
        return self == other_type or other_type is error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
265

William Stein's avatar
William Stein committed
266 267
    def subtype_of(self, other_type):
        return self.subtype_of_resolved_type(other_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
268

William Stein's avatar
William Stein committed
269 270
    def subtype_of_resolved_type(self, other_type):
        return self.same_as(other_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
271

William Stein's avatar
William Stein committed
272 273
    def assignable_from(self, src_type):
        return self.assignable_from_resolved_type(src_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
274

William Stein's avatar
William Stein committed
275 276
    def assignable_from_resolved_type(self, src_type):
        return self.same_as(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
277

William Stein's avatar
William Stein committed
278 279
    def as_argument_type(self):
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
280

William Stein's avatar
William Stein committed
281 282 283 284 285
    def is_complete(self):
        # A type is incomplete if it is an unsized array,
        # a struct whose attributes are not defined, etc.
        return 1

286
    def is_simple_buffer_dtype(self):
287
        return (self.is_int or self.is_float or self.is_complex or self.is_pyobject or
288 289
                self.is_extension_type or self.is_ptr)

290 291 292 293 294 295
    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

296 297
    def global_init_code(self, entry, code):
        # abstract
298
        pass
299

300 301
    def needs_nonecheck(self):
        return 0
302 303


304 305 306 307 308
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
309

310
def create_typedef_type(name, base_type, cname, is_external=0):
311 312
    is_fused = base_type.is_fused
    if base_type.is_complex or is_fused:
313
        if is_external:
314 315 316 317 318 319 320
            if is_fused:
                msg = "Fused"
            else:
                msg = "Complex"

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

321 322
        return base_type
    else:
323
        return CTypedefType(name, base_type, cname, is_external)
324

325

326
class CTypedefType(BaseType):
William Stein's avatar
William Stein committed
327
    #
328
    #  Pseudo-type defined with a ctypedef statement in a
329 330 331
    #  'cdef extern from' block.
    #  Delegates most attribute lookups to the base type.
    #  (Anything not defined here or in the BaseType is delegated.)
William Stein's avatar
William Stein committed
332
    #
333
    #  qualified_name      string
334
    #  typedef_name        string
335 336
    #  typedef_cname       string
    #  typedef_base_type   PyrexType
337
    #  typedef_is_external bool
Robert Bradshaw's avatar
Robert Bradshaw committed
338

339
    is_typedef = 1
340
    typedef_is_external = 0
341 342 343

    to_py_utility_code = None
    from_py_utility_code = None
344 345

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

347
    def __init__(self, name, base_type, cname, is_external=0):
348
        assert not base_type.is_complex
349
        self.typedef_name = name
William Stein's avatar
William Stein committed
350 351
        self.typedef_cname = cname
        self.typedef_base_type = base_type
352
        self.typedef_is_external = is_external
Robert Bradshaw's avatar
Robert Bradshaw committed
353

354 355 356
    def invalid_value(self):
        return self.typedef_base_type.invalid_value()

William Stein's avatar
William Stein committed
357 358
    def resolve(self):
        return self.typedef_base_type.resolve()
Robert Bradshaw's avatar
Robert Bradshaw committed
359 360

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
361
            for_display = 0, dll_linkage = None, pyrex = 0):
362
        if pyrex or for_display:
363
            base_code = self.typedef_name
364
        else:
365
            base_code = public_decl(self.typedef_cname, dll_linkage)
366
        return self.base_declaration_code(base_code, entity_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
367

368 369 370
    def as_argument_type(self):
        return self

371 372
    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
373
        # For example, the gmp mpz_t.
374 375 376
        if self.typedef_base_type.is_array:
            base_type = self.typedef_base_type.base_type
            return CPtrType(base_type).cast_code(expr_code)
377 378
        else:
            return BaseType.cast_code(self, expr_code)
379

380 381
    def __repr__(self):
        return "<CTypedefType %s>" % self.typedef_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
382

William Stein's avatar
William Stein committed
383
    def __str__(self):
384
        return self.typedef_name
385 386 387

    def _create_utility_code(self, template_utility_code,
                             template_function_name):
388
        type_name = type_identifier(self.typedef_cname)
389 390 391 392 393 394 395 396 397 398
        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
399
                if type(base_type) is CIntType:
400
                    self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
401
                    env.use_utility_code(TempitaUtilityCode.load_cached(
402
                        "CIntToPy", "TypeConversion.c",
403
                        context={"TYPE": self.empty_declaration_code(),
404
                                 "TO_PY_FUNCTION": self.to_py_function}))
405
                    return True
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
                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
421
                if type(base_type) is CIntType:
422
                    self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
423
                    env.use_utility_code(TempitaUtilityCode.load_cached(
424
                        "CIntFromPy", "TypeConversion.c",
425
                        context={"TYPE": self.empty_declaration_code(),
426
                                 "FROM_PY_FUNCTION": self.from_py_function}))
427
                    return True
428 429 430 431 432 433 434 435 436 437
                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)

438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
        if to_py_function is None:
            to_py_function = self.to_py_function
        return self.typedef_base_type.to_py_call_code(
            source_code, result_code, result_type, to_py_function)

    def from_py_call_code(self, source_code, result_code, error_pos, code,
                          from_py_function=None, error_condition=None):
        if from_py_function is None:
            from_py_function = self.from_py_function
        if error_condition is None:
            error_condition = self.error_condition(result_code)
        return self.typedef_base_type.from_py_call_code(
            source_code, result_code, error_pos, code, from_py_function, error_condition)

453
    def overflow_check_binop(self, binop, env, const_rhs=False):
454
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
455
        type = self.empty_declaration_code()
456
        name = self.specialization_name()
457
        if binop == "lshift":
458
            env.use_utility_code(TempitaUtilityCode.load_cached(
459 460
                "LeftShift", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
461 462 463 464
        else:
            if const_rhs:
                binop += "_const"
            _load_overflow_base(env)
465
            env.use_utility_code(TempitaUtilityCode.load_cached(
466 467
                "SizeCheck", "Overflow.c",
                context={'TYPE': type, 'NAME': name}))
468
            env.use_utility_code(TempitaUtilityCode.load_cached(
469 470
                "Binop", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
471 472
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

473 474 475 476 477 478 479 480 481 482 483
    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
484 485 486
    def __getattr__(self, name):
        return getattr(self.typedef_base_type, name)

487 488
    def py_type_name(self):
        return self.typedef_base_type.py_type_name()
489

490 491 492
    def can_coerce_to_pyobject(self, env):
        return self.typedef_base_type.can_coerce_to_pyobject(env)

493

494
class MemoryViewSliceType(PyrexType):
495

496
    is_memoryviewslice = 1
Kurt Smith's avatar
Kurt Smith committed
497

498 499 500
    has_attributes = 1
    scope = None

Stefan Behnel's avatar
Stefan Behnel committed
501
    # These are special cased in Defnode
502 503 504 505
    from_py_function = None
    to_py_function = None

    exception_value = None
506
    exception_check = True
507

508 509
    subtypes = ['dtype']

510
    def __init__(self, base_dtype, axes):
Stefan Behnel's avatar
Stefan Behnel committed
511
        """
512
        MemoryViewSliceType(base, axes)
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542

        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
543
        """
544
        from . import Buffer, MemoryView
545

Kurt Smith's avatar
Kurt Smith committed
546
        self.dtype = base_dtype
547
        self.axes = axes
548
        self.ndim = len(axes)
549
        self.flags = MemoryView.get_buf_flags(self.axes)
550

551 552 553
        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)

554
        self.mode = MemoryView.get_mode(axes)
555
        self.writable_needed = False
556

557
        if not self.dtype.is_fused:
558
            self.dtype_name = Buffer.mangle_dtype_name(self.dtype)
559

560 561 562
    def __hash__(self):
        return hash(self.__class__) ^ hash(self.dtype) ^ hash(tuple(self.axes))

563 564 565 566 567
    def __eq__(self, other):
        if isinstance(other, BaseType):
            return self.same_as_resolved_type(other)
        else:
            return False
568

569 570 571 572 573 574
    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)

575 576 577
    def needs_nonecheck(self):
        return True

Kurt Smith's avatar
Kurt Smith committed
578
    def is_complete(self):
579
        # incomplete since the underlying struct doesn't have a cython.memoryview object.
Kurt Smith's avatar
Kurt Smith committed
580 581 582 583
        return 0

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
584 585 586
        # XXX: we put these guards in for now...
        assert not pyrex
        assert not dll_linkage
587
        from . import MemoryView
588
        return self.base_declaration_code(
589
                MemoryView.memviewslice_cname,
590
                entity_code)
Kurt Smith's avatar
Kurt Smith committed
591

592 593
    def attributes_known(self):
        if self.scope is None:
594
            from . import Symtab
595

596 597
            self.scope = scope = Symtab.CClassScope(
                    'mvs_class_'+self.specialization_suffix(),
598 599
                    None,
                    visibility='extern')
600 601

            scope.parent_type = self
602
            scope.directives = {}
603

604 605 606 607 608
            scope.declare_var('_data', c_char_ptr_type, None,
                              cname='data', is_cdef=1)

        return True

609
    def declare_attribute(self, attribute, env, pos):
610
        from . import MemoryView, Options
611 612

        scope = self.scope
613

614
        if attribute == 'shape':
615 616
            scope.declare_var('shape',
                    c_array_type(c_py_ssize_t_type,
617 618
                                 Options.buffer_max_dims),
                    pos,
619 620 621
                    cname='shape',
                    is_cdef=1)

622
        elif attribute == 'strides':
623 624
            scope.declare_var('strides',
                    c_array_type(c_py_ssize_t_type,
625 626
                                 Options.buffer_max_dims),
                    pos,
627 628 629
                    cname='strides',
                    is_cdef=1)

630
        elif attribute == 'suboffsets':
631 632
            scope.declare_var('suboffsets',
                    c_array_type(c_py_ssize_t_type,
633 634
                                 Options.buffer_max_dims),
                    pos,
635 636 637
                    cname='suboffsets',
                    is_cdef=1)

638
        elif attribute in ("copy", "copy_fortran"):
639
            ndim = len(self.axes)
640

641 642 643 644
            follow_dim = [('direct', 'follow')]
            contig_dim = [('direct', 'contig')]
            to_axes_c = follow_dim * (ndim - 1) + contig_dim
            to_axes_f = contig_dim + follow_dim * (ndim -1)
645

646 647
            to_memview_c = MemoryViewSliceType(self.dtype, to_axes_c)
            to_memview_f = MemoryViewSliceType(self.dtype, to_axes_f)
648

649 650
            for to_memview, cython_name in [(to_memview_c, "copy"),
                                            (to_memview_f, "copy_fortran")]:
651 652 653 654 655 656 657 658 659
                copy_func_type = CFuncType(
                    to_memview,
                    [CFuncTypeArg("memviewslice", self, None)])
                copy_cname = MemoryView.copy_c_or_fortran_cname(to_memview)

                entry = scope.declare_cfunction(
                    cython_name,
                    copy_func_type, pos=pos, defining=1,
                    cname=copy_cname)
660

661 662
                utility = MemoryView.get_copy_new_utility(pos, self, to_memview)
                env.use_utility_code(utility)
663

664 665
            MemoryView.use_cython_array_utility_code(env)

666
        elif attribute in ("is_c_contig", "is_f_contig"):
667
            # is_c_contig and is_f_contig functions
668
            for (c_or_f, cython_name) in (('c', 'is_c_contig'), ('f', 'is_f_contig')):
669

670
                is_contig_name = \
671
                        MemoryView.get_is_contig_func_name(c_or_f, self.ndim)
672

Mark Florisson's avatar
Mark Florisson committed
673
                cfunctype = CFuncType(
674
                        return_type=c_bint_type,
Mark Florisson's avatar
Mark Florisson committed
675 676 677 678
                        args=[CFuncTypeArg("memviewslice", self, None)],
                        exception_value="-1",
                )

679
                entry = scope.declare_cfunction(cython_name,
Mark Florisson's avatar
Mark Florisson committed
680
                            cfunctype,
681 682 683
                            pos=pos,
                            defining=1,
                            cname=is_contig_name)
684

685 686
                entry.utility_code_definition = MemoryView.get_is_contig_utility(
                                            attribute == 'is_c_contig', self.ndim)
687

688
        return True
689

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
    def get_entry(self, node, cname=None, type=None):
        from . import MemoryView, Symtab

        if cname is None:
            assert node.is_simple() or node.is_temp or node.is_elemental
            cname = node.result()

        if type is None:
            type = node.type

        entry = Symtab.Entry(cname, cname, type, node.pos)
        return MemoryView.MemoryViewSliceBufferEntry(entry)

    def conforms_to(self, dst, broadcast=False, copying=False):
        """
        Returns True if src conforms to dst, False otherwise.

        If conformable, the types are the same, the ndims are equal, and each axis spec is conformable.

        Any packing/access spec is conformable to itself.

        'direct' and 'ptr' are conformable to 'full'.
        'contig' and 'follow' are conformable to 'strided'.
        Any other combo is not conformable.
        """
        from . import MemoryView

        src = self

        if src.dtype != dst.dtype:
            return False

        if src.ndim != dst.ndim:
            if broadcast:
                src, dst = MemoryView.broadcast_types(src, dst)
            else:
                return False

        for src_spec, dst_spec in zip(src.axes, dst.axes):
            src_access, src_packing = src_spec
            dst_access, dst_packing = dst_spec
            if src_access != dst_access and dst_access != 'full':
                return False
            if src_packing != dst_packing and dst_packing != 'strided' and not copying:
                return False

        return True

    def valid_dtype(self, dtype, i=0):
        """
        Return whether type dtype can be used as the base type of a
        memoryview slice.

        We support structs, numeric types and objects
        """
        if dtype.is_complex and dtype.real_type.is_int:
            return False

        if dtype.is_struct and dtype.kind == 'struct':
            for member in dtype.scope.var_entries:
                if not self.valid_dtype(member.type):
                    return False

            return True

        return (
            dtype.is_error or
            # Pointers are not valid (yet)
            # (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or
            (dtype.is_array and i < 8 and self.valid_dtype(dtype.base_type, i + 1)) or
            dtype.is_numeric or
            dtype.is_pyobject or
            dtype.is_fused or  # accept this as it will be replaced by specializations later
            (dtype.is_typedef and self.valid_dtype(dtype.typedef_base_type))
        )

    def validate_memslice_dtype(self, pos):
        if not self.valid_dtype(self.dtype):
            error(pos, "Invalid base type for memoryview slice: %s" % self.dtype)

    def assert_direct_dims(self, pos):
        for access, packing in self.axes:
            if access != 'direct':
                error(pos, "All dimensions must be direct")
                return False
        return True

    def transpose(self, pos):
        if not self.assert_direct_dims(pos):
            return error_type
        return MemoryViewSliceType(self.dtype, self.axes[::-1])

782
    def specialization_name(self):
783 784 785
        return '%s_%s' % (
            super(MemoryViewSliceType,self).specialization_name(),
            self.specialization_suffix())
786

787
    def specialization_suffix(self):
788
        return "%s_%s" % (self.axes_to_name(), self.dtype_name)
789

790 791 792
    def can_coerce_to_pyobject(self, env):
        return True

Mark Florisson's avatar
Mark Florisson committed
793 794 795
    def check_for_null_code(self, cname):
        return cname + '.memview'

796
    def create_from_py_utility_code(self, env):
797
        from . import MemoryView, Buffer
798 799 800

        # We don't have 'code', so use a LazyUtilityCode with a callback.
        def lazy_utility_callback(code):
801
            context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype)
802
            return TempitaUtilityCode.load(
803
                "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
804 805 806 807 808 809 810 811 812 813 814 815

        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"

816 817
        suffix = self.specialization_suffix()
        funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
818 819 820

        context = dict(
            MemoryView.context,
821
            buf_flag = self.flags,
822
            ndim = self.ndim,
823
            axes_specs = ', '.join(self.axes_to_code()),
824
            dtype_typedecl = self.dtype.empty_declaration_code(),
825 826 827 828 829 830 831 832
            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

833
    def create_to_py_utility_code(self, env):
834
        self._dtype_to_py_func, self._dtype_from_py_func = self.dtype_object_conversion_funcs(env)
835 836
        return True

837 838 839 840 841 842
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
        assert self._dtype_to_py_func
        assert self._dtype_from_py_func

        to_py_func = "(PyObject *(*)(char *)) " + self._dtype_to_py_func
        from_py_func = "(int (*)(char *, PyObject *)) " + self._dtype_from_py_func
843

844 845
        tup = (result_code, source_code, self.ndim, to_py_func, from_py_func, self.dtype.is_pyobject)
        return "%s = __pyx_memoryview_fromslice(%s, %s, %s, %s, %d);" % tup
846 847 848 849 850 851 852 853 854 855 856 857 858

    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
859 860 861
            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):
862 863
                return "NULL", "NULL"

Mark Florisson's avatar
Mark Florisson committed
864 865 866 867 868 869
            if not self.dtype.to_py_function:
                get_function = "NULL"

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

870 871 872 873 874 875
            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,
876
                dtype = self.dtype.empty_declaration_code(),
877 878 879
                error_condition = error_condition,
            )

880 881
        utility = TempitaUtilityCode.load_cached(
            utility_name, "MemoryView_C.c", context=context)
882 883
        env.use_utility_code(utility)
        return get_function, set_function
884

885
    def axes_to_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
886
        """Return a list of code constants for each axis"""
887
        from . import MemoryView
888 889 890
        d = MemoryView._spec_to_const
        return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]

891
    def axes_to_name(self):
Stefan Behnel's avatar
Stefan Behnel committed
892
        """Return an abbreviated name for our axes"""
893
        from . import MemoryView
894 895 896 897 898 899
        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

900
    def __str__(self):
901
        from . import MemoryView
902 903

        axes_code_list = []
904
        for idx, (access, packing) in enumerate(self.axes):
905 906 907 908
            flag = MemoryView.get_memoryview_flag(access, packing)
            if flag == "strided":
                axes_code_list.append(":")
            else:
909
                if flag == 'contiguous':
Mark Florisson's avatar
Mark Florisson committed
910
                    have_follow = [p for a, p in self.axes[idx - 1:idx + 2]
911 912 913 914
                                         if p == 'follow']
                    if have_follow or self.ndim == 1:
                        flag = '1'

915 916 917 918 919 920 921 922 923
                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))

924
    def specialize(self, values):
Stefan Behnel's avatar
Stefan Behnel committed
925
        """This does not validate the base type!!"""
926 927 928 929
        dtype = self.dtype.specialize(values)
        if dtype is not self.dtype:
            return MemoryViewSliceType(dtype, self.axes)

930 931
        return self

932 933
    def cast_code(self, expr_code):
        return expr_code
934

935

936 937
class BufferType(BaseType):
    #
938 939 940
    #  Delegates most attribute lookups to the base type.
    #  (Anything not defined here or in the BaseType is delegated.)
    #
941 942 943 944 945 946 947
    # dtype            PyrexType
    # ndim             int
    # mode             str
    # negative_indices bool
    # cast             bool
    # is_buffer        bool
    # writable         bool
948 949

    is_buffer = 1
950
    writable = True
951 952 953

    subtypes = ['dtype']

954
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
955 956 957
        self.base = base
        self.dtype = dtype
        self.ndim = ndim
958
        self.buffer_ptr_type = CPtrType(dtype)
959
        self.mode = mode
960
        self.negative_indices = negative_indices
961
        self.cast = cast
Robert Bradshaw's avatar
Robert Bradshaw committed
962

963 964 965
    def as_argument_type(self):
        return self

Mark Florisson's avatar
Mark Florisson committed
966 967 968 969 970 971 972
    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

973 974 975 976 977
    def get_entry(self, node):
        from . import Buffer
        assert node.is_name
        return Buffer.BufferEntry(node.entry)

978 979 980
    def __getattr__(self, name):
        return getattr(self.base, name)

981 982 983
    def __repr__(self):
        return "<BufferType %r>" % self.base

984
    def __str__(self):
985
        # avoid ', ', as fused functions split the signature string on ', '
986
        cast_str = ''
987 988
        if self.cast:
            cast_str = ',cast=True'
989

990
        return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
991
                                      cast_str)
992

993
    def assignable_from(self, other_type):
994 995 996
        if other_type.is_buffer:
            return (self.same_as(other_type, compare_base=False) and
                    self.base.assignable_from(other_type.base))
997

998 999 1000 1001 1002 1003 1004
        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
1005 1006
                self.ndim == other_type.ndim and
                self.mode == other_type.mode and
1007 1008
                self.cast == other_type.cast and
                (not compare_base or self.base.same_as(other_type.base)))
1009

1010

William Stein's avatar
William Stein committed
1011 1012 1013 1014
class PyObjectType(PyrexType):
    #
    #  Base class for all Python object types (reference-counted).
    #
1015
    #  buffer_defaults  dict or None     Default options for bu
1016 1017

    name = "object"
William Stein's avatar
William Stein committed
1018 1019
    is_pyobject = 1
    default_value = "0"
1020
    buffer_defaults = None
1021 1022
    is_extern = False
    is_subclassed = False
1023
    is_gc_simple = False
1024

William Stein's avatar
William Stein committed
1025 1026
    def __str__(self):
        return "Python object"
Robert Bradshaw's avatar
Robert Bradshaw committed
1027

William Stein's avatar
William Stein committed
1028
    def __repr__(self):
1029
        return "<PyObjectType>"
1030 1031 1032 1033

    def can_coerce_to_pyobject(self, env):
        return True

1034
    def default_coerced_ctype(self):
Stefan Behnel's avatar
Stefan Behnel committed
1035
        """The default C type that this Python type coerces to, or None."""
1036 1037
        return None

William Stein's avatar
William Stein committed
1038
    def assignable_from(self, src_type):
1039
        # except for pointers, conversion will be attempted
1040
        return not src_type.is_ptr or src_type.is_string or src_type.is_pyunicode_ptr
Robert Bradshaw's avatar
Robert Bradshaw committed
1041 1042

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1043
            for_display = 0, dll_linkage = None, pyrex = 0):
1044
        if pyrex or for_display:
1045
            base_code = "object"
William Stein's avatar
William Stein committed
1046
        else:
1047 1048 1049
            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
1050

1051 1052 1053 1054 1055
    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
1056

1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
    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

1067 1068 1069
    def global_init_code(self, entry, code):
        code.put_init_var_to_py_none(entry, nanny=False)

Mark Florisson's avatar
Mark Florisson committed
1070 1071 1072
    def check_for_null_code(self, cname):
        return cname

1073

1074 1075 1076 1077 1078 1079
builtin_types_that_cannot_create_refcycles = set([
    'bool', 'int', 'long', 'float', 'complex',
    'bytearray', 'bytes', 'unicode', 'str', 'basestring'
])


Robert Bradshaw's avatar
Robert Bradshaw committed
1080
class BuiltinObjectType(PyObjectType):
1081
    #  objstruct_cname  string           Name of PyObject struct
Robert Bradshaw's avatar
Robert Bradshaw committed
1082 1083 1084 1085 1086 1087

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

1088 1089 1090 1091 1092 1093
    # fields that let it look like an extension type
    vtabslot_cname = None
    vtabstruct_cname = None
    vtabptr_cname = None
    typedef_flag = True
    is_external = True
1094
    decl_type = 'PyObject'
1095

1096
    def __init__(self, name, cname, objstruct_cname=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
1097 1098
        self.name = name
        self.cname = cname
1099
        self.typeptr_cname = "(&%s)" % cname
1100
        self.objstruct_cname = objstruct_cname
1101
        self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles
1102 1103 1104 1105
        if name == 'type':
            # Special case the type type, as many C API calls (and other
            # libraries) actually expect a PyTypeObject* for type arguments.
            self.decl_type = objstruct_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
1106

Robert Bradshaw's avatar
Robert Bradshaw committed
1107 1108 1109 1110
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1111

Robert Bradshaw's avatar
Robert Bradshaw committed
1112 1113
    def __str__(self):
        return "%s object" % self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1114

Robert Bradshaw's avatar
Robert Bradshaw committed
1115 1116
    def __repr__(self):
        return "<%s>"% self.cname
1117 1118

    def default_coerced_ctype(self):
1119
        if self.name in ('bytes', 'bytearray'):
1120 1121 1122 1123 1124 1125 1126
            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
1127 1128
    def assignable_from(self, src_type):
        if isinstance(src_type, BuiltinObjectType):
1129
            if self.name == 'basestring':
1130
                return src_type.name in ('str', 'unicode', 'basestring')
1131 1132
            else:
                return src_type.name == self.name
1133
        elif src_type.is_extension_type:
1134 1135 1136 1137 1138
            # 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!
1139 1140
            return (src_type.module_name == '__builtin__' and
                    src_type.name == self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1141
        else:
1142
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1143

Robert Bradshaw's avatar
Robert Bradshaw committed
1144 1145
    def typeobj_is_available(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1146

Robert Bradshaw's avatar
Robert Bradshaw committed
1147 1148
    def attributes_known(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1149

Robert Bradshaw's avatar
Robert Bradshaw committed
1150
    def subtype_of(self, type):
1151
        return type.is_pyobject and type.assignable_from(self)
1152 1153

    def type_check_function(self, exact=True):
1154 1155
        type_name = self.name
        if type_name == 'str':
1156
            type_check = 'PyString_Check'
1157 1158
        elif type_name == 'basestring':
            type_check = '__Pyx_PyBaseString_Check'
1159 1160
        elif type_name == 'bytearray':
            type_check = 'PyByteArray_Check'
1161
        elif type_name == 'frozenset':
1162
            type_check = 'PyFrozenSet_Check'
1163
        else:
1164
            type_check = 'Py%s_Check' % type_name.capitalize()
Stefan Behnel's avatar
Stefan Behnel committed
1165
        if exact and type_name not in ('bool', 'slice'):
1166 1167 1168 1169 1170
            type_check += 'Exact'
        return type_check

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

1172 1173
    def type_test_code(self, arg, notnone=False, exact=True):
        type_check = self.type_check_function(exact=exact)
1174 1175
        check = 'likely(%s(%s))' % (type_check, arg)
        if not notnone:
Stefan Behnel's avatar
Stefan Behnel committed
1176
            check += '||((%s) == Py_None)' % arg
1177 1178 1179 1180 1181 1182 1183 1184 1185
        if self.name == 'basestring':
            name = '(PY_MAJOR_VERSION < 3 ? "basestring" : "str")'
            space_for_name = 16
        else:
            name = '"%s"' % self.name
            # avoid wasting too much space but limit number of different format strings
            space_for_name = (len(self.name) // 16 + 1) * 16
        error = '(PyErr_Format(PyExc_TypeError, "Expected %%.%ds, got %%.200s", %s, Py_TYPE(%s)->tp_name), 0)' % (
            space_for_name, name, arg)
1186
        return check + '||' + error
Robert Bradshaw's avatar
Robert Bradshaw committed
1187

Robert Bradshaw's avatar
Robert Bradshaw committed
1188
    def declaration_code(self, entity_code,
1189 1190
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
1191
            base_code = self.name
1192
        else:
1193
            base_code = public_decl(self.decl_type, dll_linkage)
1194 1195
            entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
1196

1197 1198 1199 1200 1201 1202
    def as_pyobject(self, cname):
        if self.decl_type == 'PyObject':
            return cname
        else:
            return "(PyObject *)" + cname

1203 1204
    def cast_code(self, expr_code, to_object_struct = False):
        return "((%s*)%s)" % (
1205
            to_object_struct and self.objstruct_cname or self.decl_type, # self.objstruct_cname may be None
1206 1207
            expr_code)

1208 1209 1210 1211
    def py_type_name(self):
        return self.name


Robert Bradshaw's avatar
Robert Bradshaw committed
1212

William Stein's avatar
William Stein committed
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
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
1224
    #  objtypedef_cname string           Name of PyObject struct typedef
William Stein's avatar
William Stein committed
1225 1226 1227 1228 1229 1230
    #  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
1231
    #  defered_declarations [thunk]      Used to declare class hierarchies in order
Robert Bradshaw's avatar
Robert Bradshaw committed
1232

William Stein's avatar
William Stein committed
1233 1234
    is_extension_type = 1
    has_attributes = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1235

1236
    objtypedef_cname = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1237

1238
    def __init__(self, name, typedef_flag, base_type, is_external=0):
William Stein's avatar
William Stein committed
1239 1240 1241
        self.name = name
        self.scope = None
        self.typedef_flag = typedef_flag
1242 1243
        if base_type is not None:
            base_type.is_subclassed = True
William Stein's avatar
William Stein committed
1244 1245 1246 1247 1248 1249 1250 1251 1252
        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
1253
        self.is_external = is_external
1254
        self.defered_declarations = []
Robert Bradshaw's avatar
Robert Bradshaw committed
1255

William Stein's avatar
William Stein committed
1256 1257 1258 1259
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1260

Stefan Behnel's avatar
Stefan Behnel committed
1261 1262 1263
    def needs_nonecheck(self):
        return True

William Stein's avatar
William Stein committed
1264
    def subtype_of_resolved_type(self, other_type):
Stefan Behnel's avatar
Stefan Behnel committed
1265
        if other_type.is_extension_type or other_type.is_builtin_type:
William Stein's avatar
William Stein committed
1266 1267 1268 1269
            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
1270

William Stein's avatar
William Stein committed
1271 1272 1273
    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
1274

William Stein's avatar
William Stein committed
1275 1276 1277 1278
    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
1279

1280 1281 1282 1283 1284 1285
    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)
1286 1287 1288 1289 1290 1291 1292 1293
        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)
1294 1295
        return False

Robert Bradshaw's avatar
Robert Bradshaw committed
1296
    def declaration_code(self, entity_code,
1297
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
1298
        if pyrex or for_display:
1299
            base_code = self.name
William Stein's avatar
William Stein committed
1300 1301
        else:
            if self.typedef_flag:
1302
                objstruct = self.objstruct_cname
William Stein's avatar
William Stein committed
1303
            else:
1304
                objstruct = "struct %s" % self.objstruct_cname
1305
            base_code = public_decl(objstruct, dll_linkage)
1306
            if deref:
1307
                assert not entity_code
1308
            else:
1309 1310
                entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
1311

1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
    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
1322 1323
    def attributes_known(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1324

William Stein's avatar
William Stein committed
1325 1326
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1327

William Stein's avatar
William Stein committed
1328
    def __repr__(self):
1329 1330
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
1331

1332 1333 1334 1335 1336 1337
    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
1338 1339 1340 1341 1342 1343 1344 1345

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
1346

William Stein's avatar
William Stein committed
1347 1348
    to_py_function = None
    from_py_function = None
1349 1350
    exception_value = None
    exception_check = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1351

1352
    def create_to_py_utility_code(self, env):
1353
        return self.to_py_function is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1354

1355
    def create_from_py_utility_code(self, env):
1356
        return self.from_py_function is not None
1357 1358 1359 1360

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

1361 1362
    def error_condition(self, result_code):
        conds = []
1363
        if self.is_string or self.is_pyunicode_ptr:
1364 1365 1366 1367 1368 1369 1370 1371 1372
            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
1373

1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
        func = self.to_py_function if to_py_function is None else to_py_function
        assert func
        if self.is_string or self.is_cpp_string:
            if result_type.is_builtin_type:
                result_type_name = result_type.name
                if result_type_name in ('bytes', 'str', 'unicode'):
                    func = func.replace("Object", result_type_name.title(), 1)
                elif result_type_name == 'bytearray':
                    func = func.replace("Object", "ByteArray", 1)
        return '%s = %s(%s)' % (
            result_code,
            func,
            source_code or 'NULL')

    def from_py_call_code(self, source_code, result_code, error_pos, code,
                          from_py_function=None, error_condition=None):
        return '%s = %s(%s); %s' % (
            result_code,
            from_py_function or self.from_py_function,
            source_code,
            code.error_goto_if(error_condition or self.error_condition(result_code), error_pos))

William Stein's avatar
William Stein committed
1397

Robert Bradshaw's avatar
Robert Bradshaw committed
1398 1399 1400
class CConstType(BaseType):

    is_const = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1401

Robert Bradshaw's avatar
Robert Bradshaw committed
1402 1403 1404
    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:
1405
            from . import Symtab
Robert Bradshaw's avatar
Robert Bradshaw committed
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
            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):
1416 1417 1418 1419
        if for_display or pyrex:
            return "const " + self.const_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex)
        else:
            return self.const_base_type.declaration_code("const %s" % entity_code, for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
1420 1421 1422 1423 1424 1425

    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
1426
            return CConstType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1427

1428 1429 1430
    def deduce_template_params(self, actual):
        return self.const_base_type.deduce_template_params(actual)

1431 1432 1433
    def can_coerce_to_pyobject(self, env):
        return self.const_base_type.can_coerce_to_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
1434 1435 1436 1437 1438 1439 1440 1441 1442
    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)


1443
class FusedType(CType):
1444 1445 1446 1447 1448 1449 1450
    """
    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

1451
    types           [PyrexType]             is the list of types to be fused
1452 1453 1454 1455
    name            str                     the name of the ctypedef
    """

    is_fused = 1
1456
    exception_check = 0
1457

1458
    def __init__(self, types, name=None):
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
        # Use list rather than set to preserve order (list should be short).
        flattened_types = []
        for t in types:
            if t.is_fused:
                # recursively merge in subtypes
                for subtype in t.types:
                    if subtype not in flattened_types:
                        flattened_types.append(subtype)
            elif t not in flattened_types:
                flattened_types.append(t)
1469
        self.types = flattened_types
1470
        self.name = name
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493

    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)


1494
class CVoidType(CType):
1495 1496 1497 1498
    #
    #   C "void" type
    #

William Stein's avatar
William Stein committed
1499
    is_void = 1
1500
    to_py_function = "__Pyx_void_to_None"
Robert Bradshaw's avatar
Robert Bradshaw committed
1501

William Stein's avatar
William Stein committed
1502 1503
    def __repr__(self):
        return "<CVoidType>"
Robert Bradshaw's avatar
Robert Bradshaw committed
1504 1505

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1506
            for_display = 0, dll_linkage = None, pyrex = 0):
1507 1508 1509 1510 1511
        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
1512

William Stein's avatar
William Stein committed
1513 1514 1515
    def is_complete(self):
        return 0

1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
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
1529 1530 1531 1532 1533 1534

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

William Stein's avatar
William Stein committed
1538 1539
    is_numeric = 1
    default_value = "0"
1540 1541
    has_attributes = True
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1542

1543
    sign_words = ("unsigned ", "", "signed ")
Robert Bradshaw's avatar
Robert Bradshaw committed
1544

1545
    def __init__(self, rank, signed = 1):
William Stein's avatar
William Stein committed
1546
        self.rank = rank
1547 1548 1549 1550
        if rank > 0 and signed == SIGNED:
            # Signed is meaningless for anything but char, and complicates
            # type promotion.
            signed = 1
William Stein's avatar
William Stein committed
1551
        self.signed = signed
Robert Bradshaw's avatar
Robert Bradshaw committed
1552

1553 1554 1555 1556
    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
1557

William Stein's avatar
William Stein committed
1558
    def __repr__(self):
1559
        return "<CNumericType %s>" % self.sign_and_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1560 1561

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1562
            for_display = 0, dll_linkage = None, pyrex = 0):
1563 1564 1565 1566 1567 1568
        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
1569

1570 1571
    def attributes_known(self):
        if self.scope is None:
1572
            from . import Symtab
1573 1574 1575 1576 1577 1578
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
            scope.directives = {}
Stefan Behnel's avatar
Stefan Behnel committed
1579
            scope.declare_cfunction(
1580
                    "conjugate",
1581
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1582 1583 1584 1585
                    pos=None,
                    defining=1,
                    cname=" ")
        return True
1586

1587
    def __lt__(self, other):
Stefan Behnel's avatar
Stefan Behnel committed
1588
        """Sort based on rank, preferring signed over unsigned"""
1589 1590 1591
        if other.is_numeric:
            return self.rank > other.rank and self.signed >= other.signed

1592 1593
        # Prefer numeric types over others
        return True
1594 1595 1596 1597 1598

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

William Stein's avatar
William Stein committed
1600

1601 1602 1603 1604 1605 1606 1607
class ForbidUseClass:
    def __repr__(self):
        raise RuntimeError()
    def __str__(self):
        raise RuntimeError()
ForbidUse = ForbidUseClass()

William Stein's avatar
William Stein committed
1608 1609

class CIntType(CNumericType):
1610

William Stein's avatar
William Stein committed
1611 1612
    is_int = 1
    typedef_flag = 0
1613 1614
    to_py_function = None
    from_py_function = None
1615
    exception_value = -1
William Stein's avatar
William Stein committed
1616

1617 1618 1619
    def can_coerce_to_pyobject(self, env):
        return True

Robert Bradshaw's avatar
Robert Bradshaw committed
1620
    def create_to_py_utility_code(self, env):
1621
        if type(self).to_py_function is None:
1622
            self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
1623
            env.use_utility_code(TempitaUtilityCode.load_cached(
1624
                "CIntToPy", "TypeConversion.c",
1625
                context={"TYPE": self.empty_declaration_code(),
1626
                         "TO_PY_FUNCTION": self.to_py_function}))
1627 1628 1629
        return True

    def create_from_py_utility_code(self, env):
1630
        if type(self).from_py_function is None:
1631
            self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
1632
            env.use_utility_code(TempitaUtilityCode.load_cached(
1633
                "CIntFromPy", "TypeConversion.c",
1634
                context={"TYPE": self.empty_declaration_code(),
1635
                         "FROM_PY_FUNCTION": self.from_py_function}))
Robert Bradshaw's avatar
Robert Bradshaw committed
1636
        return True
1637 1638

    def get_to_py_type_conversion(self):
1639
        if self.rank < list(rank_to_type_name).index('int'):
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
            # 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"
1650
            if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
1651 1652 1653 1654
                Prefix = "Long"
                TypeName = "LongLong"
            return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)

1655 1656
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_int or src_type.is_enum or src_type is error_type
1657

1658
    def invalid_value(self):
1659
        if rank_to_type_name[int(self.rank)] == 'char':
1660 1661 1662 1663 1664
            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.
1665
            return "0xbad0bad0"
William Stein's avatar
William Stein committed
1666

1667
    def overflow_check_binop(self, binop, env, const_rhs=False):
1668
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
1669
        type = self.empty_declaration_code()
1670
        name = self.specialization_name()
1671
        if binop == "lshift":
1672
            env.use_utility_code(TempitaUtilityCode.load_cached(
1673
                "LeftShift", "Overflow.c",
1674
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
1675
        else:
1676 1677 1678
            if const_rhs:
                binop += "_const"
            if type in ('int', 'long', 'long long'):
1679
                env.use_utility_code(TempitaUtilityCode.load_cached(
1680 1681
                    "BaseCaseSigned", "Overflow.c",
                    context={'INT': type, 'NAME': name}))
1682
            elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1683
                env.use_utility_code(TempitaUtilityCode.load_cached(
1684 1685
                    "BaseCaseUnsigned", "Overflow.c",
                    context={'UINT': type, 'NAME': name}))
1686 1687 1688 1689 1690
            elif self.rank <= 1:
                # sizeof(short) < sizeof(int)
                return "__Pyx_%s_%s_no_overflow" % (binop, name)
            else:
                _load_overflow_base(env)
1691
                env.use_utility_code(TempitaUtilityCode.load_cached(
1692 1693
                    "SizeCheck", "Overflow.c",
                    context={'TYPE': type, 'NAME': name}))
1694
                env.use_utility_code(TempitaUtilityCode.load_cached(
1695 1696
                    "Binop", "Overflow.c",
                    context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
1697 1698
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

1699

1700 1701 1702
def _load_overflow_base(env):
    env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
    for type in ('int', 'long', 'long long'):
1703
        env.use_utility_code(TempitaUtilityCode.load_cached(
1704 1705
            "BaseCaseSigned", "Overflow.c",
            context={'INT': type, 'NAME': type.replace(' ', '_')}))
1706
    for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1707
        env.use_utility_code(TempitaUtilityCode.load_cached(
1708 1709
            "BaseCaseUnsigned", "Overflow.c",
            context={'UINT': type, 'NAME': type.replace(' ', '_')}))
1710 1711


1712 1713
class CAnonEnumType(CIntType):

1714 1715 1716 1717
    is_enum = 1

    def sign_and_name(self):
        return 'int'
1718

1719

1720 1721
class CReturnCodeType(CIntType):

1722 1723
    to_py_function = "__Pyx_Owned_Py_None"

1724 1725
    is_returncode = True
    exception_check = False
1726

1727

1728 1729 1730 1731
class CBIntType(CIntType):

    to_py_function = "__Pyx_PyBool_FromLong"
    from_py_function = "__Pyx_PyObject_IsTrue"
Robert Bradshaw's avatar
Robert Bradshaw committed
1732
    exception_check = 1 # for C++ bool
1733

1734 1735
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
1736
        if for_display:
1737
            base_code = 'bool'
1738 1739
        elif pyrex:
            base_code = 'bint'
1740 1741 1742 1743
        else:
            base_code = public_decl('int', dll_linkage)
        return self.base_declaration_code(base_code, entity_code)

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

1747 1748 1749
    def __str__(self):
        return 'bint'

1750 1751 1752
    def py_type_name(self):
        return "bool"

1753

Stefan Behnel's avatar
Stefan Behnel committed
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
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):
1769
        env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c"))
Stefan Behnel's avatar
Stefan Behnel committed
1770 1771 1772 1773 1774 1775
        return True

    def sign_and_name(self):
        return "Py_UCS4"


1776 1777 1778
class CPyUnicodeIntType(CIntType):
    # Py_UNICODE

Stefan Behnel's avatar
Stefan Behnel committed
1779 1780
    is_unicode_char = True

1781 1782 1783 1784
    # 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.
1785

1786 1787 1788 1789
    to_py_function = "PyUnicode_FromOrdinal"
    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"

    def create_from_py_utility_code(self, env):
1790
        env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c"))
1791
        return True
1792 1793 1794 1795 1796

    def sign_and_name(self):
        return "Py_UNICODE"


1797 1798 1799 1800 1801 1802 1803 1804
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"

1805 1806 1807
class CPySSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
1808
    from_py_function = "__Pyx_PyIndex_AsSsize_t"
1809

1810
    def sign_and_name(self):
1811
        return "Py_ssize_t"
1812

1813 1814 1815 1816 1817 1818
class CSSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
    from_py_function = "PyInt_AsSsize_t"

    def sign_and_name(self):
1819
        return "Py_ssize_t"
1820

1821
class CSizeTType(CIntType):
1822

1823
    to_py_function = "__Pyx_PyInt_FromSize_t"
1824

1825
    def sign_and_name(self):
1826
        return "size_t"
1827

1828 1829 1830 1831 1832
class CPtrdiffTType(CIntType):

    def sign_and_name(self):
        return "ptrdiff_t"

1833

William Stein's avatar
William Stein committed
1834 1835 1836 1837
class CFloatType(CNumericType):

    is_float = 1
    to_py_function = "PyFloat_FromDouble"
1838
    from_py_function = "__pyx_PyFloat_AsDouble"
1839 1840

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

1842 1843
    def __init__(self, rank, math_h_modifier = ''):
        CNumericType.__init__(self, rank, 1)
1844
        self.math_h_modifier = math_h_modifier
1845 1846
        if rank == RANK_FLOAT:
            self.from_py_function = "__pyx_PyFloat_AsFloat"
Robert Bradshaw's avatar
Robert Bradshaw committed
1847

1848
    def assignable_from_resolved_type(self, src_type):
1849 1850
        return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type

1851 1852
    def invalid_value(self):
        return Naming.PYX_NAN
1853

1854
class CComplexType(CNumericType):
Robert Bradshaw's avatar
Robert Bradshaw committed
1855

1856
    is_complex = 1
1857
    to_py_function = "__pyx_PyComplex_FromComplex"
1858 1859
    has_attributes = 1
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1860

1861
    def __init__(self, real_type):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1862 1863 1864 1865 1866
        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
1867
            self.funcsuffix = "_%s" % real_type.specialization_name()
1868
        elif hasattr(real_type, 'math_h_modifier'):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1869
            self.funcsuffix = real_type.math_h_modifier
1870
        else:
Craig Citro's avatar
Craig Citro committed
1871
            self.funcsuffix = "_%s" % real_type.specialization_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1872

1873 1874
        self.real_type = real_type
        CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
1875
        self.binops = {}
Craig Citro's avatar
Craig Citro committed
1876
        self.from_parts = "%s_from_parts" % self.specialization_name()
1877
        self.default_value = "%s(0, 0)" % self.from_parts
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1878

1879
    def __eq__(self, other):
1880
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
1881
            return self.real_type == other.real_type
1882
        else:
1883
            return False
Robert Bradshaw's avatar
Robert Bradshaw committed
1884

1885 1886 1887 1888 1889
    def __ne__(self, other):
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
            return self.real_type != other.real_type
        else:
            return True
1890 1891 1892 1893 1894 1895 1896 1897 1898

    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

1899 1900
    def __hash__(self):
        return ~hash(self.real_type)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1901

Robert Bradshaw's avatar
Robert Bradshaw committed
1902
    def declaration_code(self, entity_code,
1903
            for_display = 0, dll_linkage = None, pyrex = 0):
1904 1905 1906
        if pyrex or for_display:
            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
            base_code = "%s complex" % real_code
1907
        else:
1908 1909
            base_code = public_decl(self.sign_and_name(), dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
1910

1911
    def sign_and_name(self):
Craig Citro's avatar
Craig Citro committed
1912
        real_type_name = self.real_type.specialization_name()
1913
        real_type_name = real_type_name.replace('long__double','long_double')
1914
        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
1915
        return Naming.type_prefix + real_type_name + "_complex"
Robert Bradshaw's avatar
Robert Bradshaw committed
1916

1917 1918
    def assignable_from(self, src_type):
        # Temporary hack/feature disabling, see #441
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1919 1920 1921
        if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
            and src_type.typedef_is_external):
             return False
1922 1923
        else:
            return super(CComplexType, self).assignable_from(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1924

1925 1926
    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
1927
                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
1928
                    or src_type is error_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
1929

1930 1931
    def attributes_known(self):
        if self.scope is None:
1932
            from . import Symtab
1933 1934 1935 1936 1937
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
1938
            scope.directives = {}
1939 1940
            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
1941
            scope.declare_cfunction(
1942
                    "conjugate",
1943
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1944 1945
                    pos=None,
                    defining=1,
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1946
                    cname="__Pyx_c_conj%s" % self.funcsuffix)
1947

1948
        return True
1949

1950
    def create_declaration_utility_code(self, env):
1951 1952
        # This must always be run, because a single CComplexType instance can be shared
        # across multiple compilations (the one created in the module scope)
1953 1954 1955 1956
        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
1957
                             complex_arithmetic_utility_code):
1958 1959
            env.use_utility_code(
                utility_code.specialize(
Robert Bradshaw's avatar
Robert Bradshaw committed
1960
                    self,
1961
                    real_type = self.real_type.empty_declaration_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
1962 1963
                    m = self.funcsuffix,
                    is_float = self.real_type.is_float))
1964 1965
        return True

1966 1967 1968
    def can_coerce_to_pyobject(self, env):
        return True

1969 1970 1971
    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)
1972 1973 1974 1975
        return True

    def create_from_py_utility_code(self, env):
        self.real_type.create_from_py_utility_code(env)
1976 1977 1978 1979 1980

        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
1981
                    self,
1982
                    real_type = self.real_type.empty_declaration_code(),
Robert Bradshaw's avatar
Robert Bradshaw committed
1983 1984
                    m = self.funcsuffix,
                    is_float = self.real_type.is_float))
Craig Citro's avatar
Craig Citro committed
1985
        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
1986
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1987

1988
    def lookup_op(self, nargs, op):
1989
        try:
1990
            return self.binops[nargs, op]
1991
        except KeyError:
1992 1993 1994
            pass
        try:
            op_name = complex_ops[nargs, op]
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
1995
            self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
1996 1997 1998 1999 2000 2001
            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
2002

2003 2004
    def binary_op(self, op):
        return self.lookup_op(2, op)
Robert Bradshaw's avatar
Robert Bradshaw committed
2005

2006 2007 2008
    def py_type_name(self):
        return "complex"

2009 2010 2011
    def cast_code(self, expr_code):
        return expr_code

2012 2013 2014
complex_ops = {
    (1, '-'): 'neg',
    (1, 'zero'): 'is_zero',
2015 2016 2017 2018
    (2, '+'): 'sum',
    (2, '-'): 'diff',
    (2, '*'): 'prod',
    (2, '/'): 'quot',
2019 2020
    (2, '=='): 'eq',
}
2021

2022
complex_header_utility_code = UtilityCode(
2023
proto_block='h_code',
2024
proto="""
2025 2026 2027 2028 2029 2030 2031 2032
#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
2033 2034
#endif

2035 2036 2037 2038 2039 2040 2041
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    #include <complex>
  #else
    #include <complex.h>
  #endif
#endif
Robert Bradshaw's avatar
Robert Bradshaw committed
2042 2043 2044 2045 2046

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

2049
complex_real_imag_utility_code = UtilityCode(
2050
proto="""
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
#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
2063

2064
#if defined(__cplusplus) && CYTHON_CCOMPLEX \
2065
        && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103)
2066 2067 2068 2069 2070 2071
    #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
2072 2073
""")

2074
complex_type_utility_code = UtilityCode(
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2075
proto_block='complex_type_declarations',
2076
proto="""
2077 2078 2079 2080
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    typedef ::std::complex< %(real_type)s > %(type_name)s;
  #else
2081
    typedef %(real_type)s _Complex %(type_name)s;
2082 2083 2084 2085 2086 2087 2088
  #endif
#else
    typedef struct { %(real_type)s real, imag; } %(type_name)s;
#endif
""")

complex_from_parts_utility_code = UtilityCode(
2089
proto_block='utility_code_proto',
2090
proto="""
2091
static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s, %(real_type)s);
2092 2093 2094 2095
""",
impl="""
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
2096
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
2097 2098 2099
      return ::std::complex< %(real_type)s >(x, y);
    }
  #else
2100
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
2101 2102
      return x + y*(%(type)s)_Complex_I;
    }
2103
  #endif
2104
#else
2105
    static CYTHON_INLINE %(type)s %(type_name)s_from_parts(%(real_type)s x, %(real_type)s y) {
2106
      %(type)s z;
Robert Bradshaw's avatar
Robert Bradshaw committed
2107 2108 2109
      z.real = x;
      z.imag = y;
      return z;
2110
    }
2111 2112
#endif
""")
2113

2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
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;
2128
#if CYTHON_COMPILING_IN_CPYTHON
2129 2130 2131
    if (PyComplex_CheckExact(o))
        cval = ((PyComplexObject *)o)->cval;
    else
2132
#endif
2133 2134 2135 2136 2137 2138
        cval = PyComplex_AsCComplex(o);
    return %(type_name)s_from_parts(
               (%(real_type)s)cval.real,
               (%(real_type)s)cval.imag);
}
""")
2139

Craig Citro's avatar
Craig Citro committed
2140
complex_arithmetic_utility_code = UtilityCode(
2141 2142 2143 2144 2145 2146 2147 2148 2149
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
2150
    #define __Pyx_c_is_zero%(m)s(z) ((z)==(%(real_type)s)0)
2151
    #define __Pyx_c_conj%(m)s(z)    (::std::conj(z))
Robert Bradshaw's avatar
Robert Bradshaw committed
2152 2153 2154 2155
    #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
2156 2157 2158
  #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
2159 2160 2161 2162
    #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
2163 2164
 #endif
#else
2165 2166 2167 2168 2169 2170 2171 2172
    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
2173 2174 2175 2176
    #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
2177 2178 2179 2180 2181
#endif
""",
impl="""
#if CYTHON_CCOMPLEX
#else
2182
    static CYTHON_INLINE int __Pyx_c_eq%(m)s(%(type)s a, %(type)s b) {
2183 2184
       return (a.real == b.real) && (a.imag == b.imag);
    }
2185
    static CYTHON_INLINE %(type)s __Pyx_c_sum%(m)s(%(type)s a, %(type)s b) {
2186 2187 2188 2189 2190
        %(type)s z;
        z.real = a.real + b.real;
        z.imag = a.imag + b.imag;
        return z;
    }
2191
    static CYTHON_INLINE %(type)s __Pyx_c_diff%(m)s(%(type)s a, %(type)s b) {
2192 2193 2194 2195 2196
        %(type)s z;
        z.real = a.real - b.real;
        z.imag = a.imag - b.imag;
        return z;
    }
2197
    static CYTHON_INLINE %(type)s __Pyx_c_prod%(m)s(%(type)s a, %(type)s b) {
2198 2199 2200 2201 2202
        %(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;
    }
2203
    static CYTHON_INLINE %(type)s __Pyx_c_quot%(m)s(%(type)s a, %(type)s b) {
2204
        %(type)s z;
2205
        %(real_type)s denom = b.real * b.real + b.imag * b.imag;
2206 2207 2208 2209
        z.real = (a.real * b.real + a.imag * b.imag) / denom;
        z.imag = (a.imag * b.real - a.real * b.imag) / denom;
        return z;
    }
2210
    static CYTHON_INLINE %(type)s __Pyx_c_neg%(m)s(%(type)s a) {
2211 2212 2213 2214 2215
        %(type)s z;
        z.real = -a.real;
        z.imag = -a.imag;
        return z;
    }
2216
    static CYTHON_INLINE int __Pyx_c_is_zero%(m)s(%(type)s a) {
2217 2218
       return (a.real == 0) && (a.imag == 0);
    }
2219
    static CYTHON_INLINE %(type)s __Pyx_c_conj%(m)s(%(type)s a) {
2220 2221 2222 2223 2224
        %(type)s z;
        z.real =  a.real;
        z.imag = -a.imag;
        return z;
    }
Robert Bradshaw's avatar
Robert Bradshaw committed
2225 2226
    #if %(is_float)s
        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
2227
          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
Robert Bradshaw's avatar
Robert Bradshaw committed
2228
            return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
2229 2230
          #else
            return hypot%(m)s(z.real, z.imag);
Robert Bradshaw's avatar
Robert Bradshaw committed
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
          #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
2279
#endif
2280
""")
2281

2282 2283 2284 2285
class CPointerBaseType(CType):
    # common base type for pointer/array types
    #
    #  base_type     CType              Reference type
2286 2287 2288

    subtypes = ['base_type']

2289
    def __init__(self, base_type):
William Stein's avatar
William Stein committed
2290
        self.base_type = base_type
2291 2292
        if base_type.is_const:
            base_type = base_type.const_base_type
2293 2294 2295 2296
        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
2297 2298
        else:
            if base_type.same_as(c_py_unicode_type):
2299
                self.is_pyunicode_ptr = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2300

2301
        if self.is_string and not base_type.is_error:
2302 2303 2304 2305 2306
            if base_type.signed == 2:
                self.to_py_function = "__Pyx_PyObject_FromCString"
                if self.is_ptr:
                    self.from_py_function = "__Pyx_PyObject_AsSString"
            elif base_type.signed:
2307
                self.to_py_function = "__Pyx_PyObject_FromString"
2308
                if self.is_ptr:
2309
                    self.from_py_function = "__Pyx_PyObject_AsString"
2310
            else:
2311
                self.to_py_function = "__Pyx_PyObject_FromCString"
2312
                if self.is_ptr:
2313
                    self.from_py_function = "__Pyx_PyObject_AsUString"
2314
            self.exception_value = "NULL"
2315
        elif self.is_pyunicode_ptr and not base_type.is_error:
2316 2317 2318 2319
            self.to_py_function = "__Pyx_PyUnicode_FromUnicode"
            if self.is_ptr:
                self.from_py_function = "__Pyx_PyUnicode_AsUnicode"
            self.exception_value = "NULL"
2320 2321 2322 2323

    def py_type_name(self):
        if self.is_string:
            return "bytes"
2324
        elif self.is_pyunicode_ptr:
2325
            return "unicode"
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
        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
2340
    to_tuple_function = None
2341 2342 2343 2344 2345

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

2346
    def __eq__(self, other):
2347 2348
        if isinstance(other, CType) and other.is_array and self.size == other.size:
            return self.base_type.same_as(other.base_type)
2349 2350
        return False

2351 2352 2353
    def __hash__(self):
        return hash(self.base_type) + 28 # arbitrarily chosen offset

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

William Stein's avatar
William Stein committed
2357 2358 2359 2360
    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
2361

William Stein's avatar
William Stein committed
2362
    def assignable_from_resolved_type(self, src_type):
2363 2364 2365 2366 2367 2368
        # C arrays are assigned by value, either Python containers or C arrays/pointers
        if src_type.is_pyobject:
            return True
        if src_type.is_ptr or src_type.is_array:
            return self.base_type.assignable_from(src_type.base_type)
        return False
Robert Bradshaw's avatar
Robert Bradshaw committed
2369

William Stein's avatar
William Stein committed
2370 2371 2372
    def element_ptr_type(self):
        return c_ptr_type(self.base_type)

Robert Bradshaw's avatar
Robert Bradshaw committed
2373
    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2374 2375 2376 2377 2378
            for_display = 0, dll_linkage = None, pyrex = 0):
        if self.size is not None:
            dimension_code = self.size
        else:
            dimension_code = ""
2379 2380
        if entity_code.startswith("*"):
            entity_code = "(%s)" % entity_code
William Stein's avatar
William Stein committed
2381
        return self.base_type.declaration_code(
2382
            "%s[%s]" % (entity_code, dimension_code),
William Stein's avatar
William Stein committed
2383
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2384

William Stein's avatar
William Stein committed
2385 2386
    def as_argument_type(self):
        return c_ptr_type(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2387

William Stein's avatar
William Stein committed
2388 2389 2390
    def is_complete(self):
        return self.size is not None

2391 2392 2393 2394 2395
    def specialize(self, values):
        base_type = self.base_type.specialize(values)
        if base_type == self.base_type:
            return self
        else:
2396
            return CArrayType(base_type, self.size)
2397 2398 2399 2400 2401 2402 2403

    def deduce_template_params(self, actual):
        if isinstance(actual, CArrayType):
            return self.base_type.deduce_template_params(actual.base_type)
        else:
            return None

2404 2405 2406
    def can_coerce_to_pyobject(self, env):
        return self.base_type.can_coerce_to_pyobject(env)

2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474
    def create_to_py_utility_code(self, env):
        if self.to_py_function is not None:
            return self.to_py_function
        if not self.base_type.create_to_py_utility_code(env):
            return False

        base_type = self.base_type.declaration_code("", pyrex=1)
        safe_typename = re.sub('[^a-zA-Z0-9]', '__', base_type)
        to_py_function = "__Pyx_carray_to_py_%s" % safe_typename
        to_tuple_function = "__Pyx_carray_to_tuple_%s" % safe_typename

        from .UtilityCode import CythonUtilityCode
        context = {
            'cname': to_py_function,
            'to_tuple_cname': to_tuple_function,
            'base_type': base_type,
        }
        env.use_utility_code(CythonUtilityCode.load(
            "carray.to_py", "CConvert.pyx",
            outer_module_scope=env.global_scope(),  # need access to types declared in module
            context=context, compiler_directives=dict(env.global_scope().directives)))
        self.to_tuple_function = to_tuple_function
        self.to_py_function = to_py_function
        return True

    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
        func = self.to_py_function if to_py_function is None else to_py_function
        if self.is_string or self.is_pyunicode_ptr:
            return '%s = %s(%s)' % (
                result_code,
                func,
                source_code)
        target_is_tuple = result_type.is_builtin_type and result_type.name == 'tuple'
        return '%s = %s(%s, %s)' % (
            result_code,
            self.to_tuple_function if target_is_tuple else func,
            source_code,
            self.size)

    def create_from_py_utility_code(self, env):
        if self.from_py_function is not None:
            return self.from_py_function
        if not self.base_type.create_from_py_utility_code(env):
            return False

        base_type = self.base_type.declaration_code("", pyrex=1)
        safe_typename = re.sub('[^a-zA-Z0-9]', '__', base_type)
        from_py_function = "__Pyx_carray_from_py_%s" % safe_typename

        from .UtilityCode import CythonUtilityCode
        context = {
            'cname': from_py_function,
            'base_type': base_type,
        }
        env.use_utility_code(CythonUtilityCode.load(
            "carray.from_py", "CConvert.pyx",
            outer_module_scope=env.global_scope(),  # need access to types declared in module
            context=context, compiler_directives=dict(env.global_scope().directives)))
        self.from_py_function = from_py_function
        return True

    def from_py_call_code(self, source_code, result_code, error_pos, code,
                          from_py_function=None, error_condition=None):
        call_code = "%s(%s, %s, %s)" % (
            from_py_function or self.from_py_function,
            source_code, result_code, self.size)
        return code.error_goto_if_neg(call_code, error_pos)

William Stein's avatar
William Stein committed
2475

2476 2477
class CPtrType(CPointerBaseType):
    #  base_type     CType              Reference type
Robert Bradshaw's avatar
Robert Bradshaw committed
2478

William Stein's avatar
William Stein committed
2479
    is_ptr = 1
2480
    default_value = "0"
2481

2482 2483 2484
    def __hash__(self):
        return hash(self.base_type) + 27 # arbitrarily chosen offset

2485 2486 2487 2488 2489
    def __eq__(self, other):
        if isinstance(other, CType) and other.is_ptr:
            return self.base_type.same_as(other.base_type)
        return False

Robert Bradshaw's avatar
Robert Bradshaw committed
2490 2491 2492
    def __ne__(self, other):
        return not (self == other)

William Stein's avatar
William Stein committed
2493
    def __repr__(self):
2494
        return "<CPtrType %s>" % repr(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2495

William Stein's avatar
William Stein committed
2496 2497 2498 2499
    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
2500 2501

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2502 2503 2504
            for_display = 0, dll_linkage = None, pyrex = 0):
        #print "CPtrType.declaration_code: pointer to", self.base_type ###
        return self.base_type.declaration_code(
2505
            "*%s" % entity_code,
William Stein's avatar
William Stein committed
2506
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2507

William Stein's avatar
William Stein committed
2508 2509 2510
    def assignable_from_resolved_type(self, other_type):
        if other_type is error_type:
            return 1
2511
        if other_type.is_null_ptr:
William Stein's avatar
William Stein committed
2512
            return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2513 2514
        if self.base_type.is_const:
            self = CPtrType(self.base_type.const_base_type)
2515 2516 2517 2518 2519 2520 2521
        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
2522
        if (self.base_type.is_cpp_class and other_type.is_ptr
2523 2524
                and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)):
            return 1
2525
        if other_type.is_array or other_type.is_ptr:
2526
            return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
2527
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2528

2529 2530 2531 2532 2533 2534
    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
2535

2536 2537 2538 2539 2540 2541
    def deduce_template_params(self, actual):
        if isinstance(actual, CPtrType):
            return self.base_type.deduce_template_params(actual.base_type)
        else:
            return None

2542 2543
    def invalid_value(self):
        return "1"
William Stein's avatar
William Stein committed
2544

2545 2546
    def find_cpp_operation_type(self, operator, operand_type=None):
        if self.base_type.is_cpp_class:
Stefan Behnel's avatar
Stefan Behnel committed
2547
            return self.base_type.find_cpp_operation_type(operator, operand_type)
2548 2549
        return None

2550

William Stein's avatar
William Stein committed
2551 2552 2553
class CNullPtrType(CPtrType):

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

William Stein's avatar
William Stein committed
2555

Robert Bradshaw's avatar
Robert Bradshaw committed
2556
class CReferenceType(BaseType):
Danilo Freitas's avatar
Danilo Freitas committed
2557 2558

    is_reference = 1
2559
    is_fake_reference = 0
Danilo Freitas's avatar
Danilo Freitas committed
2560 2561

    def __init__(self, base_type):
Robert Bradshaw's avatar
Robert Bradshaw committed
2562
        self.ref_base_type = base_type
Danilo Freitas's avatar
Danilo Freitas committed
2563 2564

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

Robert Bradshaw's avatar
Robert Bradshaw committed
2567 2568
    def __str__(self):
        return "%s &" % self.ref_base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2569

Robert Bradshaw's avatar
Robert Bradshaw committed
2570
    def declaration_code(self, entity_code,
Danilo Freitas's avatar
Danilo Freitas committed
2571
            for_display = 0, dll_linkage = None, pyrex = 0):
2572
        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
Robert Bradshaw's avatar
Robert Bradshaw committed
2573
        return self.ref_base_type.declaration_code(
Danilo Freitas's avatar
Danilo Freitas committed
2574 2575
            "&%s" % entity_code,
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2576

Danilo Freitas's avatar
Danilo Freitas committed
2577
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
2578 2579
        base_type = self.ref_base_type.specialize(values)
        if base_type == self.ref_base_type:
Danilo Freitas's avatar
Danilo Freitas committed
2580 2581
            return self
        else:
2582
            return type(self)(base_type)
Danilo Freitas's avatar
Danilo Freitas committed
2583

2584 2585 2586
    def deduce_template_params(self, actual):
        return self.ref_base_type.deduce_template_params(actual)

Robert Bradshaw's avatar
Robert Bradshaw committed
2587 2588 2589 2590
    def __getattr__(self, name):
        return getattr(self.ref_base_type, name)


2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606
class CFakeReferenceType(CReferenceType):

    is_fake_reference = 1

    def __repr__(self):
        return "<CFakeReferenceType %s>" % repr(self.ref_base_type)

    def __str__(self):
        return "%s [&]" % self.ref_base_type

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
        return "__Pyx_FakeReference<%s> %s" % (self.ref_base_type.empty_declaration_code(), entity_code)


William Stein's avatar
William Stein committed
2607 2608 2609 2610 2611
class CFuncType(CType):
    #  return_type      CType
    #  args             [CFuncTypeArg]
    #  has_varargs      boolean
    #  exception_value  string
2612 2613 2614 2615
    #  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
2616
    #  templates        [string] or None
2617
    #  cached_specialized_types [CFuncType]   cached specialized versions of the CFuncType if defined in a pxd
Mark Florisson's avatar
Mark Florisson committed
2618 2619
    #  from_fused       boolean    Indicates whether this is a specialized
    #                              C function
2620 2621
    #  is_strict_signature boolean  function refuses to accept coerced arguments
    #                               (used for optimisation overrides)
Robert Bradshaw's avatar
Robert Bradshaw committed
2622
    #  is_const_method  boolean
2623
    #  is_static_method boolean
Robert Bradshaw's avatar
Robert Bradshaw committed
2624

William Stein's avatar
William Stein committed
2625
    is_cfunction = 1
2626
    original_sig = None
2627
    cached_specialized_types = None
Mark Florisson's avatar
Mark Florisson committed
2628
    from_fused = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2629
    is_const_method = False
2630 2631 2632

    subtypes = ['return_type', 'args']

2633 2634
    def __init__(self, return_type, args, has_varargs = 0,
            exception_value = None, exception_check = 0, calling_convention = "",
Danilo Freitas's avatar
Danilo Freitas committed
2635
            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
Robert Bradshaw's avatar
Robert Bradshaw committed
2636 2637
            is_const_method = False, is_static_method=False,
            templates = None, is_strict_signature = False):
William Stein's avatar
William Stein committed
2638 2639 2640
        self.return_type = return_type
        self.args = args
        self.has_varargs = has_varargs
2641
        self.optional_arg_count = optional_arg_count
William Stein's avatar
William Stein committed
2642 2643
        self.exception_value = exception_value
        self.exception_check = exception_check
2644 2645
        self.calling_convention = calling_convention
        self.nogil = nogil
2646
        self.with_gil = with_gil
2647
        self.is_overridable = is_overridable
2648
        self.is_const_method = is_const_method
Robert Bradshaw's avatar
Robert Bradshaw committed
2649
        self.is_static_method = is_static_method
Danilo Freitas's avatar
Danilo Freitas committed
2650
        self.templates = templates
2651
        self.is_strict_signature = is_strict_signature
2652

William Stein's avatar
William Stein committed
2653
    def __repr__(self):
2654
        arg_reprs = list(map(repr, self.args))
William Stein's avatar
William Stein committed
2655 2656
        if self.has_varargs:
            arg_reprs.append("...")
2657 2658 2659 2660 2661 2662 2663
        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
2664
            repr(self.return_type),
2665
            self.calling_convention_prefix(),
2666 2667
            ",".join(arg_reprs),
            except_clause)
Robert Bradshaw's avatar
Robert Bradshaw committed
2668

2669 2670 2671 2672 2673 2674
    def calling_convention_prefix(self):
        cc = self.calling_convention
        if cc:
            return cc + " "
        else:
            return ""
Robert Bradshaw's avatar
Robert Bradshaw committed
2675

2676 2677 2678
    def as_argument_type(self):
        return c_ptr_type(self)

William Stein's avatar
William Stein committed
2679 2680 2681 2682
    def same_c_signature_as(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(
            other_type.resolve(), as_cmethod)

2683
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod = 0):
2684
        #print "CFuncType.same_c_signature_as_resolved_type:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
2685
        #    self, other_type, "as_cmethod =", as_cmethod ###
William Stein's avatar
William Stein committed
2686 2687 2688 2689
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2690
        if self.is_overridable != other_type.is_overridable:
2691
            return 0
William Stein's avatar
William Stein committed
2692
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
2693
        if nargs != len(other_type.args):
William Stein's avatar
William Stein committed
2694 2695 2696 2697 2698
            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):
2699 2700
            if not self.args[i].type.same_as(other_type.args[i].type):
                return 0
Stefan Behnel's avatar
Stefan Behnel committed
2701
        if self.has_varargs != other_type.has_varargs:
William Stein's avatar
William Stein committed
2702
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2703
        if self.optional_arg_count != other_type.optional_arg_count:
2704
            return 0
William Stein's avatar
William Stein committed
2705 2706
        if not self.return_type.same_as(other_type.return_type):
            return 0
2707 2708
        if not self.same_calling_convention_as(other_type):
            return 0
2709 2710
        if self.exception_check != other_type.exception_check:
            return 0
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
        if not self._same_exception_value(other_type.exception_value):
            return 0
        return 1

    def _same_exception_value(self, other_exc_value):
        if self.exception_value == other_exc_value:
            return 1
        if self.exception_check != '+':
            return 0
        if not self.exception_value or not other_exc_value:
            return 0
        if self.exception_value.type != other_exc_value.type:
            return 0
        if self.exception_value.entry and other_exc_value.entry:
            if self.exception_value.entry.cname != other_exc_value.entry.cname:
                return 0
        if self.exception_value.name != other_exc_value.name:
            return 0
William Stein's avatar
William Stein committed
2729
        return 1
2730

2731 2732
    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
2733

2734 2735
    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
2736
        #    self, other_type, "as_cmethod =", as_cmethod ###
2737 2738 2739 2740
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2741
        if not self.is_overridable and other_type.is_overridable:
2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
            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
2757
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
2758 2759 2760
            return 0
        if not self.same_calling_convention_as(other_type):
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2761 2762
        if self.nogil != other_type.nogil:
            return 0
2763 2764 2765
        if not self.exception_check and other_type.exception_check:
            # a redundant exception check doesn't make functions incompatible, but a missing one does
            return 0
2766 2767
        if not self._same_exception_value(other_type.exception_value):
            return 0
2768
        self.original_sig = other_type.original_sig or other_type
2769
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2770

2771 2772
    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
2773

2774 2775 2776 2777 2778 2779
    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
2780
        if nargs != len(other_type.args):
2781 2782 2783 2784 2785 2786 2787
            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
2788
        if self.has_varargs != other_type.has_varargs:
2789
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2790
        if self.optional_arg_count != other_type.optional_arg_count:
2791
            return 0
2792 2793
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
            return 0
2794 2795 2796
        if not self.exception_check and other_type.exception_check:
            # a redundant exception check doesn't make functions incompatible, but a missing one does
            return 0
2797 2798
        if not self._same_exception_value(other_type.exception_value):
            return 0
2799 2800
        return 1

2801
    def same_calling_convention_as(self, other):
2802 2803 2804 2805 2806 2807 2808 2809 2810
        ## 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
2811 2812 2813
        sc1 = self.calling_convention == '__stdcall'
        sc2 = other.calling_convention == '__stdcall'
        return sc1 == sc2
Robert Bradshaw's avatar
Robert Bradshaw committed
2814

William Stein's avatar
William Stein committed
2815 2816
    def same_as_resolved_type(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(other_type, as_cmethod) \
2817
            and self.nogil == other_type.nogil
Robert Bradshaw's avatar
Robert Bradshaw committed
2818

2819 2820 2821
    def pointer_assignable_from_resolved_type(self, other_type):
        return self.same_c_signature_as_resolved_type(other_type) \
            and not (self.nogil and not other_type.nogil)
Robert Bradshaw's avatar
Robert Bradshaw committed
2822 2823

    def declaration_code(self, entity_code,
2824 2825
                         for_display = 0, dll_linkage = None, pyrex = 0,
                         with_calling_convention = 1):
William Stein's avatar
William Stein committed
2826
        arg_decl_list = []
2827
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
William Stein's avatar
William Stein committed
2828 2829
            arg_decl_list.append(
                arg.type.declaration_code("", for_display, pyrex = pyrex))
2830 2831
        if self.is_overridable:
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
2832
        if self.optional_arg_count:
2833
            arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
2834 2835
        if self.has_varargs:
            arg_decl_list.append("...")
2836
        arg_decl_code = ", ".join(arg_decl_list)
William Stein's avatar
William Stein committed
2837 2838
        if not arg_decl_code and not pyrex:
            arg_decl_code = "void"
2839
        trailer = ""
2840
        if (pyrex or for_display) and not self.return_type.is_pyobject:
William Stein's avatar
William Stein committed
2841
            if self.exception_value and self.exception_check:
2842
                trailer = " except? %s" % self.exception_value
William Stein's avatar
William Stein committed
2843
            elif self.exception_value:
2844
                trailer = " except %s" % self.exception_value
Felix Wu's avatar
Felix Wu committed
2845
            elif self.exception_check == '+':
2846
                trailer = " except +"
2847 2848 2849
            elif self.exception_check and for_display:
                # not spelled out by default, unless for human eyes
                trailer = " except *"
2850 2851
            if self.nogil:
                trailer += " nogil"
2852 2853 2854 2855 2856 2857 2858
        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
2859 2860
        if self.is_const_method:
            trailer += " const"
William Stein's avatar
William Stein committed
2861
        return self.return_type.declaration_code(
2862
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
William Stein's avatar
William Stein committed
2863
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2864

2865
    def function_header_code(self, func_name, arg_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2866 2867 2868 2869 2870 2871
        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
2872

2873
    def signature_string(self):
2874
        s = self.empty_declaration_code()
2875 2876
        return s

2877 2878 2879
    def signature_cast_string(self):
        s = self.declaration_code("(*)", with_calling_convention=False)
        return '(%s)' % s
Robert Bradshaw's avatar
Robert Bradshaw committed
2880

Robert Bradshaw's avatar
Robert Bradshaw committed
2881
    def specialize(self, values):
Mark Florisson's avatar
Mark Florisson committed
2882 2883
        result = CFuncType(self.return_type.specialize(values),
                           [arg.specialize(values) for arg in self.args],
2884
                           has_varargs = self.has_varargs,
Mark Florisson's avatar
Mark Florisson committed
2885 2886 2887 2888 2889 2890 2891
                           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,
2892
                           is_const_method = self.is_const_method,
Robert Bradshaw's avatar
Robert Bradshaw committed
2893
                           is_static_method = self.is_static_method,
2894
                           templates = self.templates)
Mark Florisson's avatar
Mark Florisson committed
2895 2896 2897

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

2899 2900
    def opt_arg_cname(self, arg_name):
        return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
2901

2902 2903 2904 2905
    # 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).

2906
    def get_all_specialized_permutations(self, fused_types=None):
2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919
        """
        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()

2920
        return get_all_specialized_permutations(fused_types)
2921

2922
    def get_all_specialized_function_types(self):
2923 2924 2925 2926 2927
        """
        Get all the specific function types of this one.
        """
        assert self.is_fused

2928 2929 2930 2931 2932
        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
2933 2934 2935
        cfunc_entries = self.entry.scope.cfunc_entries
        cfunc_entries.remove(self.entry)

2936
        result = []
2937
        permutations = self.get_all_specialized_permutations()
2938

2939 2940 2941
        for cname, fused_to_specific in permutations:
            new_func_type = self.entry.type.specialize(fused_to_specific)

2942 2943 2944 2945
            if self.optional_arg_count:
                # Remember, this method is set by CFuncDeclaratorNode
                self.declare_opt_arg_struct(new_func_type, cname)

2946
            new_entry = copy.deepcopy(self.entry)
Mark Florisson's avatar
Mark Florisson committed
2947
            new_func_type.specialize_entry(new_entry, cname)
2948

2949
            new_entry.type = new_func_type
2950
            new_func_type.entry = new_entry
2951 2952
            result.append(new_func_type)

Mark Florisson's avatar
Mark Florisson committed
2953 2954
            cfunc_entries.append(new_entry)

2955 2956
        self.cached_specialized_types = result

2957
        return result
2958

Mark Florisson's avatar
Mark Florisson committed
2959
    def get_fused_types(self, result=None, seen=None, subtypes=None):
Stefan Behnel's avatar
Stefan Behnel committed
2960
        """Return fused types in the order they appear as parameter types"""
Mark Florisson's avatar
Mark Florisson committed
2961 2962
        return super(CFuncType, self).get_fused_types(result, seen,
                                                      subtypes=['args'])
2963

Mark Florisson's avatar
Mark Florisson committed
2964 2965
    def specialize_entry(self, entry, cname):
        assert not self.is_fused
2966
        specialize_entry(entry, cname)
Mark Florisson's avatar
Mark Florisson committed
2967

2968 2969
    def can_coerce_to_pyobject(self, env):
        # duplicating the decisions from create_to_py_utility_code() here avoids writing out unused code
2970 2971
        if self.has_varargs or self.optional_arg_count:
            return False
2972 2973
        if self.to_py_function is not None:
            return self.to_py_function
2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
        for arg in self.args:
            if not arg.type.is_pyobject and not arg.type.can_coerce_to_pyobject(env):
                return False
        if not self.return_type.is_pyobject and not self.return_type.can_coerce_to_pyobject(env):
            return False
        return True

    def create_to_py_utility_code(self, env):
        # FIXME: it seems we're trying to coerce in more cases than we should
        if self.to_py_function is not None:
            return self.to_py_function
        if not self.can_coerce_to_pyobject(env):
            return False
2987
        from .UtilityCode import CythonUtilityCode
2988
        safe_typename = re.sub('[^a-zA-Z0-9]', '__', self.declaration_code("", pyrex=1))
2989
        to_py_function = "__Pyx_CFunc_%s_to_py" % safe_typename
Robert Bradshaw's avatar
Robert Bradshaw committed
2990

2991 2992 2993
        for arg in self.args:
            if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
                return False
2994
        if not self.return_type.is_pyobject and not self.return_type.create_to_py_utility_code(env):
2995
            return False
2996

2997
        def declared_type(ctype):
2998
            type_displayname = str(ctype.declaration_code("", for_display=True))
2999 3000 3001 3002 3003 3004 3005 3006 3007
            if ctype.is_pyobject:
                arg_ctype = type_name = type_displayname
                if ctype.is_builtin_type:
                    arg_ctype = ctype.name
                elif not ctype.is_extension_type:
                    type_name = 'object'
                    type_displayname = None
                else:
                    type_displayname = repr(type_displayname)
3008
            elif ctype is c_bint_type:
3009
                type_name = arg_ctype = 'bint'
3010
            else:
3011 3012 3013 3014 3015 3016
                type_name = arg_ctype = type_displayname
                if ctype is c_double_type:
                    type_displayname = 'float'
                else:
                    type_displayname = repr(type_displayname)
            return type_name, arg_ctype, type_displayname
3017

3018
        class Arg(object):
3019 3020 3021 3022
            def __init__(self, arg_name, arg_type):
                self.name = arg_name
                self.type = arg_type
                self.type_cname, self.ctype, self.type_displayname = declared_type(arg_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
3023

Stefan Behnel's avatar
Stefan Behnel committed
3024
        if self.return_type.is_void:
3025
            except_clause = 'except *'
3026 3027 3028 3029
        elif self.return_type.is_pyobject:
            except_clause = ''
        elif self.exception_value:
            except_clause = ('except? %s' if self.exception_check else 'except %s') % self.exception_value
3030
        else:
3031
            except_clause = 'except *'
Robert Bradshaw's avatar
Robert Bradshaw committed
3032

3033
        context = {
3034 3035
            'cname': to_py_function,
            'args': [Arg(arg.name or 'arg%s' % ix, arg.type) for ix, arg in enumerate(self.args)],
3036
            'return_type': Arg('return', self.return_type),
3037
            'except_clause': except_clause,
3038
        }
Stefan Behnel's avatar
Stefan Behnel committed
3039
        # FIXME: directives come from first defining environment and do not adapt for reuse
3040
        env.use_utility_code(CythonUtilityCode.load(
3041
            "cfunc.to_py", "CConvert.pyx",
3042
            outer_module_scope=env.global_scope(),  # need access to types declared in module
3043
            context=context, compiler_directives=dict(env.global_scope().directives)))
3044
        self.to_py_function = to_py_function
3045 3046
        return True

Mark Florisson's avatar
Mark Florisson committed
3047

3048 3049 3050 3051
def specialize_entry(entry, cname):
    """
    Specialize an entry of a copied fused function or method
    """
3052
    entry.is_fused_specialized = True
3053
    entry.name = get_fused_cname(cname, entry.name)
Mark Florisson's avatar
Mark Florisson committed
3054

3055 3056 3057 3058 3059 3060 3061
    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)
3062

3063 3064
    if entry.func_cname:
        entry.func_cname = get_fused_cname(cname, entry.func_cname)
3065 3066 3067 3068 3069

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
3070
    assert fused_cname and orig_cname
3071 3072
    return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix,
                                                    fused_cname, orig_cname))
3073

3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087
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=()):
3088
    fused_type, = fused_types[0].get_fused_types()
3089 3090
    result = []

3091
    for newid, specific_type in enumerate(fused_type.types):
3092 3093 3094 3095
        # f2s = dict(f2s, **{ fused_type: specific_type })
        f2s = dict(f2s)
        f2s.update({ fused_type: specific_type })

3096 3097 3098
        if id:
            cname = '%s_%s' % (id, newid)
        else:
3099
            cname = str(newid)
3100 3101

        if len(fused_types) > 1:
3102
            result.extend(_get_all_specialized_permutations(
3103 3104 3105 3106 3107 3108
                                            fused_types[1:], cname, f2s))
        else:
            result.append((cname, f2s))

    return result

3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133
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()

3134

3135 3136
def get_specialized_types(type):
    """
3137
    Return a list of specialized types in their declared order.
3138
    """
3139 3140
    assert type.is_fused

3141
    if isinstance(type, FusedType):
3142
        result = list(type.types)
3143 3144
        for specialized_type in result:
            specialized_type.specialization_string = specialized_type.typeof_name()
3145 3146
    else:
        result = []
3147
        for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
3148 3149 3150 3151
            specialized_type = type.specialize(f2s)
            specialized_type.specialization_string = (
                            specialization_signature_string(type, f2s))
            result.append(specialized_type)
3152

3153
    return result
3154

William Stein's avatar
William Stein committed
3155

3156
class CFuncTypeArg(BaseType):
William Stein's avatar
William Stein committed
3157 3158 3159 3160
    #  name       string
    #  cname      string
    #  type       PyrexType
    #  pos        source file position
3161 3162 3163 3164 3165

    # 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
3166
    accept_builtin_subtypes = False
3167

3168 3169
    subtypes = ['type']

3170
    def __init__(self, name, type, pos, cname=None):
William Stein's avatar
William Stein committed
3171
        self.name = name
3172 3173 3174 3175
        if cname is not None:
            self.cname = cname
        else:
            self.cname = Naming.var_prefix + name
William Stein's avatar
William Stein committed
3176 3177
        self.type = type
        self.pos = pos
3178
        self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
Robert Bradshaw's avatar
Robert Bradshaw committed
3179

William Stein's avatar
William Stein committed
3180 3181
    def __repr__(self):
        return "%s:%s" % (self.name, repr(self.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
3182

William Stein's avatar
William Stein committed
3183 3184
    def declaration_code(self, for_display = 0):
        return self.type.declaration_code(self.cname, for_display)
Robert Bradshaw's avatar
Robert Bradshaw committed
3185

Robert Bradshaw's avatar
Robert Bradshaw committed
3186 3187
    def specialize(self, values):
        return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
William Stein's avatar
William Stein committed
3188

Mark Florisson's avatar
Mark Florisson committed
3189
class ToPyStructUtilityCode(object):
3190 3191 3192

    requires = None

3193
    def __init__(self, type, forward_decl, env):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3194
        self.type = type
Mark Florisson's avatar
Mark Florisson committed
3195 3196
        self.header = "static PyObject* %s(%s)" % (type.to_py_function,
                                                   type.declaration_code('s'))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3197
        self.forward_decl = forward_decl
3198
        self.env = env
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3199 3200

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

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3203 3204
    def __hash__(self):
        return hash(self.header)
Robert Bradshaw's avatar
Robert Bradshaw committed
3205

3206
    def get_tree(self, **kwargs):
3207
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3208

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3209 3210 3211
    def put_code(self, output):
        code = output['utility_code_def']
        proto = output['utility_code_proto']
Robert Bradshaw's avatar
Robert Bradshaw committed
3212

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3213 3214 3215
        code.putln("%s {" % self.header)
        code.putln("PyObject* res;")
        code.putln("PyObject* member;")
3216
        code.putln("res = PyDict_New(); if (unlikely(!res)) return NULL;")
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3217 3218
        for member in self.type.scope.var_entries:
            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
3219
            code.putln("%s; if (unlikely(!member)) goto bad;" % (
3220
                member.type.to_py_call_code('s.%s' % member.cname, 'member', member.type)))
3221
            code.putln("if (unlikely(PyDict_SetItem(res, %s, member) < 0)) goto bad;" % nameconst_cname)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
            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:
3233
            proto.putln(self.type.empty_declaration_code() + ';')
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3234
        proto.putln(self.header + ";")
Robert Bradshaw's avatar
Robert Bradshaw committed
3235

3236 3237
    def inject_tree_and_scope_into(self, module_node):
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3238

William Stein's avatar
William Stein committed
3239 3240 3241 3242 3243 3244 3245

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

3248
    # entry          Entry
Robert Bradshaw's avatar
Robert Bradshaw committed
3249

William Stein's avatar
William Stein committed
3250 3251
    is_struct_or_union = 1
    has_attributes = 1
Mark Florisson's avatar
Mark Florisson committed
3252
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3253

3254
    def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
William Stein's avatar
William Stein committed
3255 3256 3257 3258 3259
        self.name = name
        self.cname = cname
        self.kind = kind
        self.scope = scope
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
3260
        self.is_struct = kind == 'struct'
3261 3262 3263 3264
        self.to_py_function = "%s_to_py_%s" % (
            Naming.convert_func_prefix, self.specialization_name())
        self.from_py_function = "%s_from_py_%s" % (
            Naming.convert_func_prefix, self.specialization_name())
Robert Bradshaw's avatar
Robert Bradshaw committed
3265
        self.exception_check = True
Mark Florisson's avatar
Mark Florisson committed
3266 3267
        self._convert_to_py_code = None
        self._convert_from_py_code = None
3268
        self.packed = packed
Robert Bradshaw's avatar
Robert Bradshaw committed
3269

3270
    def create_to_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3271 3272
        if env.outer_scope is None:
            return False
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3273

Stefan Behnel's avatar
Stefan Behnel committed
3274 3275
        if self._convert_to_py_code is False:
            return None  # tri-state-ish
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3276

Mark Florisson's avatar
Mark Florisson committed
3277
        if self._convert_to_py_code is None:
3278 3279 3280
            is_union = not self.is_struct
            unsafe_union_types = set()
            safe_union_types = set()
Robert Bradshaw's avatar
Robert Bradshaw committed
3281
            for member in self.scope.var_entries:
3282 3283
                member_type = member.type
                if not member_type.create_to_py_utility_code(env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3284
                    self.to_py_function = None
Mark Florisson's avatar
Mark Florisson committed
3285
                    self._convert_to_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3286
                    return False
3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298
                if is_union:
                    if member_type.is_ptr or member_type.is_cpp_class:
                        unsafe_union_types.add(member_type)
                    else:
                        safe_union_types.add(member_type)

            if unsafe_union_types and (safe_union_types or len(unsafe_union_types) > 1):
                # unsafe mix of safe and unsafe to convert types
                self.from_py_function = None
                self._convert_from_py_code = False
                return False

3299 3300
            forward_decl = self.entry.visibility != 'extern' and not self.typedef_flag
            self._convert_to_py_code = ToPyStructUtilityCode(self, forward_decl, env)
Robert Bradshaw's avatar
Robert Bradshaw committed
3301

Mark Florisson's avatar
Mark Florisson committed
3302 3303 3304 3305 3306 3307 3308
        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

Stefan Behnel's avatar
Stefan Behnel committed
3309 3310
        if self._convert_from_py_code is False:
            return None  # tri-state-ish
Mark Florisson's avatar
Mark Florisson committed
3311 3312 3313

        if self._convert_from_py_code is None:
            for member in self.scope.var_entries:
3314
                if not member.type.create_from_py_utility_code(env):
Mark Florisson's avatar
Mark Florisson committed
3315 3316
                    self.from_py_function = None
                    self._convert_from_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3317
                    return False
Mark Florisson's avatar
Mark Florisson committed
3318 3319

            context = dict(
3320
                struct_name=self.name,
Stefan Behnel's avatar
Stefan Behnel committed
3321 3322
                var_entries=self.scope.var_entries,
                funcname=self.from_py_function,
Mark Florisson's avatar
Mark Florisson committed
3323
            )
3324 3325
            from .UtilityCode import CythonUtilityCode
            self._convert_from_py_code = CythonUtilityCode.load(
3326 3327
                "FromPyStructUtility" if self.is_struct else "FromPyUnionUtility",
                "CConvert.pyx",
3328 3329
                outer_module_scope=env.global_scope(),  # need access to types declared in module
                context=context)
Mark Florisson's avatar
Mark Florisson committed
3330 3331

        env.use_utility_code(self._convert_from_py_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3332
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3333

William Stein's avatar
William Stein committed
3334
    def __repr__(self):
Stefan Behnel's avatar
Stefan Behnel committed
3335 3336
        return "<CStructOrUnionType %s %s%s>" % (
            self.name, self.cname,
3337
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
3338

Robert Bradshaw's avatar
Robert Bradshaw committed
3339
    def declaration_code(self, entity_code,
Stefan Behnel's avatar
Stefan Behnel committed
3340
                         for_display=0, dll_linkage=None, pyrex=0):
3341 3342
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3343
        else:
3344 3345
            if self.typedef_flag:
                base_code = self.cname
William Stein's avatar
William Stein committed
3346
            else:
3347 3348 3349
                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
3350

3351
    def __eq__(self, other):
3352
        try:
Stefan Behnel's avatar
Stefan Behnel committed
3353 3354
            return (isinstance(other, CStructOrUnionType) and
                    self.name == other.name)
3355
        except AttributeError:
3356 3357 3358 3359 3360 3361 3362 3363 3364
            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
3365

Stefan Behnel's avatar
Stefan Behnel committed
3366
    def __hash__(self):
3367
        return hash(self.cname) ^ hash(self.kind)
Stefan Behnel's avatar
Stefan Behnel committed
3368

William Stein's avatar
William Stein committed
3369 3370
    def is_complete(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
3371

William Stein's avatar
William Stein committed
3372 3373 3374
    def attributes_known(self):
        return self.is_complete()

3375
    def can_be_complex(self):
3376
        # Does the struct consist of exactly two identical floats?
3377
        fields = self.scope.var_entries
3378 3379 3380
        if len(fields) != 2: return False
        a, b = fields
        return (a.type.is_float and b.type.is_float and
3381 3382
                a.type.empty_declaration_code() ==
                b.type.empty_declaration_code())
3383

3384 3385 3386 3387
    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
3388

3389 3390 3391 3392 3393
    def cast_code(self, expr_code):
        if self.is_struct:
            return expr_code
        return super(CStructOrUnionType, self).cast_code(expr_code)

3394
cpp_string_conversions = ("std::string",)
3395

3396
builtin_cpp_conversions = ("std::pair",
3397 3398 3399
                           "std::vector", "std::list",
                           "std::set", "std::unordered_set",
                           "std::map", "std::unordered_map")
3400

3401

3402 3403 3404 3405
class CppClassType(CType):
    #  name          string
    #  cname         string
    #  scope         CppClassScope
Danilo Freitas's avatar
Danilo Freitas committed
3406
    #  templates     [string] or None
Robert Bradshaw's avatar
Robert Bradshaw committed
3407

3408 3409
    is_cpp_class = 1
    has_attributes = 1
3410
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3411
    namespace = None
Robert Bradshaw's avatar
Robert Bradshaw committed
3412

3413 3414 3415 3416
    # For struct-like declaration.
    kind = "struct"
    packed = False
    typedef_flag = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3417

3418 3419
    subtypes = ['templates']

3420
    def __init__(self, name, scope, cname, base_classes, templates=None, template_type=None):
3421 3422 3423
        self.name = name
        self.cname = cname
        self.scope = scope
DaniloFreitas's avatar
DaniloFreitas committed
3424
        self.base_classes = base_classes
DaniloFreitas's avatar
DaniloFreitas committed
3425
        self.operators = []
Danilo Freitas's avatar
Danilo Freitas committed
3426
        self.templates = templates
3427
        self.template_type = template_type
Robert Bradshaw's avatar
Robert Bradshaw committed
3428
        self.specializations = {}
3429
        self.is_cpp_string = cname in cpp_string_conversions
3430

3431 3432
    def use_conversion_utility(self, from_or_to):
        pass
Robert Bradshaw's avatar
Robert Bradshaw committed
3433

3434 3435 3436 3437 3438 3439
    def maybe_unordered(self):
        if 'unordered' in self.cname:
            return 'unordered_'
        else:
            return ''

3440 3441 3442
    def create_from_py_utility_code(self, env):
        if self.from_py_function is not None:
            return True
3443
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3444
            X = "XYZABC"
3445
            tags = []
3446
            declarations = ["cdef extern from *:"]
3447
            for ix, T in enumerate(self.templates or []):
3448
                if T.is_pyobject or not T.create_from_py_utility_code(env):
3449 3450
                    return False
                tags.append(T.specialization_name())
3451
                if T.exception_value is not None:
3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470
                    # This is a hack due to the except value clause
                    # requiring a const (literal) value of the right
                    # (visible) type.
                    def guess_type(value):
                        if not T.is_typedef and (T.is_numeric or T.is_ptr):
                            return T
                        try:
                            int(value)
                            return c_longlong_type
                        except ValueError:
                            pass
                        try:
                            float(value)
                            return c_double_type
                        except ValueError:
                            pass
                        return T
                    except_type = guess_type(T.exception_value)
                    except_clause = "%s " % T.exception_value
3471 3472 3473 3474
                    if T.exception_check:
                        except_clause = "? %s" % except_clause
                    declarations.append(
                        "    ctypedef %s %s '%s'" % (
3475
                             except_type.declaration_code("", for_display=True), X[ix], T.empty_declaration_code()))
3476 3477 3478 3479
                else:
                    except_clause = "*"
                    declarations.append(
                        "    ctypedef struct %s '%s':\n        pass" % (
3480
                             X[ix], T.empty_declaration_code()))
3481 3482 3483
                declarations.append(
                    "    cdef %s %s_from_py '%s' (object) except %s" % (
                         X[ix], X[ix], T.from_py_function, except_clause))
3484 3485
            if self.cname in cpp_string_conversions:
                cls = 'string'
3486
                tags = type_identifier(self),
3487 3488
            else:
                cls = self.cname[5:]
3489
            cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
3490 3491
            context = {
                'template_type_declarations': '\n'.join(declarations),
3492 3493
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3494
                'type': self.cname,
3495
            }
3496
            from .UtilityCode import CythonUtilityCode
3497 3498
            env.use_utility_code(CythonUtilityCode.load(
                cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx", context=context))
3499 3500
            self.from_py_function = cname
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3501

3502 3503 3504
    def create_to_py_utility_code(self, env):
        if self.to_py_function is not None:
            return True
3505
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3506
            X = "XYZABC"
3507
            tags = []
3508
            declarations = ["cdef extern from *:"]
3509 3510 3511 3512
            for ix, T in enumerate(self.templates or []):
                if not T.create_to_py_utility_code(env):
                    return False
                tags.append(T.specialization_name())
3513 3514
                declarations.append(
                    "    ctypedef struct %s '%s':\n        pass" % (
3515
                         X[ix], T.empty_declaration_code()))
3516 3517 3518
                declarations.append(
                    "    cdef object %s_to_py '%s' (%s)" % (
                         X[ix], T.to_py_function, X[ix]))
3519 3520 3521
            if self.cname in cpp_string_conversions:
                cls = 'string'
                prefix = 'PyObject_'  # gets specialised by explicit type casts in CoerceToPyTypeNode
3522
                tags = type_identifier(self),
3523 3524 3525 3526
            else:
                cls = self.cname[5:]
                prefix = ''
            cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags))
3527 3528
            context = {
                'template_type_declarations': '\n'.join(declarations),
3529 3530
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3531
                'type': self.cname,
3532
            }
3533
            from .UtilityCode import CythonUtilityCode
3534 3535
            env.use_utility_code(CythonUtilityCode.load(
                cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx", context=context))
3536 3537 3538
            self.to_py_function = cname
            return True

3539 3540 3541
    def is_template_type(self):
        return self.templates is not None and self.template_type is None

3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552
    def get_fused_types(self, result=None, seen=None):
        if result is None:
            result = []
            seen = set()
        if self.namespace:
            self.namespace.get_fused_types(result, seen)
        if self.templates:
            for T in self.templates:
                T.get_fused_types(result, seen)
        return result

3553
    def specialize_here(self, pos, template_values=None):
3554
        if not self.is_template_type():
Stefan Behnel's avatar
Stefan Behnel committed
3555 3556
            error(pos, "'%s' type is not a template" % self)
            return error_type
3557
        if len(self.templates) != len(template_values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3558
            error(pos, "%s templated type receives %d arguments, got %d" %
3559 3560
                  (self.name, len(self.templates), len(template_values)))
            return error_type
3561 3562 3563 3564 3565 3566 3567 3568
        has_object_template_param = False
        for value in template_values:
            if value.is_pyobject:
                has_object_template_param = True
                error(pos,
                      "Python object type '%s' cannot be used as a template argument" % value)
        if has_object_template_param:
            return error_type
3569
        return self.specialize(dict(zip(self.templates, template_values)))
Robert Bradshaw's avatar
Robert Bradshaw committed
3570

3571
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3572
        if not self.templates and not self.namespace:
3573
            return self
Robert Bradshaw's avatar
Robert Bradshaw committed
3574 3575
        if self.templates is None:
            self.templates = []
3576
        key = tuple(values.items())
Robert Bradshaw's avatar
Robert Bradshaw committed
3577 3578
        if key in self.specializations:
            return self.specializations[key]
3579
        template_values = [t.specialize(values) for t in self.templates]
Robert Bradshaw's avatar
Robert Bradshaw committed
3580
        specialized = self.specializations[key] = \
3581
            CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3582 3583
        # Need to do these *after* self.specializations[key] is set
        # to avoid infinite recursion on circular references.
3584
        specialized.base_classes = [b.specialize(values) for b in self.base_classes]
Robert Bradshaw's avatar
Robert Bradshaw committed
3585 3586
        if self.namespace is not None:
            specialized.namespace = self.namespace.specialize(values)
3587
        specialized.scope = self.scope.specialize(values, specialized)
Robert Bradshaw's avatar
Robert Bradshaw committed
3588
        return specialized
3589

3590 3591 3592 3593
    def deduce_template_params(self, actual):
        if self == actual:
            return {}
        # TODO(robertwb): Actual type equality.
3594
        elif self.empty_declaration_code() == actual.template_type.empty_declaration_code():
3595 3596
            return reduce(
                merge_template_deductions,
3597 3598
                [formal_param.deduce_template_params(actual_param)
                 for (formal_param, actual_param) in zip(self.templates, actual.templates)],
3599 3600 3601 3602
                {})
        else:
            return None

3603 3604
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
Danilo Freitas's avatar
Danilo Freitas committed
3605
        if self.templates:
3606 3607
            template_strings = [param.declaration_code('', for_display, None, pyrex)
                                for param in self.templates]
3608 3609 3610
            if for_display:
                brackets = "[%s]"
            else:
3611
                brackets = "<%s> "
3612
            templates = brackets % ",".join(template_strings)
3613 3614
        else:
            templates = ""
3615 3616
        if pyrex or for_display:
            base_code = "%s%s" % (self.name, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3617
        else:
3618
            base_code = "%s%s" % (self.cname, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3619
            if self.namespace is not None:
3620
                base_code = "%s::%s" % (self.namespace.empty_declaration_code(), base_code)
3621 3622
            base_code = public_decl(base_code, dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
3623 3624

    def is_subclass(self, other_type):
3625 3626
        if self.same_as_resolved_type(other_type):
            return 1
3627 3628 3629
        for base_class in self.base_classes:
            if base_class.is_subclass(other_type):
                return 1
3630
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3631

3632 3633 3634 3635
    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
3636 3637
            elif (self.cname == other_type.cname and
                  self.template_type and other_type.template_type):
3638 3639
                if self.templates == other_type.templates:
                    return 1
3640
                for t1, t2 in zip(self.templates, other_type.templates):
3641 3642 3643 3644
                    if not t1.same_as_resolved_type(t2):
                        return 0
                return 1
        return 0
3645

3646 3647
    def assignable_from_resolved_type(self, other_type):
        # TODO: handle operator=(...) here?
3648 3649
        if other_type is error_type:
            return True
3650
        return other_type.is_cpp_class and other_type.is_subclass(self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3651

Robert Bradshaw's avatar
Robert Bradshaw committed
3652 3653 3654
    def attributes_known(self):
        return self.scope is not None

3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667
    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

3668 3669 3670 3671 3672
    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)

3673

3674
class TemplatePlaceholderType(CType):
Robert Bradshaw's avatar
Robert Bradshaw committed
3675

Danilo Freitas's avatar
Danilo Freitas committed
3676 3677
    def __init__(self, name):
        self.name = name
Robert Bradshaw's avatar
Robert Bradshaw committed
3678 3679

    def declaration_code(self, entity_code,
3680
            for_display = 0, dll_linkage = None, pyrex = 0):
3681 3682 3683 3684
        if entity_code:
            return self.name + " " + entity_code
        else:
            return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3685

3686 3687 3688 3689 3690 3691
    def specialize(self, values):
        if self in values:
            return values[self]
        else:
            return self

Robert Bradshaw's avatar
Robert Bradshaw committed
3692 3693 3694
    def deduce_template_params(self, actual):
        return {self: actual}

3695 3696
    def same_as_resolved_type(self, other_type):
        if isinstance(other_type, TemplatePlaceholderType):
3697
            return self.name == other_type.name
3698 3699
        else:
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3700

3701 3702
    def __hash__(self):
        return hash(self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
3703

3704 3705 3706 3707 3708
    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
3709

Robert Bradshaw's avatar
Robert Bradshaw committed
3710 3711 3712 3713 3714 3715
    def __eq__(self, other):
        if isinstance(other, TemplatePlaceholderType):
            return self.name == other.name
        else:
            return False

3716

3717
class CEnumType(CType):
William Stein's avatar
William Stein committed
3718 3719 3720
    #  name           string
    #  cname          string or None
    #  typedef_flag   boolean
3721

William Stein's avatar
William Stein committed
3722
    is_enum = 1
3723 3724
    signed = 1
    rank = -1 # Ranks below any integer type
William Stein's avatar
William Stein committed
3725 3726 3727 3728 3729 3730

    def __init__(self, name, cname, typedef_flag):
        self.name = name
        self.cname = cname
        self.values = []
        self.typedef_flag = typedef_flag
3731
        self.default_value = "(%s) 0" % self.empty_declaration_code()
Robert Bradshaw's avatar
Robert Bradshaw committed
3732

3733 3734
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3735

William Stein's avatar
William Stein committed
3736
    def __repr__(self):
3737 3738
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
3739 3740

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
3741
            for_display = 0, dll_linkage = None, pyrex = 0):
3742 3743
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3744 3745
        else:
            if self.typedef_flag:
3746
                base_code = self.cname
William Stein's avatar
William Stein committed
3747
            else:
3748 3749 3750
                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
3751

3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767
    def create_to_py_utility_code(self, env):
        self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
        env.use_utility_code(TempitaUtilityCode.load_cached(
            "CIntToPy", "TypeConversion.c",
            context={"TYPE": self.empty_declaration_code(),
                     "TO_PY_FUNCTION": self.to_py_function}))
        return True

    def create_from_py_utility_code(self, env):
        self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
        env.use_utility_code(TempitaUtilityCode.load_cached(
            "CIntFromPy", "TypeConversion.c",
            context={"TYPE": self.empty_declaration_code(),
                     "FROM_PY_FUNCTION": self.from_py_function}))
        return True

3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778
    def from_py_call_code(self, source_code, result_code, error_pos, code,
                          from_py_function=None, error_condition=None):
        rhs = "%s(%s)" % (
            from_py_function or self.from_py_function,
            source_code)
        return '%s = %s;%s' % (
            result_code,
            typecast(self, c_long_type, rhs),
            ' %s' % code.error_goto_if(error_condition or self.error_condition(result_code), error_pos))


3779 3780 3781
class CTupleType(CType):
    # components [PyrexType]

Robert Bradshaw's avatar
Robert Bradshaw committed
3782 3783
    is_ctuple = True

3784 3785 3786
    def __init__(self, cname, components):
        self.cname = cname
        self.components = components
Robert Bradshaw's avatar
Robert Bradshaw committed
3787
        self.size = len(components)
3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803
        self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
        self.from_py_function = "%s_from_py_%s" % (Naming.convert_func_prefix, self.cname)
        self.exception_check = True
        self._convert_to_py_code = None
        self._convert_from_py_code = None

    def __str__(self):
        return "(%s)" % ", ".join(str(c) for c in self.components)

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
            return str(self)
        else:
            return self.base_declaration_code(self.cname, entity_code)

3804 3805 3806 3807 3808 3809
    def can_coerce_to_pyobject(self, env):
        for component in self.components:
            if not component.can_coerce_to_pyobject(env):
                return False
        return True

3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821
    def create_to_py_utility_code(self, env):
        if self._convert_to_py_code is False:
            return None  # tri-state-ish

        if self._convert_to_py_code is None:
            for component in self.components:
                if not component.create_to_py_utility_code(env):
                    self.to_py_function = None
                    self._convert_to_py_code = False
                    return False

            context = dict(
3822
                struct_type_decl=self.empty_declaration_code(),
3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844
                components=self.components,
                funcname=self.to_py_function,
                size=len(self.components)
            )
            self._convert_to_py_code = TempitaUtilityCode.load(
                "ToPyCTupleUtility", "TypeConversion.c", context=context)

        env.use_utility_code(self._convert_to_py_code)
        return True

    def create_from_py_utility_code(self, env):
        if self._convert_from_py_code is False:
            return None  # tri-state-ish

        if self._convert_from_py_code is None:
            for component in self.components:
                if not component.create_from_py_utility_code(env):
                    self.from_py_function = None
                    self._convert_from_py_code = False
                    return False

            context = dict(
3845
                struct_type_decl=self.empty_declaration_code(),
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
                components=self.components,
                funcname=self.from_py_function,
                size=len(self.components)
            )
            self._convert_from_py_code = TempitaUtilityCode.load(
                "FromPyCTupleUtility", "TypeConversion.c", context=context)

        env.use_utility_code(self._convert_from_py_code)
        return True

3856

3857
def c_tuple_type(components):
Robert Bradshaw's avatar
Robert Bradshaw committed
3858
    components = tuple(components)
3859 3860
    cname = Naming.ctuple_type_prefix + type_list_identifier(components)
    tuple_type = CTupleType(cname, components)
3861
    return tuple_type
3862 3863


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

Robert Bradshaw's avatar
Robert Bradshaw committed
3867
    is_unspecified = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3868 3869

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

Robert Bradshaw's avatar
Robert Bradshaw committed
3873 3874
    def same_as_resolved_type(self, other_type):
        return False
Robert Bradshaw's avatar
Robert Bradshaw committed
3875

Robert Bradshaw's avatar
Robert Bradshaw committed
3876

William Stein's avatar
William Stein committed
3877 3878
class ErrorType(PyrexType):
    # Used to prevent propagation of error messages.
Robert Bradshaw's avatar
Robert Bradshaw committed
3879

William Stein's avatar
William Stein committed
3880 3881
    is_error = 1
    exception_value = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
3882
    exception_check    = 0
William Stein's avatar
William Stein committed
3883 3884
    to_py_function = "dummy"
    from_py_function = "dummy"
Robert Bradshaw's avatar
Robert Bradshaw committed
3885

3886 3887
    def create_to_py_utility_code(self, env):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3888

3889
    def create_from_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3890
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3891 3892

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

William Stein's avatar
William Stein committed
3896 3897
    def same_as_resolved_type(self, other_type):
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3898

3899 3900
    def error_condition(self, result_code):
        return "dummy"
William Stein's avatar
William Stein committed
3901 3902


3903 3904 3905
rank_to_type_name = (
    "char",         # 0
    "short",        # 1
3906 3907 3908 3909 3910 3911
    "int",          # 2
    "long",         # 3
    "PY_LONG_LONG", # 4
    "float",        # 5
    "double",       # 6
    "long double",  # 7
3912 3913
)

3914 3915 3916 3917
_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')
3918 3919 3920
UNSIGNED = 0
SIGNED = 2

3921 3922
error_type =    ErrorType()
unspecified_type = UnspecifiedType()
3923

William Stein's avatar
William Stein committed
3924 3925
py_object_type = PyObjectType()

3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938
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
3939

3940 3941 3942 3943 3944 3945 3946 3947 3948
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
3949

3950 3951 3952
c_float_complex_type =      CComplexType(c_float_type)
c_double_complex_type =     CComplexType(c_double_type)
c_longdouble_complex_type = CComplexType(c_longdouble_type)
3953

3954 3955 3956 3957
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
3958
c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
3959
c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
3960 3961 3962
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)
Robert Bradshaw's avatar
Robert Bradshaw committed
3963
c_ptrdiff_t_type =   CPtrdiffTType(RANK_LONG+0.75, SIGNED)
3964

William Stein's avatar
William Stein committed
3965
c_null_ptr_type =     CNullPtrType(c_void_type)
3966 3967
c_void_ptr_type =     CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
3968
c_char_ptr_type =     CPtrType(c_char_type)
3969
c_const_char_ptr_type = CPtrType(CConstType(c_char_type))
3970
c_uchar_ptr_type =    CPtrType(c_uchar_type)
3971
c_const_uchar_ptr_type = CPtrType(CConstType(c_uchar_type))
William Stein's avatar
William Stein committed
3972 3973
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
3974
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
3975
c_const_py_unicode_ptr_type = CPtrType(CConstType(c_py_unicode_type))
3976
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
3977
c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
3978
c_size_t_ptr_type =  CPtrType(c_size_t_type)
William Stein's avatar
William Stein committed
3979

3980 3981 3982 3983
# GIL state
c_gilstate_type = CEnumType("PyGILState_STATE", "PyGILState_STATE", True)
c_threadstate_type = CStructOrUnionType("PyThreadState", "struct", None, 1, "PyThreadState")
c_threadstate_ptr_type = CPtrType(c_threadstate_type)
3984

3985
# the Py_buffer type is defined in Builtin.py
3986 3987
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
3988

3989 3990 3991
# 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
3992 3993
cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type],
                             name="integral")
3994 3995
# Omitting long double as it might be slow
cy_floating_type = FusedType([c_float_type, c_double_type], name="floating")
3996 3997 3998 3999
cy_numeric_type = FusedType([c_short_type,
                             c_int_type,
                             c_long_type,
                             c_float_type,
4000
                             c_double_type,
4001
                             c_float_complex_type,
4002 4003
                             c_double_complex_type], name="numeric")

4004 4005 4006 4007 4008 4009 4010 4011
# 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")

4012 4013
cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
                                      None, 0, "__pyx_memoryview_obj")
4014

4015 4016
memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
                                          None, 1, "__Pyx_memviewslice")
4017

William Stein's avatar
William Stein committed
4018
modifiers_and_name_to_type = {
4019 4020 4021 4022 4023
    #(signed, longness, name) : type
    (0,  0, "char"): c_uchar_type,
    (1,  0, "char"): c_char_type,
    (2,  0, "char"): c_schar_type,

4024
    (0, -1, "int"): c_ushort_type,
4025 4026 4027 4028
    (0,  0, "int"): c_uint_type,
    (0,  1, "int"): c_ulong_type,
    (0,  2, "int"): c_ulonglong_type,

4029
    (1, -1, "int"): c_short_type,
4030 4031 4032 4033
    (1,  0, "int"): c_int_type,
    (1,  1, "int"): c_long_type,
    (1,  2, "int"): c_longlong_type,

4034
    (2, -1, "int"): c_sshort_type,
4035 4036 4037 4038 4039 4040 4041
    (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,
4042

4043
    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
4044 4045 4046 4047 4048 4049
    (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,
4050 4051 4052

    (1,  0, "bint"):       c_bint_type,
    (0,  0, "Py_UNICODE"): c_py_unicode_type,
Stefan Behnel's avatar
Stefan Behnel committed
4053
    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
4054
    (2,  0, "Py_hash_t"):  c_py_hash_t_type,
4055 4056 4057
    (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,
4058
    (2,  0, "ptrdiff_t") : c_ptrdiff_t_type,
4059

4060
    (1,  0, "object"): py_object_type,
William Stein's avatar
William Stein committed
4061 4062
}

4063 4064
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
4065
    # evidence suggests that the below is all that's allowed.
4066 4067
    if src_type.is_numeric:
        if dst_type.same_as(c_int_type):
4068 4069 4070 4071
            unsigned = (not src_type.signed)
            return (src_type.is_enum or
                    (src_type.is_int and
                     unsigned + src_type.rank < dst_type.rank))
4072 4073 4074 4075
        elif dst_type.same_as(c_double_type):
            return src_type.is_float and src_type.rank <= dst_type.rank
    return False

4076
def best_match(args, functions, pos=None, env=None):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
4077
    """
4078 4079 4080 4081 4082 4083 4084 4085 4086 4087
    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
4088
      * promotions
4089 4090 4091 4092 4093 4094 4095 4096
      * 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
4097
    """
Robert Bradshaw's avatar
Robert Bradshaw committed
4098
    # TODO: args should be a list of types, not a list of Nodes.
4099
    actual_nargs = len(args)
4100 4101 4102

    candidates = []
    errors = []
4103
    for func in functions:
4104
        error_mesg = ""
4105 4106 4107
        func_type = func.type
        if func_type.is_ptr:
            func_type = func_type.base_type
4108 4109
        # Check function type
        if not func_type.is_cfunction:
4110
            if not func_type.is_error and pos is not None:
4111 4112 4113
                error_mesg = "Calling non-function type '%s'" % func_type
            errors.append((func, error_mesg))
            continue
4114 4115 4116
        # Check no. of args
        max_nargs = len(func_type.args)
        min_nargs = max_nargs - func_type.optional_arg_count
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128
        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
Robert Bradshaw's avatar
Robert Bradshaw committed
4129 4130 4131 4132 4133 4134
        if func_type.templates:
            arg_types = [arg.type for arg in args]
            deductions = reduce(
                merge_template_deductions,
                [pattern.type.deduce_template_params(actual) for (pattern, actual) in zip(func_type.args, arg_types)],
                {})
4135 4136 4137 4138 4139 4140 4141
            if deductions is None:
                errors.append((func, "Unable to deduce type parameters"))
            elif len(deductions) < len(func_type.templates):
                errors.append((func, "Unable to deduce type parameter %s" % (
                    ", ".join([param.name for param in set(func_type.templates) - set(deductions.keys())]))))
            else:
                type_list = [deductions[param] for param in func_type.templates]
4142
                from .Symtab import Entry
4143 4144
                specialization = Entry(
                    name = func.name + "[%s]" % ",".join([str(t) for t in type_list]),
4145
                    cname = func.cname + "<%s>" % ",".join([t.empty_declaration_code() for t in type_list]),
4146 4147 4148
                    type = func_type.specialize(deductions),
                    pos = func.pos)
                candidates.append((specialization, specialization.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4149 4150
        else:
            candidates.append((func, func_type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4151

4152 4153
    # Optimize the most common case of no overloading...
    if len(candidates) == 1:
4154
        return candidates[0][0]
4155
    elif len(candidates) == 0:
4156
        if pos is not None:
4157 4158 4159
            func, errmsg = errors[0]
            if len(errors) == 1 or [1 for func, e in errors if e == errmsg]:
                error(pos, errmsg)
4160 4161
            else:
                error(pos, "no suitable method found")
4162
        return None
Robert Bradshaw's avatar
Robert Bradshaw committed
4163

4164 4165
    possibilities = []
    bad_types = []
4166
    needed_coercions = {}
Mark Florisson's avatar
merge  
Mark Florisson committed
4167

4168
    for index, (func, func_type) in enumerate(candidates):
4169
        score = [0,0,0,0]
4170
        for i in range(min(len(args), len(func_type.args))):
4171 4172
            src_type = args[i].type
            dst_type = func_type.args[i].type
4173 4174 4175

            assignable = dst_type.assignable_from(src_type)

4176
            # Now take care of unprefixed string literals. So when you call a cdef
4177 4178 4179 4180
            # 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:
4181 4182
                if src_type.is_builtin_type and src_type.name == 'str' and dst_type.resolve().is_string:
                    c_src_type = dst_type.resolve()
4183 4184 4185 4186 4187 4188 4189
                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
Stefan Behnel's avatar
Stefan Behnel committed
4190
                        needed_coercions[func] = (i, dst_type)
4191 4192

            if assignable:
Robert Bradshaw's avatar
Robert Bradshaw committed
4193
                if src_type == dst_type or dst_type.same_as(src_type):
Stefan Behnel's avatar
Stefan Behnel committed
4194
                    pass  # score 0
4195
                elif func_type.is_strict_signature:
Stefan Behnel's avatar
Stefan Behnel committed
4196
                    break  # exact match requested but not found
4197 4198
                elif is_promotion(src_type, dst_type):
                    score[2] += 1
4199 4200
                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
4201
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
4202
                                    (src_type.rank + (not src_type.signed))) + 1
4203 4204 4205 4206 4207
                elif not src_type.is_pyobject:
                    score[1] += 1
                else:
                    score[0] += 1
            else:
Stefan Behnel's avatar
Stefan Behnel committed
4208
                error_mesg = "Invalid conversion from '%s' to '%s'" % (src_type, dst_type)
4209
                bad_types.append((func, error_mesg))
4210 4211
                break
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4212
            possibilities.append((score, index, func))  # so we can sort it
4213

4214
    if possibilities:
4215
        possibilities.sort()
4216 4217 4218 4219 4220 4221 4222
        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
4223

Mark Florisson's avatar
merge  
Mark Florisson committed
4224
        function = possibilities[0][-1]
4225 4226 4227 4228 4229 4230 4231

        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

4232
    if pos is not None:
4233 4234
        if len(bad_types) == 1:
            error(pos, bad_types[0][1])
4235
        else:
4236
            error(pos, "no suitable method found")
4237

4238 4239
    return None

Robert Bradshaw's avatar
Robert Bradshaw committed
4240 4241 4242 4243
def merge_template_deductions(a, b):
    if a is None or b is None:
        return None
    all = a
4244
    for param, value in b.items():
Robert Bradshaw's avatar
Robert Bradshaw committed
4245 4246 4247 4248 4249 4250 4251
        if param in all:
            if a[param] != b[param]:
                return None
        else:
            all[param] = value
    return all

4252

William Stein's avatar
William Stein committed
4253
def widest_numeric_type(type1, type2):
Stefan Behnel's avatar
Stefan Behnel committed
4254 4255
    """Given two numeric types, return the narrowest type encompassing both of them.
    """
4256 4257 4258 4259
    if type1.is_reference:
        type1 = type1.ref_base_type
    if type2.is_reference:
        type2 = type2.ref_base_type
4260
    if type1 == type2:
4261 4262 4263 4264 4265 4266 4267 4268
        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
4269
                real_type(type1),
4270 4271 4272 4273 4274 4275 4276 4277 4278
                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
4279 4280 4281 4282
    elif type1.signed > type2.signed:
        widest_type = type2
    elif type1.is_typedef > type2.is_typedef:
        widest_type = type1
4283
    else:
4284 4285
        widest_type = type2
    return widest_type
William Stein's avatar
William Stein committed
4286

4287 4288 4289 4290 4291

def numeric_type_fits(small_type, large_type):
    return widest_numeric_type(small_type, large_type) == large_type


4292 4293 4294 4295 4296 4297 4298 4299
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.
4300 4301 4302 4303 4304
    if type1.is_reference ^ type2.is_reference:
        if type1.is_reference:
            type1 = type1.ref_base_type
        else:
            type2 = type2.ref_base_type
4305 4306 4307 4308 4309
    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
4310
        # type so that we do not lose the ability to coerce to a
4311
        # Python bool if we have to.
Robert Bradshaw's avatar
Robert Bradshaw committed
4312
        return py_object_type
4313 4314
    span_type = _spanning_type(type1, type2)
    if span_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
4315
        return error_type
4316 4317 4318 4319 4320 4321 4322 4323
    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
4324
        return type1
4325 4326
    elif type1 is py_object_type or type2 is py_object_type:
        return py_object_type
4327 4328 4329
    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
4330 4331 4332 4333 4334 4335 4336
    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
4337
        return widest_numeric_type(type1, type2)
4338 4339 4340 4341
    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)
4342
    elif type1.is_extension_type and type2.is_extension_type:
4343 4344 4345
        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
4346
    elif type1.assignable_from(type2):
4347 4348 4349
        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
4350
        return type1
4351
    elif type2.assignable_from(type1):
4352 4353 4354
        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
4355
        return type2
4356 4357 4358
    elif type1.is_ptr and type2.is_ptr:
        # incompatible pointers, void* will do as a result
        return c_void_ptr_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4359
    else:
4360 4361 4362 4363
        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
4364
        return py_object_type
4365 4366 4367 4368 4369 4370 4371 4372 4373
    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
4374 4375 4376 4377
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
4378

4379 4380 4381 4382 4383 4384 4385 4386 4387 4388
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)
4389 4390 4391 4392 4393 4394 4395
    #
    basic_type = simple_c_type(1, 0, name)
    if basic_type:
        return basic_type
    #
    signed = 1
    longness = 0
4396 4397
    if name == 'Py_UNICODE':
        signed = 0
Stefan Behnel's avatar
Stefan Behnel committed
4398 4399
    elif name == 'Py_UCS4':
        signed = 0
4400 4401
    elif name == 'Py_hash_t':
        signed = 2
4402 4403 4404
    elif name == 'Py_ssize_t':
        signed = 2
    elif name == 'ssize_t':
4405 4406 4407
        signed = 2
    elif name == 'size_t':
        signed = 0
4408
    else:
4409 4410 4411
        if name.startswith('u'):
            name = name[1:]
            signed = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
4412
        elif (name.startswith('s') and
4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425
              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
4426 4427 4428

def c_array_type(base_type, size):
    # Construct a C array type.
4429
    if base_type is error_type:
4430
        return error_type
William Stein's avatar
William Stein committed
4431 4432 4433 4434 4435
    else:
        return CArrayType(base_type, size)

def c_ptr_type(base_type):
    # Construct a C pointer type.
4436
    if base_type is error_type:
4437
        return error_type
4438 4439
    elif base_type.is_reference:
        return CPtrType(base_type.ref_base_type)
William Stein's avatar
William Stein committed
4440 4441 4442
    else:
        return CPtrType(base_type)

Danilo Freitas's avatar
Danilo Freitas committed
4443 4444
def c_ref_type(base_type):
    # Construct a C reference type
4445
    if base_type is error_type:
Danilo Freitas's avatar
Danilo Freitas committed
4446 4447 4448
        return error_type
    else:
        return CReferenceType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
4449 4450 4451 4452 4453 4454 4455

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
4456 4457 4458

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

William Stein's avatar
William Stein committed
4460 4461 4462 4463 4464 4465 4466
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.
4467 4468 4469 4470 4471 4472 4473
    if (to_type is from_type or
            (not to_type.is_pyobject and assignable_from(to_type, from_type))):
        return expr_code
    elif (to_type is py_object_type and from_type and
            from_type.is_builtin_type and from_type.name != 'type'):
        # no cast needed, builtins are PyObject* already
        return expr_code
William Stein's avatar
William Stein committed
4474 4475 4476
    else:
        #print "typecast: to", to_type, "from", from_type ###
        return to_type.cast_code(expr_code)
4477 4478 4479 4480 4481 4482

def type_list_identifier(types):
    return cap_length('__and_'.join(type_identifier(type) for type in types))

_type_identifier_cache = {}
def type_identifier(type):
4483
    decl = type.empty_declaration_code()
4484 4485 4486 4487 4488 4489 4490
    safe = _type_identifier_cache.get(decl)
    if safe is None:
        safe = decl
        safe = re.sub(' +', ' ', safe)
        safe = re.sub(' ([^a-zA-Z0-9_])', r'\1', safe)
        safe = re.sub('([^a-zA-Z0-9_]) ', r'\1', safe)
        safe = (safe.replace('__', '__dunder')
Robert Bradshaw's avatar
Robert Bradshaw committed
4491
                    .replace('const ', '__const_')
4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511
                    .replace(' ', '__space_')
                    .replace('*', '__ptr')
                    .replace('&', '__ref')
                    .replace('[', '__lArr')
                    .replace(']', '__rArr')
                    .replace('<', '__lAng')
                    .replace('>', '__rAng')
                    .replace('(', '__lParen')
                    .replace(')', '__rParen')
                    .replace(',', '__comma_')
                    .replace('::', '__in_'))
        safe = cap_length(re.sub('[^a-zA-Z0-9_]', lambda x: '__%X' % ord(x.group(0)), safe))
        _type_identifier_cache[decl] = safe
    return safe

def cap_length(s, max_prefix=63, max_len=1024):
    if len(s) <= max_prefix:
        return s
    else:
        return '%x__%s__etc' % (abs(hash(s)) % (1<<20), s[:max_len-17])