PyrexTypes.py 167 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

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

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

16
from Cython.Utils import cached_function
17 18 19 20
from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
from . import StringEncoding
from . import Naming

21
from .Errors import error, warning
22

William Stein's avatar
William Stein committed
23

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

28 29
    # List of attribute names of any subtypes
    subtypes = []
30
    _empty_declaration = None
31
    _specialization_name = None
32
    default_format_spec = None
33

34 35 36
    def can_coerce_to_pyobject(self, env):
        return False

37 38 39
    def can_coerce_from_pyobject(self, env):
        return False

40
    def can_coerce_to_pystring(self, env, format_spec=None):
41 42
        return False

43 44 45
    def convert_to_pystring(self, cvalue, code, format_spec=None):
        raise NotImplementedError("C types that support string formatting must override this method")

46
    def cast_code(self, expr_code):
47 48 49 50 51 52
        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
53

Craig Citro's avatar
Craig Citro committed
54
    def specialization_name(self):
55 56 57 58 59 60 61 62 63
        if self._specialization_name is None:
            # This is not entirely robust.
            common_subs = (self.empty_declaration_code()
                           .replace("unsigned ", "unsigned_")
                           .replace("long long", "long_long")
                           .replace(" ", "__"))
            self._specialization_name = re.sub(
                '[^a-zA-Z0-9_]', lambda x: '_%x_' % ord(x.group(0)), common_subs)
        return self._specialization_name
Robert Bradshaw's avatar
Robert Bradshaw committed
64

65 66 67 68 69 70
    def base_declaration_code(self, base_code, entity_code):
        if entity_code:
            return "%s %s" % (base_code, entity_code)
        else:
            return base_code

71 72 73 74 75 76 77
    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
78 79
    def get_fused_types(self, result=None, seen=None, subtypes=None):
        subtypes = subtypes or self.subtypes
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        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
97

Mark Florisson's avatar
Mark Florisson committed
98 99 100 101 102 103
    def specialize_fused(self, env):
        if env.fused_to_specific:
            return self.specialize(env.fused_to_specific)

        return self

104 105
    @property
    def is_fused(self):
106
        """
107
        Whether this type or any of its subtypes is a fused type
108
        """
109 110
        # Add this indirection for the is_fused property to allow overriding
        # get_fused_types in subclasses.
111 112
        return self.get_fused_types()

Robert Bradshaw's avatar
Robert Bradshaw committed
113 114 115 116 117 118 119
    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
        """
120
        return {}
Robert Bradshaw's avatar
Robert Bradshaw committed
121

122 123 124 125
    def __lt__(self, other):
        """
        For sorting. The sorting order should correspond to the preference of
        conversion from Python types.
126 127 128

        Override to provide something sensible. This is only implemented so that
        python 3 doesn't trip
129
        """
130
        return id(type(self)) < id(type(other))
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147

    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
148 149 150 151 152 153 154 155
    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

156
    def invalid_value(self):
157
        """
158 159
        Returns the most invalid value an object of this type can assume as a
        C expression string. Returns None if no such value exists.
160 161
        """

Mark Florisson's avatar
merge  
Mark Florisson committed
162

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

William Stein's avatar
William Stein committed
223
    is_pyobject = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
224
    is_unspecified = 0
William Stein's avatar
William Stein committed
225
    is_extension_type = 0
226
    is_final_type = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
227
    is_builtin_type = 0
William Stein's avatar
William Stein committed
228 229 230
    is_numeric = 0
    is_int = 0
    is_float = 0
231
    is_complex = 0
William Stein's avatar
William Stein committed
232 233 234 235
    is_void = 0
    is_array = 0
    is_ptr = 0
    is_null_ptr = 0
236
    is_reference = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
237
    is_const = 0
William Stein's avatar
William Stein committed
238 239
    is_cfunction = 0
    is_struct_or_union = 0
240
    is_cpp_class = 0
241
    is_cpp_string = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
242
    is_struct = 0
William Stein's avatar
William Stein committed
243
    is_enum = 0
244
    is_typedef = 0
William Stein's avatar
William Stein committed
245
    is_string = 0
246
    is_pyunicode_ptr = 0
Stefan Behnel's avatar
Stefan Behnel committed
247
    is_unicode_char = 0
William Stein's avatar
William Stein committed
248 249
    is_returncode = 0
    is_error = 0
250
    is_buffer = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
251
    is_ctuple = 0
252
    is_memoryviewslice = 0
253 254
    is_pythran_expr = 0
    is_numpy_buffer = 0
William Stein's avatar
William Stein committed
255 256
    has_attributes = 0
    default_value = ""
Robert Bradshaw's avatar
Robert Bradshaw committed
257

William Stein's avatar
William Stein committed
258 259 260
    def resolve(self):
        # If a typedef, returns the base type.
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
261

262
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
263
        # TODO(danilo): Override wherever it makes sense.
264
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
265

William Stein's avatar
William Stein committed
266 267 268 269
    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
270

William Stein's avatar
William Stein committed
271
    def __str__(self):
272
        return self.declaration_code("", for_display = 1).strip()
Robert Bradshaw's avatar
Robert Bradshaw committed
273

William Stein's avatar
William Stein committed
274 275
    def same_as(self, other_type, **kwds):
        return self.same_as_resolved_type(other_type.resolve(), **kwds)
Robert Bradshaw's avatar
Robert Bradshaw committed
276

William Stein's avatar
William Stein committed
277
    def same_as_resolved_type(self, other_type):
278
        return self == other_type or other_type is error_type
Robert Bradshaw's avatar
Robert Bradshaw committed
279

William Stein's avatar
William Stein committed
280 281
    def subtype_of(self, other_type):
        return self.subtype_of_resolved_type(other_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
282

William Stein's avatar
William Stein committed
283 284
    def subtype_of_resolved_type(self, other_type):
        return self.same_as(other_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
285

William Stein's avatar
William Stein committed
286 287
    def assignable_from(self, src_type):
        return self.assignable_from_resolved_type(src_type.resolve())
Robert Bradshaw's avatar
Robert Bradshaw committed
288

William Stein's avatar
William Stein committed
289 290
    def assignable_from_resolved_type(self, src_type):
        return self.same_as(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
291

William Stein's avatar
William Stein committed
292 293
    def as_argument_type(self):
        return self
Robert Bradshaw's avatar
Robert Bradshaw committed
294

William Stein's avatar
William Stein committed
295 296 297 298 299
    def is_complete(self):
        # A type is incomplete if it is an unsized array,
        # a struct whose attributes are not defined, etc.
        return 1

300
    def is_simple_buffer_dtype(self):
301
        return (self.is_int or self.is_float or self.is_complex or self.is_pyobject or
302 303
                self.is_extension_type or self.is_ptr)

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

310 311
    def global_init_code(self, entry, code):
        # abstract
312
        pass
313

314 315
    def needs_nonecheck(self):
        return 0
316 317


318 319
def public_decl(base_code, dll_linkage):
    if dll_linkage:
320
        return "%s(%s)" % (dll_linkage, base_code.replace(',', ' __PYX_COMMA '))
321 322
    else:
        return base_code
Robert Bradshaw's avatar
Robert Bradshaw committed
323

324
def create_typedef_type(name, base_type, cname, is_external=0, namespace=None):
325 326
    is_fused = base_type.is_fused
    if base_type.is_complex or is_fused:
327
        if is_external:
328 329 330 331 332 333 334
            if is_fused:
                msg = "Fused"
            else:
                msg = "Complex"

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

335 336
        return base_type
    else:
337
        return CTypedefType(name, base_type, cname, is_external, namespace)
338

339

340
class CTypedefType(BaseType):
William Stein's avatar
William Stein committed
341
    #
342
    #  Pseudo-type defined with a ctypedef statement in a
343 344 345
    #  '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
346
    #
347
    #  qualified_name      string
348
    #  typedef_name        string
349 350
    #  typedef_cname       string
    #  typedef_base_type   PyrexType
351
    #  typedef_is_external bool
Robert Bradshaw's avatar
Robert Bradshaw committed
352

353
    is_typedef = 1
354
    typedef_is_external = 0
355 356 357

    to_py_utility_code = None
    from_py_utility_code = None
358 359

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

361
    def __init__(self, name, base_type, cname, is_external=0, namespace=None):
362
        assert not base_type.is_complex
363
        self.typedef_name = name
William Stein's avatar
William Stein committed
364 365
        self.typedef_cname = cname
        self.typedef_base_type = base_type
366
        self.typedef_is_external = is_external
367
        self.typedef_namespace = namespace
Robert Bradshaw's avatar
Robert Bradshaw committed
368

369 370 371
    def invalid_value(self):
        return self.typedef_base_type.invalid_value()

William Stein's avatar
William Stein committed
372 373
    def resolve(self):
        return self.typedef_base_type.resolve()
Robert Bradshaw's avatar
Robert Bradshaw committed
374 375

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
376
            for_display = 0, dll_linkage = None, pyrex = 0):
377
        if pyrex or for_display:
378
            base_code = self.typedef_name
379
        else:
380
            base_code = public_decl(self.typedef_cname, dll_linkage)
381 382
        if self.typedef_namespace is not None and not pyrex:
            base_code = "%s::%s" % (self.typedef_namespace.empty_declaration_code(), base_code)
383
        return self.base_declaration_code(base_code, entity_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
384

385 386 387
    def as_argument_type(self):
        return self

388 389
    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
390
        # For example, the gmp mpz_t.
391 392 393
        if self.typedef_base_type.is_array:
            base_type = self.typedef_base_type.base_type
            return CPtrType(base_type).cast_code(expr_code)
394 395
        else:
            return BaseType.cast_code(self, expr_code)
396

Robert Bradshaw's avatar
Robert Bradshaw committed
397 398 399 400 401 402
    def specialize(self, values):
        base_type = self.typedef_base_type.specialize(values)
        namespace = self.typedef_namespace.specialize(values) if self.typedef_namespace else None
        if base_type is self.typedef_base_type and namespace is self.typedef_namespace:
            return self
        else:
403 404
            return create_typedef_type(self.typedef_name, base_type, self.typedef_cname,
                                0, namespace)
Robert Bradshaw's avatar
Robert Bradshaw committed
405

406 407
    def __repr__(self):
        return "<CTypedefType %s>" % self.typedef_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
408

William Stein's avatar
William Stein committed
409
    def __str__(self):
410
        return self.typedef_name
411 412 413

    def _create_utility_code(self, template_utility_code,
                             template_function_name):
414
        type_name = type_identifier(self.typedef_cname)
415 416 417 418 419 420 421 422 423 424
        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
425
                if type(base_type) is CIntType:
426
                    self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
427
                    env.use_utility_code(TempitaUtilityCode.load_cached(
428
                        "CIntToPy", "TypeConversion.c",
429
                        context={"TYPE": self.empty_declaration_code(),
430
                                 "TO_PY_FUNCTION": self.to_py_function}))
431
                    return True
432 433 434 435 436
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
                    pass
437 438 439 440 441 442 443 444 445 446 447
                elif base_type.is_cpp_string:
                    cname = "__pyx_convert_PyObject_string_to_py_%s" % type_identifier(self)
                    context = {
                        'cname': cname,
                        'type': self.typedef_cname,
                    }
                    from .UtilityCode import CythonUtilityCode
                    env.use_utility_code(CythonUtilityCode.load(
                        "string.to_py", "CppConvert.pyx", context=context))
                    self.to_py_function = cname
                    return True
448 449 450 451 452 453 454 455 456 457
            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
458
                if type(base_type) is CIntType:
459
                    self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
460
                    env.use_utility_code(TempitaUtilityCode.load_cached(
461
                        "CIntFromPy", "TypeConversion.c",
462
                        context={"TYPE": self.empty_declaration_code(),
463
                                 "FROM_PY_FUNCTION": self.from_py_function}))
464
                    return True
465 466 467 468
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
469 470 471 472 473 474 475 476 477 478 479
                elif base_type.is_cpp_string:
                    cname = '__pyx_convert_string_from_py_%s' % type_identifier(self)
                    context = {
                        'cname': cname,
                        'type': self.typedef_cname,
                    }
                    from .UtilityCode import CythonUtilityCode
                    env.use_utility_code(CythonUtilityCode.load(
                        "string.from_py", "CppConvert.pyx", context=context))
                    self.from_py_function = cname
                    return True
480 481 482 483 484 485
            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)

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
    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)

501
    def overflow_check_binop(self, binop, env, const_rhs=False):
502
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
503
        type = self.empty_declaration_code()
504
        name = self.specialization_name()
505
        if binop == "lshift":
506
            env.use_utility_code(TempitaUtilityCode.load_cached(
507 508
                "LeftShift", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
509 510 511 512
        else:
            if const_rhs:
                binop += "_const"
            _load_overflow_base(env)
513
            env.use_utility_code(TempitaUtilityCode.load_cached(
514 515
                "SizeCheck", "Overflow.c",
                context={'TYPE': type, 'NAME': name}))
516
            env.use_utility_code(TempitaUtilityCode.load_cached(
517 518
                "Binop", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
519 520
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

521 522 523
    def error_condition(self, result_code):
        if self.typedef_is_external:
            if self.exception_value:
524 525
                condition = "(%s == %s)" % (
                    result_code, self.cast_code(self.exception_value))
526 527 528 529 530 531
                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
532 533 534
    def __getattr__(self, name):
        return getattr(self.typedef_base_type, name)

535 536
    def py_type_name(self):
        return self.typedef_base_type.py_type_name()
537

538 539 540
    def can_coerce_to_pyobject(self, env):
        return self.typedef_base_type.can_coerce_to_pyobject(env)

541 542 543
    def can_coerce_from_pyobject(self, env):
        return self.typedef_base_type.can_coerce_from_pyobject(env)

544

545
class MemoryViewSliceType(PyrexType):
546

547
    is_memoryviewslice = 1
Kurt Smith's avatar
Kurt Smith committed
548

549 550 551
    has_attributes = 1
    scope = None

Stefan Behnel's avatar
Stefan Behnel committed
552
    # These are special cased in Defnode
553 554 555 556
    from_py_function = None
    to_py_function = None

    exception_value = None
557
    exception_check = True
558

559 560
    subtypes = ['dtype']

561
    def __init__(self, base_dtype, axes):
Stefan Behnel's avatar
Stefan Behnel committed
562
        """
563
        MemoryViewSliceType(base, axes)
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593

        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
594
        """
595
        from . import Buffer, MemoryView
596

Kurt Smith's avatar
Kurt Smith committed
597
        self.dtype = base_dtype
598
        self.axes = axes
599
        self.ndim = len(axes)
600
        self.flags = MemoryView.get_buf_flags(self.axes)
601

602 603 604
        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)

605
        self.mode = MemoryView.get_mode(axes)
606
        self.writable_needed = False
607

608
        if not self.dtype.is_fused:
609
            self.dtype_name = Buffer.mangle_dtype_name(self.dtype)
610

611 612 613
    def __hash__(self):
        return hash(self.__class__) ^ hash(self.dtype) ^ hash(tuple(self.axes))

614 615 616 617 618
    def __eq__(self, other):
        if isinstance(other, BaseType):
            return self.same_as_resolved_type(other)
        else:
            return False
619

620 621 622 623 624 625
    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)

626 627 628
    def needs_nonecheck(self):
        return True

Kurt Smith's avatar
Kurt Smith committed
629
    def is_complete(self):
630
        # incomplete since the underlying struct doesn't have a cython.memoryview object.
Kurt Smith's avatar
Kurt Smith committed
631 632 633 634
        return 0

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
635 636 637
        # XXX: we put these guards in for now...
        assert not pyrex
        assert not dll_linkage
638
        from . import MemoryView
639
        return self.base_declaration_code(
640
                MemoryView.memviewslice_cname,
641
                entity_code)
Kurt Smith's avatar
Kurt Smith committed
642

643 644
    def attributes_known(self):
        if self.scope is None:
645
            from . import Symtab
646

647 648
            self.scope = scope = Symtab.CClassScope(
                    'mvs_class_'+self.specialization_suffix(),
649 650
                    None,
                    visibility='extern')
651 652

            scope.parent_type = self
653
            scope.directives = {}
654

655 656 657 658 659
            scope.declare_var('_data', c_char_ptr_type, None,
                              cname='data', is_cdef=1)

        return True

660
    def declare_attribute(self, attribute, env, pos):
661
        from . import MemoryView, Options
662 663

        scope = self.scope
664

665
        if attribute == 'shape':
666 667
            scope.declare_var('shape',
                    c_array_type(c_py_ssize_t_type,
668 669
                                 Options.buffer_max_dims),
                    pos,
670 671 672
                    cname='shape',
                    is_cdef=1)

673
        elif attribute == 'strides':
674 675
            scope.declare_var('strides',
                    c_array_type(c_py_ssize_t_type,
676 677
                                 Options.buffer_max_dims),
                    pos,
678 679 680
                    cname='strides',
                    is_cdef=1)

681
        elif attribute == 'suboffsets':
682 683
            scope.declare_var('suboffsets',
                    c_array_type(c_py_ssize_t_type,
684 685
                                 Options.buffer_max_dims),
                    pos,
686 687 688
                    cname='suboffsets',
                    is_cdef=1)

689
        elif attribute in ("copy", "copy_fortran"):
690
            ndim = len(self.axes)
691

692 693 694 695
            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)
696

697 698
            to_memview_c = MemoryViewSliceType(self.dtype, to_axes_c)
            to_memview_f = MemoryViewSliceType(self.dtype, to_axes_f)
699

700 701
            for to_memview, cython_name in [(to_memview_c, "copy"),
                                            (to_memview_f, "copy_fortran")]:
702 703 704 705 706 707 708 709 710
                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)
711

712 713
                utility = MemoryView.get_copy_new_utility(pos, self, to_memview)
                env.use_utility_code(utility)
714

715 716
            MemoryView.use_cython_array_utility_code(env)

717
        elif attribute in ("is_c_contig", "is_f_contig"):
718
            # is_c_contig and is_f_contig functions
719
            for (c_or_f, cython_name) in (('C', 'is_c_contig'), ('F', 'is_f_contig')):
720

721
                is_contig_name = MemoryView.get_is_contig_func_name(c_or_f, self.ndim)
722

Mark Florisson's avatar
Mark Florisson committed
723
                cfunctype = CFuncType(
724
                        return_type=c_bint_type,
Mark Florisson's avatar
Mark Florisson committed
725 726 727 728
                        args=[CFuncTypeArg("memviewslice", self, None)],
                        exception_value="-1",
                )

729
                entry = scope.declare_cfunction(cython_name,
Mark Florisson's avatar
Mark Florisson committed
730
                            cfunctype,
731 732 733
                            pos=pos,
                            defining=1,
                            cname=is_contig_name)
734

735
                entry.utility_code_definition = MemoryView.get_is_contig_utility(c_or_f, self.ndim)
736

737
        return True
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 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
    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])

831
    def specialization_name(self):
832 833 834
        return '%s_%s' % (
            super(MemoryViewSliceType,self).specialization_name(),
            self.specialization_suffix())
835

836
    def specialization_suffix(self):
837
        return "%s_%s" % (self.axes_to_name(), self.dtype_name)
838

839 840 841
    def can_coerce_to_pyobject(self, env):
        return True

842 843 844
    def can_coerce_from_pyobject(self, env):
        return True

Mark Florisson's avatar
Mark Florisson committed
845 846 847
    def check_for_null_code(self, cname):
        return cname + '.memview'

848
    def create_from_py_utility_code(self, env):
849
        from . import MemoryView, Buffer
850 851 852

        # We don't have 'code', so use a LazyUtilityCode with a callback.
        def lazy_utility_callback(code):
853
            context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype)
854
            return TempitaUtilityCode.load(
855
                "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
856 857 858 859 860 861 862 863 864 865 866

        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"

867 868
        suffix = self.specialization_suffix()
        funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
869 870 871

        context = dict(
            MemoryView.context,
872
            buf_flag = self.flags,
873
            ndim = self.ndim,
874
            axes_specs = ', '.join(self.axes_to_code()),
875
            dtype_typedecl = self.dtype.empty_declaration_code(),
876 877 878 879 880 881 882 883
            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

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

892
    def create_to_py_utility_code(self, env):
893
        self._dtype_to_py_func, self._dtype_from_py_func = self.dtype_object_conversion_funcs(env)
894 895
        return True

896 897 898 899 900 901
    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
902

903 904
        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
905 906 907 908 909 910 911 912 913 914 915 916 917

    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
918 919 920
            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):
921 922
                return "NULL", "NULL"

Mark Florisson's avatar
Mark Florisson committed
923 924 925 926 927 928
            if not self.dtype.to_py_function:
                get_function = "NULL"

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

929 930 931 932 933 934
            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,
935
                dtype = self.dtype.empty_declaration_code(),
936 937 938
                error_condition = error_condition,
            )

939 940
        utility = TempitaUtilityCode.load_cached(
            utility_name, "MemoryView_C.c", context=context)
941 942
        env.use_utility_code(utility)
        return get_function, set_function
943

944
    def axes_to_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
945
        """Return a list of code constants for each axis"""
946
        from . import MemoryView
947 948 949
        d = MemoryView._spec_to_const
        return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]

950
    def axes_to_name(self):
Stefan Behnel's avatar
Stefan Behnel committed
951
        """Return an abbreviated name for our axes"""
952
        from . import MemoryView
953 954 955 956 957 958
        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

959
    def __str__(self):
960
        from . import MemoryView
961 962

        axes_code_list = []
963
        for idx, (access, packing) in enumerate(self.axes):
964 965 966 967
            flag = MemoryView.get_memoryview_flag(access, packing)
            if flag == "strided":
                axes_code_list.append(":")
            else:
968
                if flag == 'contiguous':
Mark Florisson's avatar
Mark Florisson committed
969
                    have_follow = [p for a, p in self.axes[idx - 1:idx + 2]
970 971 972 973
                                         if p == 'follow']
                    if have_follow or self.ndim == 1:
                        flag = '1'

974 975 976 977 978 979 980 981 982
                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))

983
    def specialize(self, values):
Stefan Behnel's avatar
Stefan Behnel committed
984
        """This does not validate the base type!!"""
985 986 987 988
        dtype = self.dtype.specialize(values)
        if dtype is not self.dtype:
            return MemoryViewSliceType(dtype, self.axes)

989 990
        return self

991 992
    def cast_code(self, expr_code):
        return expr_code
993

994

995 996
class BufferType(BaseType):
    #
997 998 999
    #  Delegates most attribute lookups to the base type.
    #  (Anything not defined here or in the BaseType is delegated.)
    #
1000 1001 1002 1003 1004 1005 1006
    # dtype            PyrexType
    # ndim             int
    # mode             str
    # negative_indices bool
    # cast             bool
    # is_buffer        bool
    # writable         bool
1007 1008

    is_buffer = 1
1009
    writable = True
1010 1011 1012

    subtypes = ['dtype']

1013
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
1014 1015 1016
        self.base = base
        self.dtype = dtype
        self.ndim = ndim
1017
        self.buffer_ptr_type = CPtrType(dtype)
1018
        self.mode = mode
1019
        self.negative_indices = negative_indices
1020
        self.cast = cast
1021
        self.is_numpy_buffer = self.base.name == "ndarray"
Robert Bradshaw's avatar
Robert Bradshaw committed
1022

1023 1024 1025
    def can_coerce_to_pyobject(self,env):
        return True

1026 1027 1028
    def can_coerce_from_pyobject(self,env):
        return True

1029 1030 1031
    def as_argument_type(self):
        return self

Mark Florisson's avatar
Mark Florisson committed
1032 1033 1034 1035 1036 1037 1038
    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

1039 1040 1041 1042 1043
    def get_entry(self, node):
        from . import Buffer
        assert node.is_name
        return Buffer.BufferEntry(node.entry)

1044 1045 1046
    def __getattr__(self, name):
        return getattr(self.base, name)

1047 1048 1049
    def __repr__(self):
        return "<BufferType %r>" % self.base

1050
    def __str__(self):
1051
        # avoid ', ', as fused functions split the signature string on ', '
1052
        cast_str = ''
1053 1054
        if self.cast:
            cast_str = ',cast=True'
1055

1056
        return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
1057
                                      cast_str)
1058

1059
    def assignable_from(self, other_type):
1060 1061 1062
        if other_type.is_buffer:
            return (self.same_as(other_type, compare_base=False) and
                    self.base.assignable_from(other_type.base))
1063

1064 1065 1066 1067 1068 1069 1070
        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
1071 1072
                self.ndim == other_type.ndim and
                self.mode == other_type.mode and
1073 1074
                self.cast == other_type.cast and
                (not compare_base or self.base.same_as(other_type.base)))
1075

1076

William Stein's avatar
William Stein committed
1077 1078 1079 1080
class PyObjectType(PyrexType):
    #
    #  Base class for all Python object types (reference-counted).
    #
1081
    #  buffer_defaults  dict or None     Default options for bu
1082 1083

    name = "object"
William Stein's avatar
William Stein committed
1084 1085
    is_pyobject = 1
    default_value = "0"
1086
    buffer_defaults = None
1087 1088
    is_extern = False
    is_subclassed = False
1089
    is_gc_simple = False
1090

William Stein's avatar
William Stein committed
1091 1092
    def __str__(self):
        return "Python object"
Robert Bradshaw's avatar
Robert Bradshaw committed
1093

William Stein's avatar
William Stein committed
1094
    def __repr__(self):
1095
        return "<PyObjectType>"
1096 1097 1098 1099

    def can_coerce_to_pyobject(self, env):
        return True

1100 1101 1102
    def can_coerce_from_pyobject(self, env):
        return True

1103
    def default_coerced_ctype(self):
Stefan Behnel's avatar
Stefan Behnel committed
1104
        """The default C type that this Python type coerces to, or None."""
1105 1106
        return None

William Stein's avatar
William Stein committed
1107
    def assignable_from(self, src_type):
1108
        # except for pointers, conversion will be attempted
1109
        return not src_type.is_ptr or src_type.is_string or src_type.is_pyunicode_ptr
Robert Bradshaw's avatar
Robert Bradshaw committed
1110 1111

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1112
            for_display = 0, dll_linkage = None, pyrex = 0):
1113
        if pyrex or for_display:
1114
            base_code = "object"
William Stein's avatar
William Stein committed
1115
        else:
1116 1117 1118
            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
1119

1120 1121 1122 1123 1124
    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
1125

1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
    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

1136 1137 1138
    def global_init_code(self, entry, code):
        code.put_init_var_to_py_none(entry, nanny=False)

Mark Florisson's avatar
Mark Florisson committed
1139 1140 1141
    def check_for_null_code(self, cname):
        return cname

1142

1143 1144 1145 1146 1147 1148
builtin_types_that_cannot_create_refcycles = set([
    'bool', 'int', 'long', 'float', 'complex',
    'bytearray', 'bytes', 'unicode', 'str', 'basestring'
])


Robert Bradshaw's avatar
Robert Bradshaw committed
1149
class BuiltinObjectType(PyObjectType):
1150
    #  objstruct_cname  string           Name of PyObject struct
Robert Bradshaw's avatar
Robert Bradshaw committed
1151 1152 1153 1154 1155

    is_builtin_type = 1
    has_attributes = 1
    base_type = None
    module_name = '__builtin__'
1156
    require_exact = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1157

1158 1159 1160 1161 1162 1163
    # fields that let it look like an extension type
    vtabslot_cname = None
    vtabstruct_cname = None
    vtabptr_cname = None
    typedef_flag = True
    is_external = True
1164
    decl_type = 'PyObject'
1165

1166
    def __init__(self, name, cname, objstruct_cname=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
1167 1168
        self.name = name
        self.cname = cname
1169
        self.typeptr_cname = "(&%s)" % cname
1170
        self.objstruct_cname = objstruct_cname
1171
        self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles
1172 1173 1174 1175
        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
1176 1177
        if name == 'Exception':
            self.require_exact = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
1178

Robert Bradshaw's avatar
Robert Bradshaw committed
1179 1180 1181 1182
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1183

Robert Bradshaw's avatar
Robert Bradshaw committed
1184 1185
    def __str__(self):
        return "%s object" % self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1186

Robert Bradshaw's avatar
Robert Bradshaw committed
1187 1188
    def __repr__(self):
        return "<%s>"% self.cname
1189 1190

    def default_coerced_ctype(self):
1191
        if self.name in ('bytes', 'bytearray'):
1192 1193 1194 1195 1196 1197 1198
            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
1199 1200
    def assignable_from(self, src_type):
        if isinstance(src_type, BuiltinObjectType):
1201
            if self.name == 'basestring':
1202
                return src_type.name in ('str', 'unicode', 'basestring')
1203 1204
            else:
                return src_type.name == self.name
1205
        elif src_type.is_extension_type:
1206 1207 1208 1209 1210
            # 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!
1211 1212
            return (src_type.module_name == '__builtin__' and
                    src_type.name == self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1213
        else:
1214
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1215

Robert Bradshaw's avatar
Robert Bradshaw committed
1216 1217
    def typeobj_is_available(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1218

Robert Bradshaw's avatar
Robert Bradshaw committed
1219 1220
    def attributes_known(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1221

Robert Bradshaw's avatar
Robert Bradshaw committed
1222
    def subtype_of(self, type):
1223
        return type.is_pyobject and type.assignable_from(self)
1224 1225

    def type_check_function(self, exact=True):
1226 1227
        type_name = self.name
        if type_name == 'str':
1228
            type_check = 'PyString_Check'
1229 1230
        elif type_name == 'basestring':
            type_check = '__Pyx_PyBaseString_Check'
1231 1232
        elif type_name == 'Exception':
            type_check = '__Pyx_PyException_Check'
1233 1234
        elif type_name == 'bytearray':
            type_check = 'PyByteArray_Check'
1235
        elif type_name == 'frozenset':
1236
            type_check = 'PyFrozenSet_Check'
1237
        else:
1238
            type_check = 'Py%s_Check' % type_name.capitalize()
1239
        if exact and type_name not in ('bool', 'slice', 'Exception'):
1240 1241 1242 1243 1244
            type_check += 'Exact'
        return type_check

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

1246 1247
    def type_test_code(self, arg, notnone=False, exact=True):
        type_check = self.type_check_function(exact=exact)
1248 1249
        check = 'likely(%s(%s))' % (type_check, arg)
        if not notnone:
Stefan Behnel's avatar
Stefan Behnel committed
1250
            check += '||((%s) == Py_None)' % arg
1251 1252 1253 1254 1255 1256 1257 1258 1259
        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)
1260
        return check + '||' + error
Robert Bradshaw's avatar
Robert Bradshaw committed
1261

Robert Bradshaw's avatar
Robert Bradshaw committed
1262
    def declaration_code(self, entity_code,
1263 1264
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
1265
            base_code = self.name
1266
        else:
1267
            base_code = public_decl(self.decl_type, dll_linkage)
1268 1269
            entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
1270

1271 1272 1273 1274 1275 1276
    def as_pyobject(self, cname):
        if self.decl_type == 'PyObject':
            return cname
        else:
            return "(PyObject *)" + cname

1277 1278
    def cast_code(self, expr_code, to_object_struct = False):
        return "((%s*)%s)" % (
1279
            to_object_struct and self.objstruct_cname or self.decl_type, # self.objstruct_cname may be None
1280 1281
            expr_code)

1282 1283 1284 1285
    def py_type_name(self):
        return self.name


Robert Bradshaw's avatar
Robert Bradshaw committed
1286

William Stein's avatar
William Stein committed
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
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
1298
    #  objtypedef_cname string           Name of PyObject struct typedef
William Stein's avatar
William Stein committed
1299 1300 1301 1302 1303 1304
    #  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
1305
    #  defered_declarations [thunk]      Used to declare class hierarchies in order
Robert Bradshaw's avatar
Robert Bradshaw committed
1306

William Stein's avatar
William Stein committed
1307 1308
    is_extension_type = 1
    has_attributes = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1309

1310
    objtypedef_cname = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1311

1312
    def __init__(self, name, typedef_flag, base_type, is_external=0):
William Stein's avatar
William Stein committed
1313 1314 1315
        self.name = name
        self.scope = None
        self.typedef_flag = typedef_flag
1316 1317
        if base_type is not None:
            base_type.is_subclassed = True
William Stein's avatar
William Stein committed
1318 1319 1320 1321 1322 1323 1324 1325 1326
        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
1327
        self.is_external = is_external
1328
        self.defered_declarations = []
Robert Bradshaw's avatar
Robert Bradshaw committed
1329

William Stein's avatar
William Stein committed
1330 1331 1332 1333
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1334

Stefan Behnel's avatar
Stefan Behnel committed
1335 1336 1337
    def needs_nonecheck(self):
        return True

William Stein's avatar
William Stein committed
1338
    def subtype_of_resolved_type(self, other_type):
Stefan Behnel's avatar
Stefan Behnel committed
1339
        if other_type.is_extension_type or other_type.is_builtin_type:
William Stein's avatar
William Stein committed
1340 1341 1342 1343
            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
1344

William Stein's avatar
William Stein committed
1345 1346 1347
    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
1348

William Stein's avatar
William Stein committed
1349 1350 1351 1352
    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
1353

1354 1355 1356 1357 1358 1359
    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)
1360 1361 1362 1363 1364 1365 1366 1367
        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)
1368 1369
        return False

Robert Bradshaw's avatar
Robert Bradshaw committed
1370
    def declaration_code(self, entity_code,
1371
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
1372
        if pyrex or for_display:
1373
            base_code = self.name
William Stein's avatar
William Stein committed
1374 1375
        else:
            if self.typedef_flag:
1376
                objstruct = self.objstruct_cname
William Stein's avatar
William Stein committed
1377
            else:
1378
                objstruct = "struct %s" % self.objstruct_cname
1379
            base_code = public_decl(objstruct, dll_linkage)
1380
            if deref:
1381
                assert not entity_code
1382
            else:
1383 1384
                entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
1385

1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
    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
1396 1397
    def attributes_known(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1398

William Stein's avatar
William Stein committed
1399 1400
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1401

William Stein's avatar
William Stein committed
1402
    def __repr__(self):
1403 1404
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
1405

1406 1407 1408 1409 1410 1411
    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
1412 1413 1414 1415 1416 1417 1418 1419

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
1420

William Stein's avatar
William Stein committed
1421 1422
    to_py_function = None
    from_py_function = None
1423 1424
    exception_value = None
    exception_check = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1425

1426
    def create_to_py_utility_code(self, env):
1427
        return self.to_py_function is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1428

1429
    def create_from_py_utility_code(self, env):
1430
        return self.from_py_function is not None
1431 1432 1433 1434

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

1435 1436 1437
    def can_coerce_from_pyobject(self, env):
        return self.create_from_py_utility_code(env)

1438 1439
    def error_condition(self, result_code):
        conds = []
1440
        if self.is_string or self.is_pyunicode_ptr:
1441 1442 1443 1444 1445 1446 1447 1448 1449
            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
1450

1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
    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))

1474

1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
class PythranExpr(CType):
    # Pythran object of a given type

    to_py_function = "to_python_from_expr"
    is_pythran_expr = True
    writable = True
    has_attributes = 1

    def __init__(self, pythran_type, org_buffer=None):
        self.org_buffer = org_buffer
        self.pythran_type = pythran_type
        self.name = self.pythran_type
        self.cname = self.pythran_type
        self.from_py_function = "from_python<%s>" % (self.pythran_type)
        self.scope = None

1491 1492 1493
    def declaration_code(self, entity_code, for_display=0, dll_linkage=None, pyrex=0):
        assert not pyrex
        return "%s %s" % (self.cname, entity_code)
1494 1495 1496 1497

    def attributes_known(self):
        if self.scope is None:
            from . import Symtab
1498 1499
            # FIXME: fake C scope, might be better represented by a struct or C++ class scope
            self.scope = scope = Symtab.CClassScope('', None, visibility="extern")
1500 1501
            scope.parent_type = self
            scope.directives = {}
1502 1503
            scope.declare_var("shape", CPtrType(c_long_type), None, cname="_shape", is_cdef=True)
            scope.declare_var("ndim", c_long_type, None, cname="value", is_cdef=True)
1504 1505

        return True
William Stein's avatar
William Stein committed
1506

1507
    def __eq__(self, other):
1508
        return isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type
1509

1510
    def __ne__(self, other):
1511
        return not (isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type)
1512

1513
    def __hash__(self):
1514
        return hash(self.pythran_type)
1515 1516


Robert Bradshaw's avatar
Robert Bradshaw committed
1517 1518 1519
class CConstType(BaseType):

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

Robert Bradshaw's avatar
Robert Bradshaw committed
1521 1522 1523
    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:
1524
            from . import Symtab
Robert Bradshaw's avatar
Robert Bradshaw committed
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
            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):
1535 1536 1537 1538
        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
1539 1540 1541 1542 1543 1544

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

1547 1548 1549
    def deduce_template_params(self, actual):
        return self.const_base_type.deduce_template_params(actual)

1550 1551 1552
    def can_coerce_to_pyobject(self, env):
        return self.const_base_type.can_coerce_to_pyobject(env)

1553 1554 1555
    def can_coerce_from_pyobject(self, env):
        return self.const_base_type.can_coerce_from_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
1556 1557 1558 1559 1560 1561 1562 1563 1564
    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)


1565
class FusedType(CType):
1566 1567 1568 1569 1570 1571 1572
    """
    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

1573
    types           [PyrexType]             is the list of types to be fused
1574 1575 1576 1577
    name            str                     the name of the ctypedef
    """

    is_fused = 1
1578
    exception_check = 0
1579

1580
    def __init__(self, types, name=None):
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
        # 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)
1591
        self.types = flattened_types
1592
        self.name = name
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615

    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)


1616
class CVoidType(CType):
1617 1618 1619 1620
    #
    #   C "void" type
    #

William Stein's avatar
William Stein committed
1621
    is_void = 1
1622
    to_py_function = "__Pyx_void_to_None"
Robert Bradshaw's avatar
Robert Bradshaw committed
1623

William Stein's avatar
William Stein committed
1624 1625
    def __repr__(self):
        return "<CVoidType>"
Robert Bradshaw's avatar
Robert Bradshaw committed
1626 1627

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1628
            for_display = 0, dll_linkage = None, pyrex = 0):
1629 1630 1631 1632 1633
        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
1634

William Stein's avatar
William Stein committed
1635 1636 1637
    def is_complete(self):
        return 0

1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
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
1651 1652 1653 1654 1655 1656

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

William Stein's avatar
William Stein committed
1660 1661
    is_numeric = 1
    default_value = "0"
1662 1663
    has_attributes = True
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1664

1665
    sign_words = ("unsigned ", "", "signed ")
Robert Bradshaw's avatar
Robert Bradshaw committed
1666

1667
    def __init__(self, rank, signed = 1):
William Stein's avatar
William Stein committed
1668
        self.rank = rank
1669 1670 1671 1672
        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
1673
        self.signed = signed
Robert Bradshaw's avatar
Robert Bradshaw committed
1674

1675 1676 1677 1678
    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
1679

William Stein's avatar
William Stein committed
1680
    def __repr__(self):
1681
        return "<CNumericType %s>" % self.sign_and_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1682 1683

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1684
            for_display = 0, dll_linkage = None, pyrex = 0):
1685 1686 1687 1688 1689 1690
        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
1691

1692 1693
    def attributes_known(self):
        if self.scope is None:
1694
            from . import Symtab
1695 1696 1697 1698 1699 1700
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
            scope.directives = {}
Stefan Behnel's avatar
Stefan Behnel committed
1701
            scope.declare_cfunction(
1702
                    "conjugate",
1703
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1704 1705 1706 1707
                    pos=None,
                    defining=1,
                    cname=" ")
        return True
1708

1709
    def __lt__(self, other):
Stefan Behnel's avatar
Stefan Behnel committed
1710
        """Sort based on rank, preferring signed over unsigned"""
1711 1712 1713
        if other.is_numeric:
            return self.rank > other.rank and self.signed >= other.signed

1714 1715
        # Prefer numeric types over others
        return True
1716 1717 1718 1719 1720

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

William Stein's avatar
William Stein committed
1722

1723 1724 1725 1726 1727 1728 1729
class ForbidUseClass:
    def __repr__(self):
        raise RuntimeError()
    def __str__(self):
        raise RuntimeError()
ForbidUse = ForbidUseClass()

William Stein's avatar
William Stein committed
1730 1731

class CIntType(CNumericType):
1732

William Stein's avatar
William Stein committed
1733 1734
    is_int = 1
    typedef_flag = 0
1735 1736
    to_py_function = None
    from_py_function = None
1737
    to_pyunicode_utility = None
1738
    default_format_spec = 'd'
1739
    exception_value = -1
William Stein's avatar
William Stein committed
1740

1741 1742 1743
    def can_coerce_to_pyobject(self, env):
        return True

1744 1745 1746
    def can_coerce_from_pyobject(self, env):
        return True

1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
    @staticmethod
    def _parse_format(format_spec):
        padding = ' '
        if not format_spec:
            return ('d', 0, padding)
        format_type = format_spec[-1]
        if format_type in ('o', 'd', 'x', 'X'):
            prefix = format_spec[:-1]
        elif format_type.isdigit():
            format_type = 'd'
            prefix = format_spec
        else:
            return (None, 0, padding)
        if not prefix:
            return (format_type, 0, padding)
        if prefix[0] == '-':
            prefix = prefix[1:]
        if prefix and prefix[0] == '0':
            padding = '0'
            prefix = prefix.lstrip('0')
        if prefix.isdigit():
            return (format_type, int(prefix), padding)
        return (None, 0, padding)

1771
    def can_coerce_to_pystring(self, env, format_spec=None):
1772 1773
        format_type, width, padding = self._parse_format(format_spec)
        return format_type is not None and width <= 2**30
1774

1775
    def convert_to_pystring(self, cvalue, code, format_spec=None):
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
        if self.to_pyunicode_utility is None:
            utility_code_name = "__Pyx_PyUnicode_From_" + self.specialization_name()
            to_pyunicode_utility = TempitaUtilityCode.load_cached(
                "CIntToPyUnicode", "TypeConversion.c",
                context={"TYPE": self.empty_declaration_code(),
                         "TO_PY_FUNCTION": utility_code_name})
            self.to_pyunicode_utility = (utility_code_name, to_pyunicode_utility)
        else:
            utility_code_name, to_pyunicode_utility = self.to_pyunicode_utility
        code.globalstate.use_utility_code(to_pyunicode_utility)
1786 1787
        format_type, width, padding_char = self._parse_format(format_spec)
        return "%s(%s, %d, '%s', '%s')" % (utility_code_name, cvalue, width, padding_char, format_type)
1788

Robert Bradshaw's avatar
Robert Bradshaw committed
1789
    def create_to_py_utility_code(self, env):
1790
        if type(self).to_py_function is None:
1791
            self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
1792
            env.use_utility_code(TempitaUtilityCode.load_cached(
1793
                "CIntToPy", "TypeConversion.c",
1794
                context={"TYPE": self.empty_declaration_code(),
1795
                         "TO_PY_FUNCTION": self.to_py_function}))
1796 1797 1798
        return True

    def create_from_py_utility_code(self, env):
1799
        if type(self).from_py_function is None:
1800
            self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
1801
            env.use_utility_code(TempitaUtilityCode.load_cached(
1802
                "CIntFromPy", "TypeConversion.c",
1803
                context={"TYPE": self.empty_declaration_code(),
1804
                         "FROM_PY_FUNCTION": self.from_py_function}))
Robert Bradshaw's avatar
Robert Bradshaw committed
1805
        return True
1806 1807

    def get_to_py_type_conversion(self):
1808
        if self.rank < list(rank_to_type_name).index('int'):
1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
            # 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"
1819
            if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
1820 1821 1822 1823
                Prefix = "Long"
                TypeName = "LongLong"
            return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)

1824 1825
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_int or src_type.is_enum or src_type is error_type
1826

1827
    def invalid_value(self):
1828
        if rank_to_type_name[int(self.rank)] == 'char':
1829 1830 1831 1832 1833
            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.
1834
            return "0xbad0bad0"
William Stein's avatar
William Stein committed
1835

1836
    def overflow_check_binop(self, binop, env, const_rhs=False):
1837
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
1838
        type = self.empty_declaration_code()
1839
        name = self.specialization_name()
1840
        if binop == "lshift":
1841
            env.use_utility_code(TempitaUtilityCode.load_cached(
1842
                "LeftShift", "Overflow.c",
1843
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
1844
        else:
1845 1846 1847
            if const_rhs:
                binop += "_const"
            if type in ('int', 'long', 'long long'):
1848
                env.use_utility_code(TempitaUtilityCode.load_cached(
1849 1850
                    "BaseCaseSigned", "Overflow.c",
                    context={'INT': type, 'NAME': name}))
1851
            elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1852
                env.use_utility_code(TempitaUtilityCode.load_cached(
1853 1854
                    "BaseCaseUnsigned", "Overflow.c",
                    context={'UINT': type, 'NAME': name}))
1855 1856 1857 1858 1859
            elif self.rank <= 1:
                # sizeof(short) < sizeof(int)
                return "__Pyx_%s_%s_no_overflow" % (binop, name)
            else:
                _load_overflow_base(env)
1860
                env.use_utility_code(TempitaUtilityCode.load_cached(
1861 1862
                    "SizeCheck", "Overflow.c",
                    context={'TYPE': type, 'NAME': name}))
1863
                env.use_utility_code(TempitaUtilityCode.load_cached(
1864 1865
                    "Binop", "Overflow.c",
                    context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
1866 1867
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

1868

1869 1870 1871
def _load_overflow_base(env):
    env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
    for type in ('int', 'long', 'long long'):
1872
        env.use_utility_code(TempitaUtilityCode.load_cached(
1873 1874
            "BaseCaseSigned", "Overflow.c",
            context={'INT': type, 'NAME': type.replace(' ', '_')}))
1875
    for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1876
        env.use_utility_code(TempitaUtilityCode.load_cached(
1877 1878
            "BaseCaseUnsigned", "Overflow.c",
            context={'UINT': type, 'NAME': type.replace(' ', '_')}))
1879 1880


1881 1882
class CAnonEnumType(CIntType):

1883 1884 1885 1886
    is_enum = 1

    def sign_and_name(self):
        return 'int'
1887

1888

1889 1890
class CReturnCodeType(CIntType):

1891 1892
    to_py_function = "__Pyx_Owned_Py_None"

1893 1894
    is_returncode = True
    exception_check = False
1895
    default_format_spec = ''
1896

1897
    def can_coerce_to_pystring(self, env, format_spec=None):
1898 1899 1900 1901
        return not format_spec

    def convert_to_pystring(self, cvalue, code, format_spec=None):
        return "__Pyx_NewRef(%s)" % code.globalstate.get_py_string_const(StringEncoding.EncodedString("None")).cname
1902

1903

1904 1905 1906 1907
class CBIntType(CIntType):

    to_py_function = "__Pyx_PyBool_FromLong"
    from_py_function = "__Pyx_PyObject_IsTrue"
1908 1909
    exception_check = 1  # for C++ bool
    default_format_spec = ''
1910

1911
    def can_coerce_to_pystring(self, env, format_spec=None):
1912
        return not format_spec or super(CBIntType, self).can_coerce_to_pystring(env, format_spec)
1913

1914 1915 1916
    def convert_to_pystring(self, cvalue, code, format_spec=None):
        if format_spec:
            return super(CBIntType, self).convert_to_pystring(cvalue, code, format_spec)
1917 1918 1919 1920 1921 1922 1923 1924
        # NOTE: no caching here as the string constant cnames depend on the current module
        utility_code_name = "__Pyx_PyUnicode_FromBInt_" + self.specialization_name()
        to_pyunicode_utility = TempitaUtilityCode.load_cached(
            "CBIntToPyUnicode", "TypeConversion.c", context={
                "TRUE_CONST":  code.globalstate.get_py_string_const(StringEncoding.EncodedString("True")).cname,
                "FALSE_CONST": code.globalstate.get_py_string_const(StringEncoding.EncodedString("False")).cname,
                "TO_PY_FUNCTION": utility_code_name,
            })
1925
        code.globalstate.use_utility_code(to_pyunicode_utility)
1926
        return "%s(%s)" % (utility_code_name, cvalue)
1927

1928 1929
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
1930
        if for_display:
1931
            base_code = 'bool'
1932 1933
        elif pyrex:
            base_code = 'bint'
1934 1935 1936 1937
        else:
            base_code = public_decl('int', dll_linkage)
        return self.base_declaration_code(base_code, entity_code)

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

1941 1942 1943
    def __str__(self):
        return 'bint'

1944 1945 1946
    def py_type_name(self):
        return "bool"

1947

Stefan Behnel's avatar
Stefan Behnel committed
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961
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"

1962
    def can_coerce_to_pystring(self, env, format_spec=None):
1963
        return False  # does the right thing anyway
1964

Stefan Behnel's avatar
Stefan Behnel committed
1965
    def create_from_py_utility_code(self, env):
1966
        env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c"))
Stefan Behnel's avatar
Stefan Behnel committed
1967 1968 1969 1970 1971 1972
        return True

    def sign_and_name(self):
        return "Py_UCS4"


1973 1974 1975
class CPyUnicodeIntType(CIntType):
    # Py_UNICODE

Stefan Behnel's avatar
Stefan Behnel committed
1976 1977
    is_unicode_char = True

1978 1979 1980 1981
    # 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.
1982

1983 1984 1985
    to_py_function = "PyUnicode_FromOrdinal"
    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"

1986
    def can_coerce_to_pystring(self, env, format_spec=None):
1987
        return False  # does the right thing anyway
1988

1989
    def create_from_py_utility_code(self, env):
1990
        env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c"))
1991
        return True
1992 1993 1994 1995 1996

    def sign_and_name(self):
        return "Py_UNICODE"


1997 1998 1999 2000 2001 2002 2003 2004
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"

2005 2006 2007
class CPySSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
2008
    from_py_function = "__Pyx_PyIndex_AsSsize_t"
2009

2010
    def sign_and_name(self):
2011
        return "Py_ssize_t"
2012

2013 2014 2015 2016 2017 2018
class CSSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
    from_py_function = "PyInt_AsSsize_t"

    def sign_and_name(self):
2019
        return "Py_ssize_t"
2020

2021
class CSizeTType(CIntType):
2022

2023
    to_py_function = "__Pyx_PyInt_FromSize_t"
2024

2025
    def sign_and_name(self):
2026
        return "size_t"
2027

2028 2029 2030 2031 2032
class CPtrdiffTType(CIntType):

    def sign_and_name(self):
        return "ptrdiff_t"

2033

William Stein's avatar
William Stein committed
2034 2035 2036 2037
class CFloatType(CNumericType):

    is_float = 1
    to_py_function = "PyFloat_FromDouble"
2038
    from_py_function = "__pyx_PyFloat_AsDouble"
2039 2040

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

2042 2043
    def __init__(self, rank, math_h_modifier = ''):
        CNumericType.__init__(self, rank, 1)
2044
        self.math_h_modifier = math_h_modifier
2045 2046
        if rank == RANK_FLOAT:
            self.from_py_function = "__pyx_PyFloat_AsFloat"
Robert Bradshaw's avatar
Robert Bradshaw committed
2047

2048
    def assignable_from_resolved_type(self, src_type):
2049 2050
        return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type

2051 2052
    def invalid_value(self):
        return Naming.PYX_NAN
2053

2054
class CComplexType(CNumericType):
Robert Bradshaw's avatar
Robert Bradshaw committed
2055

2056
    is_complex = 1
2057
    to_py_function = "__pyx_PyComplex_FromComplex"
2058 2059
    has_attributes = 1
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
2060

2061
    def __init__(self, real_type):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2062 2063
        while real_type.is_typedef and not real_type.typedef_is_external:
            real_type = real_type.typedef_base_type
2064 2065 2066
        self.funcsuffix = "_%s" % real_type.specialization_name()
        if real_type.is_float:
            self.math_h_modifier = real_type.math_h_modifier
2067
        else:
2068
            self.math_h_modifier = "_UNUSED"
Robert Bradshaw's avatar
Robert Bradshaw committed
2069

2070 2071
        self.real_type = real_type
        CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
2072
        self.binops = {}
Craig Citro's avatar
Craig Citro committed
2073
        self.from_parts = "%s_from_parts" % self.specialization_name()
2074
        self.default_value = "%s(0, 0)" % self.from_parts
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2075

2076
    def __eq__(self, other):
2077
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
2078
            return self.real_type == other.real_type
2079
        else:
2080
            return False
Robert Bradshaw's avatar
Robert Bradshaw committed
2081

2082 2083 2084 2085 2086
    def __ne__(self, other):
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
            return self.real_type != other.real_type
        else:
            return True
2087 2088 2089 2090 2091 2092 2093 2094 2095

    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

2096 2097
    def __hash__(self):
        return ~hash(self.real_type)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2098

Robert Bradshaw's avatar
Robert Bradshaw committed
2099
    def declaration_code(self, entity_code,
2100
            for_display = 0, dll_linkage = None, pyrex = 0):
2101 2102 2103
        if pyrex or for_display:
            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
            base_code = "%s complex" % real_code
2104
        else:
2105 2106
            base_code = public_decl(self.sign_and_name(), dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
2107

2108
    def sign_and_name(self):
Craig Citro's avatar
Craig Citro committed
2109
        real_type_name = self.real_type.specialization_name()
2110
        real_type_name = real_type_name.replace('long__double','long_double')
2111
        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
2112
        return Naming.type_prefix + real_type_name + "_complex"
Robert Bradshaw's avatar
Robert Bradshaw committed
2113

2114 2115
    def assignable_from(self, src_type):
        # Temporary hack/feature disabling, see #441
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2116 2117 2118
        if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
            and src_type.typedef_is_external):
             return False
2119 2120
        elif src_type.is_pyobject:
            return True
2121 2122
        else:
            return super(CComplexType, self).assignable_from(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2123

2124 2125
    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
2126
                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
2127
                    or src_type is error_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2128

2129 2130
    def attributes_known(self):
        if self.scope is None:
2131
            from . import Symtab
2132 2133 2134 2135 2136
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
2137
            scope.directives = {}
2138 2139
            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
2140
            scope.declare_cfunction(
2141
                    "conjugate",
2142
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
2143 2144
                    pos=None,
                    defining=1,
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2145
                    cname="__Pyx_c_conj%s" % self.funcsuffix)
2146

2147
        return True
2148

2149 2150 2151 2152 2153
    def _utility_code_context(self):
        return {
            'type': self.empty_declaration_code(),
            'type_name': self.specialization_name(),
            'real_type': self.real_type.empty_declaration_code(),
2154 2155
            'func_suffix': self.funcsuffix,
            'm': self.math_h_modifier,
2156 2157 2158
            'is_float': int(self.real_type.is_float)
        }

2159
    def create_declaration_utility_code(self, env):
2160 2161
        # This must always be run, because a single CComplexType instance can be shared
        # across multiple compilations (the one created in the module scope)
2162 2163 2164 2165 2166 2167
        env.use_utility_code(UtilityCode.load_cached('Header', 'Complex.c'))
        env.use_utility_code(UtilityCode.load_cached('RealImag', 'Complex.c'))
        env.use_utility_code(TempitaUtilityCode.load_cached(
            'Declarations', 'Complex.c', self._utility_code_context()))
        env.use_utility_code(TempitaUtilityCode.load_cached(
            'Arithmetic', 'Complex.c', self._utility_code_context()))
2168 2169
        return True

2170 2171 2172
    def can_coerce_to_pyobject(self, env):
        return True

2173 2174 2175
    def can_coerce_from_pyobject(self, env):
        return True

2176
    def create_to_py_utility_code(self, env):
2177
        env.use_utility_code(UtilityCode.load_cached('ToPy', 'Complex.c'))
2178 2179 2180
        return True

    def create_from_py_utility_code(self, env):
2181 2182
        env.use_utility_code(TempitaUtilityCode.load_cached(
            'FromPy', 'Complex.c', self._utility_code_context()))
Craig Citro's avatar
Craig Citro committed
2183
        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
2184
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
2185

2186
    def lookup_op(self, nargs, op):
2187
        try:
2188
            return self.binops[nargs, op]
2189
        except KeyError:
2190 2191 2192
            pass
        try:
            op_name = complex_ops[nargs, op]
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2193
            self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
2194 2195 2196 2197 2198 2199
            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
2200

2201 2202
    def binary_op(self, op):
        return self.lookup_op(2, op)
Robert Bradshaw's avatar
Robert Bradshaw committed
2203

2204 2205 2206
    def py_type_name(self):
        return "complex"

2207 2208 2209
    def cast_code(self, expr_code):
        return expr_code

2210 2211 2212
complex_ops = {
    (1, '-'): 'neg',
    (1, 'zero'): 'is_zero',
2213 2214 2215 2216
    (2, '+'): 'sum',
    (2, '-'): 'diff',
    (2, '*'): 'prod',
    (2, '/'): 'quot',
2217
    (2, '**'): 'pow',
2218 2219
    (2, '=='): 'eq',
}
2220

2221

2222 2223 2224 2225
class CPointerBaseType(CType):
    # common base type for pointer/array types
    #
    #  base_type     CType              Reference type
2226 2227 2228

    subtypes = ['base_type']

2229
    def __init__(self, base_type):
William Stein's avatar
William Stein committed
2230
        self.base_type = base_type
2231 2232
        if base_type.is_const:
            base_type = base_type.const_base_type
2233 2234 2235 2236
        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
2237 2238
        else:
            if base_type.same_as(c_py_unicode_type):
2239
                self.is_pyunicode_ptr = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2240

2241
        if self.is_string and not base_type.is_error:
2242 2243 2244
            if base_type.signed == 2:
                self.to_py_function = "__Pyx_PyObject_FromCString"
                if self.is_ptr:
2245
                    self.from_py_function = "__Pyx_PyObject_As%sSString"
2246
            elif base_type.signed:
2247
                self.to_py_function = "__Pyx_PyObject_FromString"
2248
                if self.is_ptr:
2249
                    self.from_py_function = "__Pyx_PyObject_As%sString"
2250
            else:
2251
                self.to_py_function = "__Pyx_PyObject_FromCString"
2252
                if self.is_ptr:
2253 2254 2255
                    self.from_py_function = "__Pyx_PyObject_As%sUString"
            if self.is_ptr:
                self.from_py_function %= '' if self.base_type.is_const else 'Writable'
2256
            self.exception_value = "NULL"
2257
        elif self.is_pyunicode_ptr and not base_type.is_error:
2258 2259 2260 2261
            self.to_py_function = "__Pyx_PyUnicode_FromUnicode"
            if self.is_ptr:
                self.from_py_function = "__Pyx_PyUnicode_AsUnicode"
            self.exception_value = "NULL"
2262 2263 2264 2265

    def py_type_name(self):
        if self.is_string:
            return "bytes"
2266
        elif self.is_pyunicode_ptr:
2267
            return "unicode"
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281
        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
2282
    to_tuple_function = None
2283 2284 2285 2286 2287

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

2288
    def __eq__(self, other):
2289 2290
        if isinstance(other, CType) and other.is_array and self.size == other.size:
            return self.base_type.same_as(other.base_type)
2291 2292
        return False

2293 2294 2295
    def __hash__(self):
        return hash(self.base_type) + 28 # arbitrarily chosen offset

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

William Stein's avatar
William Stein committed
2299 2300 2301 2302
    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
2303

William Stein's avatar
William Stein committed
2304
    def assignable_from_resolved_type(self, src_type):
2305 2306 2307 2308 2309 2310
        # 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
2311

William Stein's avatar
William Stein committed
2312 2313 2314
    def element_ptr_type(self):
        return c_ptr_type(self.base_type)

Robert Bradshaw's avatar
Robert Bradshaw committed
2315
    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2316 2317 2318 2319 2320
            for_display = 0, dll_linkage = None, pyrex = 0):
        if self.size is not None:
            dimension_code = self.size
        else:
            dimension_code = ""
2321 2322
        if entity_code.startswith("*"):
            entity_code = "(%s)" % entity_code
William Stein's avatar
William Stein committed
2323
        return self.base_type.declaration_code(
2324
            "%s[%s]" % (entity_code, dimension_code),
William Stein's avatar
William Stein committed
2325
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2326

William Stein's avatar
William Stein committed
2327 2328
    def as_argument_type(self):
        return c_ptr_type(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2329

William Stein's avatar
William Stein committed
2330 2331 2332
    def is_complete(self):
        return self.size is not None

2333 2334 2335 2336 2337
    def specialize(self, values):
        base_type = self.base_type.specialize(values)
        if base_type == self.base_type:
            return self
        else:
2338
            return CArrayType(base_type, self.size)
2339 2340 2341 2342 2343

    def deduce_template_params(self, actual):
        if isinstance(actual, CArrayType):
            return self.base_type.deduce_template_params(actual.base_type)
        else:
2344
            return {}
2345

2346 2347 2348
    def can_coerce_to_pyobject(self, env):
        return self.base_type.can_coerce_to_pyobject(env)

2349 2350 2351
    def can_coerce_from_pyobject(self, env):
        return self.base_type.can_coerce_from_pyobject(env)

2352 2353 2354 2355 2356 2357
    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

2358
        safe_typename = self.base_type.specialization_name()
2359 2360 2361 2362 2363 2364 2365
        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,
2366
            'base_type': self.base_type,
2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395
        }
        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

2396
        from_py_function = "__Pyx_carray_from_py_%s" % self.base_type.specialization_name()
2397 2398 2399 2400

        from .UtilityCode import CythonUtilityCode
        context = {
            'cname': from_py_function,
2401
            'base_type': self.base_type,
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
        }
        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
2417

2418 2419
class CPtrType(CPointerBaseType):
    #  base_type     CType              Reference type
Robert Bradshaw's avatar
Robert Bradshaw committed
2420

William Stein's avatar
William Stein committed
2421
    is_ptr = 1
2422
    default_value = "0"
2423

2424 2425 2426
    def __hash__(self):
        return hash(self.base_type) + 27 # arbitrarily chosen offset

2427 2428 2429 2430 2431
    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
2432 2433 2434
    def __ne__(self, other):
        return not (self == other)

William Stein's avatar
William Stein committed
2435
    def __repr__(self):
2436
        return "<CPtrType %s>" % repr(self.base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2437

William Stein's avatar
William Stein committed
2438 2439 2440 2441
    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
2442 2443

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
2444 2445 2446
            for_display = 0, dll_linkage = None, pyrex = 0):
        #print "CPtrType.declaration_code: pointer to", self.base_type ###
        return self.base_type.declaration_code(
2447
            "*%s" % entity_code,
William Stein's avatar
William Stein committed
2448
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2449

William Stein's avatar
William Stein committed
2450 2451 2452
    def assignable_from_resolved_type(self, other_type):
        if other_type is error_type:
            return 1
2453
        if other_type.is_null_ptr:
William Stein's avatar
William Stein committed
2454
            return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2455 2456
        if self.base_type.is_const:
            self = CPtrType(self.base_type.const_base_type)
2457 2458 2459 2460 2461 2462 2463
        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
2464
        if (self.base_type.is_cpp_class and other_type.is_ptr
2465 2466
                and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)):
            return 1
2467
        if other_type.is_array or other_type.is_ptr:
2468
            return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
2469
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2470

2471 2472 2473 2474 2475 2476
    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
2477

2478 2479 2480 2481
    def deduce_template_params(self, actual):
        if isinstance(actual, CPtrType):
            return self.base_type.deduce_template_params(actual.base_type)
        else:
2482
            return {}
2483

2484 2485
    def invalid_value(self):
        return "1"
William Stein's avatar
William Stein committed
2486

2487 2488
    def find_cpp_operation_type(self, operator, operand_type=None):
        if self.base_type.is_cpp_class:
Stefan Behnel's avatar
Stefan Behnel committed
2489
            return self.base_type.find_cpp_operation_type(operator, operand_type)
2490 2491
        return None

2492

William Stein's avatar
William Stein committed
2493 2494 2495
class CNullPtrType(CPtrType):

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

William Stein's avatar
William Stein committed
2497

Robert Bradshaw's avatar
Robert Bradshaw committed
2498
class CReferenceType(BaseType):
Danilo Freitas's avatar
Danilo Freitas committed
2499 2500

    is_reference = 1
2501
    is_fake_reference = 0
Danilo Freitas's avatar
Danilo Freitas committed
2502 2503

    def __init__(self, base_type):
Robert Bradshaw's avatar
Robert Bradshaw committed
2504
        self.ref_base_type = base_type
Danilo Freitas's avatar
Danilo Freitas committed
2505 2506

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

Robert Bradshaw's avatar
Robert Bradshaw committed
2509 2510
    def __str__(self):
        return "%s &" % self.ref_base_type
Robert Bradshaw's avatar
Robert Bradshaw committed
2511

Robert Bradshaw's avatar
Robert Bradshaw committed
2512
    def declaration_code(self, entity_code,
Danilo Freitas's avatar
Danilo Freitas committed
2513
            for_display = 0, dll_linkage = None, pyrex = 0):
2514
        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
Robert Bradshaw's avatar
Robert Bradshaw committed
2515
        return self.ref_base_type.declaration_code(
Danilo Freitas's avatar
Danilo Freitas committed
2516 2517
            "&%s" % entity_code,
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2518

Danilo Freitas's avatar
Danilo Freitas committed
2519
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
2520 2521
        base_type = self.ref_base_type.specialize(values)
        if base_type == self.ref_base_type:
Danilo Freitas's avatar
Danilo Freitas committed
2522 2523
            return self
        else:
2524
            return type(self)(base_type)
Danilo Freitas's avatar
Danilo Freitas committed
2525

2526 2527 2528
    def deduce_template_params(self, actual):
        return self.ref_base_type.deduce_template_params(actual)

Robert Bradshaw's avatar
Robert Bradshaw committed
2529 2530 2531 2532
    def __getattr__(self, name):
        return getattr(self.ref_base_type, name)


2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548
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
2549 2550 2551 2552 2553
class CFuncType(CType):
    #  return_type      CType
    #  args             [CFuncTypeArg]
    #  has_varargs      boolean
    #  exception_value  string
2554 2555 2556 2557
    #  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
2558
    #  templates        [string] or None
2559
    #  cached_specialized_types [CFuncType]   cached specialized versions of the CFuncType if defined in a pxd
Mark Florisson's avatar
Mark Florisson committed
2560 2561
    #  from_fused       boolean    Indicates whether this is a specialized
    #                              C function
2562 2563
    #  is_strict_signature boolean  function refuses to accept coerced arguments
    #                               (used for optimisation overrides)
Robert Bradshaw's avatar
Robert Bradshaw committed
2564
    #  is_const_method  boolean
2565
    #  is_static_method boolean
Robert Bradshaw's avatar
Robert Bradshaw committed
2566

William Stein's avatar
William Stein committed
2567
    is_cfunction = 1
2568
    original_sig = None
2569
    cached_specialized_types = None
Mark Florisson's avatar
Mark Florisson committed
2570
    from_fused = False
Robert Bradshaw's avatar
Robert Bradshaw committed
2571
    is_const_method = False
2572 2573 2574

    subtypes = ['return_type', 'args']

2575 2576
    def __init__(self, return_type, args, has_varargs = 0,
            exception_value = None, exception_check = 0, calling_convention = "",
Danilo Freitas's avatar
Danilo Freitas committed
2577
            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
Robert Bradshaw's avatar
Robert Bradshaw committed
2578 2579
            is_const_method = False, is_static_method=False,
            templates = None, is_strict_signature = False):
William Stein's avatar
William Stein committed
2580 2581 2582
        self.return_type = return_type
        self.args = args
        self.has_varargs = has_varargs
2583
        self.optional_arg_count = optional_arg_count
William Stein's avatar
William Stein committed
2584 2585
        self.exception_value = exception_value
        self.exception_check = exception_check
2586 2587
        self.calling_convention = calling_convention
        self.nogil = nogil
2588
        self.with_gil = with_gil
2589
        self.is_overridable = is_overridable
2590
        self.is_const_method = is_const_method
Robert Bradshaw's avatar
Robert Bradshaw committed
2591
        self.is_static_method = is_static_method
Danilo Freitas's avatar
Danilo Freitas committed
2592
        self.templates = templates
2593
        self.is_strict_signature = is_strict_signature
2594

William Stein's avatar
William Stein committed
2595
    def __repr__(self):
2596
        arg_reprs = list(map(repr, self.args))
William Stein's avatar
William Stein committed
2597 2598
        if self.has_varargs:
            arg_reprs.append("...")
2599 2600 2601 2602 2603 2604 2605
        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
2606
            repr(self.return_type),
2607
            self.calling_convention_prefix(),
2608 2609
            ",".join(arg_reprs),
            except_clause)
Robert Bradshaw's avatar
Robert Bradshaw committed
2610

2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
    def with_with_gil(self, with_gil):
        if with_gil == self.with_gil:
            return self
        else:
            return CFuncType(
                self.return_type, self.args, self.has_varargs,
                self.exception_value, self.exception_check,
                self.calling_convention, self.nogil,
                with_gil,
                self.is_overridable, self.optional_arg_count,
                self.is_const_method, self.is_static_method,
                self.templates, self.is_strict_signature)

2624 2625 2626 2627 2628 2629
    def calling_convention_prefix(self):
        cc = self.calling_convention
        if cc:
            return cc + " "
        else:
            return ""
Robert Bradshaw's avatar
Robert Bradshaw committed
2630

2631 2632 2633
    def as_argument_type(self):
        return c_ptr_type(self)

William Stein's avatar
William Stein committed
2634 2635 2636 2637
    def same_c_signature_as(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(
            other_type.resolve(), as_cmethod)

2638 2639
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod=False, as_pxd_definition=False,
                                          exact_semantics=True):
2640 2641
        # If 'exact_semantics' is false, allow any equivalent C signatures
        # if the Cython semantics are compatible, i.e. the same or wider for 'other_type'.
2642

2643
        #print "CFuncType.same_c_signature_as_resolved_type:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
2644
        #    self, other_type, "as_cmethod =", as_cmethod ###
William Stein's avatar
William Stein committed
2645 2646 2647 2648
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2649
        if self.is_overridable != other_type.is_overridable:
2650
            return 0
William Stein's avatar
William Stein committed
2651
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
2652
        if nargs != len(other_type.args):
William Stein's avatar
William Stein committed
2653 2654 2655 2656 2657
            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):
2658 2659
            if not self.args[i].type.same_as(other_type.args[i].type):
                return 0
Stefan Behnel's avatar
Stefan Behnel committed
2660
        if self.has_varargs != other_type.has_varargs:
William Stein's avatar
William Stein committed
2661
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2662
        if self.optional_arg_count != other_type.optional_arg_count:
2663
            return 0
2664 2665 2666 2667 2668 2669 2670
        if as_pxd_definition:
            # A narrowing of the return type declared in the pxd is allowed.
            if not self.return_type.subtype_of_resolved_type(other_type.return_type):
                return 0
        else:
            if not self.return_type.same_as(other_type.return_type):
                return 0
2671 2672
        if not self.same_calling_convention_as(other_type):
            return 0
2673 2674 2675 2676 2677
        if exact_semantics:
            if self.exception_check != other_type.exception_check:
                return 0
            if not self._same_exception_value(other_type.exception_value):
                return 0
2678 2679
        elif not self._is_exception_compatible_with(other_type):
            return 0
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695
        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
2696
        return 1
2697

2698 2699
    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
2700

2701 2702
    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
2703
        #    self, other_type, "as_cmethod =", as_cmethod ###
2704 2705 2706 2707
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2708
        if not self.is_overridable and other_type.is_overridable:
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
            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
2724
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
2725 2726 2727
            return 0
        if not self.same_calling_convention_as(other_type):
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2728 2729
        if self.nogil != other_type.nogil:
            return 0
2730 2731 2732 2733 2734 2735
        if not self._is_exception_compatible_with(other_type):
            return 0
        self.original_sig = other_type.original_sig or other_type
        return 1

    def _is_exception_compatible_with(self, other_type):
2736 2737 2738
        # narrower exception checks are ok, but prevent mismatches
        if self.exception_check == '+' and other_type.exception_check != '+':
            # must catch C++ exceptions if we raise them
2739
            return 0
2740 2741 2742 2743 2744 2745 2746
        if not other_type.exception_check or other_type.exception_value is not None:
            # if other does not *always* check exceptions, self must comply
            if not self._same_exception_value(other_type.exception_value):
                return 0
            if self.exception_check and self.exception_check != other_type.exception_check:
                # a redundant exception check doesn't make functions incompatible, but a missing one does
                return 0
2747
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2748

2749 2750
    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
2751

2752 2753 2754 2755 2756 2757
    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
2758
        if nargs != len(other_type.args):
2759 2760 2761 2762 2763 2764 2765
            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
2766
        if self.has_varargs != other_type.has_varargs:
2767
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2768
        if self.optional_arg_count != other_type.optional_arg_count:
2769
            return 0
2770 2771
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
            return 0
2772 2773 2774
        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
2775 2776
        if not self._same_exception_value(other_type.exception_value):
            return 0
2777 2778
        return 1

2779
    def same_calling_convention_as(self, other):
2780 2781 2782 2783 2784 2785 2786 2787 2788
        ## 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
2789 2790 2791
        sc1 = self.calling_convention == '__stdcall'
        sc2 = other.calling_convention == '__stdcall'
        return sc1 == sc2
Robert Bradshaw's avatar
Robert Bradshaw committed
2792

2793 2794
    def same_as_resolved_type(self, other_type, as_cmethod=False):
        return self.same_c_signature_as_resolved_type(other_type, as_cmethod=as_cmethod) \
2795
            and self.nogil == other_type.nogil
Robert Bradshaw's avatar
Robert Bradshaw committed
2796

2797
    def pointer_assignable_from_resolved_type(self, rhs_type):
2798 2799 2800 2801 2802
        # Accept compatible exception/nogil declarations for the RHS.
        if rhs_type is error_type:
            return 1
        if not rhs_type.is_cfunction:
            return 0
2803 2804
        return rhs_type.same_c_signature_as_resolved_type(self, exact_semantics=False) \
            and not (self.nogil and not rhs_type.nogil)
Robert Bradshaw's avatar
Robert Bradshaw committed
2805 2806

    def declaration_code(self, entity_code,
2807 2808
                         for_display = 0, dll_linkage = None, pyrex = 0,
                         with_calling_convention = 1):
William Stein's avatar
William Stein committed
2809
        arg_decl_list = []
2810
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
William Stein's avatar
William Stein committed
2811 2812
            arg_decl_list.append(
                arg.type.declaration_code("", for_display, pyrex = pyrex))
2813 2814
        if self.is_overridable:
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
2815
        if self.optional_arg_count:
2816
            arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
2817 2818
        if self.has_varargs:
            arg_decl_list.append("...")
2819
        arg_decl_code = ", ".join(arg_decl_list)
William Stein's avatar
William Stein committed
2820 2821
        if not arg_decl_code and not pyrex:
            arg_decl_code = "void"
2822
        trailer = ""
2823
        if (pyrex or for_display) and not self.return_type.is_pyobject:
William Stein's avatar
William Stein committed
2824
            if self.exception_value and self.exception_check:
2825
                trailer = " except? %s" % self.exception_value
William Stein's avatar
William Stein committed
2826
            elif self.exception_value:
2827
                trailer = " except %s" % self.exception_value
Felix Wu's avatar
Felix Wu committed
2828
            elif self.exception_check == '+':
2829
                trailer = " except +"
2830 2831 2832
            elif self.exception_check and for_display:
                # not spelled out by default, unless for human eyes
                trailer = " except *"
2833 2834
            if self.nogil:
                trailer += " nogil"
2835 2836 2837 2838 2839 2840 2841
        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
2842 2843
        if self.is_const_method:
            trailer += " const"
William Stein's avatar
William Stein committed
2844
        return self.return_type.declaration_code(
2845
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
William Stein's avatar
William Stein committed
2846
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2847

2848
    def function_header_code(self, func_name, arg_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2849 2850 2851 2852 2853 2854
        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
2855

2856
    def signature_string(self):
2857
        s = self.empty_declaration_code()
2858 2859
        return s

2860 2861 2862
    def signature_cast_string(self):
        s = self.declaration_code("(*)", with_calling_convention=False)
        return '(%s)' % s
Robert Bradshaw's avatar
Robert Bradshaw committed
2863

Robert Bradshaw's avatar
Robert Bradshaw committed
2864
    def specialize(self, values):
Mark Florisson's avatar
Mark Florisson committed
2865 2866
        result = CFuncType(self.return_type.specialize(values),
                           [arg.specialize(values) for arg in self.args],
2867
                           has_varargs = self.has_varargs,
Mark Florisson's avatar
Mark Florisson committed
2868 2869 2870 2871 2872 2873 2874
                           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,
2875
                           is_const_method = self.is_const_method,
Robert Bradshaw's avatar
Robert Bradshaw committed
2876
                           is_static_method = self.is_static_method,
2877
                           templates = self.templates)
Mark Florisson's avatar
Mark Florisson committed
2878 2879 2880

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

2882 2883
    def opt_arg_cname(self, arg_name):
        return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
2884

2885 2886 2887 2888
    # 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).

2889
    def get_all_specialized_permutations(self, fused_types=None):
2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902
        """
        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()

2903
        return get_all_specialized_permutations(fused_types)
2904

2905
    def get_all_specialized_function_types(self):
2906 2907 2908 2909 2910
        """
        Get all the specific function types of this one.
        """
        assert self.is_fused

2911 2912 2913 2914 2915
        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

2916
        result = []
2917
        permutations = self.get_all_specialized_permutations()
2918

2919
        new_cfunc_entries = []
2920 2921 2922
        for cname, fused_to_specific in permutations:
            new_func_type = self.entry.type.specialize(fused_to_specific)

2923 2924 2925 2926
            if self.optional_arg_count:
                # Remember, this method is set by CFuncDeclaratorNode
                self.declare_opt_arg_struct(new_func_type, cname)

2927
            new_entry = copy.deepcopy(self.entry)
Mark Florisson's avatar
Mark Florisson committed
2928
            new_func_type.specialize_entry(new_entry, cname)
2929

2930
            new_entry.type = new_func_type
2931
            new_func_type.entry = new_entry
2932 2933
            result.append(new_func_type)

2934 2935 2936 2937 2938 2939 2940 2941 2942
            new_cfunc_entries.append(new_entry)

        cfunc_entries = self.entry.scope.cfunc_entries
        try:
            cindex = cfunc_entries.index(self.entry)
        except ValueError:
            cfunc_entries.extend(new_cfunc_entries)
        else:
            cfunc_entries[cindex:cindex+1] = new_cfunc_entries
Mark Florisson's avatar
Mark Florisson committed
2943

2944 2945
        self.cached_specialized_types = result

2946
        return result
2947

Mark Florisson's avatar
Mark Florisson committed
2948
    def get_fused_types(self, result=None, seen=None, subtypes=None):
Stefan Behnel's avatar
Stefan Behnel committed
2949
        """Return fused types in the order they appear as parameter types"""
Mark Florisson's avatar
Mark Florisson committed
2950 2951
        return super(CFuncType, self).get_fused_types(result, seen,
                                                      subtypes=['args'])
2952

Mark Florisson's avatar
Mark Florisson committed
2953 2954
    def specialize_entry(self, entry, cname):
        assert not self.is_fused
2955
        specialize_entry(entry, cname)
Mark Florisson's avatar
Mark Florisson committed
2956

2957 2958
    def can_coerce_to_pyobject(self, env):
        # duplicating the decisions from create_to_py_utility_code() here avoids writing out unused code
2959 2960
        if self.has_varargs or self.optional_arg_count:
            return False
2961 2962
        if self.to_py_function is not None:
            return self.to_py_function
2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
        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
2976
        from .UtilityCode import CythonUtilityCode
2977
        safe_typename = re.sub('[^a-zA-Z0-9]', '__', self.declaration_code("", pyrex=1))
2978
        to_py_function = "__Pyx_CFunc_%s_to_py" % safe_typename
Robert Bradshaw's avatar
Robert Bradshaw committed
2979

2980 2981 2982
        for arg in self.args:
            if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
                return False
2983
        if not self.return_type.is_pyobject and not self.return_type.create_to_py_utility_code(env):
2984
            return False
2985

2986
        def declared_type(ctype):
2987
            type_displayname = str(ctype.declaration_code("", for_display=True))
2988 2989 2990 2991 2992 2993 2994 2995 2996
            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)
2997
            elif ctype is c_bint_type:
2998
                type_name = arg_ctype = 'bint'
2999
            else:
3000 3001 3002 3003 3004 3005
                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
3006

3007
        class Arg(object):
3008 3009 3010 3011
            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
3012

Stefan Behnel's avatar
Stefan Behnel committed
3013
        if self.return_type.is_void:
3014
            except_clause = 'except *'
3015 3016 3017 3018
        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
3019
        else:
3020
            except_clause = 'except *'
Robert Bradshaw's avatar
Robert Bradshaw committed
3021

3022
        context = {
3023 3024
            'cname': to_py_function,
            'args': [Arg(arg.name or 'arg%s' % ix, arg.type) for ix, arg in enumerate(self.args)],
3025
            'return_type': Arg('return', self.return_type),
3026
            'except_clause': except_clause,
3027
        }
Stefan Behnel's avatar
Stefan Behnel committed
3028
        # FIXME: directives come from first defining environment and do not adapt for reuse
3029
        env.use_utility_code(CythonUtilityCode.load(
3030
            "cfunc.to_py", "CConvert.pyx",
3031
            outer_module_scope=env.global_scope(),  # need access to types declared in module
3032
            context=context, compiler_directives=dict(env.global_scope().directives)))
3033
        self.to_py_function = to_py_function
3034 3035
        return True

Mark Florisson's avatar
Mark Florisson committed
3036

3037 3038 3039 3040
def specialize_entry(entry, cname):
    """
    Specialize an entry of a copied fused function or method
    """
3041
    entry.is_fused_specialized = True
3042
    entry.name = get_fused_cname(cname, entry.name)
Mark Florisson's avatar
Mark Florisson committed
3043

3044 3045 3046 3047 3048 3049 3050
    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)
3051

3052 3053
    if entry.func_cname:
        entry.func_cname = get_fused_cname(cname, entry.func_cname)
3054 3055 3056 3057 3058

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
3059
    assert fused_cname and orig_cname
3060 3061
    return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix,
                                                    fused_cname, orig_cname))
3062

3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076
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=()):
3077
    fused_type, = fused_types[0].get_fused_types()
3078 3079
    result = []

3080
    for newid, specific_type in enumerate(fused_type.types):
3081 3082 3083 3084
        # f2s = dict(f2s, **{ fused_type: specific_type })
        f2s = dict(f2s)
        f2s.update({ fused_type: specific_type })

3085 3086 3087
        if id:
            cname = '%s_%s' % (id, newid)
        else:
3088
            cname = str(newid)
3089 3090

        if len(fused_types) > 1:
3091
            result.extend(_get_all_specialized_permutations(
3092 3093 3094 3095 3096 3097
                                            fused_types[1:], cname, f2s))
        else:
            result.append((cname, f2s))

    return result

3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122
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()

3123

3124 3125
def get_specialized_types(type):
    """
3126
    Return a list of specialized types in their declared order.
3127
    """
3128 3129
    assert type.is_fused

3130
    if isinstance(type, FusedType):
3131
        result = list(type.types)
3132 3133
        for specialized_type in result:
            specialized_type.specialization_string = specialized_type.typeof_name()
3134 3135
    else:
        result = []
3136
        for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
3137 3138 3139 3140
            specialized_type = type.specialize(f2s)
            specialized_type.specialization_string = (
                            specialization_signature_string(type, f2s))
            result.append(specialized_type)
3141

3142
    return result
3143

William Stein's avatar
William Stein committed
3144

3145
class CFuncTypeArg(BaseType):
William Stein's avatar
William Stein committed
3146 3147 3148 3149
    #  name       string
    #  cname      string
    #  type       PyrexType
    #  pos        source file position
3150 3151 3152 3153 3154

    # 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
3155
    accept_builtin_subtypes = False
3156

3157 3158
    subtypes = ['type']

3159
    def __init__(self, name, type, pos, cname=None):
William Stein's avatar
William Stein committed
3160
        self.name = name
3161 3162 3163 3164
        if cname is not None:
            self.cname = cname
        else:
            self.cname = Naming.var_prefix + name
William Stein's avatar
William Stein committed
3165 3166
        self.type = type
        self.pos = pos
3167
        self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
Robert Bradshaw's avatar
Robert Bradshaw committed
3168

William Stein's avatar
William Stein committed
3169 3170
    def __repr__(self):
        return "%s:%s" % (self.name, repr(self.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
3171

William Stein's avatar
William Stein committed
3172 3173
    def declaration_code(self, for_display = 0):
        return self.type.declaration_code(self.cname, for_display)
Robert Bradshaw's avatar
Robert Bradshaw committed
3174

Robert Bradshaw's avatar
Robert Bradshaw committed
3175 3176
    def specialize(self, values):
        return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
William Stein's avatar
William Stein committed
3177

Mark Florisson's avatar
Mark Florisson committed
3178
class ToPyStructUtilityCode(object):
3179 3180 3181

    requires = None

3182
    def __init__(self, type, forward_decl, env):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3183
        self.type = type
Mark Florisson's avatar
Mark Florisson committed
3184 3185
        self.header = "static PyObject* %s(%s)" % (type.to_py_function,
                                                   type.declaration_code('s'))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3186
        self.forward_decl = forward_decl
3187
        self.env = env
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3188 3189

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

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3192 3193
    def __hash__(self):
        return hash(self.header)
Robert Bradshaw's avatar
Robert Bradshaw committed
3194

3195
    def get_tree(self, **kwargs):
3196
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3197

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3198 3199 3200
    def put_code(self, output):
        code = output['utility_code_def']
        proto = output['utility_code_proto']
Robert Bradshaw's avatar
Robert Bradshaw committed
3201

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3202 3203 3204
        code.putln("%s {" % self.header)
        code.putln("PyObject* res;")
        code.putln("PyObject* member;")
3205 3206
        code.putln("res = __Pyx_PyDict_NewPresized(%d); if (unlikely(!res)) return NULL;" %
                   len(self.type.scope.var_entries))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3207 3208
        for member in self.type.scope.var_entries:
            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
3209
            code.putln("%s; if (unlikely(!member)) goto bad;" % (
3210
                member.type.to_py_call_code('s.%s' % member.cname, 'member', member.type)))
3211
            code.putln("if (unlikely(PyDict_SetItem(res, %s, member) < 0)) goto bad;" % nameconst_cname)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222
            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:
3223
            proto.putln(self.type.empty_declaration_code() + ';')
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3224
        proto.putln(self.header + ";")
Robert Bradshaw's avatar
Robert Bradshaw committed
3225

3226 3227
    def inject_tree_and_scope_into(self, module_node):
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3228

William Stein's avatar
William Stein committed
3229 3230 3231 3232 3233 3234 3235

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

3238
    # entry          Entry
Robert Bradshaw's avatar
Robert Bradshaw committed
3239

William Stein's avatar
William Stein committed
3240 3241
    is_struct_or_union = 1
    has_attributes = 1
Mark Florisson's avatar
Mark Florisson committed
3242
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3243

3244
    def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
William Stein's avatar
William Stein committed
3245 3246 3247 3248 3249
        self.name = name
        self.cname = cname
        self.kind = kind
        self.scope = scope
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
3250
        self.is_struct = kind == 'struct'
3251 3252 3253 3254
        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
3255
        self.exception_check = True
Mark Florisson's avatar
Mark Florisson committed
3256 3257
        self._convert_to_py_code = None
        self._convert_from_py_code = None
3258
        self.packed = packed
Robert Bradshaw's avatar
Robert Bradshaw committed
3259

3260
    def can_coerce_to_pyobject(self, env):
Stefan Behnel's avatar
Stefan Behnel committed
3261 3262
        if self._convert_to_py_code is False:
            return None  # tri-state-ish
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3263

3264 3265 3266
        if env.outer_scope is None:
            return False

Mark Florisson's avatar
Mark Florisson committed
3267
        if self._convert_to_py_code is None:
3268 3269 3270
            is_union = not self.is_struct
            unsafe_union_types = set()
            safe_union_types = set()
Robert Bradshaw's avatar
Robert Bradshaw committed
3271
            for member in self.scope.var_entries:
3272
                member_type = member.type
3273
                if not member_type.can_coerce_to_pyobject(env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3274
                    self.to_py_function = None
Mark Florisson's avatar
Mark Florisson committed
3275
                    self._convert_to_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3276
                    return False
3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288
                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

3289 3290 3291 3292 3293 3294 3295 3296 3297
        return True

    def create_to_py_utility_code(self, env):
        if not self.can_coerce_to_pyobject(env):
            return False

        if self._convert_to_py_code is None:
            for member in self.scope.var_entries:
                member.type.create_to_py_utility_code(env)
3298 3299
            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
3300

Mark Florisson's avatar
Mark Florisson committed
3301 3302 3303
        env.use_utility_code(self._convert_to_py_code)
        return True

Robert Bradshaw's avatar
Robert Bradshaw committed
3304
    def can_coerce_from_pyobject(self, env):
3305 3306 3307
        if env.outer_scope is None or self._convert_from_py_code is False:
            return False
        for member in self.scope.var_entries:
Robert Bradshaw's avatar
Robert Bradshaw committed
3308
            if not member.type.can_coerce_from_pyobject(env):
3309 3310 3311
                return False
        return True

Mark Florisson's avatar
Mark Florisson committed
3312 3313 3314 3315
    def create_from_py_utility_code(self, env):
        if env.outer_scope is None:
            return False

Stefan Behnel's avatar
Stefan Behnel committed
3316 3317
        if self._convert_from_py_code is False:
            return None  # tri-state-ish
Mark Florisson's avatar
Mark Florisson committed
3318 3319

        if self._convert_from_py_code is None:
3320 3321 3322 3323 3324
            if not self.scope.var_entries:
                # There are obviously missing fields; don't allow instantiation
                # where absolutely no content is provided.
                return False

Mark Florisson's avatar
Mark Florisson committed
3325
            for member in self.scope.var_entries:
3326
                if not member.type.create_from_py_utility_code(env):
Mark Florisson's avatar
Mark Florisson committed
3327 3328
                    self.from_py_function = None
                    self._convert_from_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3329
                    return False
Mark Florisson's avatar
Mark Florisson committed
3330 3331

            context = dict(
3332
                struct_type=self,
Stefan Behnel's avatar
Stefan Behnel committed
3333 3334
                var_entries=self.scope.var_entries,
                funcname=self.from_py_function,
Mark Florisson's avatar
Mark Florisson committed
3335
            )
3336 3337
            from .UtilityCode import CythonUtilityCode
            self._convert_from_py_code = CythonUtilityCode.load(
3338 3339
                "FromPyStructUtility" if self.is_struct else "FromPyUnionUtility",
                "CConvert.pyx",
3340 3341
                outer_module_scope=env.global_scope(),  # need access to types declared in module
                context=context)
Mark Florisson's avatar
Mark Florisson committed
3342 3343

        env.use_utility_code(self._convert_from_py_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3344
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3345

William Stein's avatar
William Stein committed
3346
    def __repr__(self):
Stefan Behnel's avatar
Stefan Behnel committed
3347 3348
        return "<CStructOrUnionType %s %s%s>" % (
            self.name, self.cname,
3349
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
3350

Robert Bradshaw's avatar
Robert Bradshaw committed
3351
    def declaration_code(self, entity_code,
Stefan Behnel's avatar
Stefan Behnel committed
3352
                         for_display=0, dll_linkage=None, pyrex=0):
3353 3354
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3355
        else:
3356 3357
            if self.typedef_flag:
                base_code = self.cname
William Stein's avatar
William Stein committed
3358
            else:
3359 3360 3361
                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
3362

3363
    def __eq__(self, other):
3364
        try:
Stefan Behnel's avatar
Stefan Behnel committed
3365 3366
            return (isinstance(other, CStructOrUnionType) and
                    self.name == other.name)
3367
        except AttributeError:
3368 3369 3370 3371 3372 3373 3374 3375 3376
            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
3377

Stefan Behnel's avatar
Stefan Behnel committed
3378
    def __hash__(self):
3379
        return hash(self.cname) ^ hash(self.kind)
Stefan Behnel's avatar
Stefan Behnel committed
3380

William Stein's avatar
William Stein committed
3381 3382
    def is_complete(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
3383

William Stein's avatar
William Stein committed
3384 3385 3386
    def attributes_known(self):
        return self.is_complete()

3387
    def can_be_complex(self):
3388
        # Does the struct consist of exactly two identical floats?
3389
        fields = self.scope.var_entries
3390 3391 3392
        if len(fields) != 2: return False
        a, b = fields
        return (a.type.is_float and b.type.is_float and
3393 3394
                a.type.empty_declaration_code() ==
                b.type.empty_declaration_code())
3395

3396 3397 3398 3399
    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
3400

3401 3402 3403 3404 3405
    def cast_code(self, expr_code):
        if self.is_struct:
            return expr_code
        return super(CStructOrUnionType, self).cast_code(expr_code)

3406
cpp_string_conversions = ("std::string",)
3407

3408 3409 3410 3411 3412 3413 3414 3415 3416
builtin_cpp_conversions = {
    # type                element template params
    "std::pair":          2,
    "std::vector":        1,
    "std::list":          1,
    "std::set":           1,
    "std::unordered_set": 1,
    "std::map":           2,
    "std::unordered_map": 2,
3417
    "std::complex":       1,
3418
}
3419

3420 3421 3422 3423
class CppClassType(CType):
    #  name          string
    #  cname         string
    #  scope         CppClassScope
Danilo Freitas's avatar
Danilo Freitas committed
3424
    #  templates     [string] or None
Robert Bradshaw's avatar
Robert Bradshaw committed
3425

3426 3427
    is_cpp_class = 1
    has_attributes = 1
3428
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3429
    namespace = None
Robert Bradshaw's avatar
Robert Bradshaw committed
3430

3431 3432 3433 3434
    # For struct-like declaration.
    kind = "struct"
    packed = False
    typedef_flag = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3435

3436 3437
    subtypes = ['templates']

3438
    def __init__(self, name, scope, cname, base_classes, templates=None, template_type=None):
3439 3440 3441
        self.name = name
        self.cname = cname
        self.scope = scope
DaniloFreitas's avatar
DaniloFreitas committed
3442
        self.base_classes = base_classes
DaniloFreitas's avatar
DaniloFreitas committed
3443
        self.operators = []
Danilo Freitas's avatar
Danilo Freitas committed
3444
        self.templates = templates
3445
        self.template_type = template_type
3446
        self.num_optional_templates = sum(is_optional_template_param(T) for T in templates or ())
Robert Bradshaw's avatar
Robert Bradshaw committed
3447 3448 3449 3450
        if templates:
            self.specializations = {tuple(zip(templates, templates)): self}
        else:
            self.specializations = {}
3451
        self.is_cpp_string = cname in cpp_string_conversions
3452

3453 3454
    def use_conversion_utility(self, from_or_to):
        pass
Robert Bradshaw's avatar
Robert Bradshaw committed
3455

3456 3457 3458 3459 3460 3461
    def maybe_unordered(self):
        if 'unordered' in self.cname:
            return 'unordered_'
        else:
            return ''

3462
    def can_coerce_from_pyobject(self, env):
3463 3464
        if self.cname in builtin_cpp_conversions:
            template_count = builtin_cpp_conversions[self.cname]
3465
            for ix, T in enumerate(self.templates or []):
3466
                if ix >= template_count:
3467 3468 3469 3470
                    break
                if T.is_pyobject or not T.can_coerce_from_pyobject(env):
                    return False
            return True
3471 3472 3473
        elif self.cname in cpp_string_conversions:
            return True
        return False
3474

3475 3476 3477
    def create_from_py_utility_code(self, env):
        if self.from_py_function is not None:
            return True
3478
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3479
            X = "XYZABC"
3480
            tags = []
3481
            context = {}
3482
            for ix, T in enumerate(self.templates or []):
3483 3484
                if ix >= builtin_cpp_conversions[self.cname]:
                    break
3485
                if T.is_pyobject or not T.create_from_py_utility_code(env):
3486 3487
                    return False
                tags.append(T.specialization_name())
3488 3489
                context[X[ix]] = T

3490 3491
            if self.cname in cpp_string_conversions:
                cls = 'string'
3492
                tags = type_identifier(self),
3493 3494
            else:
                cls = self.cname[5:]
3495
            cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
3496
            context.update({
3497 3498
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3499
                'type': self.cname,
3500
            })
3501
            from .UtilityCode import CythonUtilityCode
3502
            env.use_utility_code(CythonUtilityCode.load(
3503 3504
                cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx",
                context=context, compiler_directives=env.directives))
3505 3506
            self.from_py_function = cname
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3507

3508
    def can_coerce_to_pyobject(self, env):
3509 3510 3511 3512 3513 3514 3515 3516
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
            for ix, T in enumerate(self.templates or []):
                if ix >= builtin_cpp_conversions[self.cname]:
                    break
                if T.is_pyobject or not T.can_coerce_to_pyobject(env):
                    return False
            return True

3517

3518 3519 3520
    def create_to_py_utility_code(self, env):
        if self.to_py_function is not None:
            return True
3521
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3522
            X = "XYZABC"
3523
            tags = []
3524
            context = {}
3525
            for ix, T in enumerate(self.templates or []):
3526 3527
                if ix >= builtin_cpp_conversions[self.cname]:
                    break
3528 3529 3530
                if not T.create_to_py_utility_code(env):
                    return False
                tags.append(T.specialization_name())
3531 3532
                context[X[ix]] = T

3533 3534 3535
            if self.cname in cpp_string_conversions:
                cls = 'string'
                prefix = 'PyObject_'  # gets specialised by explicit type casts in CoerceToPyTypeNode
3536
                tags = type_identifier(self),
3537 3538 3539 3540
            else:
                cls = self.cname[5:]
                prefix = ''
            cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags))
3541
            context.update({
3542 3543
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3544
                'type': self.cname,
3545
            })
3546
            from .UtilityCode import CythonUtilityCode
3547
            env.use_utility_code(CythonUtilityCode.load(
3548 3549
                cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx",
                context=context, compiler_directives=env.directives))
3550 3551 3552
            self.to_py_function = cname
            return True

3553 3554 3555
    def is_template_type(self):
        return self.templates is not None and self.template_type is None

3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566
    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

3567
    def specialize_here(self, pos, template_values=None):
3568
        if not self.is_template_type():
Stefan Behnel's avatar
Stefan Behnel committed
3569 3570
            error(pos, "'%s' type is not a template" % self)
            return error_type
3571
        if len(self.templates) - self.num_optional_templates <= len(template_values) < len(self.templates):
3572
            num_defaults = len(self.templates) - len(template_values)
3573
            partial_specialization = self.declaration_code('', template_params=template_values)
3574 3575 3576 3577 3578 3579 3580 3581
            # Most of the time we don't need to declare anything typed to these
            # default template arguments, but when we do there's no way in C++
            # to reference this directly.  However, it is common convention to
            # provide a typedef in the template class that resolves to each
            # template type.  For now, allow the user to specify this name as
            # the template parameter.
            # TODO: Allow typedefs in cpp classes and search for it in this
            # classes scope as a concrete name we could use.
3582
            template_values = template_values + [
3583 3584 3585
                TemplatePlaceholderType(
                    "%s::%s" % (partial_specialization, param.name), True)
                for param in self.templates[-num_defaults:]]
3586
        if len(self.templates) != len(template_values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3587
            error(pos, "%s templated type receives %d arguments, got %d" %
3588 3589
                  (self.name, len(self.templates), len(template_values)))
            return error_type
3590 3591 3592 3593 3594 3595 3596 3597
        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
3598
        return self.specialize(dict(zip(self.templates, template_values)))
Robert Bradshaw's avatar
Robert Bradshaw committed
3599

3600
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3601
        if not self.templates and not self.namespace:
3602
            return self
Robert Bradshaw's avatar
Robert Bradshaw committed
3603 3604
        if self.templates is None:
            self.templates = []
3605
        key = tuple(values.items())
Robert Bradshaw's avatar
Robert Bradshaw committed
3606 3607
        if key in self.specializations:
            return self.specializations[key]
3608
        template_values = [t.specialize(values) for t in self.templates]
Robert Bradshaw's avatar
Robert Bradshaw committed
3609
        specialized = self.specializations[key] = \
3610
            CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3611 3612
        # Need to do these *after* self.specializations[key] is set
        # to avoid infinite recursion on circular references.
3613
        specialized.base_classes = [b.specialize(values) for b in self.base_classes]
Robert Bradshaw's avatar
Robert Bradshaw committed
3614 3615
        if self.namespace is not None:
            specialized.namespace = self.namespace.specialize(values)
3616
        specialized.scope = self.scope.specialize(values, specialized)
3617 3618 3619 3620 3621 3622 3623 3624
        if self.cname == 'std::vector':
          # vector<bool> is special cased in the C++ standard, and its
          # accessors do not necessarily return references to the underlying
          # elements (which may be bit-packed).
          # http://www.cplusplus.com/reference/vector/vector-bool/
          # Here we pretend that the various methods return bool values
          # (as the actual returned values are coercable to such, and
          # we don't support call expressions as lvalues).
3625 3626
          T = values.get(self.templates[0], None)
          if T and not T.is_fused and T.empty_declaration_code() == 'bool':
3627 3628 3629
            for bit_ref_returner in ('at', 'back', 'front'):
              if bit_ref_returner in specialized.scope.entries:
                specialized.scope.entries[bit_ref_returner].type.return_type = T
Robert Bradshaw's avatar
Robert Bradshaw committed
3630
        return specialized
3631

3632
    def deduce_template_params(self, actual):
3633 3634 3635 3636
        if actual.is_const:
            actual = actual.const_base_type
        if actual.is_reference:
            actual = actual.ref_base_type
3637 3638
        if self == actual:
            return {}
3639
        elif actual.is_cpp_class:
3640
            self_template_type = self
3641 3642
            while getattr(self_template_type, 'template_type', None):
                self_template_type = self_template_type.template_type
3643 3644 3645 3646 3647 3648
            def all_bases(cls):
                yield cls
                for parent in cls.base_classes:
                    for base in all_bases(parent):
                        yield base
            for actual_base in all_bases(actual):
3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659
                template_type = actual_base
                while getattr(template_type, 'template_type', None):
                    template_type = template_type.template_type
                    if (self_template_type.empty_declaration_code()
                            == template_type.empty_declaration_code()):
                        return reduce(
                            merge_template_deductions,
                            [formal_param.deduce_template_params(actual_param)
                             for (formal_param, actual_param)
                             in zip(self.templates, actual_base.templates)],
                            {})
3660
        else:
3661
            return {}
3662

3663
    def declaration_code(self, entity_code,
3664 3665 3666 3667
            for_display = 0, dll_linkage = None, pyrex = 0,
            template_params = None):
        if template_params is None:
            template_params = self.templates
Danilo Freitas's avatar
Danilo Freitas committed
3668
        if self.templates:
3669
            template_strings = [param.declaration_code('', for_display, None, pyrex)
3670
                                for param in template_params
3671
                                if not is_optional_template_param(param) and not param.is_fused]
3672 3673 3674
            if for_display:
                brackets = "[%s]"
            else:
3675
                brackets = "<%s> "
3676
            templates = brackets % ",".join(template_strings)
3677 3678
        else:
            templates = ""
3679 3680
        if pyrex or for_display:
            base_code = "%s%s" % (self.name, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3681
        else:
3682
            base_code = "%s%s" % (self.cname, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3683
            if self.namespace is not None:
3684
                base_code = "%s::%s" % (self.namespace.empty_declaration_code(), base_code)
3685 3686
            base_code = public_decl(base_code, dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
3687 3688

    def is_subclass(self, other_type):
3689 3690
        if self.same_as_resolved_type(other_type):
            return 1
3691 3692 3693
        for base_class in self.base_classes:
            if base_class.is_subclass(other_type):
                return 1
3694
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3695

Robert Bradshaw's avatar
Robert Bradshaw committed
3696 3697 3698 3699 3700 3701 3702 3703
    def subclass_dist(self, super_type):
        if self.same_as_resolved_type(super_type):
            return 0
        elif not self.base_classes:
            return float('inf')
        else:
            return 1 + min(b.subclass_dist(super_type) for b in self.base_classes)

3704 3705 3706 3707
    def same_as_resolved_type(self, other_type):
        if other_type.is_cpp_class:
            if self == other_type:
                return 1
3708 3709 3710 3711 3712
            # This messy logic is needed due to GH Issue #1852.
            elif (self.cname == other_type.cname and
                  (self.template_type and other_type.template_type
                   or self.templates
                   or other_type.templates)):
3713 3714
                if self.templates == other_type.templates:
                    return 1
3715
                for t1, t2 in zip(self.templates, other_type.templates):
3716 3717
                    if is_optional_template_param(t1) and is_optional_template_param(t2):
                      break
3718 3719 3720 3721
                    if not t1.same_as_resolved_type(t2):
                        return 0
                return 1
        return 0
3722

3723 3724
    def assignable_from_resolved_type(self, other_type):
        # TODO: handle operator=(...) here?
3725 3726
        if other_type is error_type:
            return True
3727 3728
        elif other_type.is_cpp_class:
            return other_type.is_subclass(self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3729

Robert Bradshaw's avatar
Robert Bradshaw committed
3730 3731 3732
    def attributes_known(self):
        return self.scope is not None

3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745
    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

3746 3747 3748 3749 3750
    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)

3751

3752
class TemplatePlaceholderType(CType):
Robert Bradshaw's avatar
Robert Bradshaw committed
3753

3754
    def __init__(self, name, optional=False):
Danilo Freitas's avatar
Danilo Freitas committed
3755
        self.name = name
3756
        self.optional = optional
Robert Bradshaw's avatar
Robert Bradshaw committed
3757 3758

    def declaration_code(self, entity_code,
3759
            for_display = 0, dll_linkage = None, pyrex = 0):
3760 3761 3762 3763
        if entity_code:
            return self.name + " " + entity_code
        else:
            return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3764

3765 3766 3767 3768 3769 3770
    def specialize(self, values):
        if self in values:
            return values[self]
        else:
            return self

Robert Bradshaw's avatar
Robert Bradshaw committed
3771 3772 3773
    def deduce_template_params(self, actual):
        return {self: actual}

3774 3775
    def same_as_resolved_type(self, other_type):
        if isinstance(other_type, TemplatePlaceholderType):
3776
            return self.name == other_type.name
3777 3778
        else:
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3779

3780 3781
    def __hash__(self):
        return hash(self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
3782

3783 3784 3785 3786 3787
    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
3788

Robert Bradshaw's avatar
Robert Bradshaw committed
3789 3790 3791 3792 3793 3794
    def __eq__(self, other):
        if isinstance(other, TemplatePlaceholderType):
            return self.name == other.name
        else:
            return False

3795 3796 3797
def is_optional_template_param(type):
    return isinstance(type, TemplatePlaceholderType) and type.optional

3798

3799
class CEnumType(CType):
William Stein's avatar
William Stein committed
3800 3801 3802
    #  name           string
    #  cname          string or None
    #  typedef_flag   boolean
3803
    #  values         [string], populated during declaration analysis
3804

William Stein's avatar
William Stein committed
3805
    is_enum = 1
3806 3807
    signed = 1
    rank = -1 # Ranks below any integer type
William Stein's avatar
William Stein committed
3808

3809
    def __init__(self, name, cname, typedef_flag, namespace=None):
William Stein's avatar
William Stein committed
3810 3811 3812 3813
        self.name = name
        self.cname = cname
        self.values = []
        self.typedef_flag = typedef_flag
3814
        self.namespace = namespace
3815
        self.default_value = "(%s) 0" % self.empty_declaration_code()
Robert Bradshaw's avatar
Robert Bradshaw committed
3816

3817 3818
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3819

William Stein's avatar
William Stein committed
3820
    def __repr__(self):
3821 3822
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
3823 3824

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
3825
            for_display = 0, dll_linkage = None, pyrex = 0):
3826 3827
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3828
        else:
3829 3830 3831 3832
            if self.namespace:
                base_code = "%s::%s" % (
                    self.namespace.empty_declaration_code(), self.cname)
            elif self.typedef_flag:
3833
                base_code = self.cname
William Stein's avatar
William Stein committed
3834
            else:
3835 3836 3837
                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
3838

3839 3840 3841 3842 3843 3844 3845 3846
    def specialize(self, values):
        if self.namespace:
            namespace = self.namespace.specialize(values)
            if namespace != self.namespace:
                return CEnumType(
                    self.name, self.cname, self.typedef_flag, namespace)
        return self

3847 3848 3849 3850 3851 3852
    def can_coerce_to_pyobject(self, env):
        return True

    def can_coerce_from_pyobject(self, env):
        return True

3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868
    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

3869 3870 3871 3872 3873 3874 3875 3876 3877 3878
    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))

3879 3880 3881 3882 3883 3884 3885 3886
    def create_type_wrapper(self, env):
        from .UtilityCode import CythonUtilityCode
        env.use_utility_code(CythonUtilityCode.load(
            "EnumType", "CpdefEnums.pyx",
            context={"name": self.name,
                     "items": tuple(self.values)},
            outer_module_scope=env.global_scope()))

3887

3888 3889 3890
class CTupleType(CType):
    # components [PyrexType]

Robert Bradshaw's avatar
Robert Bradshaw committed
3891 3892
    is_ctuple = True

3893 3894 3895
    def __init__(self, cname, components):
        self.cname = cname
        self.components = components
Robert Bradshaw's avatar
Robert Bradshaw committed
3896
        self.size = len(components)
3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912
        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)

3913 3914 3915 3916 3917 3918
    def can_coerce_to_pyobject(self, env):
        for component in self.components:
            if not component.can_coerce_to_pyobject(env):
                return False
        return True

3919 3920 3921 3922 3923 3924
    def can_coerce_from_pyobject(self, env):
        for component in self.components:
            if not component.can_coerce_from_pyobject(env):
                return False
        return True

3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936
    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(
3937
                struct_type_decl=self.empty_declaration_code(),
3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959
                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(
3960
                struct_type_decl=self.empty_declaration_code(),
3961 3962 3963 3964 3965 3966 3967 3968 3969 3970
                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

3971

3972
def c_tuple_type(components):
Robert Bradshaw's avatar
Robert Bradshaw committed
3973
    components = tuple(components)
3974 3975
    cname = Naming.ctuple_type_prefix + type_list_identifier(components)
    tuple_type = CTupleType(cname, components)
3976
    return tuple_type
3977 3978


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

Robert Bradshaw's avatar
Robert Bradshaw committed
3982
    is_unspecified = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
3983 3984

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

Robert Bradshaw's avatar
Robert Bradshaw committed
3988 3989
    def same_as_resolved_type(self, other_type):
        return False
Robert Bradshaw's avatar
Robert Bradshaw committed
3990

Robert Bradshaw's avatar
Robert Bradshaw committed
3991

William Stein's avatar
William Stein committed
3992 3993
class ErrorType(PyrexType):
    # Used to prevent propagation of error messages.
Robert Bradshaw's avatar
Robert Bradshaw committed
3994

William Stein's avatar
William Stein committed
3995 3996
    is_error = 1
    exception_value = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
3997
    exception_check    = 0
William Stein's avatar
William Stein committed
3998 3999
    to_py_function = "dummy"
    from_py_function = "dummy"
Robert Bradshaw's avatar
Robert Bradshaw committed
4000

4001 4002
    def create_to_py_utility_code(self, env):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
4003

4004
    def create_from_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
4005
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
4006 4007

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

William Stein's avatar
William Stein committed
4011 4012
    def same_as_resolved_type(self, other_type):
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
4013

4014 4015
    def error_condition(self, result_code):
        return "dummy"
William Stein's avatar
William Stein committed
4016 4017


4018 4019 4020
rank_to_type_name = (
    "char",         # 0
    "short",        # 1
4021 4022 4023 4024 4025 4026
    "int",          # 2
    "long",         # 3
    "PY_LONG_LONG", # 4
    "float",        # 5
    "double",       # 6
    "long double",  # 7
4027 4028
)

4029 4030 4031 4032
_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')
4033 4034 4035
UNSIGNED = 0
SIGNED = 2

4036 4037
error_type =    ErrorType()
unspecified_type = UnspecifiedType()
4038

William Stein's avatar
William Stein committed
4039 4040
py_object_type = PyObjectType()

4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053
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
4054

4055 4056 4057 4058 4059 4060 4061 4062 4063
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
4064

4065 4066 4067
c_float_complex_type =      CComplexType(c_float_type)
c_double_complex_type =     CComplexType(c_double_type)
c_longdouble_complex_type = CComplexType(c_longdouble_type)
4068

4069 4070 4071 4072
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
4073
c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
4074
c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
4075 4076 4077
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
4078
c_ptrdiff_t_type =   CPtrdiffTType(RANK_LONG+0.75, SIGNED)
4079

William Stein's avatar
William Stein committed
4080
c_null_ptr_type =     CNullPtrType(c_void_type)
4081 4082
c_void_ptr_type =     CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
4083
c_char_ptr_type =     CPtrType(c_char_type)
4084
c_const_char_ptr_type = CPtrType(CConstType(c_char_type))
4085
c_uchar_ptr_type =    CPtrType(c_uchar_type)
4086
c_const_uchar_ptr_type = CPtrType(CConstType(c_uchar_type))
William Stein's avatar
William Stein committed
4087 4088
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
4089
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
4090
c_const_py_unicode_ptr_type = CPtrType(CConstType(c_py_unicode_type))
4091
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
4092
c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
4093
c_size_t_ptr_type =  CPtrType(c_size_t_type)
William Stein's avatar
William Stein committed
4094

4095 4096 4097 4098
# 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)
4099

4100
# the Py_buffer type is defined in Builtin.py
4101 4102
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
4103

4104 4105 4106
# 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
4107 4108
cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type],
                             name="integral")
4109 4110
# Omitting long double as it might be slow
cy_floating_type = FusedType([c_float_type, c_double_type], name="floating")
4111 4112 4113 4114
cy_numeric_type = FusedType([c_short_type,
                             c_int_type,
                             c_long_type,
                             c_float_type,
4115
                             c_double_type,
4116
                             c_float_complex_type,
4117 4118
                             c_double_complex_type], name="numeric")

4119 4120 4121 4122 4123 4124 4125 4126
# 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")

4127 4128
cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
                                      None, 0, "__pyx_memoryview_obj")
4129

4130 4131
memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
                                          None, 1, "__Pyx_memviewslice")
4132

William Stein's avatar
William Stein committed
4133
modifiers_and_name_to_type = {
4134 4135 4136 4137 4138
    #(signed, longness, name) : type
    (0,  0, "char"): c_uchar_type,
    (1,  0, "char"): c_char_type,
    (2,  0, "char"): c_schar_type,

4139
    (0, -1, "int"): c_ushort_type,
4140 4141 4142 4143
    (0,  0, "int"): c_uint_type,
    (0,  1, "int"): c_ulong_type,
    (0,  2, "int"): c_ulonglong_type,

4144
    (1, -1, "int"): c_short_type,
4145 4146 4147 4148
    (1,  0, "int"): c_int_type,
    (1,  1, "int"): c_long_type,
    (1,  2, "int"): c_longlong_type,

4149
    (2, -1, "int"): c_sshort_type,
4150 4151 4152 4153 4154 4155 4156
    (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,
4157

4158
    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
4159 4160 4161 4162 4163 4164
    (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,
4165 4166 4167

    (1,  0, "bint"):       c_bint_type,
    (0,  0, "Py_UNICODE"): c_py_unicode_type,
Stefan Behnel's avatar
Stefan Behnel committed
4168
    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
4169
    (2,  0, "Py_hash_t"):  c_py_hash_t_type,
4170 4171 4172
    (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,
4173
    (2,  0, "ptrdiff_t") : c_ptrdiff_t_type,
4174

4175
    (1,  0, "object"): py_object_type,
William Stein's avatar
William Stein committed
4176 4177
}

4178 4179
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
4180
    # evidence suggests that the below is all that's allowed.
4181 4182
    if src_type.is_numeric:
        if dst_type.same_as(c_int_type):
4183 4184 4185 4186
            unsigned = (not src_type.signed)
            return (src_type.is_enum or
                    (src_type.is_int and
                     unsigned + src_type.rank < dst_type.rank))
4187 4188 4189 4190
        elif dst_type.same_as(c_double_type):
            return src_type.is_float and src_type.rank <= dst_type.rank
    return False

Robert Bradshaw's avatar
Robert Bradshaw committed
4191
def best_match(arg_types, functions, pos=None, env=None, args=None):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
4192
    """
4193 4194 4195 4196 4197 4198 4199 4200 4201 4202
    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
4203
      * promotions
4204 4205 4206 4207 4208 4209 4210 4211
      * 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
4212
    """
Robert Bradshaw's avatar
Robert Bradshaw committed
4213
    # TODO: args should be a list of types, not a list of Nodes.
4214
    actual_nargs = len(arg_types)
4215 4216 4217

    candidates = []
    errors = []
4218
    for func in functions:
4219
        error_mesg = ""
4220 4221 4222
        func_type = func.type
        if func_type.is_ptr:
            func_type = func_type.base_type
4223 4224
        # Check function type
        if not func_type.is_cfunction:
4225
            if not func_type.is_error and pos is not None:
4226 4227 4228
                error_mesg = "Calling non-function type '%s'" % func_type
            errors.append((func, error_mesg))
            continue
4229 4230 4231
        # Check no. of args
        max_nargs = len(func_type.args)
        min_nargs = max_nargs - func_type.optional_arg_count
4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243
        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
4244 4245 4246 4247 4248
        if func_type.templates:
            deductions = reduce(
                merge_template_deductions,
                [pattern.type.deduce_template_params(actual) for (pattern, actual) in zip(func_type.args, arg_types)],
                {})
4249
            if deductions is None:
Joe Jevnik's avatar
Joe Jevnik committed
4250
                errors.append((func, "Unable to deduce type parameters for %s given (%s)" % (func_type, ', '.join(map(str, arg_types)))))
4251 4252 4253 4254 4255
            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]
4256
                from .Symtab import Entry
4257 4258
                specialization = Entry(
                    name = func.name + "[%s]" % ",".join([str(t) for t in type_list]),
4259
                    cname = func.cname + "<%s>" % ",".join([t.empty_declaration_code() for t in type_list]),
4260 4261 4262
                    type = func_type.specialize(deductions),
                    pos = func.pos)
                candidates.append((specialization, specialization.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4263 4264
        else:
            candidates.append((func, func_type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4265

4266 4267
    # Optimize the most common case of no overloading...
    if len(candidates) == 1:
4268
        return candidates[0][0]
4269
    elif len(candidates) == 0:
4270
        if pos is not None:
4271 4272 4273
            func, errmsg = errors[0]
            if len(errors) == 1 or [1 for func, e in errors if e == errmsg]:
                error(pos, errmsg)
4274 4275
            else:
                error(pos, "no suitable method found")
4276
        return None
Robert Bradshaw's avatar
Robert Bradshaw committed
4277

4278 4279
    possibilities = []
    bad_types = []
4280
    needed_coercions = {}
Mark Florisson's avatar
merge  
Mark Florisson committed
4281

4282
    for index, (func, func_type) in enumerate(candidates):
Robert Bradshaw's avatar
Robert Bradshaw committed
4283
        score = [0,0,0,0,0,0,0]
Robert Bradshaw's avatar
Robert Bradshaw committed
4284 4285
        for i in range(min(actual_nargs, len(func_type.args))):
            src_type = arg_types[i]
4286
            dst_type = func_type.args[i].type
4287 4288 4289

            assignable = dst_type.assignable_from(src_type)

4290
            # Now take care of unprefixed string literals. So when you call a cdef
4291 4292 4293
            # 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
4294 4295 4296 4297 4298 4299 4300 4301 4302
            if not assignable:
                c_src_type = None
                if src_type.is_pyobject:
                    if src_type.is_builtin_type and src_type.name == 'str' and dst_type.resolve().is_string:
                        c_src_type = dst_type.resolve()
                    else:
                        c_src_type = src_type.default_coerced_ctype()
                elif src_type.is_pythran_expr:
                        c_src_type = src_type.org_buffer
4303

4304
                if c_src_type is not None:
4305 4306 4307
                    assignable = dst_type.assignable_from(c_src_type)
                    if assignable:
                        src_type = c_src_type
Stefan Behnel's avatar
Stefan Behnel committed
4308
                        needed_coercions[func] = (i, dst_type)
4309 4310

            if assignable:
Robert Bradshaw's avatar
Robert Bradshaw committed
4311
                if src_type == dst_type or dst_type.same_as(src_type):
Stefan Behnel's avatar
Stefan Behnel committed
4312
                    pass  # score 0
4313
                elif func_type.is_strict_signature:
Stefan Behnel's avatar
Stefan Behnel committed
4314
                    break  # exact match requested but not found
4315 4316
                elif is_promotion(src_type, dst_type):
                    score[2] += 1
4317 4318
                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
4319
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
4320
                                    (src_type.rank + (not src_type.signed))) + 1
Robert Bradshaw's avatar
Robert Bradshaw committed
4321 4322 4323 4324 4325 4326 4327
                elif dst_type.is_ptr and src_type.is_ptr:
                    if dst_type.base_type == c_void_type:
                        score[4] += 1
                    elif src_type.base_type.is_cpp_class and src_type.base_type.is_subclass(dst_type.base_type):
                        score[6] += src_type.base_type.subclass_dist(dst_type.base_type)
                    else:
                        score[5] += 1
4328 4329 4330 4331 4332
                elif not src_type.is_pyobject:
                    score[1] += 1
                else:
                    score[0] += 1
            else:
Stefan Behnel's avatar
Stefan Behnel committed
4333
                error_mesg = "Invalid conversion from '%s' to '%s'" % (src_type, dst_type)
4334
                bad_types.append((func, error_mesg))
4335 4336
                break
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4337
            possibilities.append((score, index, func))  # so we can sort it
4338

4339
    if possibilities:
4340
        possibilities.sort()
4341 4342 4343 4344 4345 4346 4347
        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
4348

Mark Florisson's avatar
merge  
Mark Florisson committed
4349
        function = possibilities[0][-1]
4350 4351 4352 4353 4354 4355 4356

        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

4357
    if pos is not None:
4358 4359
        if len(bad_types) == 1:
            error(pos, bad_types[0][1])
4360
        else:
4361
            error(pos, "no suitable method found")
4362

4363 4364
    return None

Robert Bradshaw's avatar
Robert Bradshaw committed
4365 4366 4367 4368
def merge_template_deductions(a, b):
    if a is None or b is None:
        return None
    all = a
4369
    for param, value in b.items():
Robert Bradshaw's avatar
Robert Bradshaw committed
4370 4371 4372 4373 4374 4375 4376
        if param in all:
            if a[param] != b[param]:
                return None
        else:
            all[param] = value
    return all

4377

William Stein's avatar
William Stein committed
4378
def widest_numeric_type(type1, type2):
Stefan Behnel's avatar
Stefan Behnel committed
4379 4380
    """Given two numeric types, return the narrowest type encompassing both of them.
    """
4381 4382 4383 4384
    if type1.is_reference:
        type1 = type1.ref_base_type
    if type2.is_reference:
        type2 = type2.ref_base_type
4385 4386 4387 4388
    if type1.is_const:
        type1 = type1.const_base_type
    if type2.is_const:
        type2 = type2.const_base_type
4389
    if type1 == type2:
4390 4391 4392 4393 4394 4395 4396 4397
        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
4398
                real_type(type1),
4399 4400 4401 4402 4403 4404 4405 4406 4407
                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
4408 4409 4410 4411
    elif type1.signed > type2.signed:
        widest_type = type2
    elif type1.is_typedef > type2.is_typedef:
        widest_type = type1
4412
    else:
4413 4414
        widest_type = type2
    return widest_type
William Stein's avatar
William Stein committed
4415

4416 4417 4418 4419 4420

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


4421 4422 4423 4424 4425 4426 4427 4428
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.
4429 4430 4431 4432 4433
    if type1.is_reference ^ type2.is_reference:
        if type1.is_reference:
            type1 = type1.ref_base_type
        else:
            type2 = type2.ref_base_type
4434 4435 4436 4437 4438
    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
4439
        # type so that we do not lose the ability to coerce to a
4440
        # Python bool if we have to.
Robert Bradshaw's avatar
Robert Bradshaw committed
4441
        return py_object_type
4442 4443
    span_type = _spanning_type(type1, type2)
    if span_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
4444
        return error_type
4445 4446 4447 4448 4449 4450 4451 4452
    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
4453
        return type1
4454 4455
    elif type1 is py_object_type or type2 is py_object_type:
        return py_object_type
4456 4457 4458
    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
4459 4460 4461 4462 4463 4464 4465
    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
4466
        return widest_numeric_type(type1, type2)
4467 4468 4469 4470
    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)
4471
    elif type1.is_extension_type and type2.is_extension_type:
4472 4473 4474
        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
4475
    elif type1.assignable_from(type2):
4476 4477 4478
        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
4479
        return type1
4480
    elif type2.assignable_from(type1):
4481 4482 4483
        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
4484
        return type2
4485
    elif type1.is_ptr and type2.is_ptr:
4486 4487 4488 4489
        if type1.base_type.is_cpp_class and type2.base_type.is_cpp_class:
            common_base = widest_cpp_type(type1.base_type, type2.base_type)
            if common_base:
                return CPtrType(common_base)
4490 4491
        # incompatible pointers, void* will do as a result
        return c_void_ptr_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4492
    else:
4493 4494 4495 4496
        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
4497
        return py_object_type
4498 4499 4500 4501 4502 4503 4504 4505 4506
    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

4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524
def widest_cpp_type(type1, type2):
    @cached_function
    def bases(type):
        all = set()
        for base in type.base_classes:
            all.add(base)
            all.update(bases(base))
        return all
    common_bases = bases(type1).intersection(bases(type2))
    common_bases_bases = reduce(set.union, [bases(b) for b in common_bases], set())
    candidates = [b for b in common_bases if b not in common_bases_bases]
    if len(candidates) == 1:
        return candidates[0]
    else:
        # Fall back to void* for now.
        return None


William Stein's avatar
William Stein committed
4525 4526 4527 4528
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
4529

4530 4531 4532 4533 4534 4535 4536 4537 4538 4539
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)
4540 4541 4542 4543 4544 4545 4546
    #
    basic_type = simple_c_type(1, 0, name)
    if basic_type:
        return basic_type
    #
    signed = 1
    longness = 0
4547 4548
    if name == 'Py_UNICODE':
        signed = 0
Stefan Behnel's avatar
Stefan Behnel committed
4549 4550
    elif name == 'Py_UCS4':
        signed = 0
4551 4552
    elif name == 'Py_hash_t':
        signed = 2
4553 4554 4555
    elif name == 'Py_ssize_t':
        signed = 2
    elif name == 'ssize_t':
4556 4557 4558
        signed = 2
    elif name == 'size_t':
        signed = 0
4559
    else:
4560 4561 4562
        if name.startswith('u'):
            name = name[1:]
            signed = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
4563
        elif (name.startswith('s') and
4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576
              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
4577 4578 4579

def c_array_type(base_type, size):
    # Construct a C array type.
4580
    if base_type is error_type:
4581
        return error_type
William Stein's avatar
William Stein committed
4582 4583 4584 4585 4586
    else:
        return CArrayType(base_type, size)

def c_ptr_type(base_type):
    # Construct a C pointer type.
4587
    if base_type is error_type:
4588
        return error_type
4589 4590
    elif base_type.is_reference:
        return CPtrType(base_type.ref_base_type)
William Stein's avatar
William Stein committed
4591 4592 4593
    else:
        return CPtrType(base_type)

Danilo Freitas's avatar
Danilo Freitas committed
4594 4595
def c_ref_type(base_type):
    # Construct a C reference type
4596
    if base_type is error_type:
Danilo Freitas's avatar
Danilo Freitas committed
4597 4598 4599
        return error_type
    else:
        return CReferenceType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
4600 4601 4602 4603 4604 4605 4606

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
4607 4608 4609

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

William Stein's avatar
William Stein committed
4611 4612 4613 4614 4615 4616 4617
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.
4618 4619 4620 4621 4622 4623 4624
    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
4625 4626 4627
    else:
        #print "typecast: to", to_type, "from", from_type ###
        return to_type.cast_code(expr_code)
4628 4629 4630 4631 4632 4633

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

_type_identifier_cache = {}
def type_identifier(type):
4634
    decl = type.empty_declaration_code()
4635 4636 4637 4638 4639 4640 4641
    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
4642
                    .replace('const ', '__const_')
4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662
                    .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])