PyrexTypes.py 168 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
    #  has_attributes        boolean     Has C dot-selectable attributes
195 196
    #  default_value         string      Initial value that can be assigned before first user assignment.
    #  declaration_value     string      The value statically assigned on declaration (if any).
197
    #  entry                 Entry       The Entry for this type
William Stein's avatar
William Stein committed
198
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
199
    #  declaration_code(entity_code,
William Stein's avatar
William Stein committed
200 201 202 203 204 205 206 207 208
    #      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'
209
    #      statement of a Cython include file.
William Stein's avatar
William Stein committed
210 211 212 213 214 215 216 217 218 219
    #
    #  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():
220
    #    Coerces array and C function types into pointer type for use as
William Stein's avatar
William Stein committed
221 222
    #    a formal argument type.
    #
Robert Bradshaw's avatar
Robert Bradshaw committed
223

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

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

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

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

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

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

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

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

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

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

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

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

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

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

306 307 308 309 310 311
    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

312 313
    def global_init_code(self, entry, code):
        # abstract
314
        pass
315

316 317
    def needs_nonecheck(self):
        return 0
318

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
    def _assign_from_py_code(self, source_code, result_code, error_pos, code,
                             from_py_function=None, error_condition=None, extra_args=None):
        args = ', ' + ', '.join('%s' % arg for arg in extra_args) if extra_args else ''
        convert_call = "%s(%s%s)" % (
            from_py_function or self.from_py_function,
            source_code,
            args,
        )
        if self.is_enum:
            convert_call = typecast(self, c_long_type, convert_call)
        return '%s = %s; %s' % (
            result_code,
            convert_call,
            code.error_goto_if(error_condition or self.error_condition(result_code), error_pos))

334

335 336
def public_decl(base_code, dll_linkage):
    if dll_linkage:
337
        return "%s(%s)" % (dll_linkage, base_code.replace(',', ' __PYX_COMMA '))
338 339
    else:
        return base_code
Robert Bradshaw's avatar
Robert Bradshaw committed
340

341
def create_typedef_type(name, base_type, cname, is_external=0, namespace=None):
342 343
    is_fused = base_type.is_fused
    if base_type.is_complex or is_fused:
344
        if is_external:
345 346 347 348 349 350 351
            if is_fused:
                msg = "Fused"
            else:
                msg = "Complex"

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

352 353
        return base_type
    else:
354
        return CTypedefType(name, base_type, cname, is_external, namespace)
355

356

357
class CTypedefType(BaseType):
William Stein's avatar
William Stein committed
358
    #
359
    #  Pseudo-type defined with a ctypedef statement in a
360 361 362
    #  '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
363
    #
364
    #  qualified_name      string
365
    #  typedef_name        string
366 367
    #  typedef_cname       string
    #  typedef_base_type   PyrexType
368
    #  typedef_is_external bool
Robert Bradshaw's avatar
Robert Bradshaw committed
369

370
    is_typedef = 1
371
    typedef_is_external = 0
372 373 374

    to_py_utility_code = None
    from_py_utility_code = None
375 376

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

378
    def __init__(self, name, base_type, cname, is_external=0, namespace=None):
379
        assert not base_type.is_complex
380
        self.typedef_name = name
William Stein's avatar
William Stein committed
381 382
        self.typedef_cname = cname
        self.typedef_base_type = base_type
383
        self.typedef_is_external = is_external
384
        self.typedef_namespace = namespace
Robert Bradshaw's avatar
Robert Bradshaw committed
385

386 387 388
    def invalid_value(self):
        return self.typedef_base_type.invalid_value()

William Stein's avatar
William Stein committed
389 390
    def resolve(self):
        return self.typedef_base_type.resolve()
Robert Bradshaw's avatar
Robert Bradshaw committed
391 392

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
393
            for_display = 0, dll_linkage = None, pyrex = 0):
394
        if pyrex or for_display:
395
            base_code = self.typedef_name
396
        else:
397
            base_code = public_decl(self.typedef_cname, dll_linkage)
398 399
        if self.typedef_namespace is not None and not pyrex:
            base_code = "%s::%s" % (self.typedef_namespace.empty_declaration_code(), base_code)
400
        return self.base_declaration_code(base_code, entity_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
401

402 403 404
    def as_argument_type(self):
        return self

405 406
    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
407
        # For example, the gmp mpz_t.
408 409 410
        if self.typedef_base_type.is_array:
            base_type = self.typedef_base_type.base_type
            return CPtrType(base_type).cast_code(expr_code)
411 412
        else:
            return BaseType.cast_code(self, expr_code)
413

Robert Bradshaw's avatar
Robert Bradshaw committed
414 415 416 417 418 419
    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:
420 421
            return create_typedef_type(self.typedef_name, base_type, self.typedef_cname,
                                0, namespace)
Robert Bradshaw's avatar
Robert Bradshaw committed
422

423 424
    def __repr__(self):
        return "<CTypedefType %s>" % self.typedef_cname
Robert Bradshaw's avatar
Robert Bradshaw committed
425

William Stein's avatar
William Stein committed
426
    def __str__(self):
427
        return self.typedef_name
428 429 430

    def _create_utility_code(self, template_utility_code,
                             template_function_name):
431
        type_name = type_identifier(self.typedef_cname)
432 433 434 435 436 437 438 439 440 441
        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
442
                if type(base_type) is CIntType:
443
                    self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
444
                    env.use_utility_code(TempitaUtilityCode.load_cached(
445
                        "CIntToPy", "TypeConversion.c",
446
                        context={"TYPE": self.empty_declaration_code(),
447
                                 "TO_PY_FUNCTION": self.to_py_function}))
448
                    return True
449 450 451 452 453
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
                    pass
454 455 456 457 458 459 460 461 462 463 464
                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
465 466 467 468 469 470 471 472 473 474
            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
475
                if type(base_type) is CIntType:
476
                    self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
477
                    env.use_utility_code(TempitaUtilityCode.load_cached(
478
                        "CIntFromPy", "TypeConversion.c",
479
                        context={"TYPE": self.empty_declaration_code(),
480
                                 "FROM_PY_FUNCTION": self.from_py_function}))
481
                    return True
482 483 484 485
                elif base_type.is_float:
                    pass # XXX implement!
                elif base_type.is_complex:
                    pass # XXX implement!
486 487 488 489 490 491 492 493 494 495 496
                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
497 498 499 500 501 502
            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)

503 504 505 506 507 508 509 510 511
    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):
        return self.typedef_base_type.from_py_call_code(
512 513 514 515
            source_code, result_code, error_pos, code,
            from_py_function or self.from_py_function,
            error_condition or self.error_condition(result_code)
        )
516

517
    def overflow_check_binop(self, binop, env, const_rhs=False):
518
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
519
        type = self.empty_declaration_code()
520
        name = self.specialization_name()
521
        if binop == "lshift":
522
            env.use_utility_code(TempitaUtilityCode.load_cached(
523 524
                "LeftShift", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
525 526 527 528
        else:
            if const_rhs:
                binop += "_const"
            _load_overflow_base(env)
529
            env.use_utility_code(TempitaUtilityCode.load_cached(
530 531
                "SizeCheck", "Overflow.c",
                context={'TYPE': type, 'NAME': name}))
532
            env.use_utility_code(TempitaUtilityCode.load_cached(
533 534
                "Binop", "Overflow.c",
                context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
535 536
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

537 538 539
    def error_condition(self, result_code):
        if self.typedef_is_external:
            if self.exception_value:
540 541
                condition = "(%s == %s)" % (
                    result_code, self.cast_code(self.exception_value))
542 543 544 545 546 547
                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
548 549 550
    def __getattr__(self, name):
        return getattr(self.typedef_base_type, name)

551 552
    def py_type_name(self):
        return self.typedef_base_type.py_type_name()
553

554 555 556
    def can_coerce_to_pyobject(self, env):
        return self.typedef_base_type.can_coerce_to_pyobject(env)

557 558 559
    def can_coerce_from_pyobject(self, env):
        return self.typedef_base_type.can_coerce_from_pyobject(env)

560

561
class MemoryViewSliceType(PyrexType):
562

563
    is_memoryviewslice = 1
Kurt Smith's avatar
Kurt Smith committed
564

565 566 567
    has_attributes = 1
    scope = None

Stefan Behnel's avatar
Stefan Behnel committed
568
    # These are special cased in Defnode
569 570 571 572
    from_py_function = None
    to_py_function = None

    exception_value = None
573
    exception_check = True
574

575 576
    subtypes = ['dtype']

577
    def __init__(self, base_dtype, axes):
Stefan Behnel's avatar
Stefan Behnel committed
578
        """
579
        MemoryViewSliceType(base, axes)
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609

        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
610
        """
611
        from . import Buffer, MemoryView
612

Kurt Smith's avatar
Kurt Smith committed
613
        self.dtype = base_dtype
614
        self.axes = axes
615
        self.ndim = len(axes)
616
        self.flags = MemoryView.get_buf_flags(self.axes)
617

618 619 620
        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)

621
        self.mode = MemoryView.get_mode(axes)
622
        self.writable_needed = False
623

624
        if not self.dtype.is_fused:
625
            self.dtype_name = Buffer.mangle_dtype_name(self.dtype)
626

627 628 629
    def __hash__(self):
        return hash(self.__class__) ^ hash(self.dtype) ^ hash(tuple(self.axes))

630 631 632 633 634
    def __eq__(self, other):
        if isinstance(other, BaseType):
            return self.same_as_resolved_type(other)
        else:
            return False
635

636 637
    def same_as_resolved_type(self, other_type):
        return ((other_type.is_memoryviewslice and
638
            self.writable_needed == other_type.writable_needed and
639 640 641 642
            self.dtype.same_as(other_type.dtype) and
            self.axes == other_type.axes) or
            other_type is error_type)

643 644 645
    def needs_nonecheck(self):
        return True

Kurt Smith's avatar
Kurt Smith committed
646
    def is_complete(self):
647
        # incomplete since the underlying struct doesn't have a cython.memoryview object.
Kurt Smith's avatar
Kurt Smith committed
648 649 650 651
        return 0

    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
652 653 654
        # XXX: we put these guards in for now...
        assert not pyrex
        assert not dll_linkage
655
        from . import MemoryView
656
        return self.base_declaration_code(
657
                MemoryView.memviewslice_cname,
658
                entity_code)
Kurt Smith's avatar
Kurt Smith committed
659

660 661
    def attributes_known(self):
        if self.scope is None:
662
            from . import Symtab
663

664 665
            self.scope = scope = Symtab.CClassScope(
                    'mvs_class_'+self.specialization_suffix(),
666 667
                    None,
                    visibility='extern')
668 669

            scope.parent_type = self
670
            scope.directives = {}
671

672 673 674 675 676
            scope.declare_var('_data', c_char_ptr_type, None,
                              cname='data', is_cdef=1)

        return True

677
    def declare_attribute(self, attribute, env, pos):
678
        from . import MemoryView, Options
679 680

        scope = self.scope
681

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

690
        elif attribute == 'strides':
691 692
            scope.declare_var('strides',
                    c_array_type(c_py_ssize_t_type,
693 694
                                 Options.buffer_max_dims),
                    pos,
695 696 697
                    cname='strides',
                    is_cdef=1)

698
        elif attribute == 'suboffsets':
699 700
            scope.declare_var('suboffsets',
                    c_array_type(c_py_ssize_t_type,
701 702
                                 Options.buffer_max_dims),
                    pos,
703 704 705
                    cname='suboffsets',
                    is_cdef=1)

706
        elif attribute in ("copy", "copy_fortran"):
707
            ndim = len(self.axes)
708

709 710 711 712
            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)
713

714 715
            to_memview_c = MemoryViewSliceType(self.dtype, to_axes_c)
            to_memview_f = MemoryViewSliceType(self.dtype, to_axes_f)
716

717 718
            for to_memview, cython_name in [(to_memview_c, "copy"),
                                            (to_memview_f, "copy_fortran")]:
719 720 721 722 723 724 725 726 727
                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)
728

729 730
                utility = MemoryView.get_copy_new_utility(pos, self, to_memview)
                env.use_utility_code(utility)
731

732 733
            MemoryView.use_cython_array_utility_code(env)

734
        elif attribute in ("is_c_contig", "is_f_contig"):
735
            # is_c_contig and is_f_contig functions
736
            for (c_or_f, cython_name) in (('C', 'is_c_contig'), ('F', 'is_f_contig')):
737

738
                is_contig_name = MemoryView.get_is_contig_func_name(c_or_f, self.ndim)
739

Mark Florisson's avatar
Mark Florisson committed
740
                cfunctype = CFuncType(
741
                        return_type=c_bint_type,
Mark Florisson's avatar
Mark Florisson committed
742 743 744 745
                        args=[CFuncTypeArg("memviewslice", self, None)],
                        exception_value="-1",
                )

746
                entry = scope.declare_cfunction(cython_name,
Mark Florisson's avatar
Mark Florisson committed
747
                            cfunctype,
748 749 750
                            pos=pos,
                            defining=1,
                            cname=is_contig_name)
751

752
                entry.utility_code_definition = MemoryView.get_is_contig_utility(c_or_f, self.ndim)
753

754
        return True
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
    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

785 786 787 788
        if self.writable_needed and not dst.writable_needed:
            return False

        src_dtype, dst_dtype = src.dtype, dst.dtype
789 790
        if dst_dtype.is_const:
            # Requesting read-only views is always ok => consider only the non-const base type.
791
            dst_dtype = dst_dtype.const_base_type
792 793 794
            if src_dtype.is_const:
                # When assigning between read-only views, compare only the non-const base types.
                src_dtype = src_dtype.const_base_type
795 796

        if src_dtype != dst_dtype:
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 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
            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])

859
    def specialization_name(self):
860 861 862
        return '%s_%s' % (
            super(MemoryViewSliceType,self).specialization_name(),
            self.specialization_suffix())
863

864
    def specialization_suffix(self):
865
        return "%s_%s" % (self.axes_to_name(), self.dtype_name)
866

867 868 869
    def can_coerce_to_pyobject(self, env):
        return True

870 871 872
    def can_coerce_from_pyobject(self, env):
        return True

Mark Florisson's avatar
Mark Florisson committed
873 874 875
    def check_for_null_code(self, cname):
        return cname + '.memview'

876
    def create_from_py_utility_code(self, env):
877
        from . import MemoryView, Buffer
878 879 880

        # We don't have 'code', so use a LazyUtilityCode with a callback.
        def lazy_utility_callback(code):
881
            context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype)
882
            return TempitaUtilityCode.load(
883
                "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
884 885 886 887 888 889 890 891 892 893 894

        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"

895 896
        suffix = self.specialization_suffix()
        funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
897 898 899

        context = dict(
            MemoryView.context,
900
            buf_flag = self.flags,
901
            ndim = self.ndim,
902
            axes_specs = ', '.join(self.axes_to_code()),
903
            dtype_typedecl = self.dtype.empty_declaration_code(),
904 905 906 907 908 909 910 911
            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

912 913
    def from_py_call_code(self, source_code, result_code, error_pos, code,
                          from_py_function=None, error_condition=None):
914 915 916
        # NOTE: auto-detection of readonly buffers is disabled:
        # writable = self.writable_needed or not self.dtype.is_const
        writable = not self.dtype.is_const
917 918
        return self._assign_from_py_code(
            source_code, result_code, error_pos, code, from_py_function, error_condition,
919
            extra_args=['PyBUF_WRITABLE' if writable else '0'])
920

921
    def create_to_py_utility_code(self, env):
922
        self._dtype_to_py_func, self._dtype_from_py_func = self.dtype_object_conversion_funcs(env)
923 924
        return True

925 926 927 928 929 930
    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
931

932 933
        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
934 935 936 937 938 939 940 941 942 943 944 945 946

    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:
947 948
            self.dtype.create_to_py_utility_code(env)
            to_py_function = self.dtype.to_py_function
949

950 951 952 953
            from_py_function = None
            if not self.dtype.is_const:
                self.dtype.create_from_py_utility_code(env)
                from_py_function = self.dtype.from_py_function
Mark Florisson's avatar
Mark Florisson committed
954

955 956 957 958 959
            if not (to_py_function or from_py_function):
                return "NULL", "NULL"
            if not to_py_function:
                get_function = "NULL"
            if not from_py_function:
Mark Florisson's avatar
Mark Florisson committed
960 961
                set_function = "NULL"

962 963 964 965
            utility_name = "MemviewDtypeToObject"
            error_condition = (self.dtype.error_condition('value') or
                               'PyErr_Occurred()')
            context.update(
966 967 968 969
                to_py_function=to_py_function,
                from_py_function=from_py_function,
                dtype=self.dtype.empty_declaration_code(),
                error_condition=error_condition,
970 971
            )

972 973
        utility = TempitaUtilityCode.load_cached(
            utility_name, "MemoryView_C.c", context=context)
974 975
        env.use_utility_code(utility)
        return get_function, set_function
976

977
    def axes_to_code(self):
Stefan Behnel's avatar
Stefan Behnel committed
978
        """Return a list of code constants for each axis"""
979
        from . import MemoryView
980 981 982
        d = MemoryView._spec_to_const
        return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]

983
    def axes_to_name(self):
Stefan Behnel's avatar
Stefan Behnel committed
984
        """Return an abbreviated name for our axes"""
985
        from . import MemoryView
986 987 988 989 990 991
        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

992
    def __str__(self):
993
        from . import MemoryView
994 995

        axes_code_list = []
996
        for idx, (access, packing) in enumerate(self.axes):
997 998 999 1000
            flag = MemoryView.get_memoryview_flag(access, packing)
            if flag == "strided":
                axes_code_list.append(":")
            else:
1001
                if flag == 'contiguous':
Mark Florisson's avatar
Mark Florisson committed
1002
                    have_follow = [p for a, p in self.axes[idx - 1:idx + 2]
1003 1004 1005 1006
                                         if p == 'follow']
                    if have_follow or self.ndim == 1:
                        flag = '1'

1007 1008 1009 1010 1011 1012 1013 1014 1015
                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))

1016
    def specialize(self, values):
Stefan Behnel's avatar
Stefan Behnel committed
1017
        """This does not validate the base type!!"""
1018 1019 1020 1021
        dtype = self.dtype.specialize(values)
        if dtype is not self.dtype:
            return MemoryViewSliceType(dtype, self.axes)

1022 1023
        return self

1024 1025
    def cast_code(self, expr_code):
        return expr_code
1026

1027

1028 1029
class BufferType(BaseType):
    #
1030 1031 1032
    #  Delegates most attribute lookups to the base type.
    #  (Anything not defined here or in the BaseType is delegated.)
    #
1033 1034 1035 1036 1037 1038 1039
    # dtype            PyrexType
    # ndim             int
    # mode             str
    # negative_indices bool
    # cast             bool
    # is_buffer        bool
    # writable         bool
1040 1041

    is_buffer = 1
1042
    writable = True
1043 1044 1045

    subtypes = ['dtype']

1046
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
1047 1048 1049
        self.base = base
        self.dtype = dtype
        self.ndim = ndim
1050
        self.buffer_ptr_type = CPtrType(dtype)
1051
        self.mode = mode
1052
        self.negative_indices = negative_indices
1053
        self.cast = cast
1054
        self.is_numpy_buffer = self.base.name == "ndarray"
Robert Bradshaw's avatar
Robert Bradshaw committed
1055

1056 1057 1058
    def can_coerce_to_pyobject(self,env):
        return True

1059 1060 1061
    def can_coerce_from_pyobject(self,env):
        return True

1062 1063 1064
    def as_argument_type(self):
        return self

Mark Florisson's avatar
Mark Florisson committed
1065 1066 1067 1068 1069 1070 1071
    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

1072 1073 1074 1075 1076
    def get_entry(self, node):
        from . import Buffer
        assert node.is_name
        return Buffer.BufferEntry(node.entry)

1077 1078 1079
    def __getattr__(self, name):
        return getattr(self.base, name)

1080 1081 1082
    def __repr__(self):
        return "<BufferType %r>" % self.base

1083
    def __str__(self):
1084
        # avoid ', ', as fused functions split the signature string on ', '
1085
        cast_str = ''
1086 1087
        if self.cast:
            cast_str = ',cast=True'
1088

1089
        return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
1090
                                      cast_str)
1091

1092
    def assignable_from(self, other_type):
1093 1094 1095
        if other_type.is_buffer:
            return (self.same_as(other_type, compare_base=False) and
                    self.base.assignable_from(other_type.base))
1096

1097 1098 1099 1100 1101 1102 1103
        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
1104 1105
                self.ndim == other_type.ndim and
                self.mode == other_type.mode and
1106 1107
                self.cast == other_type.cast and
                (not compare_base or self.base.same_as(other_type.base)))
1108

1109

William Stein's avatar
William Stein committed
1110 1111 1112 1113
class PyObjectType(PyrexType):
    #
    #  Base class for all Python object types (reference-counted).
    #
1114
    #  buffer_defaults  dict or None     Default options for bu
1115 1116

    name = "object"
William Stein's avatar
William Stein committed
1117 1118
    is_pyobject = 1
    default_value = "0"
1119
    declaration_value = "0"
1120
    buffer_defaults = None
1121 1122
    is_extern = False
    is_subclassed = False
1123
    is_gc_simple = False
1124

William Stein's avatar
William Stein committed
1125 1126
    def __str__(self):
        return "Python object"
Robert Bradshaw's avatar
Robert Bradshaw committed
1127

William Stein's avatar
William Stein committed
1128
    def __repr__(self):
1129
        return "<PyObjectType>"
1130 1131 1132 1133

    def can_coerce_to_pyobject(self, env):
        return True

1134 1135 1136
    def can_coerce_from_pyobject(self, env):
        return True

1137
    def default_coerced_ctype(self):
Stefan Behnel's avatar
Stefan Behnel committed
1138
        """The default C type that this Python type coerces to, or None."""
1139 1140
        return None

William Stein's avatar
William Stein committed
1141
    def assignable_from(self, src_type):
1142
        # except for pointers, conversion will be attempted
1143
        return not src_type.is_ptr or src_type.is_string or src_type.is_pyunicode_ptr
Robert Bradshaw's avatar
Robert Bradshaw committed
1144 1145

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1146
            for_display = 0, dll_linkage = None, pyrex = 0):
1147
        if pyrex or for_display:
1148
            base_code = "object"
William Stein's avatar
William Stein committed
1149
        else:
1150 1151 1152
            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
1153

1154 1155 1156 1157 1158
    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
1159

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

1170 1171 1172
    def global_init_code(self, entry, code):
        code.put_init_var_to_py_none(entry, nanny=False)

Mark Florisson's avatar
Mark Florisson committed
1173 1174 1175
    def check_for_null_code(self, cname):
        return cname

1176

1177 1178 1179 1180 1181 1182
builtin_types_that_cannot_create_refcycles = set([
    'bool', 'int', 'long', 'float', 'complex',
    'bytearray', 'bytes', 'unicode', 'str', 'basestring'
])


Robert Bradshaw's avatar
Robert Bradshaw committed
1183
class BuiltinObjectType(PyObjectType):
1184
    #  objstruct_cname  string           Name of PyObject struct
Robert Bradshaw's avatar
Robert Bradshaw committed
1185 1186 1187 1188 1189

    is_builtin_type = 1
    has_attributes = 1
    base_type = None
    module_name = '__builtin__'
1190
    require_exact = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1191

1192 1193 1194 1195 1196 1197
    # fields that let it look like an extension type
    vtabslot_cname = None
    vtabstruct_cname = None
    vtabptr_cname = None
    typedef_flag = True
    is_external = True
1198
    decl_type = 'PyObject'
1199

1200
    def __init__(self, name, cname, objstruct_cname=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
1201 1202
        self.name = name
        self.cname = cname
1203
        self.typeptr_cname = "(&%s)" % cname
1204
        self.objstruct_cname = objstruct_cname
1205
        self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles
1206 1207 1208 1209
        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
1210 1211
        if name == 'Exception':
            self.require_exact = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
1212

Robert Bradshaw's avatar
Robert Bradshaw committed
1213 1214 1215 1216
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1217

Robert Bradshaw's avatar
Robert Bradshaw committed
1218 1219
    def __str__(self):
        return "%s object" % self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1220

Robert Bradshaw's avatar
Robert Bradshaw committed
1221 1222
    def __repr__(self):
        return "<%s>"% self.cname
1223 1224

    def default_coerced_ctype(self):
1225
        if self.name in ('bytes', 'bytearray'):
1226 1227 1228 1229 1230 1231 1232
            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
1233 1234
    def assignable_from(self, src_type):
        if isinstance(src_type, BuiltinObjectType):
1235
            if self.name == 'basestring':
1236
                return src_type.name in ('str', 'unicode', 'basestring')
1237 1238
            else:
                return src_type.name == self.name
1239
        elif src_type.is_extension_type:
1240 1241 1242 1243 1244
            # 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!
1245 1246
            return (src_type.module_name == '__builtin__' and
                    src_type.name == self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
1247
        else:
1248
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1249

Robert Bradshaw's avatar
Robert Bradshaw committed
1250 1251
    def typeobj_is_available(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1252

Robert Bradshaw's avatar
Robert Bradshaw committed
1253 1254
    def attributes_known(self):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
1255

Robert Bradshaw's avatar
Robert Bradshaw committed
1256
    def subtype_of(self, type):
1257
        return type.is_pyobject and type.assignable_from(self)
1258 1259

    def type_check_function(self, exact=True):
1260 1261
        type_name = self.name
        if type_name == 'str':
1262
            type_check = 'PyString_Check'
1263 1264
        elif type_name == 'basestring':
            type_check = '__Pyx_PyBaseString_Check'
1265 1266
        elif type_name == 'Exception':
            type_check = '__Pyx_PyException_Check'
1267 1268
        elif type_name == 'bytearray':
            type_check = 'PyByteArray_Check'
1269
        elif type_name == 'frozenset':
1270
            type_check = 'PyFrozenSet_Check'
1271
        else:
1272
            type_check = 'Py%s_Check' % type_name.capitalize()
1273
        if exact and type_name not in ('bool', 'slice', 'Exception'):
1274 1275 1276 1277 1278
            type_check += 'Exact'
        return type_check

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

1280 1281
    def type_test_code(self, arg, notnone=False, exact=True):
        type_check = self.type_check_function(exact=exact)
1282 1283
        check = 'likely(%s(%s))' % (type_check, arg)
        if not notnone:
Stefan Behnel's avatar
Stefan Behnel committed
1284
            check += '||((%s) == Py_None)' % arg
1285 1286 1287 1288 1289 1290 1291 1292 1293
        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)
1294
        return check + '||' + error
Robert Bradshaw's avatar
Robert Bradshaw committed
1295

Robert Bradshaw's avatar
Robert Bradshaw committed
1296
    def declaration_code(self, entity_code,
1297 1298
            for_display = 0, dll_linkage = None, pyrex = 0):
        if pyrex or for_display:
1299
            base_code = self.name
1300
        else:
1301
            base_code = public_decl(self.decl_type, dll_linkage)
1302 1303
            entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
1304

1305 1306 1307 1308 1309 1310
    def as_pyobject(self, cname):
        if self.decl_type == 'PyObject':
            return cname
        else:
            return "(PyObject *)" + cname

1311 1312
    def cast_code(self, expr_code, to_object_struct = False):
        return "((%s*)%s)" % (
1313
            to_object_struct and self.objstruct_cname or self.decl_type, # self.objstruct_cname may be None
1314 1315
            expr_code)

1316 1317 1318 1319
    def py_type_name(self):
        return self.name


Robert Bradshaw's avatar
Robert Bradshaw committed
1320

William Stein's avatar
William Stein committed
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
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
1332
    #  objtypedef_cname string           Name of PyObject struct typedef
William Stein's avatar
William Stein committed
1333 1334 1335 1336 1337 1338
    #  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
1339
    #  early_init       boolean          Whether to initialize early (as opposed to during module execution).
1340
    #  defered_declarations [thunk]      Used to declare class hierarchies in order
Robert Bradshaw's avatar
Robert Bradshaw committed
1341

William Stein's avatar
William Stein committed
1342 1343
    is_extension_type = 1
    has_attributes = 1
1344
    early_init = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1345

1346
    objtypedef_cname = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1347

1348
    def __init__(self, name, typedef_flag, base_type, is_external=0):
William Stein's avatar
William Stein committed
1349 1350 1351
        self.name = name
        self.scope = None
        self.typedef_flag = typedef_flag
1352 1353
        if base_type is not None:
            base_type.is_subclassed = True
William Stein's avatar
William Stein committed
1354 1355 1356 1357 1358 1359 1360 1361 1362
        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
1363
        self.is_external = is_external
1364
        self.defered_declarations = []
Robert Bradshaw's avatar
Robert Bradshaw committed
1365

William Stein's avatar
William Stein committed
1366 1367 1368 1369
    def set_scope(self, scope):
        self.scope = scope
        if scope:
            scope.parent_type = self
Robert Bradshaw's avatar
Robert Bradshaw committed
1370

Stefan Behnel's avatar
Stefan Behnel committed
1371 1372 1373
    def needs_nonecheck(self):
        return True

William Stein's avatar
William Stein committed
1374
    def subtype_of_resolved_type(self, other_type):
Stefan Behnel's avatar
Stefan Behnel committed
1375
        if other_type.is_extension_type or other_type.is_builtin_type:
William Stein's avatar
William Stein committed
1376 1377 1378 1379
            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
1380

William Stein's avatar
William Stein committed
1381 1382 1383
    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
1384

William Stein's avatar
William Stein committed
1385 1386 1387 1388
    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
1389

1390 1391 1392 1393 1394 1395
    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)
1396 1397 1398 1399 1400 1401 1402 1403
        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)
1404 1405
        return False

Robert Bradshaw's avatar
Robert Bradshaw committed
1406
    def declaration_code(self, entity_code,
1407
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
1408
        if pyrex or for_display:
1409
            base_code = self.name
William Stein's avatar
William Stein committed
1410 1411
        else:
            if self.typedef_flag:
1412
                objstruct = self.objstruct_cname
William Stein's avatar
William Stein committed
1413
            else:
1414
                objstruct = "struct %s" % self.objstruct_cname
1415
            base_code = public_decl(objstruct, dll_linkage)
1416
            if deref:
1417
                assert not entity_code
1418
            else:
1419 1420
                entity_code = "*%s" % entity_code
        return self.base_declaration_code(base_code, entity_code)
William Stein's avatar
William Stein committed
1421

1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
    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
1432 1433
    def attributes_known(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1434

William Stein's avatar
William Stein committed
1435 1436
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
1437

William Stein's avatar
William Stein committed
1438
    def __repr__(self):
1439 1440
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
1441

1442 1443 1444 1445 1446 1447
    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
1448 1449 1450 1451 1452 1453 1454 1455

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
1456

William Stein's avatar
William Stein committed
1457 1458
    to_py_function = None
    from_py_function = None
1459 1460
    exception_value = None
    exception_check = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
1461

1462
    def create_to_py_utility_code(self, env):
1463
        return self.to_py_function is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
1464

1465
    def create_from_py_utility_code(self, env):
1466
        return self.from_py_function is not None
1467 1468 1469 1470

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

1471 1472 1473
    def can_coerce_from_pyobject(self, env):
        return self.create_from_py_utility_code(env)

1474 1475
    def error_condition(self, result_code):
        conds = []
1476
        if self.is_string or self.is_pyunicode_ptr:
1477 1478 1479 1480 1481 1482 1483 1484 1485
            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
1486

1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
    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):
1504 1505 1506
        return self._assign_from_py_code(
            source_code, result_code, error_pos, code, from_py_function, error_condition)

1507

1508

1509 1510 1511
class PythranExpr(CType):
    # Pythran object of a given type

1512
    to_py_function = "__Pyx_pythran_to_python"
1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
    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

1525 1526 1527
    def declaration_code(self, entity_code, for_display=0, dll_linkage=None, pyrex=0):
        assert not pyrex
        return "%s %s" % (self.cname, entity_code)
1528 1529 1530 1531

    def attributes_known(self):
        if self.scope is None:
            from . import Symtab
1532 1533
            # FIXME: fake C scope, might be better represented by a struct or C++ class scope
            self.scope = scope = Symtab.CClassScope('', None, visibility="extern")
1534 1535
            scope.parent_type = self
            scope.directives = {}
1536 1537
            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)
1538 1539

        return True
William Stein's avatar
William Stein committed
1540

1541
    def __eq__(self, other):
1542
        return isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type
1543

1544
    def __ne__(self, other):
1545
        return not (isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type)
1546

1547
    def __hash__(self):
1548
        return hash(self.pythran_type)
1549 1550


Robert Bradshaw's avatar
Robert Bradshaw committed
1551 1552 1553
class CConstType(BaseType):

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

Robert Bradshaw's avatar
Robert Bradshaw committed
1555 1556 1557
    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:
1558
            from . import Symtab
Robert Bradshaw's avatar
Robert Bradshaw committed
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
            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):
1569 1570 1571 1572
        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
1573 1574 1575 1576 1577 1578

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

1581 1582 1583
    def deduce_template_params(self, actual):
        return self.const_base_type.deduce_template_params(actual)

1584 1585 1586
    def can_coerce_to_pyobject(self, env):
        return self.const_base_type.can_coerce_to_pyobject(env)

1587 1588 1589
    def can_coerce_from_pyobject(self, env):
        return self.const_base_type.can_coerce_from_pyobject(env)

Robert Bradshaw's avatar
Robert Bradshaw committed
1590 1591 1592 1593 1594 1595 1596 1597 1598
    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)


1599
class FusedType(CType):
1600 1601 1602 1603 1604 1605 1606
    """
    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

1607
    types           [PyrexType]             is the list of types to be fused
1608 1609 1610 1611
    name            str                     the name of the ctypedef
    """

    is_fused = 1
1612
    exception_check = 0
1613

1614
    def __init__(self, types, name=None):
1615 1616 1617 1618 1619 1620 1621 1622 1623 1624
        # 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)
1625
        self.types = flattened_types
1626
        self.name = name
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649

    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)


1650
class CVoidType(CType):
1651 1652 1653 1654
    #
    #   C "void" type
    #

William Stein's avatar
William Stein committed
1655
    is_void = 1
1656
    to_py_function = "__Pyx_void_to_None"
Robert Bradshaw's avatar
Robert Bradshaw committed
1657

William Stein's avatar
William Stein committed
1658 1659
    def __repr__(self):
        return "<CVoidType>"
Robert Bradshaw's avatar
Robert Bradshaw committed
1660 1661

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1662
            for_display = 0, dll_linkage = None, pyrex = 0):
1663 1664 1665 1666 1667
        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
1668

William Stein's avatar
William Stein committed
1669 1670 1671
    def is_complete(self):
        return 0

1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
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
1685 1686 1687 1688 1689 1690

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

William Stein's avatar
William Stein committed
1694 1695
    is_numeric = 1
    default_value = "0"
1696 1697
    has_attributes = True
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
1698

1699
    sign_words = ("unsigned ", "", "signed ")
Robert Bradshaw's avatar
Robert Bradshaw committed
1700

1701
    def __init__(self, rank, signed = 1):
William Stein's avatar
William Stein committed
1702
        self.rank = rank
1703 1704 1705 1706
        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
1707
        self.signed = signed
Robert Bradshaw's avatar
Robert Bradshaw committed
1708

1709 1710 1711 1712
    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
1713

William Stein's avatar
William Stein committed
1714
    def __repr__(self):
1715
        return "<CNumericType %s>" % self.sign_and_name()
Robert Bradshaw's avatar
Robert Bradshaw committed
1716 1717

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
1718
            for_display = 0, dll_linkage = None, pyrex = 0):
1719 1720 1721 1722 1723 1724
        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
1725

1726 1727
    def attributes_known(self):
        if self.scope is None:
1728
            from . import Symtab
1729 1730 1731 1732 1733 1734
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
            scope.directives = {}
Stefan Behnel's avatar
Stefan Behnel committed
1735
            scope.declare_cfunction(
1736
                    "conjugate",
1737
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
1738 1739 1740 1741
                    pos=None,
                    defining=1,
                    cname=" ")
        return True
1742

1743
    def __lt__(self, other):
Stefan Behnel's avatar
Stefan Behnel committed
1744
        """Sort based on rank, preferring signed over unsigned"""
1745 1746 1747
        if other.is_numeric:
            return self.rank > other.rank and self.signed >= other.signed

1748 1749
        # Prefer numeric types over others
        return True
1750 1751 1752 1753 1754

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

William Stein's avatar
William Stein committed
1756

1757 1758 1759 1760 1761 1762 1763
class ForbidUseClass:
    def __repr__(self):
        raise RuntimeError()
    def __str__(self):
        raise RuntimeError()
ForbidUse = ForbidUseClass()

William Stein's avatar
William Stein committed
1764

1765 1766 1767
class CIntLike(object):
    """Mixin for shared behaviour of C integers and enums.
    """
1768 1769
    to_py_function = None
    from_py_function = None
1770
    to_pyunicode_utility = None
1771
    default_format_spec = 'd'
William Stein's avatar
William Stein committed
1772

1773 1774 1775
    def can_coerce_to_pyobject(self, env):
        return True

1776 1777 1778
    def can_coerce_from_pyobject(self, env):
        return True

1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796
    def create_to_py_utility_code(self, env):
        if type(self).to_py_function is None:
            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):
        if type(self).from_py_function is None:
            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

1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820
    @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)

1821
    def can_coerce_to_pystring(self, env, format_spec=None):
1822 1823
        format_type, width, padding = self._parse_format(format_spec)
        return format_type is not None and width <= 2**30
1824

1825
    def convert_to_pystring(self, cvalue, code, format_spec=None):
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
        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)
1836 1837
        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)
1838

1839

1840 1841 1842 1843 1844
class CIntType(CIntLike, CNumericType):

    is_int = 1
    typedef_flag = 0
    exception_value = -1
1845 1846

    def get_to_py_type_conversion(self):
1847
        if self.rank < list(rank_to_type_name).index('int'):
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
            # 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"
1858
            if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
1859 1860 1861 1862
                Prefix = "Long"
                TypeName = "LongLong"
            return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)

1863 1864
    def assignable_from_resolved_type(self, src_type):
        return src_type.is_int or src_type.is_enum or src_type is error_type
1865

1866
    def invalid_value(self):
1867
        if rank_to_type_name[int(self.rank)] == 'char':
1868 1869 1870 1871 1872
            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.
1873
            return "0xbad0bad0"
William Stein's avatar
William Stein committed
1874

1875
    def overflow_check_binop(self, binop, env, const_rhs=False):
1876
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
1877
        type = self.empty_declaration_code()
1878
        name = self.specialization_name()
1879
        if binop == "lshift":
1880
            env.use_utility_code(TempitaUtilityCode.load_cached(
1881
                "LeftShift", "Overflow.c",
1882
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
1883
        else:
1884 1885 1886
            if const_rhs:
                binop += "_const"
            if type in ('int', 'long', 'long long'):
1887
                env.use_utility_code(TempitaUtilityCode.load_cached(
1888 1889
                    "BaseCaseSigned", "Overflow.c",
                    context={'INT': type, 'NAME': name}))
1890
            elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1891
                env.use_utility_code(TempitaUtilityCode.load_cached(
1892 1893
                    "BaseCaseUnsigned", "Overflow.c",
                    context={'UINT': type, 'NAME': name}))
1894 1895 1896 1897 1898
            elif self.rank <= 1:
                # sizeof(short) < sizeof(int)
                return "__Pyx_%s_%s_no_overflow" % (binop, name)
            else:
                _load_overflow_base(env)
1899
                env.use_utility_code(TempitaUtilityCode.load_cached(
1900 1901
                    "SizeCheck", "Overflow.c",
                    context={'TYPE': type, 'NAME': name}))
1902
                env.use_utility_code(TempitaUtilityCode.load_cached(
1903 1904
                    "Binop", "Overflow.c",
                    context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
1905 1906
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)

1907

1908 1909 1910
def _load_overflow_base(env):
    env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
    for type in ('int', 'long', 'long long'):
1911
        env.use_utility_code(TempitaUtilityCode.load_cached(
1912 1913
            "BaseCaseSigned", "Overflow.c",
            context={'INT': type, 'NAME': type.replace(' ', '_')}))
1914
    for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
1915
        env.use_utility_code(TempitaUtilityCode.load_cached(
1916 1917
            "BaseCaseUnsigned", "Overflow.c",
            context={'UINT': type, 'NAME': type.replace(' ', '_')}))
1918 1919


1920 1921
class CAnonEnumType(CIntType):

1922 1923 1924 1925
    is_enum = 1

    def sign_and_name(self):
        return 'int'
1926

1927

1928 1929
class CReturnCodeType(CIntType):

1930 1931
    to_py_function = "__Pyx_Owned_Py_None"

1932 1933
    is_returncode = True
    exception_check = False
1934
    default_format_spec = ''
1935

1936
    def can_coerce_to_pystring(self, env, format_spec=None):
1937 1938 1939 1940
        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
1941

1942

1943 1944 1945 1946
class CBIntType(CIntType):

    to_py_function = "__Pyx_PyBool_FromLong"
    from_py_function = "__Pyx_PyObject_IsTrue"
1947 1948
    exception_check = 1  # for C++ bool
    default_format_spec = ''
1949

1950
    def can_coerce_to_pystring(self, env, format_spec=None):
1951
        return not format_spec or super(CBIntType, self).can_coerce_to_pystring(env, format_spec)
1952

1953 1954 1955
    def convert_to_pystring(self, cvalue, code, format_spec=None):
        if format_spec:
            return super(CBIntType, self).convert_to_pystring(cvalue, code, format_spec)
1956 1957 1958 1959 1960 1961 1962 1963
        # 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,
            })
1964
        code.globalstate.use_utility_code(to_pyunicode_utility)
1965
        return "%s(%s)" % (utility_code_name, cvalue)
1966

1967 1968
    def declaration_code(self, entity_code,
            for_display = 0, dll_linkage = None, pyrex = 0):
1969
        if for_display:
1970
            base_code = 'bool'
1971 1972
        elif pyrex:
            base_code = 'bint'
1973 1974 1975 1976
        else:
            base_code = public_decl('int', dll_linkage)
        return self.base_declaration_code(base_code, entity_code)

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

1980 1981 1982
    def __str__(self):
        return 'bint'

1983 1984 1985
    def py_type_name(self):
        return "bool"

1986

Stefan Behnel's avatar
Stefan Behnel committed
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
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"

2001
    def can_coerce_to_pystring(self, env, format_spec=None):
2002
        return False  # does the right thing anyway
2003

Stefan Behnel's avatar
Stefan Behnel committed
2004
    def create_from_py_utility_code(self, env):
2005
        env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c"))
Stefan Behnel's avatar
Stefan Behnel committed
2006 2007 2008 2009 2010 2011
        return True

    def sign_and_name(self):
        return "Py_UCS4"


2012 2013 2014
class CPyUnicodeIntType(CIntType):
    # Py_UNICODE

Stefan Behnel's avatar
Stefan Behnel committed
2015 2016
    is_unicode_char = True

2017 2018 2019 2020
    # 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.
2021

2022 2023 2024
    to_py_function = "PyUnicode_FromOrdinal"
    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"

2025
    def can_coerce_to_pystring(self, env, format_spec=None):
2026
        return False  # does the right thing anyway
2027

2028
    def create_from_py_utility_code(self, env):
2029
        env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c"))
2030
        return True
2031 2032 2033 2034 2035

    def sign_and_name(self):
        return "Py_UNICODE"


2036 2037 2038 2039 2040 2041 2042 2043
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"

2044 2045 2046
class CPySSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
2047
    from_py_function = "__Pyx_PyIndex_AsSsize_t"
2048

2049
    def sign_and_name(self):
2050
        return "Py_ssize_t"
2051

2052 2053 2054 2055 2056 2057
class CSSizeTType(CIntType):

    to_py_function = "PyInt_FromSsize_t"
    from_py_function = "PyInt_AsSsize_t"

    def sign_and_name(self):
2058
        return "Py_ssize_t"
2059

2060
class CSizeTType(CIntType):
2061

2062
    to_py_function = "__Pyx_PyInt_FromSize_t"
2063

2064
    def sign_and_name(self):
2065
        return "size_t"
2066

2067 2068 2069 2070 2071
class CPtrdiffTType(CIntType):

    def sign_and_name(self):
        return "ptrdiff_t"

2072

William Stein's avatar
William Stein committed
2073 2074 2075 2076
class CFloatType(CNumericType):

    is_float = 1
    to_py_function = "PyFloat_FromDouble"
2077
    from_py_function = "__pyx_PyFloat_AsDouble"
2078 2079

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

2081 2082
    def __init__(self, rank, math_h_modifier = ''):
        CNumericType.__init__(self, rank, 1)
2083
        self.math_h_modifier = math_h_modifier
2084 2085
        if rank == RANK_FLOAT:
            self.from_py_function = "__pyx_PyFloat_AsFloat"
Robert Bradshaw's avatar
Robert Bradshaw committed
2086

2087
    def assignable_from_resolved_type(self, src_type):
2088 2089
        return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type

2090 2091
    def invalid_value(self):
        return Naming.PYX_NAN
2092

2093
class CComplexType(CNumericType):
Robert Bradshaw's avatar
Robert Bradshaw committed
2094

2095
    is_complex = 1
2096
    to_py_function = "__pyx_PyComplex_FromComplex"
2097 2098
    has_attributes = 1
    scope = None
Robert Bradshaw's avatar
Robert Bradshaw committed
2099

2100
    def __init__(self, real_type):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2101 2102
        while real_type.is_typedef and not real_type.typedef_is_external:
            real_type = real_type.typedef_base_type
2103 2104 2105
        self.funcsuffix = "_%s" % real_type.specialization_name()
        if real_type.is_float:
            self.math_h_modifier = real_type.math_h_modifier
2106
        else:
2107
            self.math_h_modifier = "_UNUSED"
Robert Bradshaw's avatar
Robert Bradshaw committed
2108

2109 2110
        self.real_type = real_type
        CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
2111
        self.binops = {}
Craig Citro's avatar
Craig Citro committed
2112
        self.from_parts = "%s_from_parts" % self.specialization_name()
2113
        self.default_value = "%s(0, 0)" % self.from_parts
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2114

2115
    def __eq__(self, other):
2116
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
2117
            return self.real_type == other.real_type
2118
        else:
2119
            return False
Robert Bradshaw's avatar
Robert Bradshaw committed
2120

2121 2122 2123 2124 2125
    def __ne__(self, other):
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
            return self.real_type != other.real_type
        else:
            return True
2126 2127 2128 2129 2130 2131 2132 2133 2134

    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

2135 2136
    def __hash__(self):
        return ~hash(self.real_type)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2137

Robert Bradshaw's avatar
Robert Bradshaw committed
2138
    def declaration_code(self, entity_code,
2139
            for_display = 0, dll_linkage = None, pyrex = 0):
2140 2141 2142
        if pyrex or for_display:
            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
            base_code = "%s complex" % real_code
2143
        else:
2144 2145
            base_code = public_decl(self.sign_and_name(), dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
2146

2147
    def sign_and_name(self):
Craig Citro's avatar
Craig Citro committed
2148
        real_type_name = self.real_type.specialization_name()
2149
        real_type_name = real_type_name.replace('long__double','long_double')
2150
        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
2151
        return Naming.type_prefix + real_type_name + "_complex"
Robert Bradshaw's avatar
Robert Bradshaw committed
2152

2153 2154
    def assignable_from(self, src_type):
        # Temporary hack/feature disabling, see #441
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2155 2156 2157
        if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
            and src_type.typedef_is_external):
             return False
2158 2159
        elif src_type.is_pyobject:
            return True
2160 2161
        else:
            return super(CComplexType, self).assignable_from(src_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2162

2163 2164
    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
2165
                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
2166
                    or src_type is error_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2167

2168 2169
    def attributes_known(self):
        if self.scope is None:
2170
            from . import Symtab
2171 2172 2173 2174 2175
            self.scope = scope = Symtab.CClassScope(
                    '',
                    None,
                    visibility="extern")
            scope.parent_type = self
2176
            scope.directives = {}
2177 2178
            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
2179
            scope.declare_cfunction(
2180
                    "conjugate",
2181
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
2182 2183
                    pos=None,
                    defining=1,
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2184
                    cname="__Pyx_c_conj%s" % self.funcsuffix)
2185

2186
        return True
2187

2188 2189 2190 2191 2192
    def _utility_code_context(self):
        return {
            'type': self.empty_declaration_code(),
            'type_name': self.specialization_name(),
            'real_type': self.real_type.empty_declaration_code(),
2193 2194
            'func_suffix': self.funcsuffix,
            'm': self.math_h_modifier,
2195 2196 2197
            'is_float': int(self.real_type.is_float)
        }

2198
    def create_declaration_utility_code(self, env):
2199 2200
        # This must always be run, because a single CComplexType instance can be shared
        # across multiple compilations (the one created in the module scope)
2201 2202 2203 2204 2205 2206
        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()))
2207 2208
        return True

2209 2210 2211
    def can_coerce_to_pyobject(self, env):
        return True

2212 2213 2214
    def can_coerce_from_pyobject(self, env):
        return True

2215
    def create_to_py_utility_code(self, env):
2216
        env.use_utility_code(UtilityCode.load_cached('ToPy', 'Complex.c'))
2217 2218 2219
        return True

    def create_from_py_utility_code(self, env):
2220 2221
        env.use_utility_code(TempitaUtilityCode.load_cached(
            'FromPy', 'Complex.c', self._utility_code_context()))
Craig Citro's avatar
Craig Citro committed
2222
        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
2223
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
2224

2225
    def lookup_op(self, nargs, op):
2226
        try:
2227
            return self.binops[nargs, op]
2228
        except KeyError:
2229 2230 2231
            pass
        try:
            op_name = complex_ops[nargs, op]
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
2232
            self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
2233 2234 2235 2236 2237 2238
            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
2239

2240 2241
    def binary_op(self, op):
        return self.lookup_op(2, op)
Robert Bradshaw's avatar
Robert Bradshaw committed
2242

2243 2244 2245
    def py_type_name(self):
        return "complex"

2246 2247 2248
    def cast_code(self, expr_code):
        return expr_code

2249 2250 2251
complex_ops = {
    (1, '-'): 'neg',
    (1, 'zero'): 'is_zero',
2252 2253 2254 2255
    (2, '+'): 'sum',
    (2, '-'): 'diff',
    (2, '*'): 'prod',
    (2, '/'): 'quot',
2256
    (2, '**'): 'pow',
2257 2258
    (2, '=='): 'eq',
}
2259

2260

2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279
class CPyTSSTType(CType):
    #
    #   PEP-539 "Py_tss_t" type
    #

    declaration_value = "Py_tss_NEEDS_INIT"

    def __repr__(self):
        return "<Py_tss_t>"

    def declaration_code(self, entity_code,
                         for_display=0, dll_linkage=None, pyrex=0):
        if pyrex or for_display:
            base_code = "Py_tss_t"
        else:
            base_code = public_decl("Py_tss_t", dll_linkage)
        return self.base_declaration_code(base_code, entity_code)


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

    subtypes = ['base_type']

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

2299
        if self.is_string and not base_type.is_error:
2300 2301 2302
            if base_type.signed == 2:
                self.to_py_function = "__Pyx_PyObject_FromCString"
                if self.is_ptr:
2303
                    self.from_py_function = "__Pyx_PyObject_As%sSString"
2304
            elif base_type.signed:
2305
                self.to_py_function = "__Pyx_PyObject_FromString"
2306
                if self.is_ptr:
2307
                    self.from_py_function = "__Pyx_PyObject_As%sString"
2308
            else:
2309
                self.to_py_function = "__Pyx_PyObject_FromCString"
2310
                if self.is_ptr:
2311 2312 2313
                    self.from_py_function = "__Pyx_PyObject_As%sUString"
            if self.is_ptr:
                self.from_py_function %= '' if self.base_type.is_const else 'Writable'
2314
            self.exception_value = "NULL"
2315
        elif self.is_pyunicode_ptr and not base_type.is_error:
2316 2317 2318 2319
            self.to_py_function = "__Pyx_PyUnicode_FromUnicode"
            if self.is_ptr:
                self.from_py_function = "__Pyx_PyUnicode_AsUnicode"
            self.exception_value = "NULL"
2320 2321 2322 2323

    def py_type_name(self):
        if self.is_string:
            return "bytes"
2324
        elif self.is_pyunicode_ptr:
2325
            return "unicode"
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
        else:
            return super(CPointerBaseType, self).py_type_name()

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


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

    is_array = 1
2340
    to_tuple_function = None
2341 2342 2343 2344 2345

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

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

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

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

William Stein's avatar
William Stein committed
2357 2358 2359 2360
    def same_as_resolved_type(self, other_type):
        return ((other_type.is_array and
            self.base_type.same_as(other_type.base_type))
                or other_type is error_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
2361

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

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

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

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

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

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

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

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

2407 2408 2409
    def can_coerce_from_pyobject(self, env):
        return self.base_type.can_coerce_from_pyobject(env)

2410 2411 2412 2413 2414 2415
    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

2416
        safe_typename = self.base_type.specialization_name()
2417 2418 2419 2420 2421 2422 2423
        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,
2424
            'base_type': self.base_type,
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453
        }
        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

2454
        from_py_function = "__Pyx_carray_from_py_%s" % self.base_type.specialization_name()
2455 2456 2457 2458

        from .UtilityCode import CythonUtilityCode
        context = {
            'cname': from_py_function,
2459
            'base_type': self.base_type,
2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
        }
        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):
2470
        assert not error_condition, '%s: %s' % (error_pos, error_condition)
2471 2472 2473 2474 2475
        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
2476

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

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

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

2486 2487 2488 2489 2490
    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
2491 2492 2493
    def __ne__(self, other):
        return not (self == other)

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

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

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

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

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

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

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

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

2551

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

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

William Stein's avatar
William Stein committed
2556

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

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

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

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

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

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

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

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

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


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

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

    subtypes = ['return_type', 'args']

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

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

2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
    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)

2683 2684 2685 2686 2687 2688
    def calling_convention_prefix(self):
        cc = self.calling_convention
        if cc:
            return cc + " "
        else:
            return ""
Robert Bradshaw's avatar
Robert Bradshaw committed
2689

2690 2691 2692
    def as_argument_type(self):
        return c_ptr_type(self)

William Stein's avatar
William Stein committed
2693 2694 2695 2696
    def same_c_signature_as(self, other_type, as_cmethod = 0):
        return self.same_c_signature_as_resolved_type(
            other_type.resolve(), as_cmethod)

2697 2698
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod=False, as_pxd_definition=False,
                                          exact_semantics=True):
2699 2700
        # 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'.
2701

2702
        #print "CFuncType.same_c_signature_as_resolved_type:", \
Robert Bradshaw's avatar
Robert Bradshaw committed
2703
        #    self, other_type, "as_cmethod =", as_cmethod ###
William Stein's avatar
William Stein committed
2704 2705 2706 2707
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2708
        if self.is_overridable != other_type.is_overridable:
2709
            return 0
William Stein's avatar
William Stein committed
2710
        nargs = len(self.args)
Stefan Behnel's avatar
Stefan Behnel committed
2711
        if nargs != len(other_type.args):
William Stein's avatar
William Stein committed
2712 2713 2714 2715 2716
            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):
2717 2718
            if not self.args[i].type.same_as(other_type.args[i].type):
                return 0
Stefan Behnel's avatar
Stefan Behnel committed
2719
        if self.has_varargs != other_type.has_varargs:
William Stein's avatar
William Stein committed
2720
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2721
        if self.optional_arg_count != other_type.optional_arg_count:
2722
            return 0
2723 2724 2725 2726 2727 2728 2729
        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
2730 2731
        if not self.same_calling_convention_as(other_type):
            return 0
2732 2733 2734 2735 2736
        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
2737
        elif not self._is_exception_compatible_with(other_type):
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754
            return 0
        return 1

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

2757 2758
    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
2759

2760 2761
    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
2762
        #    self, other_type, "as_cmethod =", as_cmethod ###
2763 2764 2765 2766
        if other_type is error_type:
            return 1
        if not other_type.is_cfunction:
            return 0
2767
        if not self.is_overridable and other_type.is_overridable:
2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782
            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
2783
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
2784 2785 2786
            return 0
        if not self.same_calling_convention_as(other_type):
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
2787 2788
        if self.nogil != other_type.nogil:
            return 0
2789
        if not self._is_exception_compatible_with(other_type):
2790
            return 0
2791
        self.original_sig = other_type.original_sig or other_type
2792
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2793

2794
    def _is_exception_compatible_with(self, other_type):
2795 2796 2797
        # 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
2798
            return 0
2799 2800 2801 2802 2803 2804 2805
        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
2806
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
2807

2808 2809
    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
2810

2811 2812 2813 2814 2815 2816
    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
2817
        if nargs != len(other_type.args):
2818 2819 2820 2821 2822 2823 2824
            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
2825
        if self.has_varargs != other_type.has_varargs:
2826
            return 0
Stefan Behnel's avatar
Stefan Behnel committed
2827
        if self.optional_arg_count != other_type.optional_arg_count:
2828
            return 0
2829 2830
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
            return 0
2831 2832 2833
        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
2834 2835
        if not self._same_exception_value(other_type.exception_value):
            return 0
2836 2837
        return 1

2838
    def same_calling_convention_as(self, other):
2839 2840 2841 2842 2843 2844 2845 2846 2847
        ## 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
2848 2849 2850
        sc1 = self.calling_convention == '__stdcall'
        sc2 = other.calling_convention == '__stdcall'
        return sc1 == sc2
Robert Bradshaw's avatar
Robert Bradshaw committed
2851

2852 2853
    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) \
2854
            and self.nogil == other_type.nogil
Robert Bradshaw's avatar
Robert Bradshaw committed
2855

2856
    def pointer_assignable_from_resolved_type(self, rhs_type):
2857 2858 2859 2860 2861
        # Accept compatible exception/nogil declarations for the RHS.
        if rhs_type is error_type:
            return 1
        if not rhs_type.is_cfunction:
            return 0
2862 2863
        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
2864 2865

    def declaration_code(self, entity_code,
2866 2867
                         for_display = 0, dll_linkage = None, pyrex = 0,
                         with_calling_convention = 1):
William Stein's avatar
William Stein committed
2868
        arg_decl_list = []
2869
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
William Stein's avatar
William Stein committed
2870 2871
            arg_decl_list.append(
                arg.type.declaration_code("", for_display, pyrex = pyrex))
2872 2873
        if self.is_overridable:
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
2874
        if self.optional_arg_count:
2875
            arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
William Stein's avatar
William Stein committed
2876 2877
        if self.has_varargs:
            arg_decl_list.append("...")
2878
        arg_decl_code = ", ".join(arg_decl_list)
William Stein's avatar
William Stein committed
2879 2880
        if not arg_decl_code and not pyrex:
            arg_decl_code = "void"
2881
        trailer = ""
2882
        if (pyrex or for_display) and not self.return_type.is_pyobject:
William Stein's avatar
William Stein committed
2883
            if self.exception_value and self.exception_check:
2884
                trailer = " except? %s" % self.exception_value
William Stein's avatar
William Stein committed
2885
            elif self.exception_value:
2886
                trailer = " except %s" % self.exception_value
Felix Wu's avatar
Felix Wu committed
2887
            elif self.exception_check == '+':
2888
                trailer = " except +"
2889 2890 2891
            elif self.exception_check and for_display:
                # not spelled out by default, unless for human eyes
                trailer = " except *"
2892 2893
            if self.nogil:
                trailer += " nogil"
2894 2895 2896 2897 2898 2899 2900
        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
2901 2902
        if self.is_const_method:
            trailer += " const"
William Stein's avatar
William Stein committed
2903
        return self.return_type.declaration_code(
2904
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
William Stein's avatar
William Stein committed
2905
            for_display, dll_linkage, pyrex)
Robert Bradshaw's avatar
Robert Bradshaw committed
2906

2907
    def function_header_code(self, func_name, arg_code):
Robert Bradshaw's avatar
Robert Bradshaw committed
2908 2909 2910 2911 2912 2913
        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
2914

2915
    def signature_string(self):
2916
        s = self.empty_declaration_code()
2917 2918
        return s

2919 2920 2921
    def signature_cast_string(self):
        s = self.declaration_code("(*)", with_calling_convention=False)
        return '(%s)' % s
Robert Bradshaw's avatar
Robert Bradshaw committed
2922

Robert Bradshaw's avatar
Robert Bradshaw committed
2923
    def specialize(self, values):
Mark Florisson's avatar
Mark Florisson committed
2924 2925
        result = CFuncType(self.return_type.specialize(values),
                           [arg.specialize(values) for arg in self.args],
2926
                           has_varargs = self.has_varargs,
Mark Florisson's avatar
Mark Florisson committed
2927 2928 2929 2930 2931 2932 2933
                           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,
2934
                           is_const_method = self.is_const_method,
Robert Bradshaw's avatar
Robert Bradshaw committed
2935
                           is_static_method = self.is_static_method,
2936
                           templates = self.templates)
Mark Florisson's avatar
Mark Florisson committed
2937 2938 2939

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

2941 2942
    def opt_arg_cname(self, arg_name):
        return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
2943

2944 2945 2946 2947
    # 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).

2948
    def get_all_specialized_permutations(self, fused_types=None):
2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
        """
        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()

2962
        return get_all_specialized_permutations(fused_types)
2963

2964
    def get_all_specialized_function_types(self):
2965 2966 2967 2968 2969
        """
        Get all the specific function types of this one.
        """
        assert self.is_fused

2970 2971 2972 2973 2974
        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

2975
        result = []
2976
        permutations = self.get_all_specialized_permutations()
2977

2978
        new_cfunc_entries = []
2979 2980 2981
        for cname, fused_to_specific in permutations:
            new_func_type = self.entry.type.specialize(fused_to_specific)

2982 2983 2984 2985
            if self.optional_arg_count:
                # Remember, this method is set by CFuncDeclaratorNode
                self.declare_opt_arg_struct(new_func_type, cname)

2986
            new_entry = copy.deepcopy(self.entry)
Mark Florisson's avatar
Mark Florisson committed
2987
            new_func_type.specialize_entry(new_entry, cname)
2988

2989
            new_entry.type = new_func_type
2990
            new_func_type.entry = new_entry
2991 2992
            result.append(new_func_type)

2993 2994 2995 2996 2997 2998 2999 3000 3001
            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
3002

3003 3004
        self.cached_specialized_types = result

3005
        return result
3006

Mark Florisson's avatar
Mark Florisson committed
3007
    def get_fused_types(self, result=None, seen=None, subtypes=None):
Stefan Behnel's avatar
Stefan Behnel committed
3008
        """Return fused types in the order they appear as parameter types"""
Mark Florisson's avatar
Mark Florisson committed
3009 3010
        return super(CFuncType, self).get_fused_types(result, seen,
                                                      subtypes=['args'])
3011

Mark Florisson's avatar
Mark Florisson committed
3012 3013
    def specialize_entry(self, entry, cname):
        assert not self.is_fused
3014
        specialize_entry(entry, cname)
Mark Florisson's avatar
Mark Florisson committed
3015

3016 3017
    def can_coerce_to_pyobject(self, env):
        # duplicating the decisions from create_to_py_utility_code() here avoids writing out unused code
3018 3019
        if self.has_varargs or self.optional_arg_count:
            return False
3020 3021
        if self.to_py_function is not None:
            return self.to_py_function
3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034
        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
3035
        from .UtilityCode import CythonUtilityCode
3036
        safe_typename = re.sub('[^a-zA-Z0-9]', '__', self.declaration_code("", pyrex=1))
3037
        to_py_function = "__Pyx_CFunc_%s_to_py" % safe_typename
Robert Bradshaw's avatar
Robert Bradshaw committed
3038

3039 3040 3041
        for arg in self.args:
            if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
                return False
3042
        if not self.return_type.is_pyobject and not self.return_type.create_to_py_utility_code(env):
3043
            return False
3044

3045
        def declared_type(ctype):
3046
            type_displayname = str(ctype.declaration_code("", for_display=True))
3047 3048 3049 3050 3051 3052 3053 3054 3055
            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)
3056
            elif ctype is c_bint_type:
3057
                type_name = arg_ctype = 'bint'
3058
            else:
3059 3060 3061 3062 3063 3064
                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
3065

3066
        class Arg(object):
3067 3068 3069 3070
            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
3071

Stefan Behnel's avatar
Stefan Behnel committed
3072
        if self.return_type.is_void:
3073
            except_clause = 'except *'
3074 3075 3076 3077
        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
3078
        else:
3079
            except_clause = 'except *'
Robert Bradshaw's avatar
Robert Bradshaw committed
3080

3081
        context = {
3082 3083
            'cname': to_py_function,
            'args': [Arg(arg.name or 'arg%s' % ix, arg.type) for ix, arg in enumerate(self.args)],
3084
            'return_type': Arg('return', self.return_type),
3085
            'except_clause': except_clause,
3086
        }
Stefan Behnel's avatar
Stefan Behnel committed
3087
        # FIXME: directives come from first defining environment and do not adapt for reuse
3088
        env.use_utility_code(CythonUtilityCode.load(
3089
            "cfunc.to_py", "CConvert.pyx",
3090
            outer_module_scope=env.global_scope(),  # need access to types declared in module
3091
            context=context, compiler_directives=dict(env.global_scope().directives)))
3092
        self.to_py_function = to_py_function
3093 3094
        return True

Mark Florisson's avatar
Mark Florisson committed
3095

3096 3097 3098 3099
def specialize_entry(entry, cname):
    """
    Specialize an entry of a copied fused function or method
    """
3100
    entry.is_fused_specialized = True
3101
    entry.name = get_fused_cname(cname, entry.name)
Mark Florisson's avatar
Mark Florisson committed
3102

3103 3104 3105 3106 3107 3108 3109
    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)
3110

3111 3112
    if entry.func_cname:
        entry.func_cname = get_fused_cname(cname, entry.func_cname)
3113 3114 3115 3116 3117

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
3118
    assert fused_cname and orig_cname
3119 3120
    return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix,
                                                    fused_cname, orig_cname))
3121

3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
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=()):
3136
    fused_type, = fused_types[0].get_fused_types()
3137 3138
    result = []

3139
    for newid, specific_type in enumerate(fused_type.types):
3140 3141 3142 3143
        # f2s = dict(f2s, **{ fused_type: specific_type })
        f2s = dict(f2s)
        f2s.update({ fused_type: specific_type })

3144 3145 3146
        if id:
            cname = '%s_%s' % (id, newid)
        else:
3147
            cname = str(newid)
3148 3149

        if len(fused_types) > 1:
3150
            result.extend(_get_all_specialized_permutations(
3151 3152 3153 3154 3155 3156
                                            fused_types[1:], cname, f2s))
        else:
            result.append((cname, f2s))

    return result

3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181
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()

3182

3183 3184
def get_specialized_types(type):
    """
3185
    Return a list of specialized types in their declared order.
3186
    """
3187 3188
    assert type.is_fused

3189
    if isinstance(type, FusedType):
3190
        result = list(type.types)
3191 3192
        for specialized_type in result:
            specialized_type.specialization_string = specialized_type.typeof_name()
3193 3194
    else:
        result = []
3195
        for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
3196 3197 3198 3199
            specialized_type = type.specialize(f2s)
            specialized_type.specialization_string = (
                            specialization_signature_string(type, f2s))
            result.append(specialized_type)
3200

3201
    return result
3202

William Stein's avatar
William Stein committed
3203

3204
class CFuncTypeArg(BaseType):
William Stein's avatar
William Stein committed
3205 3206 3207 3208
    #  name       string
    #  cname      string
    #  type       PyrexType
    #  pos        source file position
3209 3210 3211 3212 3213

    # 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
3214
    accept_builtin_subtypes = False
3215
    annotation = None
3216

3217 3218
    subtypes = ['type']

3219
    def __init__(self, name, type, pos, cname=None, annotation=None):
William Stein's avatar
William Stein committed
3220
        self.name = name
3221 3222 3223 3224
        if cname is not None:
            self.cname = cname
        else:
            self.cname = Naming.var_prefix + name
3225 3226
        if annotation is not None:
            self.annotation = annotation
William Stein's avatar
William Stein committed
3227 3228
        self.type = type
        self.pos = pos
3229
        self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
Robert Bradshaw's avatar
Robert Bradshaw committed
3230

William Stein's avatar
William Stein committed
3231 3232
    def __repr__(self):
        return "%s:%s" % (self.name, repr(self.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
3233

William Stein's avatar
William Stein committed
3234 3235
    def declaration_code(self, for_display = 0):
        return self.type.declaration_code(self.cname, for_display)
Robert Bradshaw's avatar
Robert Bradshaw committed
3236

Robert Bradshaw's avatar
Robert Bradshaw committed
3237 3238
    def specialize(self, values):
        return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
William Stein's avatar
William Stein committed
3239

3240

Mark Florisson's avatar
Mark Florisson committed
3241
class ToPyStructUtilityCode(object):
3242 3243 3244

    requires = None

3245
    def __init__(self, type, forward_decl, env):
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3246
        self.type = type
Mark Florisson's avatar
Mark Florisson committed
3247 3248
        self.header = "static PyObject* %s(%s)" % (type.to_py_function,
                                                   type.declaration_code('s'))
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3249
        self.forward_decl = forward_decl
3250
        self.env = env
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3251 3252

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

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3255 3256
    def __hash__(self):
        return hash(self.header)
Robert Bradshaw's avatar
Robert Bradshaw committed
3257

3258
    def get_tree(self, **kwargs):
3259
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3260

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3261 3262 3263
    def put_code(self, output):
        code = output['utility_code_def']
        proto = output['utility_code_proto']
Robert Bradshaw's avatar
Robert Bradshaw committed
3264

Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3265 3266 3267
        code.putln("%s {" % self.header)
        code.putln("PyObject* res;")
        code.putln("PyObject* member;")
3268 3269
        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
3270 3271
        for member in self.type.scope.var_entries:
            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
3272
            code.putln("%s; if (unlikely(!member)) goto bad;" % (
3273
                member.type.to_py_call_code('s.%s' % member.cname, 'member', member.type)))
3274
            code.putln("if (unlikely(PyDict_SetItem(res, %s, member) < 0)) goto bad;" % nameconst_cname)
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
            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:
3286
            proto.putln(self.type.empty_declaration_code() + ';')
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3287
        proto.putln(self.header + ";")
Robert Bradshaw's avatar
Robert Bradshaw committed
3288

3289 3290
    def inject_tree_and_scope_into(self, module_node):
        pass
Vitja Makarov's avatar
Vitja Makarov committed
3291

William Stein's avatar
William Stein committed
3292 3293 3294 3295 3296 3297 3298

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

3301
    # entry          Entry
Robert Bradshaw's avatar
Robert Bradshaw committed
3302

William Stein's avatar
William Stein committed
3303 3304
    is_struct_or_union = 1
    has_attributes = 1
Mark Florisson's avatar
Mark Florisson committed
3305
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3306

3307
    def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
William Stein's avatar
William Stein committed
3308 3309 3310 3311 3312
        self.name = name
        self.cname = cname
        self.kind = kind
        self.scope = scope
        self.typedef_flag = typedef_flag
Robert Bradshaw's avatar
Robert Bradshaw committed
3313
        self.is_struct = kind == 'struct'
3314 3315 3316 3317
        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
3318
        self.exception_check = True
Mark Florisson's avatar
Mark Florisson committed
3319 3320
        self._convert_to_py_code = None
        self._convert_from_py_code = None
3321
        self.packed = packed
Robert Bradshaw's avatar
Robert Bradshaw committed
3322

3323
    def can_coerce_to_pyobject(self, env):
Stefan Behnel's avatar
Stefan Behnel committed
3324 3325
        if self._convert_to_py_code is False:
            return None  # tri-state-ish
Dag Sverre Seljebotn's avatar
Dag Sverre Seljebotn committed
3326

3327 3328 3329
        if env.outer_scope is None:
            return False

Mark Florisson's avatar
Mark Florisson committed
3330
        if self._convert_to_py_code is None:
3331 3332 3333
            is_union = not self.is_struct
            unsafe_union_types = set()
            safe_union_types = set()
Robert Bradshaw's avatar
Robert Bradshaw committed
3334
            for member in self.scope.var_entries:
3335
                member_type = member.type
3336
                if not member_type.can_coerce_to_pyobject(env):
Robert Bradshaw's avatar
Robert Bradshaw committed
3337
                    self.to_py_function = None
Mark Florisson's avatar
Mark Florisson committed
3338
                    self._convert_to_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3339
                    return False
3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351
                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

3352 3353 3354 3355 3356 3357 3358 3359 3360
        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)
3361 3362
            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
3363

Mark Florisson's avatar
Mark Florisson committed
3364 3365 3366
        env.use_utility_code(self._convert_to_py_code)
        return True

Robert Bradshaw's avatar
Robert Bradshaw committed
3367
    def can_coerce_from_pyobject(self, env):
3368 3369 3370
        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
3371
            if not member.type.can_coerce_from_pyobject(env):
3372 3373 3374
                return False
        return True

Mark Florisson's avatar
Mark Florisson committed
3375 3376 3377 3378
    def create_from_py_utility_code(self, env):
        if env.outer_scope is None:
            return False

Stefan Behnel's avatar
Stefan Behnel committed
3379 3380
        if self._convert_from_py_code is False:
            return None  # tri-state-ish
Mark Florisson's avatar
Mark Florisson committed
3381 3382

        if self._convert_from_py_code is None:
3383 3384 3385 3386 3387
            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
3388
            for member in self.scope.var_entries:
3389
                if not member.type.create_from_py_utility_code(env):
Mark Florisson's avatar
Mark Florisson committed
3390 3391
                    self.from_py_function = None
                    self._convert_from_py_code = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3392
                    return False
Mark Florisson's avatar
Mark Florisson committed
3393 3394

            context = dict(
3395
                struct_type=self,
Stefan Behnel's avatar
Stefan Behnel committed
3396 3397
                var_entries=self.scope.var_entries,
                funcname=self.from_py_function,
Mark Florisson's avatar
Mark Florisson committed
3398
            )
3399 3400
            from .UtilityCode import CythonUtilityCode
            self._convert_from_py_code = CythonUtilityCode.load(
3401 3402
                "FromPyStructUtility" if self.is_struct else "FromPyUnionUtility",
                "CConvert.pyx",
3403 3404
                outer_module_scope=env.global_scope(),  # need access to types declared in module
                context=context)
Mark Florisson's avatar
Mark Florisson committed
3405 3406

        env.use_utility_code(self._convert_from_py_code)
Robert Bradshaw's avatar
Robert Bradshaw committed
3407
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3408

William Stein's avatar
William Stein committed
3409
    def __repr__(self):
Stefan Behnel's avatar
Stefan Behnel committed
3410 3411
        return "<CStructOrUnionType %s %s%s>" % (
            self.name, self.cname,
3412
            ("", " typedef")[self.typedef_flag])
William Stein's avatar
William Stein committed
3413

Robert Bradshaw's avatar
Robert Bradshaw committed
3414
    def declaration_code(self, entity_code,
Stefan Behnel's avatar
Stefan Behnel committed
3415
                         for_display=0, dll_linkage=None, pyrex=0):
3416 3417
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3418
        else:
3419 3420
            if self.typedef_flag:
                base_code = self.cname
William Stein's avatar
William Stein committed
3421
            else:
3422 3423 3424
                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
3425

3426
    def __eq__(self, other):
3427
        try:
Stefan Behnel's avatar
Stefan Behnel committed
3428 3429
            return (isinstance(other, CStructOrUnionType) and
                    self.name == other.name)
3430
        except AttributeError:
3431 3432 3433 3434 3435 3436 3437 3438 3439
            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
3440

Stefan Behnel's avatar
Stefan Behnel committed
3441
    def __hash__(self):
3442
        return hash(self.cname) ^ hash(self.kind)
Stefan Behnel's avatar
Stefan Behnel committed
3443

William Stein's avatar
William Stein committed
3444 3445
    def is_complete(self):
        return self.scope is not None
Robert Bradshaw's avatar
Robert Bradshaw committed
3446

William Stein's avatar
William Stein committed
3447 3448 3449
    def attributes_known(self):
        return self.is_complete()

3450
    def can_be_complex(self):
3451
        # Does the struct consist of exactly two identical floats?
3452
        fields = self.scope.var_entries
3453 3454 3455
        if len(fields) != 2: return False
        a, b = fields
        return (a.type.is_float and b.type.is_float and
3456 3457
                a.type.empty_declaration_code() ==
                b.type.empty_declaration_code())
3458

3459 3460 3461 3462
    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
3463

3464 3465 3466 3467 3468
    def cast_code(self, expr_code):
        if self.is_struct:
            return expr_code
        return super(CStructOrUnionType, self).cast_code(expr_code)

3469
cpp_string_conversions = ("std::string",)
3470

3471 3472 3473 3474 3475 3476 3477 3478 3479
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,
3480
    "std::complex":       1,
3481
}
3482

3483 3484 3485 3486
class CppClassType(CType):
    #  name          string
    #  cname         string
    #  scope         CppClassScope
Danilo Freitas's avatar
Danilo Freitas committed
3487
    #  templates     [string] or None
Robert Bradshaw's avatar
Robert Bradshaw committed
3488

3489 3490
    is_cpp_class = 1
    has_attributes = 1
3491
    exception_check = True
Robert Bradshaw's avatar
Robert Bradshaw committed
3492
    namespace = None
Robert Bradshaw's avatar
Robert Bradshaw committed
3493

3494 3495 3496 3497
    # For struct-like declaration.
    kind = "struct"
    packed = False
    typedef_flag = False
Robert Bradshaw's avatar
Robert Bradshaw committed
3498

3499 3500
    subtypes = ['templates']

3501
    def __init__(self, name, scope, cname, base_classes, templates=None, template_type=None):
3502 3503 3504
        self.name = name
        self.cname = cname
        self.scope = scope
DaniloFreitas's avatar
DaniloFreitas committed
3505
        self.base_classes = base_classes
DaniloFreitas's avatar
DaniloFreitas committed
3506
        self.operators = []
Danilo Freitas's avatar
Danilo Freitas committed
3507
        self.templates = templates
3508
        self.template_type = template_type
3509
        self.num_optional_templates = sum(is_optional_template_param(T) for T in templates or ())
Robert Bradshaw's avatar
Robert Bradshaw committed
3510 3511 3512 3513
        if templates:
            self.specializations = {tuple(zip(templates, templates)): self}
        else:
            self.specializations = {}
3514
        self.is_cpp_string = cname in cpp_string_conversions
3515

3516 3517
    def use_conversion_utility(self, from_or_to):
        pass
Robert Bradshaw's avatar
Robert Bradshaw committed
3518

3519 3520 3521 3522 3523 3524
    def maybe_unordered(self):
        if 'unordered' in self.cname:
            return 'unordered_'
        else:
            return ''

3525
    def can_coerce_from_pyobject(self, env):
3526 3527
        if self.cname in builtin_cpp_conversions:
            template_count = builtin_cpp_conversions[self.cname]
3528
            for ix, T in enumerate(self.templates or []):
3529
                if ix >= template_count:
3530 3531 3532 3533
                    break
                if T.is_pyobject or not T.can_coerce_from_pyobject(env):
                    return False
            return True
3534 3535 3536
        elif self.cname in cpp_string_conversions:
            return True
        return False
3537

3538 3539 3540
    def create_from_py_utility_code(self, env):
        if self.from_py_function is not None:
            return True
3541
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3542
            X = "XYZABC"
3543
            tags = []
3544
            context = {}
3545
            for ix, T in enumerate(self.templates or []):
3546 3547
                if ix >= builtin_cpp_conversions[self.cname]:
                    break
3548
                if T.is_pyobject or not T.create_from_py_utility_code(env):
3549 3550
                    return False
                tags.append(T.specialization_name())
3551 3552
                context[X[ix]] = T

3553 3554
            if self.cname in cpp_string_conversions:
                cls = 'string'
3555
                tags = type_identifier(self),
3556 3557
            else:
                cls = self.cname[5:]
3558
            cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
3559
            context.update({
3560 3561
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3562
                'type': self.cname,
3563
            })
3564
            from .UtilityCode import CythonUtilityCode
3565
            env.use_utility_code(CythonUtilityCode.load(
3566 3567
                cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx",
                context=context, compiler_directives=env.directives))
3568 3569
            self.from_py_function = cname
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3570

3571
    def can_coerce_to_pyobject(self, env):
3572 3573 3574 3575 3576 3577 3578 3579
        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

3580

3581 3582 3583
    def create_to_py_utility_code(self, env):
        if self.to_py_function is not None:
            return True
3584
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
3585
            X = "XYZABC"
3586
            tags = []
3587
            context = {}
3588
            for ix, T in enumerate(self.templates or []):
3589 3590
                if ix >= builtin_cpp_conversions[self.cname]:
                    break
3591 3592 3593
                if not T.create_to_py_utility_code(env):
                    return False
                tags.append(T.specialization_name())
3594 3595
                context[X[ix]] = T

3596 3597 3598
            if self.cname in cpp_string_conversions:
                cls = 'string'
                prefix = 'PyObject_'  # gets specialised by explicit type casts in CoerceToPyTypeNode
3599
                tags = type_identifier(self),
3600 3601 3602 3603
            else:
                cls = self.cname[5:]
                prefix = ''
            cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags))
3604
            context.update({
3605 3606
                'cname': cname,
                'maybe_unordered': self.maybe_unordered(),
3607
                'type': self.cname,
3608
            })
3609
            from .UtilityCode import CythonUtilityCode
3610
            env.use_utility_code(CythonUtilityCode.load(
3611 3612
                cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx",
                context=context, compiler_directives=env.directives))
3613 3614 3615
            self.to_py_function = cname
            return True

3616 3617 3618
    def is_template_type(self):
        return self.templates is not None and self.template_type is None

3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629
    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

3630
    def specialize_here(self, pos, template_values=None):
3631
        if not self.is_template_type():
Stefan Behnel's avatar
Stefan Behnel committed
3632 3633
            error(pos, "'%s' type is not a template" % self)
            return error_type
3634
        if len(self.templates) - self.num_optional_templates <= len(template_values) < len(self.templates):
3635
            num_defaults = len(self.templates) - len(template_values)
3636
            partial_specialization = self.declaration_code('', template_params=template_values)
3637 3638 3639 3640 3641 3642 3643 3644
            # 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.
3645
            template_values = template_values + [
3646 3647 3648
                TemplatePlaceholderType(
                    "%s::%s" % (partial_specialization, param.name), True)
                for param in self.templates[-num_defaults:]]
3649
        if len(self.templates) != len(template_values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3650
            error(pos, "%s templated type receives %d arguments, got %d" %
3651 3652
                  (self.name, len(self.templates), len(template_values)))
            return error_type
3653 3654 3655 3656 3657 3658 3659 3660
        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
3661
        return self.specialize(dict(zip(self.templates, template_values)))
Robert Bradshaw's avatar
Robert Bradshaw committed
3662

3663
    def specialize(self, values):
Robert Bradshaw's avatar
Robert Bradshaw committed
3664
        if not self.templates and not self.namespace:
3665
            return self
Robert Bradshaw's avatar
Robert Bradshaw committed
3666 3667
        if self.templates is None:
            self.templates = []
3668
        key = tuple(values.items())
Robert Bradshaw's avatar
Robert Bradshaw committed
3669 3670
        if key in self.specializations:
            return self.specializations[key]
3671
        template_values = [t.specialize(values) for t in self.templates]
Robert Bradshaw's avatar
Robert Bradshaw committed
3672
        specialized = self.specializations[key] = \
3673
            CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
Robert Bradshaw's avatar
Robert Bradshaw committed
3674 3675
        # Need to do these *after* self.specializations[key] is set
        # to avoid infinite recursion on circular references.
3676
        specialized.base_classes = [b.specialize(values) for b in self.base_classes]
Robert Bradshaw's avatar
Robert Bradshaw committed
3677 3678
        if self.namespace is not None:
            specialized.namespace = self.namespace.specialize(values)
3679
        specialized.scope = self.scope.specialize(values, specialized)
3680 3681 3682 3683 3684 3685 3686 3687
        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).
3688 3689
          T = values.get(self.templates[0], None)
          if T and not T.is_fused and T.empty_declaration_code() == 'bool':
3690 3691 3692
            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
3693
        return specialized
3694

3695
    def deduce_template_params(self, actual):
3696 3697 3698 3699
        if actual.is_const:
            actual = actual.const_base_type
        if actual.is_reference:
            actual = actual.ref_base_type
3700 3701
        if self == actual:
            return {}
3702
        elif actual.is_cpp_class:
3703
            self_template_type = self
3704 3705
            while getattr(self_template_type, 'template_type', None):
                self_template_type = self_template_type.template_type
3706 3707 3708 3709 3710 3711
            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):
3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722
                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)],
                            {})
3723
        else:
3724
            return {}
3725

3726
    def declaration_code(self, entity_code,
3727 3728 3729 3730
            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
3731
        if self.templates:
3732
            template_strings = [param.declaration_code('', for_display, None, pyrex)
3733
                                for param in template_params
3734
                                if not is_optional_template_param(param) and not param.is_fused]
3735 3736 3737
            if for_display:
                brackets = "[%s]"
            else:
3738
                brackets = "<%s> "
3739
            templates = brackets % ",".join(template_strings)
3740 3741
        else:
            templates = ""
3742 3743
        if pyrex or for_display:
            base_code = "%s%s" % (self.name, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3744
        else:
3745
            base_code = "%s%s" % (self.cname, templates)
Robert Bradshaw's avatar
Robert Bradshaw committed
3746
            if self.namespace is not None:
3747
                base_code = "%s::%s" % (self.namespace.empty_declaration_code(), base_code)
3748 3749
            base_code = public_decl(base_code, dll_linkage)
        return self.base_declaration_code(base_code, entity_code)
3750 3751

    def is_subclass(self, other_type):
3752 3753
        if self.same_as_resolved_type(other_type):
            return 1
3754 3755 3756
        for base_class in self.base_classes:
            if base_class.is_subclass(other_type):
                return 1
3757
        return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3758

Robert Bradshaw's avatar
Robert Bradshaw committed
3759 3760 3761 3762 3763 3764 3765 3766
    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)

3767 3768 3769 3770
    def same_as_resolved_type(self, other_type):
        if other_type.is_cpp_class:
            if self == other_type:
                return 1
3771 3772 3773 3774 3775
            # 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)):
3776 3777
                if self.templates == other_type.templates:
                    return 1
3778
                for t1, t2 in zip(self.templates, other_type.templates):
3779 3780
                    if is_optional_template_param(t1) and is_optional_template_param(t2):
                      break
3781 3782 3783 3784
                    if not t1.same_as_resolved_type(t2):
                        return 0
                return 1
        return 0
3785

3786 3787
    def assignable_from_resolved_type(self, other_type):
        # TODO: handle operator=(...) here?
3788 3789
        if other_type is error_type:
            return True
3790 3791
        elif other_type.is_cpp_class:
            return other_type.is_subclass(self)
3792 3793
        elif other_type.is_string and self.cname in cpp_string_conversions:
            return True
Robert Bradshaw's avatar
Robert Bradshaw committed
3794

Robert Bradshaw's avatar
Robert Bradshaw committed
3795 3796 3797
    def attributes_known(self):
        return self.scope is not None

3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
    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

3811 3812 3813 3814 3815
    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)

3816

3817
class TemplatePlaceholderType(CType):
Robert Bradshaw's avatar
Robert Bradshaw committed
3818

3819
    def __init__(self, name, optional=False):
Danilo Freitas's avatar
Danilo Freitas committed
3820
        self.name = name
3821
        self.optional = optional
Robert Bradshaw's avatar
Robert Bradshaw committed
3822 3823

    def declaration_code(self, entity_code,
3824
            for_display = 0, dll_linkage = None, pyrex = 0):
3825 3826 3827 3828
        if entity_code:
            return self.name + " " + entity_code
        else:
            return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3829

3830 3831 3832 3833 3834 3835
    def specialize(self, values):
        if self in values:
            return values[self]
        else:
            return self

Robert Bradshaw's avatar
Robert Bradshaw committed
3836 3837 3838
    def deduce_template_params(self, actual):
        return {self: actual}

3839 3840
    def same_as_resolved_type(self, other_type):
        if isinstance(other_type, TemplatePlaceholderType):
3841
            return self.name == other_type.name
3842 3843
        else:
            return 0
Robert Bradshaw's avatar
Robert Bradshaw committed
3844

3845 3846
    def __hash__(self):
        return hash(self.name)
Robert Bradshaw's avatar
Robert Bradshaw committed
3847

3848 3849 3850 3851 3852
    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
3853

Robert Bradshaw's avatar
Robert Bradshaw committed
3854 3855 3856 3857 3858 3859
    def __eq__(self, other):
        if isinstance(other, TemplatePlaceholderType):
            return self.name == other.name
        else:
            return False

3860 3861 3862
def is_optional_template_param(type):
    return isinstance(type, TemplatePlaceholderType) and type.optional

3863

3864
class CEnumType(CIntLike, CType):
William Stein's avatar
William Stein committed
3865 3866 3867
    #  name           string
    #  cname          string or None
    #  typedef_flag   boolean
3868
    #  values         [string], populated during declaration analysis
3869

William Stein's avatar
William Stein committed
3870
    is_enum = 1
3871 3872
    signed = 1
    rank = -1 # Ranks below any integer type
William Stein's avatar
William Stein committed
3873

3874
    def __init__(self, name, cname, typedef_flag, namespace=None):
William Stein's avatar
William Stein committed
3875 3876 3877 3878
        self.name = name
        self.cname = cname
        self.values = []
        self.typedef_flag = typedef_flag
3879
        self.namespace = namespace
3880
        self.default_value = "(%s) 0" % self.empty_declaration_code()
Robert Bradshaw's avatar
Robert Bradshaw committed
3881

3882 3883
    def __str__(self):
        return self.name
Robert Bradshaw's avatar
Robert Bradshaw committed
3884

William Stein's avatar
William Stein committed
3885
    def __repr__(self):
3886 3887
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
            ("", " typedef")[self.typedef_flag])
Robert Bradshaw's avatar
Robert Bradshaw committed
3888 3889

    def declaration_code(self, entity_code,
William Stein's avatar
William Stein committed
3890
            for_display = 0, dll_linkage = None, pyrex = 0):
3891 3892
        if pyrex or for_display:
            base_code = self.name
William Stein's avatar
William Stein committed
3893
        else:
3894 3895 3896 3897
            if self.namespace:
                base_code = "%s::%s" % (
                    self.namespace.empty_declaration_code(), self.cname)
            elif self.typedef_flag:
3898
                base_code = self.cname
William Stein's avatar
William Stein committed
3899
            else:
3900 3901 3902
                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
3903

3904 3905 3906 3907 3908 3909 3910 3911
    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

3912 3913 3914 3915 3916 3917 3918 3919
    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()))

3920

3921 3922 3923
class CTupleType(CType):
    # components [PyrexType]

Robert Bradshaw's avatar
Robert Bradshaw committed
3924 3925
    is_ctuple = True

3926 3927 3928
    def __init__(self, cname, components):
        self.cname = cname
        self.components = components
Robert Bradshaw's avatar
Robert Bradshaw committed
3929
        self.size = len(components)
3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945
        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)

3946 3947 3948 3949 3950 3951
    def can_coerce_to_pyobject(self, env):
        for component in self.components:
            if not component.can_coerce_to_pyobject(env):
                return False
        return True

3952 3953 3954 3955 3956 3957
    def can_coerce_from_pyobject(self, env):
        for component in self.components:
            if not component.can_coerce_from_pyobject(env):
                return False
        return True

3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969
    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(
3970
                struct_type_decl=self.empty_declaration_code(),
3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
                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(
3993
                struct_type_decl=self.empty_declaration_code(),
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003
                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

4004

4005
def c_tuple_type(components):
Robert Bradshaw's avatar
Robert Bradshaw committed
4006
    components = tuple(components)
4007 4008
    cname = Naming.ctuple_type_prefix + type_list_identifier(components)
    tuple_type = CTupleType(cname, components)
4009
    return tuple_type
4010 4011


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

Robert Bradshaw's avatar
Robert Bradshaw committed
4015
    is_unspecified = 1
Robert Bradshaw's avatar
Robert Bradshaw committed
4016 4017

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

Robert Bradshaw's avatar
Robert Bradshaw committed
4021 4022
    def same_as_resolved_type(self, other_type):
        return False
Robert Bradshaw's avatar
Robert Bradshaw committed
4023

Robert Bradshaw's avatar
Robert Bradshaw committed
4024

William Stein's avatar
William Stein committed
4025 4026
class ErrorType(PyrexType):
    # Used to prevent propagation of error messages.
Robert Bradshaw's avatar
Robert Bradshaw committed
4027

William Stein's avatar
William Stein committed
4028 4029
    is_error = 1
    exception_value = "0"
Robert Bradshaw's avatar
Robert Bradshaw committed
4030
    exception_check    = 0
William Stein's avatar
William Stein committed
4031 4032
    to_py_function = "dummy"
    from_py_function = "dummy"
Robert Bradshaw's avatar
Robert Bradshaw committed
4033

4034 4035
    def create_to_py_utility_code(self, env):
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
4036

4037
    def create_from_py_utility_code(self, env):
Robert Bradshaw's avatar
Robert Bradshaw committed
4038
        return True
Robert Bradshaw's avatar
Robert Bradshaw committed
4039 4040

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

William Stein's avatar
William Stein committed
4044 4045
    def same_as_resolved_type(self, other_type):
        return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
4046

4047 4048
    def error_condition(self, result_code):
        return "dummy"
William Stein's avatar
William Stein committed
4049 4050


4051 4052 4053
rank_to_type_name = (
    "char",         # 0
    "short",        # 1
4054 4055 4056 4057 4058 4059
    "int",          # 2
    "long",         # 3
    "PY_LONG_LONG", # 4
    "float",        # 5
    "double",       # 6
    "long double",  # 7
4060 4061
)

4062 4063 4064 4065
_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')
4066 4067 4068
UNSIGNED = 0
SIGNED = 2

4069 4070
error_type =    ErrorType()
unspecified_type = UnspecifiedType()
4071

William Stein's avatar
William Stein committed
4072 4073
py_object_type = PyObjectType()

4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086
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
4087

4088 4089 4090 4091 4092 4093 4094 4095 4096
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
4097

4098 4099 4100
c_float_complex_type =      CComplexType(c_float_type)
c_double_complex_type =     CComplexType(c_double_type)
c_longdouble_complex_type = CComplexType(c_longdouble_type)
4101

4102 4103 4104 4105
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
4106
c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
4107
c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
4108 4109 4110
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
4111
c_ptrdiff_t_type =   CPtrdiffTType(RANK_LONG+0.75, SIGNED)
4112

William Stein's avatar
William Stein committed
4113
c_null_ptr_type =     CNullPtrType(c_void_type)
4114 4115
c_void_ptr_type =     CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
4116
c_char_ptr_type =     CPtrType(c_char_type)
4117
c_const_char_ptr_type = CPtrType(CConstType(c_char_type))
4118
c_uchar_ptr_type =    CPtrType(c_uchar_type)
4119
c_const_uchar_ptr_type = CPtrType(CConstType(c_uchar_type))
William Stein's avatar
William Stein committed
4120 4121
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
4122
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
4123
c_const_py_unicode_ptr_type = CPtrType(CConstType(c_py_unicode_type))
4124
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
4125
c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
4126
c_size_t_ptr_type =  CPtrType(c_size_t_type)
William Stein's avatar
William Stein committed
4127

4128 4129 4130 4131
# 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)
4132

4133 4134 4135
# PEP-539 "Py_tss_t" type
c_pytss_t_type = CPyTSSTType()

4136
# the Py_buffer type is defined in Builtin.py
4137 4138
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
4139

4140 4141 4142
# 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
4143 4144
cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type],
                             name="integral")
4145 4146
# Omitting long double as it might be slow
cy_floating_type = FusedType([c_float_type, c_double_type], name="floating")
4147 4148 4149 4150
cy_numeric_type = FusedType([c_short_type,
                             c_int_type,
                             c_long_type,
                             c_float_type,
4151
                             c_double_type,
4152
                             c_float_complex_type,
4153 4154
                             c_double_complex_type], name="numeric")

4155 4156 4157 4158 4159 4160 4161 4162
# 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")

4163 4164
cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
                                      None, 0, "__pyx_memoryview_obj")
4165

4166 4167
memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
                                          None, 1, "__Pyx_memviewslice")
4168

William Stein's avatar
William Stein committed
4169
modifiers_and_name_to_type = {
4170 4171 4172 4173 4174
    #(signed, longness, name) : type
    (0,  0, "char"): c_uchar_type,
    (1,  0, "char"): c_char_type,
    (2,  0, "char"): c_schar_type,

4175
    (0, -1, "int"): c_ushort_type,
4176 4177 4178 4179
    (0,  0, "int"): c_uint_type,
    (0,  1, "int"): c_ulong_type,
    (0,  2, "int"): c_ulonglong_type,

4180
    (1, -1, "int"): c_short_type,
4181 4182 4183 4184
    (1,  0, "int"): c_int_type,
    (1,  1, "int"): c_long_type,
    (1,  2, "int"): c_longlong_type,

4185
    (2, -1, "int"): c_sshort_type,
4186 4187 4188 4189 4190 4191 4192
    (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,
4193

4194
    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
4195 4196 4197 4198 4199 4200
    (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,
4201
    (1,  0, "Py_tss_t"): c_pytss_t_type,
4202 4203 4204

    (1,  0, "bint"):       c_bint_type,
    (0,  0, "Py_UNICODE"): c_py_unicode_type,
Stefan Behnel's avatar
Stefan Behnel committed
4205
    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
4206
    (2,  0, "Py_hash_t"):  c_py_hash_t_type,
4207 4208 4209
    (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,
4210
    (2,  0, "ptrdiff_t") : c_ptrdiff_t_type,
4211

4212
    (1,  0, "object"): py_object_type,
William Stein's avatar
William Stein committed
4213 4214
}

4215 4216
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
4217
    # evidence suggests that the below is all that's allowed.
4218 4219
    if src_type.is_numeric:
        if dst_type.same_as(c_int_type):
4220 4221 4222 4223
            unsigned = (not src_type.signed)
            return (src_type.is_enum or
                    (src_type.is_int and
                     unsigned + src_type.rank < dst_type.rank))
4224 4225 4226 4227
        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
4228
def best_match(arg_types, functions, pos=None, env=None, args=None):
Robert Bradshaw's avatar
merge  
Robert Bradshaw committed
4229
    """
4230 4231 4232 4233 4234 4235 4236 4237 4238 4239
    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
4240
      * promotions
4241 4242 4243 4244 4245 4246 4247 4248
      * 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
4249
    """
Robert Bradshaw's avatar
Robert Bradshaw committed
4250
    # TODO: args should be a list of types, not a list of Nodes.
4251
    actual_nargs = len(arg_types)
4252 4253 4254

    candidates = []
    errors = []
4255
    for func in functions:
4256
        error_mesg = ""
4257 4258 4259
        func_type = func.type
        if func_type.is_ptr:
            func_type = func_type.base_type
4260 4261
        # Check function type
        if not func_type.is_cfunction:
4262
            if not func_type.is_error and pos is not None:
4263 4264 4265
                error_mesg = "Calling non-function type '%s'" % func_type
            errors.append((func, error_mesg))
            continue
4266 4267 4268
        # Check no. of args
        max_nargs = len(func_type.args)
        min_nargs = max_nargs - func_type.optional_arg_count
4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280
        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
4281 4282 4283 4284 4285
        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)],
                {})
4286
            if deductions is None:
Joe Jevnik's avatar
Joe Jevnik committed
4287
                errors.append((func, "Unable to deduce type parameters for %s given (%s)" % (func_type, ', '.join(map(str, arg_types)))))
4288 4289 4290 4291 4292
            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]
4293
                from .Symtab import Entry
4294 4295
                specialization = Entry(
                    name = func.name + "[%s]" % ",".join([str(t) for t in type_list]),
4296
                    cname = func.cname + "<%s>" % ",".join([t.empty_declaration_code() for t in type_list]),
4297 4298 4299
                    type = func_type.specialize(deductions),
                    pos = func.pos)
                candidates.append((specialization, specialization.type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4300 4301
        else:
            candidates.append((func, func_type))
Robert Bradshaw's avatar
Robert Bradshaw committed
4302

4303 4304
    # Optimize the most common case of no overloading...
    if len(candidates) == 1:
4305
        return candidates[0][0]
4306
    elif len(candidates) == 0:
4307
        if pos is not None:
4308 4309 4310
            func, errmsg = errors[0]
            if len(errors) == 1 or [1 for func, e in errors if e == errmsg]:
                error(pos, errmsg)
4311 4312
            else:
                error(pos, "no suitable method found")
4313
        return None
Robert Bradshaw's avatar
Robert Bradshaw committed
4314

4315 4316
    possibilities = []
    bad_types = []
4317
    needed_coercions = {}
Mark Florisson's avatar
merge  
Mark Florisson committed
4318

4319
    for index, (func, func_type) in enumerate(candidates):
Robert Bradshaw's avatar
Robert Bradshaw committed
4320
        score = [0,0,0,0,0,0,0]
Robert Bradshaw's avatar
Robert Bradshaw committed
4321 4322
        for i in range(min(actual_nargs, len(func_type.args))):
            src_type = arg_types[i]
4323
            dst_type = func_type.args[i].type
4324 4325 4326

            assignable = dst_type.assignable_from(src_type)

4327
            # Now take care of unprefixed string literals. So when you call a cdef
4328 4329 4330
            # 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
4331 4332 4333 4334 4335 4336 4337 4338 4339
            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
4340

4341
                if c_src_type is not None:
4342 4343 4344
                    assignable = dst_type.assignable_from(c_src_type)
                    if assignable:
                        src_type = c_src_type
Stefan Behnel's avatar
Stefan Behnel committed
4345
                        needed_coercions[func] = (i, dst_type)
4346 4347

            if assignable:
Robert Bradshaw's avatar
Robert Bradshaw committed
4348
                if src_type == dst_type or dst_type.same_as(src_type):
Stefan Behnel's avatar
Stefan Behnel committed
4349
                    pass  # score 0
4350
                elif func_type.is_strict_signature:
Stefan Behnel's avatar
Stefan Behnel committed
4351
                    break  # exact match requested but not found
4352 4353
                elif is_promotion(src_type, dst_type):
                    score[2] += 1
4354 4355
                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
4356
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
4357
                                    (src_type.rank + (not src_type.signed))) + 1
Robert Bradshaw's avatar
Robert Bradshaw committed
4358 4359 4360 4361 4362 4363 4364
                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
4365 4366 4367 4368 4369
                elif not src_type.is_pyobject:
                    score[1] += 1
                else:
                    score[0] += 1
            else:
Stefan Behnel's avatar
Stefan Behnel committed
4370
                error_mesg = "Invalid conversion from '%s' to '%s'" % (src_type, dst_type)
4371
                bad_types.append((func, error_mesg))
4372 4373
                break
        else:
Stefan Behnel's avatar
Stefan Behnel committed
4374
            possibilities.append((score, index, func))  # so we can sort it
4375

4376
    if possibilities:
4377
        possibilities.sort()
4378 4379 4380 4381 4382 4383 4384
        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
4385

Mark Florisson's avatar
merge  
Mark Florisson committed
4386
        function = possibilities[0][-1]
4387 4388 4389 4390 4391 4392 4393

        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

4394
    if pos is not None:
4395 4396
        if len(bad_types) == 1:
            error(pos, bad_types[0][1])
4397
        else:
4398
            error(pos, "no suitable method found")
4399

4400 4401
    return None

Robert Bradshaw's avatar
Robert Bradshaw committed
4402 4403 4404 4405
def merge_template_deductions(a, b):
    if a is None or b is None:
        return None
    all = a
4406
    for param, value in b.items():
Robert Bradshaw's avatar
Robert Bradshaw committed
4407 4408 4409 4410 4411 4412 4413
        if param in all:
            if a[param] != b[param]:
                return None
        else:
            all[param] = value
    return all

4414

William Stein's avatar
William Stein committed
4415
def widest_numeric_type(type1, type2):
Stefan Behnel's avatar
Stefan Behnel committed
4416 4417
    """Given two numeric types, return the narrowest type encompassing both of them.
    """
4418 4419 4420 4421
    if type1.is_reference:
        type1 = type1.ref_base_type
    if type2.is_reference:
        type2 = type2.ref_base_type
4422 4423 4424 4425
    if type1.is_const:
        type1 = type1.const_base_type
    if type2.is_const:
        type2 = type2.const_base_type
4426
    if type1 == type2:
4427 4428 4429 4430 4431 4432 4433 4434
        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
4435
                real_type(type1),
4436 4437 4438 4439 4440 4441 4442 4443 4444
                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
4445 4446 4447 4448
    elif type1.signed > type2.signed:
        widest_type = type2
    elif type1.is_typedef > type2.is_typedef:
        widest_type = type1
4449
    else:
4450 4451
        widest_type = type2
    return widest_type
William Stein's avatar
William Stein committed
4452

4453 4454 4455 4456 4457

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


4458 4459 4460 4461 4462 4463 4464 4465
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.
4466 4467 4468 4469 4470
    if type1.is_reference ^ type2.is_reference:
        if type1.is_reference:
            type1 = type1.ref_base_type
        else:
            type2 = type2.ref_base_type
4471 4472 4473 4474 4475
    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
4476
        # type so that we do not lose the ability to coerce to a
4477
        # Python bool if we have to.
Robert Bradshaw's avatar
Robert Bradshaw committed
4478
        return py_object_type
4479 4480
    span_type = _spanning_type(type1, type2)
    if span_type is None:
Stefan Behnel's avatar
Stefan Behnel committed
4481
        return error_type
4482 4483 4484 4485 4486 4487 4488 4489
    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
4490
        return type1
4491 4492
    elif type1 is py_object_type or type2 is py_object_type:
        return py_object_type
4493 4494 4495
    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
4496 4497 4498 4499 4500 4501 4502
    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
4503
        return widest_numeric_type(type1, type2)
4504 4505 4506 4507
    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)
4508
    elif type1.is_extension_type and type2.is_extension_type:
4509 4510 4511
        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
4512
    elif type1.assignable_from(type2):
4513 4514 4515
        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
4516
        return type1
4517
    elif type2.assignable_from(type1):
4518 4519 4520
        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
4521
        return type2
4522
    elif type1.is_ptr and type2.is_ptr:
4523 4524 4525 4526
        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)
4527 4528
        # incompatible pointers, void* will do as a result
        return c_void_ptr_type
Robert Bradshaw's avatar
Robert Bradshaw committed
4529
    else:
4530 4531 4532 4533
        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
4534
        return py_object_type
4535 4536 4537 4538 4539 4540 4541 4542 4543
    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

4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561
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
4562 4563 4564 4565
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
4566

4567 4568 4569 4570 4571 4572 4573 4574 4575 4576
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)
4577 4578 4579 4580 4581 4582 4583
    #
    basic_type = simple_c_type(1, 0, name)
    if basic_type:
        return basic_type
    #
    signed = 1
    longness = 0
4584 4585
    if name == 'Py_UNICODE':
        signed = 0
Stefan Behnel's avatar
Stefan Behnel committed
4586 4587
    elif name == 'Py_UCS4':
        signed = 0
4588 4589
    elif name == 'Py_hash_t':
        signed = 2
4590 4591 4592
    elif name == 'Py_ssize_t':
        signed = 2
    elif name == 'ssize_t':
4593 4594 4595
        signed = 2
    elif name == 'size_t':
        signed = 0
4596
    else:
4597 4598 4599
        if name.startswith('u'):
            name = name[1:]
            signed = 0
Robert Bradshaw's avatar
Robert Bradshaw committed
4600
        elif (name.startswith('s') and
4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613
              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
4614 4615 4616

def c_array_type(base_type, size):
    # Construct a C array type.
4617
    if base_type is error_type:
4618
        return error_type
William Stein's avatar
William Stein committed
4619 4620 4621 4622 4623
    else:
        return CArrayType(base_type, size)

def c_ptr_type(base_type):
    # Construct a C pointer type.
4624
    if base_type is error_type:
4625
        return error_type
4626 4627
    elif base_type.is_reference:
        return CPtrType(base_type.ref_base_type)
William Stein's avatar
William Stein committed
4628 4629 4630
    else:
        return CPtrType(base_type)

Danilo Freitas's avatar
Danilo Freitas committed
4631 4632
def c_ref_type(base_type):
    # Construct a C reference type
4633
    if base_type is error_type:
Danilo Freitas's avatar
Danilo Freitas committed
4634 4635 4636
        return error_type
    else:
        return CReferenceType(base_type)
Robert Bradshaw's avatar
Robert Bradshaw committed
4637 4638 4639 4640 4641 4642 4643

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
4644 4645 4646

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

William Stein's avatar
William Stein committed
4648 4649 4650 4651 4652 4653 4654
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.
4655 4656 4657 4658 4659 4660 4661
    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
4662 4663 4664
    else:
        #print "typecast: to", to_type, "from", from_type ###
        return to_type.cast_code(expr_code)
4665 4666 4667 4668 4669 4670

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

_type_identifier_cache = {}
def type_identifier(type):
4671
    decl = type.empty_declaration_code()
4672 4673 4674 4675 4676 4677 4678
    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
4679
                    .replace('const ', '__const_')
4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699
                    .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])