cython

Форк
0
/
PyrexTypes.py 
5556 строк · 204.4 Кб
1
#
2
#   Cython/Python language types
3
#
4

5

6
import copy
7
import hashlib
8
import re
9

10
from functools import partial, reduce
11
from itertools import product
12

13
from Cython.Utils import cached_function
14
from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
15
from . import StringEncoding
16
from . import Naming
17

18
from .Errors import error, CannotSpecialize, performance_hint
19

20

21
class BaseType:
22
    #
23
    #  Base class for all Cython types including pseudo-types.
24

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

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

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

37
    def can_coerce_to_pystring(self, env, format_spec=None):
38
        return False
39

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

43
    def cast_code(self, expr_code):
44
        return "((%s)%s)" % (self.empty_declaration_code(), expr_code)
45

46
    def empty_declaration_code(self, pyrex=False):
47
        if pyrex:
48
            return self.declaration_code('', pyrex=True)
49
        if self._empty_declaration is None:
50
            self._empty_declaration = self.declaration_code('')
51
        return self._empty_declaration
52

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

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

71
    def __deepcopy__(self, memo):
72
        """
73
        Types never need to be copied, if we do copy, Unfortunate Things
74
        Will Happen!
75
        """
76
        return self
77

78
    def get_fused_types(self, result=None, seen=None, subtypes=None, include_function_return_type=False):
79
        subtypes = subtypes or self.subtypes
80
        if not subtypes:
81
            return None
82

83
        if result is None:
84
            result = []
85
            seen = set()
86

87
        for attr in subtypes:
88
            list_or_subtype = getattr(self, attr)
89
            if list_or_subtype:
90
                if isinstance(list_or_subtype, BaseType):
91
                    list_or_subtype.get_fused_types(result, seen, include_function_return_type=include_function_return_type)
92
                else:
93
                    for subtype in list_or_subtype:
94
                        subtype.get_fused_types(result, seen, include_function_return_type=include_function_return_type)
95

96
        return result
97

98
    def specialize_fused(self, env):
99
        if env.fused_to_specific:
100
            return self.specialize(env.fused_to_specific)
101

102
        return self
103

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

113
    def deduce_template_params(self, actual):
114
        """
115
        Deduce any template params in this (argument) type given the actual
116
        argument type.
117

118
        https://en.cppreference.com/w/cpp/language/function_template#Template_argument_deduction
119
        """
120
        return {}
121

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

127
        Override to provide something sensible. This is only implemented so that
128
        python 3 doesn't trip
129
        """
130
        return id(type(self)) < id(type(other))
131

132
    def py_type_name(self):
133
        """
134
        Return the name of the Python type that can coerce to this type.
135
        """
136

137
    def typeof_name(self):
138
        """
139
        Return the string with which fused python functions can be indexed.
140
        """
141
        if self.is_builtin_type or self.py_type_name() == 'object':
142
            index_name = self.py_type_name()
143
        else:
144
            index_name = str(self)
145

146
        return index_name
147

148
    def check_for_null_code(self, cname):
149
        """
150
        Return the code for a NULL-check in case an UnboundLocalError should
151
        be raised if an entry of this type is referenced before assignment.
152
        Returns None if no check should be performed.
153
        """
154
        return None
155

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

162

163
class PyrexType(BaseType):
164
    #
165
    #  Base class for all Cython types
166
    #
167
    #  is_pyobject           boolean     Is a Python object type
168
    #  is_extension_type     boolean     Is a Python extension type
169
    #  is_final_type         boolean     Is a final extension type
170
    #  is_numeric            boolean     Is a C numeric type
171
    #  is_int                boolean     Is a C integer type
172
    #  is_float              boolean     Is a C floating point type
173
    #  is_complex            boolean     Is a C complex type
174
    #  is_void               boolean     Is the C void type
175
    #  is_array              boolean     Is a C array type
176
    #  is_ptr                boolean     Is a C pointer type
177
    #  is_null_ptr           boolean     Is the type of NULL
178
    #  is_reference          boolean     Is a C reference type
179
    #  is_rvalue_reference   boolean     Is a C++ rvalue reference type
180
    #  is_const              boolean     Is a C const type
181
    #  is_volatile           boolean     Is a C volatile type
182
    #  is_cv_qualified       boolean     Is a C const or volatile type
183
    #  is_cfunction          boolean     Is a C function type
184
    #  is_struct_or_union    boolean     Is a C struct or union type
185
    #  is_struct             boolean     Is a C struct type
186
    #  is_cpp_class          boolean     Is a C++ class
187
    #  is_optional_cpp_class boolean     Is a C++ class with variable lifetime handled with std::optional
188
    #  is_enum               boolean     Is a C enum type
189
    #  is_cpp_enum           boolean     Is a C++ scoped enum type
190
    #  is_typedef            boolean     Is a typedef type
191
    #  is_string             boolean     Is a C char * type
192
    #  is_pyunicode_ptr      boolean     Is a C PyUNICODE * type
193
    #  is_cpp_string         boolean     Is a C++ std::string type
194
    #  python_type_constructor_name     string or None     non-None if it is a Python type constructor that can be indexed/"templated"
195
    #  is_unicode_char       boolean     Is either Py_UCS4 or Py_UNICODE
196
    #  is_returncode         boolean     Is used only to signal exceptions
197
    #  is_error              boolean     Is the dummy error type
198
    #  is_buffer             boolean     Is buffer access type
199
    #  is_pythran_expr       boolean     Is Pythran expr
200
    #  is_numpy_buffer       boolean     Is Numpy array buffer
201
    #  has_attributes        boolean     Has C dot-selectable attributes
202
    #  needs_cpp_construction  boolean     Needs C++ constructor and destructor when used in a cdef class
203
    #  needs_refcounting     boolean     Needs code to be generated similar to incref/gotref/decref.
204
    #                                    Largely used internally.
205
    #  refcounting_needs_gil boolean     Reference counting needs GIL to be acquired.
206
    #  equivalent_type       type        A C or Python type that is equivalent to this Python or C type.
207
    #  default_value         string      Initial value that can be assigned before first user assignment.
208
    #  declaration_value     string      The value statically assigned on declaration (if any).
209
    #  entry                 Entry       The Entry for this type
210
    #
211
    #  declaration_code(entity_code,
212
    #      for_display = 0, dll_linkage = None, pyrex = 0)
213
    #    Returns a code fragment for the declaration of an entity
214
    #    of this type, given a code fragment for the entity.
215
    #    * If for_display, this is for reading by a human in an error
216
    #      message; otherwise it must be valid C code.
217
    #    * If dll_linkage is not None, it must be 'DL_EXPORT' or
218
    #      'DL_IMPORT', and will be added to the base type part of
219
    #      the declaration.
220
    #    * If pyrex = 1, this is for use in a 'cdef extern'
221
    #      statement of a Cython include file.
222
    #
223
    #  assignable_from(src_type)
224
    #    Tests whether a variable of this type can be
225
    #    assigned a value of type src_type.
226
    #
227
    #  same_as(other_type)
228
    #    Tests whether this type represents the same type
229
    #    as other_type.
230
    #
231
    #  as_argument_type():
232
    #    Coerces array and C function types into pointer type for use as
233
    #    a formal argument type.
234
    #
235

236
    is_pyobject = 0
237
    is_unspecified = 0
238
    is_extension_type = 0
239
    is_final_type = 0
240
    is_builtin_type = 0
241
    is_cython_builtin_type = 0
242
    is_numeric = 0
243
    is_int = 0
244
    is_float = 0
245
    is_complex = 0
246
    is_void = 0
247
    is_array = 0
248
    is_ptr = 0
249
    is_null_ptr = 0
250
    is_reference = 0
251
    is_fake_reference = 0
252
    is_rvalue_reference = 0
253
    is_const = 0
254
    is_volatile = 0
255
    is_cv_qualified = 0
256
    is_cfunction = 0
257
    is_struct_or_union = 0
258
    is_cpp_class = 0
259
    is_optional_cpp_class = 0
260
    python_type_constructor_name = None
261
    is_cpp_string = 0
262
    is_struct = 0
263
    is_enum = 0
264
    is_cpp_enum = False
265
    is_typedef = 0
266
    is_string = 0
267
    is_pyunicode_ptr = 0
268
    is_unicode_char = 0
269
    is_returncode = 0
270
    is_error = 0
271
    is_buffer = 0
272
    is_ctuple = 0
273
    is_memoryviewslice = 0
274
    is_pythran_expr = 0
275
    is_numpy_buffer = 0
276
    has_attributes = 0
277
    needs_cpp_construction = 0
278
    needs_refcounting = 0
279
    refcounting_needs_gil = True
280
    equivalent_type = None
281
    default_value = ""
282
    declaration_value = ""
283

284
    def resolve(self):
285
        # If a typedef, returns the base type.
286
        return self
287

288
    def specialize(self, values):
289
        # Returns the concrete type if this is a fused type, or otherwise the type itself.
290
        # May raise Errors.CannotSpecialize on failure
291
        return self
292

293
    def literal_code(self, value):
294
        # Returns a C code fragment representing a literal
295
        # value of this type.
296
        return str(value)
297

298
    def __str__(self):
299
        return self.declaration_code("", for_display = 1).strip()
300

301
    def same_as(self, other_type, **kwds):
302
        return self.same_as_resolved_type(other_type.resolve(), **kwds)
303

304
    def same_as_resolved_type(self, other_type):
305
        return self == other_type or other_type is error_type
306

307
    def subtype_of(self, other_type):
308
        return self.subtype_of_resolved_type(other_type.resolve())
309

310
    def subtype_of_resolved_type(self, other_type):
311
        return self.same_as(other_type)
312

313
    def assignable_from(self, src_type):
314
        return self.assignable_from_resolved_type(src_type.resolve())
315

316
    def assignable_from_resolved_type(self, src_type):
317
        return self.same_as(src_type)
318

319
    def assignment_failure_extra_info(self, src_type, src_name):
320
        """Override if you can provide useful extra information about why an assignment didn't work.
321

322
        src_name may be None if unavailable"""
323
        return ""
324

325
    def as_argument_type(self):
326
        return self
327

328
    def is_complete(self):
329
        # A type is incomplete if it is an unsized array,
330
        # a struct whose attributes are not defined, etc.
331
        return 1
332

333
    def is_simple_buffer_dtype(self):
334
        return False
335

336
    def can_be_optional(self):
337
        """Returns True if type can be used with typing.Optional[]."""
338
        return False
339

340
    def struct_nesting_depth(self):
341
        # Returns the number levels of nested structs. This is
342
        # used for constructing a stack for walking the run-time
343
        # type information of the struct.
344
        return 1
345

346
    def global_init_code(self, entry, code):
347
        # abstract
348
        pass
349

350
    def needs_nonecheck(self):
351
        return 0
352

353
    def _assign_from_py_code(self, source_code, result_code, error_pos, code,
354
                             from_py_function=None, error_condition=None, extra_args=None,
355
                             special_none_cvalue=None):
356
        args = ', ' + ', '.join('%s' % arg for arg in extra_args) if extra_args else ''
357
        convert_call = "%s(%s%s)" % (
358
            from_py_function or self.from_py_function,
359
            source_code,
360
            args,
361
        )
362
        if self.is_enum:
363
            convert_call = typecast(self, c_long_type, convert_call)
364
        if special_none_cvalue:
365
            # NOTE: requires 'source_code' to be simple!
366
            convert_call = "(__Pyx_Py_IsNone(%s) ? (%s) : (%s))" % (
367
                source_code, special_none_cvalue, convert_call)
368
        return '%s = %s; %s' % (
369
            result_code,
370
            convert_call,
371
            code.error_goto_if(error_condition or self.error_condition(result_code), error_pos))
372

373
    def _generate_dummy_refcounting(self, code, *ignored_args, **ignored_kwds):
374
        if self.needs_refcounting:
375
            raise NotImplementedError("Ref-counting operation not yet implemented for type %s" %
376
                                      self)
377

378
    def _generate_dummy_refcounting_assignment(self, code, cname, rhs_cname, *ignored_args, **ignored_kwds):
379
        if self.needs_refcounting:
380
            raise NotImplementedError("Ref-counting operation not yet implemented for type %s" %
381
                                      self)
382
        code.putln("%s = %s" % (cname, rhs_cname))
383

384
    generate_incref = generate_xincref = generate_decref = generate_xdecref \
385
        = generate_decref_clear = generate_xdecref_clear \
386
        = generate_gotref = generate_xgotref = generate_giveref = generate_xgiveref \
387
            = _generate_dummy_refcounting
388

389
    generate_decref_set = generate_xdecref_set = _generate_dummy_refcounting_assignment
390

391
    def nullcheck_string(self, code, cname):
392
        if self.needs_refcounting:
393
            raise NotImplementedError("Ref-counting operation not yet implemented for type %s" %
394
                                      self)
395
        code.putln("1")
396

397
    def cpp_optional_declaration_code(self, entity_code, dll_linkage=None):
398
        # declares an std::optional c++ variable
399
        raise NotImplementedError(
400
            "cpp_optional_declaration_code only implemented for c++ classes and not type %s" % self)
401

402

403
def public_decl(base_code, dll_linkage):
404
    if dll_linkage:
405
        return "%s(%s)" % (dll_linkage, base_code.replace(',', ' __PYX_COMMA '))
406
    else:
407
        return base_code
408

409

410
def create_typedef_type(name, base_type, cname, is_external=0, namespace=None):
411
    if is_external:
412
        if base_type.is_complex or base_type.is_fused:
413
            raise ValueError("%s external typedefs not supported" % (
414
                "Fused" if base_type.is_fused else "Complex"))
415
    if base_type.is_complex or base_type.is_fused:
416
        return base_type
417
    return CTypedefType(name, base_type, cname, is_external, namespace)
418

419

420
class CTypedefType(BaseType):
421
    #
422
    #  Pseudo-type defined with a ctypedef statement in a
423
    #  'cdef extern from' block.
424
    #  Delegates most attribute lookups to the base type.
425
    #  (Anything not defined here or in the BaseType is delegated.)
426
    #
427
    #  qualified_name      string
428
    #  typedef_name        string
429
    #  typedef_cname       string
430
    #  typedef_base_type   PyrexType
431
    #  typedef_is_external bool
432

433
    is_typedef = 1
434
    typedef_is_external = 0
435

436
    to_py_utility_code = None
437
    from_py_utility_code = None
438

439
    subtypes = ['typedef_base_type']
440

441
    def __init__(self, name, base_type, cname, is_external=0, namespace=None):
442
        assert not base_type.is_complex
443
        self.typedef_name = name
444
        self.typedef_cname = cname
445
        self.typedef_base_type = base_type
446
        self.typedef_is_external = is_external
447
        self.typedef_namespace = namespace
448

449
    def invalid_value(self):
450
        return self.typedef_base_type.invalid_value()
451

452
    def resolve(self):
453
        return self.typedef_base_type.resolve()
454

455
    def declaration_code(self, entity_code,
456
            for_display = 0, dll_linkage = None, pyrex = 0):
457
        if pyrex or for_display:
458
            base_code = self.typedef_name
459
        else:
460
            base_code = public_decl(self.typedef_cname, dll_linkage)
461
        if self.typedef_namespace is not None and not pyrex:
462
            base_code = "%s::%s" % (self.typedef_namespace.empty_declaration_code(), base_code)
463
        return self.base_declaration_code(base_code, entity_code)
464

465
    def as_argument_type(self):
466
        return self
467

468
    def cast_code(self, expr_code):
469
        # If self is really an array (rather than pointer), we can't cast.
470
        # For example, the gmp mpz_t.
471
        if self.typedef_base_type.is_array:
472
            base_type = self.typedef_base_type.base_type
473
            return CPtrType(base_type).cast_code(expr_code)
474
        else:
475
            return BaseType.cast_code(self, expr_code)
476

477
    def specialize(self, values):
478
        base_type = self.typedef_base_type.specialize(values)
479
        namespace = self.typedef_namespace.specialize(values) if self.typedef_namespace else None
480
        if base_type is self.typedef_base_type and namespace is self.typedef_namespace:
481
            return self
482
        else:
483
            return create_typedef_type(self.typedef_name, base_type, self.typedef_cname,
484
                                0, namespace)
485

486
    def __repr__(self):
487
        return "<CTypedefType %s>" % self.typedef_cname
488

489
    def __str__(self):
490
        return self.typedef_name
491

492
    def _create_utility_code(self, template_utility_code,
493
                             template_function_name):
494
        type_name = type_identifier(self.typedef_cname)
495
        utility_code = template_utility_code.specialize(
496
            type     = self.typedef_cname,
497
            TypeName = type_name)
498
        function_name = template_function_name % type_name
499
        return utility_code, function_name
500

501
    def create_to_py_utility_code(self, env):
502
        if self.typedef_is_external:
503
            if not self.to_py_utility_code:
504
                base_type = self.typedef_base_type
505
                if type(base_type) is CIntType:
506
                    self.to_py_function = "__Pyx_PyLong_From_" + self.specialization_name()
507
                    env.use_utility_code(TempitaUtilityCode.load_cached(
508
                        "CIntToPy", "TypeConversion.c",
509
                        context={"TYPE": self.empty_declaration_code(),
510
                                 "TO_PY_FUNCTION": self.to_py_function}))
511
                    return True
512
                elif base_type.is_float:
513
                    pass  # XXX implement!
514
                elif base_type.is_complex:
515
                    pass  # XXX implement!
516
                    pass
517
                elif base_type.is_cpp_string:
518
                    cname = "__pyx_convert_PyObject_string_to_py_%s" % type_identifier(self)
519
                    context = {
520
                        'cname': cname,
521
                        'type': self.typedef_cname,
522
                    }
523
                    from .UtilityCode import CythonUtilityCode
524
                    env.use_utility_code(CythonUtilityCode.load(
525
                        "string.to_py", "CppConvert.pyx", context=context))
526
                    self.to_py_function = cname
527
                    return True
528
            if self.to_py_utility_code:
529
                env.use_utility_code(self.to_py_utility_code)
530
                return True
531
        # delegation
532
        return self.typedef_base_type.create_to_py_utility_code(env)
533

534
    def create_from_py_utility_code(self, env):
535
        if self.typedef_is_external:
536
            if not self.from_py_utility_code:
537
                base_type = self.typedef_base_type
538
                if type(base_type) is CIntType:
539
                    self.from_py_function = "__Pyx_PyLong_As_" + self.specialization_name()
540
                    env.use_utility_code(TempitaUtilityCode.load_cached(
541
                        "CIntFromPy", "TypeConversion.c",
542
                        context={
543
                            "TYPE": self.empty_declaration_code(),
544
                            "FROM_PY_FUNCTION": self.from_py_function,
545
                            "IS_ENUM": base_type.is_enum,
546
                        }))
547
                    return True
548
                elif base_type.is_float:
549
                    pass  # XXX implement!
550
                elif base_type.is_complex:
551
                    pass  # XXX implement!
552
                elif base_type.is_cpp_string:
553
                    cname = '__pyx_convert_string_from_py_%s' % type_identifier(self)
554
                    context = {
555
                        'cname': cname,
556
                        'type': self.typedef_cname,
557
                    }
558
                    from .UtilityCode import CythonUtilityCode
559
                    env.use_utility_code(CythonUtilityCode.load(
560
                        "string.from_py", "CppConvert.pyx", context=context))
561
                    self.from_py_function = cname
562
                    return True
563
            if self.from_py_utility_code:
564
                env.use_utility_code(self.from_py_utility_code)
565
                return True
566
        # delegation
567
        return self.typedef_base_type.create_from_py_utility_code(env)
568

569
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
570
        if to_py_function is None:
571
            to_py_function = self.to_py_function
572
        return self.typedef_base_type.to_py_call_code(
573
            source_code, result_code, result_type, to_py_function)
574

575
    def from_py_call_code(self, source_code, result_code, error_pos, code,
576
                          from_py_function=None, error_condition=None,
577
                          special_none_cvalue=None):
578
        return self.typedef_base_type.from_py_call_code(
579
            source_code, result_code, error_pos, code,
580
            from_py_function or self.from_py_function,
581
            error_condition or self.error_condition(result_code),
582
            special_none_cvalue=special_none_cvalue,
583
        )
584

585
    def overflow_check_binop(self, binop, env, const_rhs=False):
586
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
587
        type = self.empty_declaration_code()
588
        name = self.specialization_name()
589
        if binop == "lshift":
590
            env.use_utility_code(TempitaUtilityCode.load_cached(
591
                "LeftShift", "Overflow.c",
592
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
593
        else:
594
            if const_rhs:
595
                binop += "_const"
596
            _load_overflow_base(env)
597
            env.use_utility_code(TempitaUtilityCode.load_cached(
598
                "SizeCheck", "Overflow.c",
599
                context={'TYPE': type, 'NAME': name}))
600
            env.use_utility_code(TempitaUtilityCode.load_cached(
601
                "Binop", "Overflow.c",
602
                context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
603
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)
604

605
    def error_condition(self, result_code):
606
        if self.typedef_is_external:
607
            if self.exception_value is not None:
608
                condition = "(%s == %s)" % (
609
                    result_code, self.cast_code(self.exception_value))
610
                if self.exception_check:
611
                    condition += " && PyErr_Occurred()"
612
                return condition
613
        # delegation
614
        return self.typedef_base_type.error_condition(result_code)
615

616
    def __getattr__(self, name):
617
        return getattr(self.typedef_base_type, name)
618

619
    def py_type_name(self):
620
        return self.typedef_base_type.py_type_name()
621

622
    def can_coerce_to_pyobject(self, env):
623
        return self.typedef_base_type.can_coerce_to_pyobject(env)
624

625
    def can_coerce_from_pyobject(self, env):
626
        return self.typedef_base_type.can_coerce_from_pyobject(env)
627

628

629
class MemoryViewSliceType(PyrexType):
630

631
    is_memoryviewslice = 1
632
    default_value = "{ 0, 0, { 0 }, { 0 }, { 0 } }"
633

634
    has_attributes = 1
635
    needs_refcounting = 1  # Ideally this would be true and reference counting for
636
        # memoryview and pyobject code could be generated in the same way.
637
        # However, memoryviews are sufficiently specialized that this doesn't
638
        # seem practical. Implement a limited version of it for now
639
    refcounting_needs_gil = False  # __PYX_XCLEAR_MEMVIEW acquires GIL internally.
640
    scope = None
641

642
    # These are special cased in Defnode
643
    from_py_function = None
644
    to_py_function = None
645

646
    exception_value = None
647
    exception_check = True
648

649
    subtypes = ['dtype']
650

651
    def __init__(self, base_dtype, axes):
652
        """
653
        MemoryViewSliceType(base, axes)
654

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

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

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

668
        the packing specifiers specify how the array elements are laid-out
669
        in memory.
670

671
        'contig' -- The data is contiguous in memory along this dimension.
672
                At most one dimension may be specified as 'contig'.
673
        'strided' -- The data isn't contiguous along this dimension.
674
        'follow' -- Used for C/Fortran contiguous arrays, a 'follow' dimension
675
            has its stride automatically computed from extents of the other
676
            dimensions to ensure C or Fortran memory layout.
677

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

681
        Fortran-contiguous memory has 'direct' as the access spec, 'contig' as
682
        the *first* axis' packing spec and 'follow' for all other packing
683
        specs.
684
        """
685
        from . import Buffer, MemoryView
686

687
        self.dtype = base_dtype
688
        self.axes = axes
689
        self.ndim = len(axes)
690
        self.flags = MemoryView.get_buf_flags(self.axes)
691

692
        self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes)
693
        assert not (self.is_c_contig and self.is_f_contig)
694

695
        self.mode = MemoryView.get_mode(axes)
696
        self.writable_needed = False
697

698
        if not self.dtype.is_fused:
699
            self.dtype_name = Buffer.mangle_dtype_name(self.dtype)
700

701
    def __hash__(self):
702
        return hash(self.__class__) ^ hash(self.dtype) ^ hash(tuple(self.axes))
703

704
    def __eq__(self, other):
705
        if isinstance(other, BaseType):
706
            return self.same_as_resolved_type(other)
707
        else:
708
            return False
709

710
    def __ne__(self, other):
711
        # TODO drop when Python2 is dropped
712
        return not (self == other)
713

714
    def same_as_resolved_type(self, other_type):
715
        return ((other_type.is_memoryviewslice and
716
            #self.writable_needed == other_type.writable_needed and  # FIXME: should be only uni-directional
717
            self.dtype.same_as(other_type.dtype) and
718
            self.axes == other_type.axes) or
719
            other_type is error_type)
720

721
    def needs_nonecheck(self):
722
        return True
723

724
    def is_complete(self):
725
        # incomplete since the underlying struct doesn't have a cython.memoryview object.
726
        return 0
727

728
    def can_be_optional(self):
729
        """Returns True if type can be used with typing.Optional[]."""
730
        return True
731

732
    def declaration_code(self, entity_code,
733
            for_display = 0, dll_linkage = None, pyrex = 0):
734
        # XXX: we put these guards in for now...
735
        assert not dll_linkage
736
        from . import MemoryView
737
        base_code = StringEncoding.EncodedString(
738
            str(self) if pyrex or for_display else MemoryView.memviewslice_cname)
739
        return self.base_declaration_code(
740
                base_code,
741
                entity_code)
742

743
    def attributes_known(self):
744
        if self.scope is None:
745
            from . import Symtab
746

747
            self.scope = scope = Symtab.CClassScope(
748
                    'mvs_class_'+self.specialization_suffix(),
749
                    None,
750
                    visibility='extern',
751
                    parent_type=self)
752

753
            scope.directives = {}
754

755
            scope.declare_var('_data', c_char_ptr_type, None,
756
                              cname='data', is_cdef=1)
757

758
        return True
759

760
    def declare_attribute(self, attribute, env, pos):
761
        from . import MemoryView, Options
762

763
        scope = self.scope
764

765
        if attribute == 'shape':
766
            scope.declare_var('shape',
767
                    c_array_type(c_py_ssize_t_type,
768
                                 Options.buffer_max_dims),
769
                    pos,
770
                    cname='shape',
771
                    is_cdef=1)
772

773
        elif attribute == 'strides':
774
            scope.declare_var('strides',
775
                    c_array_type(c_py_ssize_t_type,
776
                                 Options.buffer_max_dims),
777
                    pos,
778
                    cname='strides',
779
                    is_cdef=1)
780

781
        elif attribute == 'suboffsets':
782
            scope.declare_var('suboffsets',
783
                    c_array_type(c_py_ssize_t_type,
784
                                 Options.buffer_max_dims),
785
                    pos,
786
                    cname='suboffsets',
787
                    is_cdef=1)
788

789
        elif attribute in ("copy", "copy_fortran"):
790
            ndim = len(self.axes)
791

792
            follow_dim = [('direct', 'follow')]
793
            contig_dim = [('direct', 'contig')]
794
            to_axes_c = follow_dim * (ndim - 1) + contig_dim
795
            to_axes_f = contig_dim + follow_dim * (ndim -1)
796

797
            dtype = self.dtype
798
            if dtype.is_cv_qualified:
799
                dtype = dtype.cv_base_type
800

801
            to_memview_c = MemoryViewSliceType(dtype, to_axes_c)
802
            to_memview_f = MemoryViewSliceType(dtype, to_axes_f)
803

804
            for to_memview, cython_name in [(to_memview_c, "copy"),
805
                                            (to_memview_f, "copy_fortran")]:
806
                copy_func_type = CFuncType(
807
                    to_memview,
808
                    [CFuncTypeArg("memviewslice", self, None)])
809
                copy_cname = MemoryView.copy_c_or_fortran_cname(to_memview)
810

811
                entry = scope.declare_cfunction(
812
                    cython_name,
813
                    copy_func_type, pos=pos, defining=1,
814
                    cname=copy_cname)
815

816
                utility = MemoryView.get_copy_new_utility(pos, self, to_memview)
817
                env.use_utility_code(utility)
818

819
            MemoryView.use_cython_array_utility_code(env)
820

821
        elif attribute in ("is_c_contig", "is_f_contig"):
822
            # is_c_contig and is_f_contig functions
823
            for (c_or_f, cython_name) in (('C', 'is_c_contig'), ('F', 'is_f_contig')):
824

825
                is_contig_name = MemoryView.get_is_contig_func_name(c_or_f, self.ndim)
826

827
                cfunctype = CFuncType(
828
                        return_type=c_bint_type,
829
                        args=[CFuncTypeArg("memviewslice", self, None)],
830
                        exception_value=-1,
831
                )
832

833
                entry = scope.declare_cfunction(cython_name,
834
                            cfunctype,
835
                            pos=pos,
836
                            defining=1,
837
                            cname=is_contig_name)
838

839
                entry.utility_code_definition = MemoryView.get_is_contig_utility(c_or_f, self.ndim)
840

841
        return True
842

843
    def get_entry(self, node, cname=None, type=None):
844
        from . import MemoryView, Symtab
845

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

850
        if type is None:
851
            type = node.type
852

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

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

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

862
        Any packing/access spec is conformable to itself.
863

864
        'direct' and 'ptr' are conformable to 'full'.
865
        'contig' and 'follow' are conformable to 'strided'.
866
        Any other combo is not conformable.
867
        """
868
        from . import MemoryView
869

870
        src = self
871

872
        #if not copying and self.writable_needed and not dst.writable_needed:
873
        #    return False
874

875
        src_dtype, dst_dtype = src.dtype, dst.dtype
876
        # We can add but not remove const/volatile modifiers
877
        # (except if we are copying by value, then anything is fine)
878
        if not copying:
879
            if src_dtype.is_const and not dst_dtype.is_const:
880
                return False
881
            if src_dtype.is_volatile and not dst_dtype.is_volatile:
882
                return False
883
        # const/volatile checks are done, remove those qualifiers
884
        if src_dtype.is_cv_qualified:
885
            src_dtype = src_dtype.cv_base_type
886
        if dst_dtype.is_cv_qualified:
887
            dst_dtype = dst_dtype.cv_base_type
888

889
        if not src_dtype.same_as(dst_dtype):
890
            return False
891

892
        if src.ndim != dst.ndim:
893
            if broadcast:
894
                src, dst = MemoryView.broadcast_types(src, dst)
895
            else:
896
                return False
897

898
        for src_spec, dst_spec in zip(src.axes, dst.axes):
899
            src_access, src_packing = src_spec
900
            dst_access, dst_packing = dst_spec
901
            if src_access != dst_access and dst_access != 'full':
902
                return False
903
            if src_packing != dst_packing and dst_packing != 'strided' and not copying:
904
                return False
905

906
        return True
907

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

913
        We support structs, numeric types and objects
914
        """
915
        if dtype.is_complex and dtype.real_type.is_int:
916
            return False
917

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

923
            return True
924

925
        return (
926
            dtype.is_error or
927
            # Pointers are not valid (yet)
928
            # (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or
929
            (dtype.is_array and i < 8 and self.valid_dtype(dtype.base_type, i + 1)) or
930
            dtype.is_numeric or
931
            dtype.is_pyobject or
932
            dtype.is_fused or  # accept this as it will be replaced by specializations later
933
            (dtype.is_typedef and self.valid_dtype(dtype.typedef_base_type))
934
        )
935

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

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

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

952
    def specialization_name(self):
953
        return '%s_%s' % (
954
            super().specialization_name(),
955
            self.specialization_suffix())
956

957
    def specialization_suffix(self):
958
        return "%s_%s" % (self.axes_to_name(), self.dtype_name)
959

960
    def can_coerce_to_pyobject(self, env):
961
        return True
962

963
    def can_coerce_from_pyobject(self, env):
964
        return True
965

966
    def check_for_null_code(self, cname):
967
        return cname + '.memview'
968

969
    def create_from_py_utility_code(self, env):
970
        from . import MemoryView, Buffer
971

972
        # We don't have 'code', so use a LazyUtilityCode with a callback.
973
        def lazy_utility_callback(code):
974
            context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype)
975
            return TempitaUtilityCode.load(
976
                "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
977

978
        env.use_utility_code(MemoryView.memviewslice_init_code)
979
        env.use_utility_code(LazyUtilityCode(lazy_utility_callback))
980

981
        if self.is_c_contig:
982
            c_or_f_flag = "__Pyx_IS_C_CONTIG"
983
        elif self.is_f_contig:
984
            c_or_f_flag = "__Pyx_IS_F_CONTIG"
985
        else:
986
            c_or_f_flag = "0"
987

988
        suffix = self.specialization_suffix()
989
        funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
990

991
        context = dict(
992
            MemoryView.context,
993
            buf_flag = self.flags,
994
            ndim = self.ndim,
995
            axes_specs = ', '.join(self.axes_to_code()),
996
            dtype_typedecl = self.dtype.empty_declaration_code(),
997
            struct_nesting_depth = self.dtype.struct_nesting_depth(),
998
            c_or_f_flag = c_or_f_flag,
999
            funcname = funcname,
1000
        )
1001

1002
        self.from_py_function = funcname
1003
        return True
1004

1005
    def from_py_call_code(self, source_code, result_code, error_pos, code,
1006
                          from_py_function=None, error_condition=None,
1007
                          special_none_cvalue=None):
1008
        # NOTE: auto-detection of readonly buffers is disabled:
1009
        # writable = self.writable_needed or not self.dtype.is_const
1010
        writable = not self.dtype.is_const
1011
        return self._assign_from_py_code(
1012
            source_code, result_code, error_pos, code, from_py_function, error_condition,
1013
            extra_args=['PyBUF_WRITABLE' if writable else '0'],
1014
            special_none_cvalue=special_none_cvalue,
1015
        )
1016

1017
    def create_to_py_utility_code(self, env):
1018
        self._dtype_to_py_func, self._dtype_from_py_func = self.dtype_object_conversion_funcs(env)
1019
        return True
1020

1021
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
1022
        assert self._dtype_to_py_func
1023
        assert self._dtype_from_py_func
1024

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

1028
        tup = (result_code, source_code, self.ndim, to_py_func, from_py_func, self.dtype.is_pyobject)
1029
        return "%s = __pyx_memoryview_fromslice(%s, %s, %s, %s, %d);" % tup
1030

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

1035
        context = dict(
1036
            get_function = get_function,
1037
            set_function = set_function,
1038
        )
1039

1040
        if self.dtype.is_pyobject:
1041
            utility_name = "MemviewObjectToObject"
1042
        else:
1043
            self.dtype.create_to_py_utility_code(env)
1044
            to_py_function = self.dtype.to_py_function
1045

1046
            from_py_function = None
1047
            if not self.dtype.is_const:
1048
                self.dtype.create_from_py_utility_code(env)
1049
                from_py_function = self.dtype.from_py_function
1050

1051
            if not (to_py_function or from_py_function):
1052
                return "NULL", "NULL"
1053
            if not to_py_function:
1054
                get_function = "NULL"
1055
            if not from_py_function:
1056
                set_function = "NULL"
1057

1058
            utility_name = "MemviewDtypeToObject"
1059
            error_condition = (self.dtype.error_condition('value') or
1060
                               'PyErr_Occurred()')
1061
            context.update(
1062
                to_py_function=to_py_function,
1063
                from_py_function=from_py_function,
1064
                dtype=self.dtype.empty_declaration_code(),
1065
                error_condition=error_condition,
1066
            )
1067

1068
        utility = TempitaUtilityCode.load_cached(
1069
            utility_name, "MemoryView_C.c", context=context)
1070
        env.use_utility_code(utility)
1071
        return get_function, set_function
1072

1073
    def axes_to_code(self):
1074
        """Return a list of code constants for each axis"""
1075
        from . import MemoryView
1076
        d = MemoryView._spec_to_const
1077
        return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]
1078

1079
    def axes_to_name(self):
1080
        """Return an abbreviated name for our axes"""
1081
        from . import MemoryView
1082
        d = MemoryView._spec_to_abbrev
1083
        return "".join(["%s%s" % (d[a], d[p]) for a, p in self.axes])
1084

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

1088
    def __str__(self):
1089
        from . import MemoryView
1090

1091
        axes_code_list = []
1092
        for idx, (access, packing) in enumerate(self.axes):
1093
            flag = MemoryView.get_memoryview_flag(access, packing)
1094
            if flag == "strided":
1095
                axes_code_list.append(":")
1096
            else:
1097
                if flag == 'contiguous':
1098
                    have_follow = [p for a, p in self.axes[idx - 1:idx + 2]
1099
                                         if p == 'follow']
1100
                    if have_follow or self.ndim == 1:
1101
                        flag = '1'
1102

1103
                axes_code_list.append("::" + flag)
1104

1105
        if self.dtype.is_pyobject:
1106
            dtype_name = self.dtype.name
1107
        else:
1108
            dtype_name = self.dtype
1109

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

1112
    def specialize(self, values):
1113
        """This does not validate the base type!!"""
1114
        dtype = self.dtype.specialize(values)
1115
        if dtype is not self.dtype:
1116
            return MemoryViewSliceType(dtype, self.axes)
1117

1118
        return self
1119

1120
    def cast_code(self, expr_code):
1121
        return expr_code
1122

1123
    # When memoryviews are increfed currently seems heavily special-cased.
1124
    # Therefore, use our own function for now
1125
    def generate_incref(self, code, name, **kwds):
1126
        pass
1127

1128
    def generate_incref_memoryviewslice(self, code, slice_cname, have_gil):
1129
        # TODO ideally would be done separately
1130
        code.putln("__PYX_INC_MEMVIEW(&%s, %d);" % (slice_cname, int(have_gil)))
1131

1132
    # decref however did look to always apply for memoryview slices
1133
    # with "have_gil" set to True by default
1134
    def generate_xdecref(self, code, cname, nanny, have_gil):
1135
        code.putln("__PYX_XCLEAR_MEMVIEW(&%s, %d);" % (cname, int(have_gil)))
1136

1137
    def generate_decref(self, code, cname, nanny, have_gil):
1138
        # Fall back to xdecref since we don't care to have a separate decref version for this.
1139
        self.generate_xdecref(code, cname, nanny, have_gil)
1140

1141
    def generate_xdecref_clear(self, code, cname, clear_before_decref, **kwds):
1142
        self.generate_xdecref(code, cname, **kwds)
1143
        code.putln("%s.memview = NULL; %s.data = NULL;" % (cname, cname))
1144

1145
    def generate_decref_clear(self, code, cname, **kwds):
1146
        # memoryviews don't currently distinguish between xdecref and decref
1147
        self.generate_xdecref_clear(code, cname, **kwds)
1148

1149
    # memoryviews don't participate in giveref/gotref
1150
    generate_gotref = generate_xgotref = generate_xgiveref = generate_giveref = lambda *args: None
1151

1152

1153

1154
class BufferType(BaseType):
1155
    #
1156
    #  Delegates most attribute lookups to the base type.
1157
    #  (Anything not defined here or in the BaseType is delegated.)
1158
    #
1159
    # dtype            PyrexType
1160
    # ndim             int
1161
    # mode             str
1162
    # negative_indices bool
1163
    # cast             bool
1164
    # is_buffer        bool
1165
    # writable         bool
1166

1167
    is_buffer = 1
1168
    writable = True
1169

1170
    subtypes = ['dtype']
1171

1172
    def __init__(self, base, dtype, ndim, mode, negative_indices, cast):
1173
        self.base = base
1174
        self.dtype = dtype
1175
        self.ndim = ndim
1176
        self.buffer_ptr_type = CPtrType(dtype)
1177
        self.mode = mode
1178
        self.negative_indices = negative_indices
1179
        self.cast = cast
1180
        self.is_numpy_buffer = self.base.name == "ndarray"
1181

1182
    def can_coerce_to_pyobject(self,env):
1183
        return True
1184

1185
    def can_coerce_from_pyobject(self,env):
1186
        return True
1187

1188
    def as_argument_type(self):
1189
        return self
1190

1191
    def specialize(self, values):
1192
        dtype = self.dtype.specialize(values)
1193
        if dtype is not self.dtype:
1194
            return BufferType(self.base, dtype, self.ndim, self.mode,
1195
                              self.negative_indices, self.cast)
1196
        return self
1197

1198
    def get_entry(self, node):
1199
        from . import Buffer
1200
        assert node.is_name
1201
        return Buffer.BufferEntry(node.entry)
1202

1203
    def __getattr__(self, name):
1204
        return getattr(self.base, name)
1205

1206
    def __repr__(self):
1207
        return "<BufferType %r>" % self.base
1208

1209
    def __str__(self):
1210
        # avoid ', ', as fused functions split the signature string on ', '
1211
        cast_str = ''
1212
        if self.cast:
1213
            cast_str = ',cast=True'
1214

1215
        return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim,
1216
                                      cast_str)
1217

1218
    def assignable_from(self, other_type):
1219
        if other_type.is_buffer:
1220
            return (self.same_as(other_type, compare_base=False) and
1221
                    self.base.assignable_from(other_type.base))
1222

1223
        return self.base.assignable_from(other_type)
1224

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

1229
        return (self.dtype.same_as(other_type.dtype) and
1230
                self.ndim == other_type.ndim and
1231
                self.mode == other_type.mode and
1232
                self.cast == other_type.cast and
1233
                (not compare_base or self.base.same_as(other_type.base)))
1234

1235

1236
class PyObjectType(PyrexType):
1237
    #
1238
    #  Base class for all Python object types (reference-counted).
1239
    #
1240
    #  buffer_defaults  dict or None     Default options for buffer
1241

1242
    name = "object"
1243
    is_pyobject = 1
1244
    default_value = "0"
1245
    declaration_value = "0"
1246
    buffer_defaults = None
1247
    is_external = False
1248
    is_subclassed = False
1249
    is_gc_simple = False
1250
    builtin_trashcan = False  # builtin type using trashcan
1251
    needs_refcounting = True
1252

1253
    def __str__(self):
1254
        return "Python object"
1255

1256
    def __repr__(self):
1257
        return "<PyObjectType>"
1258

1259
    def can_coerce_to_pyobject(self, env):
1260
        return True
1261

1262
    def can_coerce_from_pyobject(self, env):
1263
        return True
1264

1265
    def can_be_optional(self):
1266
        """Returns True if type can be used with typing.Optional[]."""
1267
        return True
1268

1269
    def default_coerced_ctype(self):
1270
        """The default C type that this Python type coerces to, or None."""
1271
        return None
1272

1273
    def assignable_from(self, src_type):
1274
        # except for pointers, conversion will be attempted
1275
        return not src_type.is_ptr or src_type.is_string or src_type.is_pyunicode_ptr
1276

1277
    def is_simple_buffer_dtype(self):
1278
        return True
1279

1280
    def declaration_code(self, entity_code,
1281
            for_display = 0, dll_linkage = None, pyrex = 0):
1282
        if pyrex or for_display:
1283
            base_code = "object"
1284
        else:
1285
            base_code = public_decl("PyObject", dll_linkage)
1286
            entity_code = "*%s" % entity_code
1287
        return self.base_declaration_code(base_code, entity_code)
1288

1289
    def as_pyobject(self, cname):
1290
        if (not self.is_complete()) or self.is_extension_type:
1291
            return "(PyObject *)" + cname
1292
        else:
1293
            return cname
1294

1295
    def py_type_name(self):
1296
        return "object"
1297

1298
    def __lt__(self, other):
1299
        """
1300
        Make sure we sort highest, as instance checking on py_type_name
1301
        ('object') is always true
1302
        """
1303
        return False
1304

1305
    def global_init_code(self, entry, code):
1306
        code.put_init_var_to_py_none(entry, nanny=False)
1307

1308
    def check_for_null_code(self, cname):
1309
        return cname
1310

1311
    def generate_incref(self, code, cname, nanny):
1312
        if nanny:
1313
            code.funcstate.needs_refnanny = True
1314
            code.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname))
1315
        else:
1316
            code.putln("Py_INCREF(%s);" % self.as_pyobject(cname))
1317

1318
    def generate_xincref(self, code, cname, nanny):
1319
        if nanny:
1320
            code.funcstate.needs_refnanny = True
1321
            code.putln("__Pyx_XINCREF(%s);" % self.as_pyobject(cname))
1322
        else:
1323
            code.putln("Py_XINCREF(%s);" % self.as_pyobject(cname))
1324

1325
    def generate_decref(self, code, cname, nanny, have_gil):
1326
        # have_gil is for the benefit of memoryviewslice - it's ignored here
1327
        assert have_gil
1328
        self._generate_decref(code, cname, nanny, null_check=False, clear=False)
1329

1330
    def generate_xdecref(self, code, cname, nanny, have_gil):
1331
        # in this (and other) PyObjectType functions, have_gil is being
1332
        # passed to provide a common interface with MemoryviewSlice.
1333
        # It's ignored here
1334
        self._generate_decref(code, cname, nanny, null_check=True,
1335
                         clear=False)
1336

1337
    def generate_decref_clear(self, code, cname, clear_before_decref, nanny, have_gil):
1338
        self._generate_decref(code, cname, nanny, null_check=False,
1339
                         clear=True, clear_before_decref=clear_before_decref)
1340

1341
    def generate_xdecref_clear(self, code, cname, clear_before_decref=False, nanny=True, have_gil=None):
1342
        self._generate_decref(code, cname, nanny, null_check=True,
1343
                         clear=True, clear_before_decref=clear_before_decref)
1344

1345
    def generate_gotref(self, code, cname):
1346
        code.funcstate.needs_refnanny = True
1347
        code.putln("__Pyx_GOTREF(%s);" % self.as_pyobject(cname))
1348

1349
    def generate_xgotref(self, code, cname):
1350
        code.funcstate.needs_refnanny = True
1351
        code.putln("__Pyx_XGOTREF(%s);" % self.as_pyobject(cname))
1352

1353
    def generate_giveref(self, code, cname):
1354
        code.funcstate.needs_refnanny = True
1355
        code.putln("__Pyx_GIVEREF(%s);" % self.as_pyobject(cname))
1356

1357
    def generate_xgiveref(self, code, cname):
1358
        code.funcstate.needs_refnanny = True
1359
        code.putln("__Pyx_XGIVEREF(%s);" % self.as_pyobject(cname))
1360

1361
    def generate_decref_set(self, code, cname, rhs_cname):
1362
        code.funcstate.needs_refnanny = True
1363
        code.putln("__Pyx_DECREF_SET(%s, %s);" % (cname, rhs_cname))
1364

1365
    def generate_xdecref_set(self, code, cname, rhs_cname):
1366
        code.funcstate.needs_refnanny = True
1367
        code.putln("__Pyx_XDECREF_SET(%s, %s);" % (cname, rhs_cname))
1368

1369
    def _generate_decref(self, code, cname, nanny, null_check=False,
1370
                    clear=False, clear_before_decref=False):
1371
        prefix = '__Pyx' if nanny else 'Py'
1372
        X = 'X' if null_check else ''
1373

1374
        if nanny:
1375
            code.funcstate.needs_refnanny = True
1376

1377
        if clear:
1378
            if clear_before_decref:
1379
                if not nanny:
1380
                    X = ''  # CPython doesn't have a Py_XCLEAR()
1381
                code.putln("%s_%sCLEAR(%s);" % (prefix, X, cname))
1382
            else:
1383
                code.putln("%s_%sDECREF(%s); %s = 0;" % (
1384
                    prefix, X, self.as_pyobject(cname), cname))
1385
        else:
1386
            code.putln("%s_%sDECREF(%s);" % (
1387
                prefix, X, self.as_pyobject(cname)))
1388

1389
    def nullcheck_string(self, cname):
1390
        return cname
1391

1392

1393
builtin_types_that_cannot_create_refcycles = frozenset({
1394
    'object', 'bool', 'int', 'long', 'float', 'complex',
1395
    'bytearray', 'bytes', 'str',
1396
})
1397

1398
builtin_types_with_trashcan = frozenset({
1399
    'dict', 'list', 'set', 'frozenset', 'tuple', 'type',
1400
})
1401

1402

1403
class BuiltinObjectType(PyObjectType):
1404
    #  objstruct_cname  string           Name of PyObject struct
1405

1406
    is_builtin_type = 1
1407
    has_attributes = 1
1408
    base_type = None
1409
    module_name = '__builtin__'
1410
    require_exact = 1
1411

1412
    # fields that let it look like an extension type
1413
    vtabslot_cname = None
1414
    vtabstruct_cname = None
1415
    vtabptr_cname = None
1416
    typedef_flag = True
1417
    is_external = True
1418
    decl_type = 'PyObject'
1419

1420
    def __init__(self, name, cname, objstruct_cname=None):
1421
        self.name = name
1422
        self.typeptr_cname = "(%s)" % cname
1423
        self.objstruct_cname = objstruct_cname
1424
        self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles
1425
        self.builtin_trashcan = name in builtin_types_with_trashcan
1426
        if name == 'type':
1427
            # Special case the type type, as many C API calls (and other
1428
            # libraries) actually expect a PyTypeObject* for type arguments.
1429
            self.decl_type = objstruct_cname
1430
        if name == 'Exception':
1431
            self.require_exact = 0
1432

1433
    def set_scope(self, scope):
1434
        self.scope = scope
1435
        if scope:
1436
            scope.parent_type = self
1437

1438
    def __str__(self):
1439
        return "%s object" % self.name
1440

1441
    def __repr__(self):
1442
        return "<%s>"% self.typeptr_cname
1443

1444
    def default_coerced_ctype(self):
1445
        if self.name in ('bytes', 'bytearray'):
1446
            return c_char_ptr_type
1447
        elif self.name == 'bool':
1448
            return c_bint_type
1449
        elif self.name == 'float':
1450
            return c_double_type
1451
        return None
1452

1453
    def assignable_from(self, src_type):
1454
        if isinstance(src_type, BuiltinObjectType):
1455
            return src_type.name == self.name
1456
        elif src_type.is_extension_type:
1457
            # FIXME: This is an ugly special case that we currently
1458
            # keep supporting.  It allows users to specify builtin
1459
            # types as external extension types, while keeping them
1460
            # compatible with the real builtin types.  We already
1461
            # generate a warning for it.  Big TODO: remove!
1462
            return (src_type.module_name == '__builtin__' and
1463
                    src_type.name == self.name)
1464
        else:
1465
            return True
1466

1467
    def typeobj_is_available(self):
1468
        return True
1469

1470
    def attributes_known(self):
1471
        return True
1472

1473
    def subtype_of(self, type):
1474
        return type.is_pyobject and type.assignable_from(self)
1475

1476
    def type_check_function(self, exact=True):
1477
        type_name = self.name
1478
        if type_name == 'str':
1479
            type_check = 'PyUnicode_Check'
1480
        elif type_name == 'Exception':
1481
            type_check = '__Pyx_PyException_Check'
1482
        elif type_name == 'BaseException':
1483
            type_check = '__Pyx_PyBaseException_Check'
1484
        elif type_name == 'bytearray':
1485
            type_check = 'PyByteArray_Check'
1486
        elif type_name == 'frozenset':
1487
            type_check = 'PyFrozenSet_Check'
1488
        elif type_name == 'int':
1489
            type_check = 'PyLong_Check'
1490
        elif type_name == "memoryview":
1491
            # capitalize doesn't catch the 'V'
1492
            type_check = "PyMemoryView_Check"
1493
        else:
1494
            type_check = 'Py%s_Check' % type_name.capitalize()
1495
        if exact and type_name not in ('bool', 'slice', 'Exception', 'memoryview'):
1496
            type_check += 'Exact'
1497
        return type_check
1498

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

1502
    def type_test_code(self, arg, notnone=False, exact=True):
1503
        type_check = self.type_check_function(exact=exact)
1504
        check = f'likely({type_check}({arg}))'
1505
        if not notnone:
1506
            check += f'||(({arg}) == Py_None)'
1507
        return check + f' || __Pyx_RaiseUnexpectedTypeError("{self.name}", {arg})'
1508

1509
    def declaration_code(self, entity_code,
1510
            for_display = 0, dll_linkage = None, pyrex = 0):
1511
        if pyrex or for_display:
1512
            base_code = self.name
1513
        else:
1514
            base_code = public_decl(self.decl_type, dll_linkage)
1515
            entity_code = "*%s" % entity_code
1516
        return self.base_declaration_code(base_code, entity_code)
1517

1518
    def as_pyobject(self, cname):
1519
        if self.decl_type == 'PyObject':
1520
            return cname
1521
        else:
1522
            return "(PyObject *)" + cname
1523

1524
    def cast_code(self, expr_code, to_object_struct = False):
1525
        return "((%s*)%s)" % (
1526
            to_object_struct and self.objstruct_cname or self.decl_type,  # self.objstruct_cname may be None
1527
            expr_code)
1528

1529
    def py_type_name(self):
1530
        return self.name
1531

1532

1533

1534
class PyExtensionType(PyObjectType):
1535
    #
1536
    #  A Python extension type.
1537
    #
1538
    #  name             string
1539
    #  scope            CClassScope      Attribute namespace
1540
    #  typedef_flag     boolean
1541
    #  base_type        PyExtensionType or None
1542
    #  module_name      string or None   Qualified name of defining module
1543
    #  objstruct_cname  string           Name of PyObject struct
1544
    #  objtypedef_cname string           Name of PyObject struct typedef
1545
    #  typeobj_cname    string or None   C code fragment referring to type object
1546
    #  typeptr_cname    string or None   Name of pointer to external type object
1547
    #  vtabslot_cname   string           Name of C method table member
1548
    #  vtabstruct_cname string           Name of C method table struct
1549
    #  vtabptr_cname    string           Name of pointer to C method table
1550
    #  vtable_cname     string           Name of C method table definition
1551
    #  early_init       boolean          Whether to initialize early (as opposed to during module execution).
1552
    #  defered_declarations [thunk]      Used to declare class hierarchies in order
1553
    #  is_external      boolean          Defined in a extern block
1554
    #  check_size       'warn', 'error', 'ignore'    What to do if tp_basicsize does not match
1555
    #  dataclass_fields  OrderedDict nor None   Used for inheriting from dataclasses
1556
    #  multiple_bases    boolean          Does this class have multiple bases
1557
    #  has_sequence_flag  boolean        Set Py_TPFLAGS_SEQUENCE
1558

1559
    is_extension_type = 1
1560
    has_attributes = 1
1561
    early_init = 1
1562

1563
    objtypedef_cname = None
1564
    dataclass_fields = None
1565
    multiple_bases = False
1566
    has_sequence_flag = False
1567

1568
    def __init__(self, name, typedef_flag, base_type, is_external=0, check_size=None):
1569
        self.name = name
1570
        self.scope = None
1571
        self.typedef_flag = typedef_flag
1572
        if base_type is not None:
1573
            base_type.is_subclassed = True
1574
        self.base_type = base_type
1575
        self.module_name = None
1576
        self.objstruct_cname = None
1577
        self.typeobj_cname = None
1578
        self.typeptr_cname = None
1579
        self.vtabslot_cname = None
1580
        self.vtabstruct_cname = None
1581
        self.vtabptr_cname = None
1582
        self.vtable_cname = None
1583
        self.is_external = is_external
1584
        self.check_size = check_size or 'warn'
1585
        self.defered_declarations = []
1586

1587
    def set_scope(self, scope):
1588
        self.scope = scope
1589
        if scope:
1590
            scope.parent_type = self
1591

1592
    def needs_nonecheck(self):
1593
        return True
1594

1595
    def subtype_of_resolved_type(self, other_type):
1596
        if other_type.is_extension_type or other_type.is_builtin_type:
1597
            return self is other_type or (
1598
                self.base_type and self.base_type.subtype_of(other_type))
1599
        else:
1600
            return other_type is py_object_type
1601

1602
    def typeobj_is_available(self):
1603
        # Do we have a pointer to the type object?
1604
        return self.typeptr_cname
1605

1606
    def typeobj_is_imported(self):
1607
        # If we don't know the C name of the type object but we do
1608
        # know which module it's defined in, it will be imported.
1609
        return self.typeobj_cname is None and self.module_name is not None
1610

1611
    def assignable_from(self, src_type):
1612
        if self == src_type:
1613
            return True
1614
        if isinstance(src_type, PyExtensionType):
1615
            if src_type.base_type is not None:
1616
                return self.assignable_from(src_type.base_type)
1617
        if isinstance(src_type, BuiltinObjectType):
1618
            # FIXME: This is an ugly special case that we currently
1619
            # keep supporting.  It allows users to specify builtin
1620
            # types as external extension types, while keeping them
1621
            # compatible with the real builtin types.  We already
1622
            # generate a warning for it.  Big TODO: remove!
1623
            return (self.module_name == '__builtin__' and
1624
                    self.name == src_type.name)
1625
        return False
1626

1627
    def declaration_code(self, entity_code,
1628
            for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
1629
        if pyrex or for_display:
1630
            base_code = self.name
1631
        else:
1632
            if self.typedef_flag:
1633
                objstruct = self.objstruct_cname
1634
            else:
1635
                objstruct = "struct %s" % self.objstruct_cname
1636
            base_code = public_decl(objstruct, dll_linkage)
1637
            if deref:
1638
                assert not entity_code
1639
            else:
1640
                entity_code = "*%s" % entity_code
1641
        return self.base_declaration_code(base_code, entity_code)
1642

1643
    def type_test_code(self, py_arg, notnone=False):
1644

1645
        none_check = "((%s) == Py_None)" % py_arg
1646
        type_check = "likely(__Pyx_TypeTest(%s, %s))" % (
1647
            py_arg, self.typeptr_cname)
1648
        if notnone:
1649
            return type_check
1650
        else:
1651
            return "likely(%s || %s)" % (none_check, type_check)
1652

1653
    def attributes_known(self):
1654
        return self.scope is not None
1655

1656
    def __str__(self):
1657
        return self.name
1658

1659
    def __repr__(self):
1660
        return "<PyExtensionType %s%s>" % (self.scope.class_name,
1661
            ("", " typedef")[self.typedef_flag])
1662

1663
    def py_type_name(self):
1664
        if not self.module_name:
1665
            return self.name
1666

1667
        return "__import__(%r, None, None, ['']).%s" % (self.module_name,
1668
                                                        self.name)
1669

1670
class CType(PyrexType):
1671
    #
1672
    #  Base class for all C types (non-reference-counted).
1673
    #
1674
    #  to_py_function     string     C function for converting to Python object
1675
    #  from_py_function   string     C function for constructing from Python object
1676
    #
1677

1678
    to_py_function = None
1679
    to_py_utility_code = None
1680
    from_py_function = None
1681
    from_py_utility_code = None
1682
    exception_value = None
1683
    exception_check = 1
1684

1685
    def create_to_py_utility_code(self, env):
1686
        if self.to_py_function is not None:
1687
            if self.to_py_utility_code is not None:
1688
                env.use_utility_code(self.to_py_utility_code)
1689
            return True
1690
        return False
1691

1692
    def create_from_py_utility_code(self, env):
1693
        if self.from_py_function is not None:
1694
            if self.from_py_utility_code is not None:
1695
                env.use_utility_code(self.from_py_utility_code)
1696
            return True
1697
        return False
1698

1699
    def can_coerce_to_pyobject(self, env):
1700
        return self.create_to_py_utility_code(env)
1701

1702
    def can_coerce_from_pyobject(self, env):
1703
        return self.create_from_py_utility_code(env)
1704

1705
    def error_condition(self, result_code):
1706
        conds = []
1707
        if self.is_string or self.is_pyunicode_ptr:
1708
            conds.append("(!%s)" % result_code)
1709
        elif self.exception_value is not None:
1710
            conds.append("(%s == (%s)%s)" % (result_code, self.sign_and_name(), self.exception_value))
1711
        if self.exception_check:
1712
            conds.append("PyErr_Occurred()")
1713
        if len(conds) > 0:
1714
            return " && ".join(conds)
1715
        else:
1716
            return 0
1717

1718
    _builtin_type_name_map = {
1719
        'bytearray': 'ByteArray',
1720
        'bytes': 'Bytes',
1721
        'str': 'Unicode',
1722
        'unicode': 'Unicode',
1723
    }
1724

1725
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
1726
        func = self.to_py_function if to_py_function is None else to_py_function
1727
        assert func
1728
        if self.is_string or self.is_cpp_string:
1729
            if result_type.is_builtin_type:
1730
                result_type_name = self._builtin_type_name_map.get(result_type.name)
1731
                if result_type_name:
1732
                    func = func.replace("Object", result_type_name, 1)
1733
        return '%s = %s(%s)' % (
1734
            result_code,
1735
            func,
1736
            source_code or 'NULL')
1737

1738
    def from_py_call_code(self, source_code, result_code, error_pos, code,
1739
                          from_py_function=None, error_condition=None,
1740
                          special_none_cvalue=None):
1741
        return self._assign_from_py_code(
1742
            source_code, result_code, error_pos, code, from_py_function, error_condition,
1743
            special_none_cvalue=special_none_cvalue)
1744

1745

1746

1747
class PythranExpr(CType):
1748
    # Pythran object of a given type
1749

1750
    to_py_function = "__Pyx_pythran_to_python"
1751
    is_pythran_expr = True
1752
    writable = True
1753
    has_attributes = 1
1754

1755
    def __init__(self, pythran_type, org_buffer=None):
1756
        self.org_buffer = org_buffer
1757
        self.pythran_type = pythran_type
1758
        self.name = self.pythran_type
1759
        self.cname = self.pythran_type
1760
        self.from_py_function = "from_python<%s>" % (self.pythran_type)
1761
        self.scope = None
1762

1763
    def declaration_code(self, entity_code, for_display=0, dll_linkage=None, pyrex=0):
1764
        assert not pyrex
1765
        return "%s %s" % (self.cname, entity_code)
1766

1767
    def attributes_known(self):
1768
        if self.scope is None:
1769
            from . import Symtab
1770
            # FIXME: fake C scope, might be better represented by a struct or C++ class scope
1771
            self.scope = scope = Symtab.CClassScope(
1772
                '', None, visibility="extern", parent_type=self
1773
            )
1774
            scope.directives = {}
1775

1776
            scope.declare_var("ndim", c_long_type, pos=None, cname="value", is_cdef=True)
1777
            scope.declare_cproperty(
1778
                "shape", c_ptr_type(c_long_type), "__Pyx_PythranShapeAccessor",
1779
                doc="Pythran array shape",
1780
                visibility="extern",
1781
                nogil=True,
1782
            )
1783

1784
        return True
1785

1786
    def __eq__(self, other):
1787
        return isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type
1788

1789
    def __ne__(self, other):
1790
        return not (isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type)
1791

1792
    def __hash__(self):
1793
        return hash(self.pythran_type)
1794

1795

1796
class CConstOrVolatileType(BaseType):
1797
    "A C const or volatile type"
1798

1799
    subtypes = ['cv_base_type']
1800

1801
    is_cv_qualified = 1
1802

1803
    def __init__(self, base_type, is_const=0, is_volatile=0):
1804
        self.cv_base_type = base_type
1805
        self.is_const = is_const
1806
        self.is_volatile = is_volatile
1807
        if base_type.has_attributes and base_type.scope is not None:
1808
            from .Symtab import CConstOrVolatileScope
1809
            self.scope = CConstOrVolatileScope(base_type.scope, is_const, is_volatile)
1810

1811
    def cv_string(self):
1812
        cvstring = ""
1813
        if self.is_const:
1814
            cvstring = "const " + cvstring
1815
        if self.is_volatile:
1816
            cvstring = "volatile " + cvstring
1817
        return cvstring
1818

1819
    def __repr__(self):
1820
        return "<CConstOrVolatileType %s%r>" % (self.cv_string(), self.cv_base_type)
1821

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

1825
    def declaration_code(self, entity_code,
1826
            for_display = 0, dll_linkage = None, pyrex = 0):
1827
        cv = self.cv_string()
1828
        if for_display or pyrex:
1829
            return cv + self.cv_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex)
1830
        else:
1831
            return self.cv_base_type.declaration_code(cv + entity_code, for_display, dll_linkage, pyrex)
1832

1833
    def specialize(self, values):
1834
        base_type = self.cv_base_type.specialize(values)
1835
        if base_type == self.cv_base_type:
1836
            return self
1837
        return CConstOrVolatileType(base_type,
1838
                self.is_const, self.is_volatile)
1839

1840
    def deduce_template_params(self, actual):
1841
        return self.cv_base_type.deduce_template_params(actual)
1842

1843
    def can_coerce_to_pyobject(self, env):
1844
        return self.cv_base_type.can_coerce_to_pyobject(env)
1845

1846
    def can_coerce_from_pyobject(self, env):
1847
        return self.cv_base_type.can_coerce_from_pyobject(env)
1848

1849
    def create_to_py_utility_code(self, env):
1850
        if self.cv_base_type.create_to_py_utility_code(env):
1851
            self.to_py_function = self.cv_base_type.to_py_function
1852
            return True
1853

1854
    def same_as_resolved_type(self, other_type):
1855
        if other_type.is_cv_qualified:
1856
            return self.cv_base_type.same_as_resolved_type(other_type.cv_base_type)
1857
        # Accept cv LHS <- non-cv RHS.
1858
        return self.cv_base_type.same_as_resolved_type(other_type)
1859

1860
    def __getattr__(self, name):
1861
        return getattr(self.cv_base_type, name)
1862

1863

1864
def CConstType(base_type):
1865
    return CConstOrVolatileType(base_type, is_const=1)
1866

1867

1868
class FusedType(CType):
1869
    """
1870
    Represents a Fused Type. All it needs to do is keep track of the types
1871
    it aggregates, as it will be replaced with its specific version wherever
1872
    needed.
1873

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

1876
    types           [PyrexType]             is the list of types to be fused
1877
    name            str                     the name of the ctypedef
1878
    """
1879

1880
    is_fused = 1
1881
    exception_check = 0
1882

1883
    def __init__(self, types, name=None):
1884
        # Use list rather than set to preserve order (list should be short).
1885
        flattened_types = []
1886
        for t in types:
1887
            if t.is_fused:
1888
                # recursively merge in subtypes
1889
                if isinstance(t, FusedType):
1890
                    t_types = t.types
1891
                else:
1892
                    # handle types that aren't a fused type themselves but contain fused types
1893
                    # for example a C++ template where the template type is fused.
1894
                    t_fused_types = t.get_fused_types()
1895
                    t_types = []
1896
                    for substitution in product(
1897
                        *[fused_type.types for fused_type in t_fused_types]
1898
                    ):
1899
                        t_types.append(
1900
                            t.specialize(
1901
                                {
1902
                                    fused_type: sub
1903
                                    for fused_type, sub in zip(
1904
                                        t_fused_types, substitution
1905
                                    )
1906
                                }
1907
                            )
1908
                        )
1909
                for subtype in t_types:
1910
                    if subtype not in flattened_types:
1911
                        flattened_types.append(subtype)
1912
            elif t not in flattened_types:
1913
                flattened_types.append(t)
1914
        self.types = flattened_types
1915
        self.name = name
1916

1917
    def declaration_code(self, entity_code, for_display = 0,
1918
                         dll_linkage = None, pyrex = 0):
1919
        if pyrex or for_display:
1920
            return self.name
1921

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

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

1927
    def specialize(self, values):
1928
        if self in values:
1929
            return values[self]
1930
        else:
1931
            raise CannotSpecialize()
1932

1933
    def get_fused_types(self, result=None, seen=None, include_function_return_type=False):
1934
        if result is None:
1935
            return [self]
1936

1937
        if self not in seen:
1938
            result.append(self)
1939
            seen.add(self)
1940

1941

1942
class CVoidType(CType):
1943
    #
1944
    #   C "void" type
1945
    #
1946

1947
    is_void = 1
1948
    to_py_function = "__Pyx_void_to_None"
1949

1950
    def __repr__(self):
1951
        return "<CVoidType>"
1952

1953
    def declaration_code(self, entity_code,
1954
            for_display = 0, dll_linkage = None, pyrex = 0):
1955
        if pyrex or for_display:
1956
            base_code = "void"
1957
        else:
1958
            base_code = public_decl("void", dll_linkage)
1959
        return self.base_declaration_code(base_code, entity_code)
1960

1961
    def is_complete(self):
1962
        return 0
1963

1964
class InvisibleVoidType(CVoidType):
1965
    #
1966
    #   For use with C++ constructors and destructors return types.
1967
    #   Acts like void, but does not print out a declaration.
1968
    #
1969
    def declaration_code(self, entity_code,
1970
            for_display = 0, dll_linkage = None, pyrex = 0):
1971
        if pyrex or for_display:
1972
            base_code = "[void]"
1973
        else:
1974
            base_code = public_decl("", dll_linkage)
1975
        return self.base_declaration_code(base_code, entity_code)
1976

1977

1978
class CNumericType(CType):
1979
    #
1980
    #   Base class for all C numeric types.
1981
    #
1982
    #   rank      integer     Relative size
1983
    #   signed    integer     0 = unsigned, 1 = unspecified, 2 = explicitly signed
1984
    #
1985

1986
    is_numeric = 1
1987
    default_value = "0"
1988
    has_attributes = True
1989
    scope = None
1990

1991
    sign_words = ("unsigned ", "", "signed ")
1992

1993
    def __init__(self, rank, signed = 1):
1994
        self.rank = rank
1995
        if rank > 0 and signed == SIGNED:
1996
            # Signed is meaningless for anything but char, and complicates
1997
            # type promotion.
1998
            signed = 1
1999
        self.signed = signed
2000

2001
    def sign_and_name(self):
2002
        s = self.sign_words[self.signed]
2003
        n = rank_to_type_name[self.rank]
2004
        return s + n
2005

2006
    def is_simple_buffer_dtype(self):
2007
        return True
2008

2009
    def __repr__(self):
2010
        return "<CNumericType %s>" % self.sign_and_name()
2011

2012
    def declaration_code(self, entity_code,
2013
            for_display = 0, dll_linkage = None, pyrex = 0):
2014
        type_name = self.sign_and_name()
2015
        if pyrex or for_display:
2016
            base_code = type_name.replace('PY_LONG_LONG', 'long long')
2017
        else:
2018
            base_code = public_decl(type_name, dll_linkage)
2019
        base_code = StringEncoding.EncodedString(base_code)
2020
        return self.base_declaration_code(base_code, entity_code)
2021

2022
    def attributes_known(self):
2023
        if self.scope is None:
2024
            from . import Symtab
2025
            self.scope = scope = Symtab.CClassScope(
2026
                    '',
2027
                    None,
2028
                    visibility="extern",
2029
                    parent_type=self)
2030
            scope.directives = {}
2031
            scope.declare_cfunction(
2032
                    "conjugate",
2033
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
2034
                    pos=None,
2035
                    defining=1,
2036
                    cname=" ")
2037
        return True
2038

2039
    def __lt__(self, other):
2040
        """Sort based on rank, preferring signed over unsigned"""
2041
        if other.is_numeric:
2042
            return self.rank > other.rank and self.signed >= other.signed
2043

2044
        # Prefer numeric types over others
2045
        return True
2046

2047
    def py_type_name(self):
2048
        if self.rank <= 4:
2049
            return "int"
2050
        return "float"
2051

2052

2053
class ForbidUseClass:
2054
    def __repr__(self):
2055
        raise RuntimeError()
2056
    def __str__(self):
2057
        raise RuntimeError()
2058
ForbidUse = ForbidUseClass()
2059

2060

2061
class CIntLike:
2062
    """Mixin for shared behaviour of C integers and enums.
2063
    """
2064
    to_py_function = None
2065
    from_py_function = None
2066
    to_pyunicode_utility = None
2067
    default_format_spec = 'd'
2068

2069
    def can_coerce_to_pyobject(self, env):
2070
        return True
2071

2072
    def can_coerce_from_pyobject(self, env):
2073
        return True
2074

2075
    def create_to_py_utility_code(self, env):
2076
        if type(self).to_py_function is None:
2077
            self.to_py_function = "__Pyx_PyLong_From_" + self.specialization_name()
2078
            env.use_utility_code(TempitaUtilityCode.load_cached(
2079
                "CIntToPy", "TypeConversion.c",
2080
                context={"TYPE": self.empty_declaration_code(),
2081
                         "TO_PY_FUNCTION": self.to_py_function}))
2082
        return True
2083

2084
    def create_from_py_utility_code(self, env):
2085
        if type(self).from_py_function is None:
2086
            self.from_py_function = "__Pyx_PyLong_As_" + self.specialization_name()
2087
            env.use_utility_code(TempitaUtilityCode.load_cached(
2088
                "CIntFromPy", "TypeConversion.c",
2089
                context={
2090
                    "TYPE": self.empty_declaration_code(),
2091
                    "FROM_PY_FUNCTION": self.from_py_function,
2092
                    "IS_ENUM": self.is_enum,
2093
                }))
2094
        return True
2095

2096
    @staticmethod
2097
    def _parse_format(format_spec):
2098
        # We currently only allow ' ' and '0' as padding, i.e. ASCII characters.
2099
        padding = ' '
2100
        if not format_spec:
2101
            return ('d', 0, padding)
2102

2103
        format_type = format_spec[-1]
2104
        if format_type in 'odxXc':
2105
            prefix = format_spec[:-1]
2106
        elif format_type.isdigit():
2107
            format_type = 'd'
2108
            prefix = format_spec
2109
        else:
2110
            return (None, 0, padding)
2111

2112
        if not prefix:
2113
            return (format_type, 0, padding)
2114

2115
        if prefix[0] in '>-':
2116
            prefix = prefix[1:]
2117
        if prefix and prefix[0] == '0':
2118
            padding = '0'
2119
            prefix = prefix.lstrip('0')
2120
        if prefix.isdigit():
2121
            return (format_type, int(prefix), padding)
2122

2123
        return (None, 0, padding)
2124

2125
    def can_coerce_to_pystring(self, env, format_spec=None):
2126
        format_type, width, padding = self._parse_format(format_spec)
2127
        return format_type is not None and width <= 2**30
2128

2129
    def convert_to_pystring(self, cvalue, code, format_spec=None):
2130
        if self.to_pyunicode_utility is not None:
2131
            conversion_func_cname, to_pyunicode_utility = self.to_pyunicode_utility
2132
        else:
2133
            conversion_func_cname = f"__Pyx_PyUnicode_From_{self.specialization_name()}"
2134
            to_pyunicode_utility = TempitaUtilityCode.load_cached(
2135
                "CIntToPyUnicode", "TypeConversion.c",
2136
                context={"TYPE": self.empty_declaration_code(),
2137
                        "TO_PY_FUNCTION": conversion_func_cname})
2138
            self.to_pyunicode_utility = (conversion_func_cname, to_pyunicode_utility)
2139

2140
        code.globalstate.use_utility_code(to_pyunicode_utility)
2141
        format_type, width, padding_char = self._parse_format(format_spec)
2142
        return "%s(%s, %d, '%s', '%s')" % (conversion_func_cname, cvalue, width, padding_char, format_type)
2143

2144

2145
class CIntType(CIntLike, CNumericType):
2146

2147
    is_int = 1
2148
    typedef_flag = 0
2149
    exception_value = -1
2150

2151
    def get_to_py_type_conversion(self):
2152
        if self.rank < list(rank_to_type_name).index('int'):
2153
            # This assumes sizeof(short) < sizeof(int)
2154
            return "PyLong_FromLong"
2155

2156
        # PyLong_From[Unsigned]Long[Long]
2157
        SignWord = "" if self.signed else "Unsigned"
2158
        TypeName = "Long"
2159
        if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
2160
            TypeName = "LongLong"
2161
        return f"PyLong_From{SignWord}{TypeName}"
2162

2163
    def assignable_from_resolved_type(self, src_type):
2164
        return src_type.is_int or src_type.is_enum or src_type is error_type
2165

2166
    def invalid_value(self):
2167
        if rank_to_type_name[int(self.rank)] == 'char':
2168
            return "'?'"
2169
        else:
2170
            # We do not really know the size of the type, so return
2171
            # a 32-bit literal and rely on casting to final type. It will
2172
            # be negative for signed ints, which is good.
2173
            return "0xbad0bad0"
2174

2175
    def overflow_check_binop(self, binop, env, const_rhs=False):
2176
        env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
2177
        type = self.empty_declaration_code()
2178
        name = self.specialization_name()
2179
        if binop == "lshift":
2180
            env.use_utility_code(TempitaUtilityCode.load_cached(
2181
                "LeftShift", "Overflow.c",
2182
                context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
2183
        else:
2184
            if const_rhs:
2185
                binop += "_const"
2186
            if type in ('int', 'long', 'long long'):
2187
                env.use_utility_code(TempitaUtilityCode.load_cached(
2188
                    "BaseCaseSigned", "Overflow.c",
2189
                    context={'INT': type, 'NAME': name}))
2190
            elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
2191
                env.use_utility_code(TempitaUtilityCode.load_cached(
2192
                    "BaseCaseUnsigned", "Overflow.c",
2193
                    context={'UINT': type, 'NAME': name}))
2194
            elif self.rank <= 1:
2195
                # sizeof(short) < sizeof(int)
2196
                return "__Pyx_%s_%s_no_overflow" % (binop, name)
2197
            else:
2198
                _load_overflow_base(env)
2199
                env.use_utility_code(TempitaUtilityCode.load_cached(
2200
                    "SizeCheck", "Overflow.c",
2201
                    context={'TYPE': type, 'NAME': name}))
2202
                env.use_utility_code(TempitaUtilityCode.load_cached(
2203
                    "Binop", "Overflow.c",
2204
                    context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
2205
        return "__Pyx_%s_%s_checking_overflow" % (binop, name)
2206

2207

2208
def _load_overflow_base(env):
2209
    env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
2210
    for type in ('int', 'long', 'long long'):
2211
        env.use_utility_code(TempitaUtilityCode.load_cached(
2212
            "BaseCaseSigned", "Overflow.c",
2213
            context={'INT': type, 'NAME': type.replace(' ', '_')}))
2214
    for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
2215
        env.use_utility_code(TempitaUtilityCode.load_cached(
2216
            "BaseCaseUnsigned", "Overflow.c",
2217
            context={'UINT': type, 'NAME': type.replace(' ', '_')}))
2218

2219

2220
class CAnonEnumType(CIntType):
2221

2222
    is_enum = 1
2223

2224
    def sign_and_name(self):
2225
        return 'int'
2226

2227
    def specialization_name(self):
2228
        # ensure that the to/from Python functions don't conflict with
2229
        # "int"
2230
        return '__pyx_anon_enum'
2231

2232

2233
class CReturnCodeType(CIntType):
2234

2235
    to_py_function = "__Pyx_Owned_Py_None"
2236

2237
    is_returncode = True
2238
    exception_check = False
2239
    default_format_spec = ''
2240

2241
    def specialization_name(self):
2242
        # I don't think we should end up creating PyLong_As_int/PyLong_From_int functions
2243
        # for this type, but it's better they're distinct in case it happens.
2244
        return super().specialization_name() + "return_code"
2245

2246
    def can_coerce_to_pystring(self, env, format_spec=None):
2247
        return not format_spec
2248

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

2252

2253
class CBIntType(CIntType):
2254

2255
    to_py_function = "__Pyx_PyBool_FromLong"
2256
    from_py_function = "__Pyx_PyObject_IsTrue"
2257
    exception_check = 1  # for C++ bool
2258
    default_format_spec = ''
2259

2260
    def can_coerce_to_pystring(self, env, format_spec=None):
2261
        return not format_spec or super().can_coerce_to_pystring(env, format_spec)
2262

2263
    def convert_to_pystring(self, cvalue, code, format_spec=None):
2264
        if format_spec:
2265
            return super().convert_to_pystring(cvalue, code, format_spec)
2266
        # NOTE: no caching here as the string constant cnames depend on the current module
2267
        utility_code_name = "__Pyx_PyUnicode_FromBInt_" + self.specialization_name()
2268
        to_pyunicode_utility = TempitaUtilityCode.load_cached(
2269
            "CBIntToPyUnicode", "TypeConversion.c", context={
2270
                "TRUE_CONST":  code.globalstate.get_py_string_const(StringEncoding.EncodedString("True")).cname,
2271
                "FALSE_CONST": code.globalstate.get_py_string_const(StringEncoding.EncodedString("False")).cname,
2272
                "TO_PY_FUNCTION": utility_code_name,
2273
            })
2274
        code.globalstate.use_utility_code(to_pyunicode_utility)
2275
        return "%s(%s)" % (utility_code_name, cvalue)
2276

2277
    def declaration_code(self, entity_code,
2278
            for_display = 0, dll_linkage = None, pyrex = 0):
2279
        if for_display:
2280
            base_code = 'bool'
2281
        elif pyrex:
2282
            base_code = 'bint'
2283
        else:
2284
            base_code = public_decl('int', dll_linkage)
2285
        return self.base_declaration_code(base_code, entity_code)
2286

2287
    def specialization_name(self):
2288
        return "bint"
2289

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

2293
    def __str__(self):
2294
        return 'bint'
2295

2296
    def py_type_name(self):
2297
        return "bool"
2298

2299

2300
class CPyUCS4IntType(CIntType):
2301
    # Py_UCS4
2302

2303
    is_unicode_char = True
2304

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

2311
    to_py_function = "__Pyx_PyUnicode_FromOrdinal"
2312
    from_py_function = "__Pyx_PyObject_AsPy_UCS4"
2313

2314
    def can_coerce_to_pystring(self, env, format_spec=None):
2315
        return False  # does the right thing anyway
2316

2317
    def create_from_py_utility_code(self, env):
2318
        env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c"))
2319
        return True
2320

2321
    def sign_and_name(self):
2322
        return "Py_UCS4"
2323

2324

2325
class CPyUnicodeIntType(CIntType):
2326
    # Py_UNICODE
2327

2328
    is_unicode_char = True
2329

2330
    # Py_UNICODE coerces from and to single character unicode strings,
2331
    # but we also allow Python integers as input.  The value range for
2332
    # Py_UNICODE is 0..1114111, which is checked when converting from
2333
    # an integer value.
2334

2335
    to_py_function = "__Pyx_PyUnicode_FromOrdinal"
2336
    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"
2337

2338
    def can_coerce_to_pystring(self, env, format_spec=None):
2339
        return False  # does the right thing anyway
2340

2341
    def create_from_py_utility_code(self, env):
2342
        env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c"))
2343
        return True
2344

2345
    def sign_and_name(self):
2346
        return "Py_UNICODE"
2347

2348

2349
class CPyHashTType(CIntType):
2350

2351
    to_py_function = "__Pyx_PyLong_FromHash_t"
2352
    from_py_function = "__Pyx_PyLong_AsHash_t"
2353

2354
    def sign_and_name(self):
2355
        return "Py_hash_t"
2356

2357
class CPySSizeTType(CIntType):
2358

2359
    to_py_function = "PyLong_FromSsize_t"
2360
    from_py_function = "__Pyx_PyIndex_AsSsize_t"
2361

2362
    def sign_and_name(self):
2363
        return "Py_ssize_t"
2364

2365
class CSSizeTType(CIntType):
2366

2367
    to_py_function = "PyLong_FromSsize_t"
2368
    from_py_function = "PyLong_AsSsize_t"
2369

2370
    def sign_and_name(self):
2371
        return "Py_ssize_t"
2372

2373
class CSizeTType(CIntType):
2374

2375
    to_py_function = "__Pyx_PyLong_FromSize_t"
2376

2377
    def sign_and_name(self):
2378
        return "size_t"
2379

2380
class CPtrdiffTType(CIntType):
2381

2382
    def sign_and_name(self):
2383
        return "ptrdiff_t"
2384

2385

2386
class CFloatType(CNumericType):
2387

2388
    is_float = 1
2389
    to_py_function = "PyFloat_FromDouble"
2390
    from_py_function = "__Pyx_PyFloat_AsDouble"
2391

2392
    exception_value = -1
2393

2394
    def __init__(self, rank, math_h_modifier = ''):
2395
        CNumericType.__init__(self, rank, 1)
2396
        self.math_h_modifier = math_h_modifier
2397
        if rank == RANK_FLOAT:
2398
            self.from_py_function = "__Pyx_PyFloat_AsFloat"
2399

2400
    def assignable_from_resolved_type(self, src_type):
2401
        return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type
2402

2403
    def invalid_value(self):
2404
        return Naming.PYX_NAN
2405

2406
class CComplexType(CNumericType):
2407

2408
    is_complex = 1
2409
    has_attributes = 1
2410
    scope = None
2411

2412
    @property
2413
    def to_py_function(self):
2414
        return "__pyx_PyComplex_FromComplex%s" % self.implementation_suffix
2415

2416
    def __init__(self, real_type):
2417
        while real_type.is_typedef and not real_type.typedef_is_external:
2418
            real_type = real_type.typedef_base_type
2419
        self.funcsuffix = "_%s" % real_type.specialization_name()
2420
        if not real_type.is_float:
2421
            # neither C nor C++ supports non-floating complex numbers,
2422
            # so fall back the on Cython implementation.
2423
            self.implementation_suffix = "_Cy"
2424
        elif real_type.is_typedef and real_type.typedef_is_external:
2425
            # C can't handle typedefs in complex numbers,
2426
            # so in this case also fall back on the Cython implementation.
2427
            self.implementation_suffix = "_CyTypedef"
2428
        else:
2429
            self.implementation_suffix = ""
2430
        if real_type.is_float:
2431
            self.math_h_modifier = real_type.math_h_modifier
2432
        else:
2433
            self.math_h_modifier = "_UNUSED"
2434

2435
        self.real_type = real_type
2436
        CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
2437
        self.binops = {}
2438
        self.from_parts = "%s_from_parts" % self.specialization_name()
2439
        self.default_value = "%s(0, 0)" % self.from_parts
2440

2441
    def __eq__(self, other):
2442
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
2443
            return self.real_type == other.real_type
2444
        else:
2445
            return False
2446

2447
    def __ne__(self, other):
2448
        if isinstance(self, CComplexType) and isinstance(other, CComplexType):
2449
            return self.real_type != other.real_type
2450
        else:
2451
            return True
2452

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

2461
    def __hash__(self):
2462
        return ~hash(self.real_type)
2463

2464
    def declaration_code(self, entity_code,
2465
            for_display = 0, dll_linkage = None, pyrex = 0):
2466
        if pyrex or for_display:
2467
            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
2468
            base_code = "%s complex" % real_code
2469
        else:
2470
            base_code = public_decl(self.sign_and_name(), dll_linkage)
2471
        return self.base_declaration_code(base_code, entity_code)
2472

2473
    def sign_and_name(self):
2474
        real_type_name = self.real_type.specialization_name()
2475
        real_type_name = real_type_name.replace('long__double','long_double')
2476
        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
2477
        return Naming.type_prefix + real_type_name + "_complex"
2478

2479
    def assignable_from(self, src_type):
2480
        # Temporary hack/feature disabling, see #441
2481
        if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
2482
                and src_type.typedef_is_external):
2483
            return False
2484
        elif src_type.is_pyobject:
2485
            return True
2486
        else:
2487
            return super().assignable_from(src_type)
2488

2489
    def assignable_from_resolved_type(self, src_type):
2490
        return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type)
2491
            or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
2492
            or src_type is error_type)
2493

2494
    def attributes_known(self):
2495
        if self.scope is None:
2496
            from . import Symtab
2497
            self.scope = scope = Symtab.CClassScope(
2498
                    '',
2499
                    None,
2500
                    visibility="extern",
2501
                    parent_type=self)
2502
            scope.directives = {}
2503
            scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True)
2504
            scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True)
2505
            scope.declare_cfunction(
2506
                    "conjugate",
2507
                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
2508
                    pos=None,
2509
                    defining=1,
2510
                    cname="__Pyx_c_conj%s" % self.funcsuffix)
2511

2512
        return True
2513

2514
    def _utility_code_context(self):
2515
        return {
2516
            'type': self.empty_declaration_code(),
2517
            'type_name': self.specialization_name(),
2518
            'real_type': self.real_type.empty_declaration_code(),
2519
            'func_suffix': self.funcsuffix,
2520
            'm': self.math_h_modifier,
2521
            'is_float': int(self.real_type.is_float),
2522
            'is_extern_float_typedef': int(
2523
                self.real_type.is_float and self.real_type.is_typedef and self.real_type.typedef_is_external)
2524
        }
2525

2526
    def create_declaration_utility_code(self, env):
2527
        # This must always be run, because a single CComplexType instance can be shared
2528
        # across multiple compilations (the one created in the module scope)
2529
        if self.real_type.is_float:
2530
            env.use_utility_code(UtilityCode.load_cached('Header', 'Complex.c'))
2531
        utility_code_context = self._utility_code_context()
2532
        env.use_utility_code(UtilityCode.load_cached(
2533
            'RealImag' + self.implementation_suffix, 'Complex.c'))
2534
        env.use_utility_code(TempitaUtilityCode.load_cached(
2535
            'Declarations', 'Complex.c', utility_code_context))
2536
        env.use_utility_code(TempitaUtilityCode.load_cached(
2537
            'Arithmetic', 'Complex.c', utility_code_context))
2538
        return True
2539

2540
    def can_coerce_to_pyobject(self, env):
2541
        return True
2542

2543
    def can_coerce_from_pyobject(self, env):
2544
        return True
2545

2546
    def create_to_py_utility_code(self, env):
2547
        env.use_utility_code(TempitaUtilityCode.load_cached(
2548
            'ToPy', 'Complex.c', self._utility_code_context()))
2549
        return True
2550

2551
    def create_from_py_utility_code(self, env):
2552
        env.use_utility_code(TempitaUtilityCode.load_cached(
2553
            'FromPy', 'Complex.c', self._utility_code_context()))
2554
        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
2555
        return True
2556

2557
    def lookup_op(self, nargs, op):
2558
        try:
2559
            return self.binops[nargs, op]
2560
        except KeyError:
2561
            pass
2562
        try:
2563
            op_name = complex_ops[nargs, op]
2564
            self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix)
2565
            return func_name
2566
        except KeyError:
2567
            return None
2568

2569
    def unary_op(self, op):
2570
        return self.lookup_op(1, op)
2571

2572
    def binary_op(self, op):
2573
        return self.lookup_op(2, op)
2574

2575
    def py_type_name(self):
2576
        return "complex"
2577

2578
    def cast_code(self, expr_code):
2579
        return expr_code
2580

2581
    def real_code(self, expr_code):
2582
        return "__Pyx_CREAL%s(%s)" % (self.implementation_suffix, expr_code)
2583

2584
    def imag_code(self, expr_code):
2585
        return "__Pyx_CIMAG%s(%s)" % (self.implementation_suffix, expr_code)
2586

2587
complex_ops = {
2588
    (1, '-'): 'neg',
2589
    (1, 'zero'): 'is_zero',
2590
    (2, '+'): 'sum',
2591
    (2, '-'): 'diff',
2592
    (2, '*'): 'prod',
2593
    (2, '/'): 'quot',
2594
    (2, '**'): 'pow',
2595
    (2, '=='): 'eq',
2596
}
2597

2598

2599
class SoftCComplexType(CComplexType):
2600
    """
2601
    a**b in Python can return either a complex or a float
2602
    depending on the sign of a. This "soft complex" type is
2603
    stored as a C complex (and so is a little slower than a
2604
    direct C double) but it prints/coerces to a float if
2605
    the imaginary part is 0. Therefore it provides a C
2606
    representation of the Python behaviour.
2607
    """
2608

2609
    to_py_function = "__pyx_Py_FromSoftComplex"
2610

2611
    def __init__(self):
2612
        super().__init__(c_double_type)
2613

2614
    def declaration_code(self, entity_code, for_display=0, dll_linkage=None, pyrex=0):
2615
        base_result =  super().declaration_code(
2616
            entity_code,
2617
            for_display=for_display,
2618
            dll_linkage=dll_linkage,
2619
            pyrex=pyrex,
2620
        )
2621
        if for_display:
2622
            return "soft %s" % base_result
2623
        else:
2624
            return base_result
2625

2626
    def create_to_py_utility_code(self, env):
2627
        env.use_utility_code(UtilityCode.load_cached('SoftComplexToPy', 'Complex.c'))
2628
        return True
2629

2630
    def __repr__(self):
2631
        result = super().__repr__()
2632
        assert result[-1] == ">"
2633
        return "%s (soft)%s" % (result[:-1], result[-1])
2634

2635
class CPyTSSTType(CType):
2636
    #
2637
    #   PEP-539 "Py_tss_t" type
2638
    #
2639

2640
    declaration_value = "Py_tss_NEEDS_INIT"
2641

2642
    def __repr__(self):
2643
        return "<Py_tss_t>"
2644

2645
    def declaration_code(self, entity_code,
2646
                         for_display=0, dll_linkage=None, pyrex=0):
2647
        if pyrex or for_display:
2648
            base_code = "Py_tss_t"
2649
        else:
2650
            base_code = public_decl("Py_tss_t", dll_linkage)
2651
        return self.base_declaration_code(base_code, entity_code)
2652

2653

2654
class CPointerBaseType(CType):
2655
    # common base type for pointer/array types
2656
    #
2657
    #  base_type     CType              Reference type
2658

2659
    subtypes = ['base_type']
2660

2661
    def __init__(self, base_type):
2662
        self.base_type = base_type
2663
        if base_type.is_cv_qualified:
2664
            base_type = base_type.cv_base_type
2665
        for char_type in (c_char_type, c_uchar_type, c_schar_type):
2666
            if base_type.same_as(char_type):
2667
                self.is_string = 1
2668
                break
2669
        else:
2670
            if base_type.same_as(c_py_unicode_type):
2671
                self.is_pyunicode_ptr = 1
2672

2673
        if self.is_string and not base_type.is_error:
2674
            if base_type.signed == 2:
2675
                self.to_py_function = "__Pyx_PyObject_FromCString"
2676
                if self.is_ptr:
2677
                    self.from_py_function = "__Pyx_PyObject_As%sSString"
2678
            elif base_type.signed:
2679
                self.to_py_function = "__Pyx_PyObject_FromString"
2680
                if self.is_ptr:
2681
                    self.from_py_function = "__Pyx_PyObject_As%sString"
2682
            else:
2683
                self.to_py_function = "__Pyx_PyObject_FromCString"
2684
                if self.is_ptr:
2685
                    self.from_py_function = "__Pyx_PyObject_As%sUString"
2686
            if self.is_ptr:
2687
                self.from_py_function %= '' if self.base_type.is_const else 'Writable'
2688
            self.exception_value = "NULL"
2689
        elif self.is_pyunicode_ptr and not base_type.is_error:
2690
            self.to_py_function = "__Pyx_PyUnicode_FromUnicode"
2691
            self.to_py_utility_code = UtilityCode.load_cached(
2692
                "pyunicode_from_unicode", "StringTools.c")
2693
            if self.is_ptr:
2694
                self.from_py_function = "__Pyx_PyUnicode_AsUnicode"
2695
            self.exception_value = "NULL"
2696

2697
    def py_type_name(self):
2698
        if self.is_string:
2699
            return "bytes"
2700
        elif self.is_pyunicode_ptr:
2701
            return "unicode"
2702
        else:
2703
            return super().py_type_name()
2704

2705
    def literal_code(self, value):
2706
        if self.is_string:
2707
            assert isinstance(value, str)
2708
            return '"%s"' % StringEncoding.escape_byte_string(value)
2709
        return str(value)
2710

2711

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

2716
    is_array = 1
2717
    to_tuple_function = None
2718

2719
    def __init__(self, base_type, size):
2720
        super().__init__(base_type)
2721
        self.size = size
2722

2723
    def __eq__(self, other):
2724
        if isinstance(other, CType) and other.is_array and self.size == other.size:
2725
            return self.base_type.same_as(other.base_type)
2726
        return False
2727

2728
    def __hash__(self):
2729
        return hash(self.base_type) + 28  # arbitrarily chosen offset
2730

2731
    def __repr__(self):
2732
        return "<CArrayType %s %s>" % (self.size, repr(self.base_type))
2733

2734
    def same_as_resolved_type(self, other_type):
2735
        return ((other_type.is_array and
2736
            self.base_type.same_as(other_type.base_type))
2737
                or other_type is error_type)
2738

2739
    def assignable_from_resolved_type(self, src_type):
2740
        # C arrays are assigned by value, either Python containers or C arrays/pointers
2741
        if src_type.is_pyobject:
2742
            return True
2743
        if src_type.is_ptr or src_type.is_array:
2744
            return self.base_type.assignable_from(src_type.base_type)
2745
        return False
2746

2747
    def element_ptr_type(self):
2748
        return c_ptr_type(self.base_type)
2749

2750
    def declaration_code(self, entity_code,
2751
            for_display = 0, dll_linkage = None, pyrex = 0):
2752
        if self.size is not None:
2753
            dimension_code = self.size
2754
        else:
2755
            dimension_code = ""
2756
        if entity_code.startswith("*"):
2757
            entity_code = "(%s)" % entity_code
2758
        return self.base_type.declaration_code(
2759
            "%s[%s]" % (entity_code, dimension_code),
2760
            for_display, dll_linkage, pyrex)
2761

2762
    def as_argument_type(self):
2763
        return c_ptr_type(self.base_type)
2764

2765
    def is_complete(self):
2766
        return self.size is not None
2767

2768
    def specialize(self, values):
2769
        base_type = self.base_type.specialize(values)
2770
        if base_type == self.base_type:
2771
            return self
2772
        else:
2773
            return CArrayType(base_type, self.size)
2774

2775
    def deduce_template_params(self, actual):
2776
        if isinstance(actual, CArrayType):
2777
            return self.base_type.deduce_template_params(actual.base_type)
2778
        else:
2779
            return {}
2780

2781
    def can_coerce_to_pyobject(self, env):
2782
        return self.base_type.can_coerce_to_pyobject(env)
2783

2784
    def can_coerce_from_pyobject(self, env):
2785
        return self.base_type.can_coerce_from_pyobject(env)
2786

2787
    def create_to_py_utility_code(self, env):
2788
        if self.to_py_function is not None:
2789
            return self.to_py_function
2790
        if not self.base_type.create_to_py_utility_code(env):
2791
            return False
2792

2793
        safe_typename = self.base_type.specialization_name()
2794
        to_py_function = "__Pyx_carray_to_py_%s" % safe_typename
2795
        to_tuple_function = "__Pyx_carray_to_tuple_%s" % safe_typename
2796

2797
        from .UtilityCode import CythonUtilityCode
2798
        context = {
2799
            'cname': to_py_function,
2800
            'to_tuple_cname': to_tuple_function,
2801
            'base_type': self.base_type,
2802
        }
2803
        env.use_utility_code(CythonUtilityCode.load(
2804
            "carray.to_py", "CConvert.pyx",
2805
            outer_module_scope=env.global_scope(),  # need access to types declared in module
2806
            context=context, compiler_directives=dict(env.global_scope().directives)))
2807
        self.to_tuple_function = to_tuple_function
2808
        self.to_py_function = to_py_function
2809
        return True
2810

2811
    def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None):
2812
        func = self.to_py_function if to_py_function is None else to_py_function
2813
        if self.is_string or self.is_pyunicode_ptr:
2814
            return '%s = %s(%s)' % (
2815
                result_code,
2816
                func,
2817
                source_code)
2818
        target_is_tuple = result_type.is_builtin_type and result_type.name == 'tuple'
2819
        return '%s = %s(%s, %s)' % (
2820
            result_code,
2821
            self.to_tuple_function if target_is_tuple else func,
2822
            source_code,
2823
            self.size)
2824

2825
    def create_from_py_utility_code(self, env):
2826
        if self.from_py_function is not None:
2827
            return self.from_py_function
2828
        if not self.base_type.create_from_py_utility_code(env):
2829
            return False
2830

2831
        from_py_function = "__Pyx_carray_from_py_%s" % self.base_type.specialization_name()
2832

2833
        from .UtilityCode import CythonUtilityCode
2834
        context = {
2835
            'cname': from_py_function,
2836
            'base_type': self.base_type,
2837
        }
2838
        env.use_utility_code(CythonUtilityCode.load(
2839
            "carray.from_py", "CConvert.pyx",
2840
            outer_module_scope=env.global_scope(),  # need access to types declared in module
2841
            context=context, compiler_directives=dict(env.global_scope().directives)))
2842
        self.from_py_function = from_py_function
2843
        return True
2844

2845
    def from_py_call_code(self, source_code, result_code, error_pos, code,
2846
                          from_py_function=None, error_condition=None,
2847
                          special_none_cvalue=None):
2848
        assert not error_condition, '%s: %s' % (error_pos, error_condition)
2849
        assert not special_none_cvalue, '%s: %s' % (error_pos, special_none_cvalue)  # not currently supported
2850
        call_code = "%s(%s, %s, %s)" % (
2851
            from_py_function or self.from_py_function,
2852
            source_code, result_code, self.size)
2853
        return code.error_goto_if_neg(call_code, error_pos)
2854

2855
    def error_condition(self, result_code):
2856
        # It isn't possible to use CArrays as return type so the error_condition
2857
        # is irrelevant. Returning a falsy value does avoid an error when getting
2858
        # from_py_call_code from a typedef.
2859
        return ""
2860

2861

2862
class CPtrType(CPointerBaseType):
2863
    #  base_type     CType              Reference type
2864

2865
    is_ptr = 1
2866
    default_value = "0"
2867
    exception_value = "NULL"
2868

2869
    def __hash__(self):
2870
        return hash(self.base_type) + 27  # arbitrarily chosen offset
2871

2872
    def __eq__(self, other):
2873
        if isinstance(other, CType) and other.is_ptr:
2874
            return self.base_type.same_as(other.base_type)
2875
        return False
2876

2877
    def __ne__(self, other):
2878
        return not (self == other)
2879

2880
    def __repr__(self):
2881
        return "<CPtrType %s>" % repr(self.base_type)
2882

2883
    def same_as_resolved_type(self, other_type):
2884
        return ((other_type.is_ptr and
2885
            self.base_type.same_as(other_type.base_type))
2886
                or other_type is error_type)
2887

2888
    def is_simple_buffer_dtype(self):
2889
        return True
2890

2891
    def declaration_code(self, entity_code,
2892
            for_display = 0, dll_linkage = None, pyrex = 0):
2893
        #print "CPtrType.declaration_code: pointer to", self.base_type ###
2894
        return self.base_type.declaration_code(
2895
            "*%s" % entity_code,
2896
            for_display, dll_linkage, pyrex)
2897

2898
    def assignable_from_resolved_type(self, other_type):
2899
        if other_type is error_type:
2900
            return True
2901
        if other_type.is_null_ptr:
2902
            return True
2903
        ptr_base_type = self.base_type
2904
        if ptr_base_type.is_cv_qualified:
2905
            ptr_base_type = ptr_base_type.cv_base_type
2906
        if ptr_base_type.is_cfunction:
2907
            if other_type.is_ptr:
2908
                other_type = other_type.base_type.resolve()
2909
            if other_type.is_cfunction:
2910
                return ptr_base_type.pointer_assignable_from_resolved_type(other_type)
2911
            else:
2912
                return False
2913
        if (ptr_base_type.is_cpp_class and other_type.is_ptr
2914
                and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(ptr_base_type)):
2915
            return True
2916
        if other_type.is_array or other_type.is_ptr:
2917
            return ptr_base_type.is_void or ptr_base_type.same_as(other_type.base_type)
2918
        return False
2919

2920
    def assignment_failure_extra_info(self, src_type, src_name):
2921
        if self.base_type.is_cfunction and src_type.is_ptr:
2922
            src_type = src_type.base_type.resolve()
2923
        if self.base_type.is_cfunction and src_type.is_cfunction:
2924
            copied_src_type = copy.copy(src_type)
2925
            # make the exception values the same as us
2926
            copied_src_type.exception_check = self.base_type.exception_check
2927
            copied_src_type.exception_value = self.base_type.exception_value
2928
            if self.base_type.pointer_assignable_from_resolved_type(copied_src_type):
2929
                # the only reason we can't assign is because of exception incompatibility
2930
                msg = " Exception values are incompatible."
2931
                if not self.base_type.exception_check and self.base_type.exception_value is None:
2932
                    if src_name is None:
2933
                        src_name = "the value being assigned"
2934
                    else:
2935
                        src_name = "'{}'".format(src_name)
2936
                    msg += f" Suggest adding 'noexcept' to the type of {src_name}."
2937
                return msg
2938
        return super().assignment_failure_extra_info(src_type, src_name)
2939

2940
    def specialize(self, values):
2941
        base_type = self.base_type.specialize(values)
2942
        if base_type == self.base_type:
2943
            return self
2944
        else:
2945
            return CPtrType(base_type)
2946

2947
    def deduce_template_params(self, actual):
2948
        if isinstance(actual, CPtrType):
2949
            return self.base_type.deduce_template_params(actual.base_type)
2950
        else:
2951
            return {}
2952

2953
    def invalid_value(self):
2954
        return "1"
2955

2956
    def find_cpp_operation_type(self, operator, operand_type=None):
2957
        if self.base_type.is_cpp_class:
2958
            return self.base_type.find_cpp_operation_type(operator, operand_type)
2959
        return None
2960

2961
    def get_fused_types(self, result=None, seen=None, include_function_return_type=False):
2962
        # For function pointers, include the return type - unlike for fused functions themselves,
2963
        # where the return type cannot be an independent fused type (i.e. is derived or non-fused).
2964
        return super(CPointerBaseType, self).get_fused_types(result, seen, include_function_return_type=True)
2965

2966

2967
class CNullPtrType(CPtrType):
2968

2969
    is_null_ptr = 1
2970

2971

2972
class CReferenceBaseType(BaseType):
2973

2974
    is_fake_reference = 0
2975

2976
    # Common base type for C reference and C++ rvalue reference types.
2977

2978
    subtypes = ['ref_base_type']
2979

2980
    def __init__(self, base_type):
2981
        self.ref_base_type = base_type
2982

2983
    def __repr__(self):
2984
        return "<%r %s>" % (self.__class__.__name__, self.ref_base_type)
2985

2986
    def specialize(self, values):
2987
        base_type = self.ref_base_type.specialize(values)
2988
        if base_type == self.ref_base_type:
2989
            return self
2990
        else:
2991
            return type(self)(base_type)
2992

2993
    def deduce_template_params(self, actual):
2994
        return self.ref_base_type.deduce_template_params(actual)
2995

2996
    def __getattr__(self, name):
2997
        return getattr(self.ref_base_type, name)
2998

2999

3000
class CReferenceType(CReferenceBaseType):
3001

3002
    is_reference = 1
3003

3004
    def __str__(self):
3005
        return "%s &" % self.ref_base_type
3006

3007
    def declaration_code(self, entity_code,
3008
            for_display = 0, dll_linkage = None, pyrex = 0):
3009
        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
3010
        return self.ref_base_type.declaration_code(
3011
            "&%s" % entity_code,
3012
            for_display, dll_linkage, pyrex)
3013

3014

3015
class CFakeReferenceType(CReferenceType):
3016

3017
    is_fake_reference = 1
3018

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

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

3027

3028
class CppRvalueReferenceType(CReferenceBaseType):
3029

3030
    is_rvalue_reference = 1
3031

3032
    def __str__(self):
3033
        return "%s &&" % self.ref_base_type
3034

3035
    def declaration_code(self, entity_code,
3036
            for_display = 0, dll_linkage = None, pyrex = 0):
3037
        return self.ref_base_type.declaration_code(
3038
            "&&%s" % entity_code,
3039
            for_display, dll_linkage, pyrex)
3040

3041

3042
class CFuncType(CType):
3043
    #  return_type      CType
3044
    #  args             [CFuncTypeArg]
3045
    #  has_varargs      boolean
3046
    #  exception_value  string
3047
    #  exception_check  boolean    True if PyErr_Occurred check needed
3048
    #  calling_convention  string  Function calling convention
3049
    #  nogil            boolean    Can be called without gil
3050
    #  with_gil         boolean    Acquire gil around function body
3051
    #  templates        [string] or None
3052
    #  cached_specialized_types [CFuncType]   cached specialized versions of the CFuncType if defined in a pxd
3053
    #  from_fused       boolean    Indicates whether this is a specialized
3054
    #                              C function
3055
    #  is_strict_signature boolean  function refuses to accept coerced arguments
3056
    #                               (used for optimisation overrides)
3057
    #  is_const_method  boolean
3058
    #  is_static_method boolean
3059
    #  op_arg_struct    CPtrType   Pointer to optional argument struct
3060

3061
    is_cfunction = 1
3062
    original_sig = None
3063
    cached_specialized_types = None
3064
    from_fused = False
3065
    is_const_method = False
3066
    op_arg_struct = None
3067

3068
    subtypes = ['return_type', 'args']
3069

3070
    def __init__(self, return_type, args, has_varargs = 0,
3071
            exception_value = None, exception_check = 0, calling_convention = "",
3072
            nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
3073
            is_const_method = False, is_static_method=False,
3074
            templates = None, is_strict_signature = False):
3075
        self.return_type = return_type
3076
        self.args = args
3077
        self.has_varargs = has_varargs
3078
        self.optional_arg_count = optional_arg_count
3079
        self.exception_value = exception_value
3080
        self.exception_check = exception_check
3081
        self.calling_convention = calling_convention
3082
        self.nogil = nogil
3083
        self.with_gil = with_gil
3084
        self.is_overridable = is_overridable
3085
        self.is_const_method = is_const_method
3086
        self.is_static_method = is_static_method
3087
        self.templates = templates
3088
        self.is_strict_signature = is_strict_signature
3089

3090
    def __repr__(self):
3091
        arg_reprs = list(map(repr, self.args))
3092
        if self.has_varargs:
3093
            arg_reprs.append("...")
3094
        if self.exception_value is not None:
3095
            except_clause = " %r" % self.exception_value
3096
        else:
3097
            except_clause = ""
3098
        if self.exception_check:
3099
            except_clause += "?"
3100
        return "<CFuncType %s %s[%s]%s>" % (
3101
            repr(self.return_type),
3102
            self.calling_convention_prefix(),
3103
            ",".join(arg_reprs),
3104
            except_clause)
3105

3106
    def with_with_gil(self, with_gil):
3107
        if with_gil == self.with_gil:
3108
            return self
3109
        else:
3110
            return CFuncType(
3111
                self.return_type, self.args, self.has_varargs,
3112
                self.exception_value, self.exception_check,
3113
                self.calling_convention, self.nogil,
3114
                with_gil,
3115
                self.is_overridable, self.optional_arg_count,
3116
                self.is_const_method, self.is_static_method,
3117
                self.templates, self.is_strict_signature)
3118

3119
    def calling_convention_prefix(self):
3120
        cc = self.calling_convention
3121
        if cc:
3122
            return cc + " "
3123
        else:
3124
            return ""
3125

3126
    def as_argument_type(self):
3127
        return c_ptr_type(self)
3128

3129
    def same_c_signature_as(self, other_type, as_cmethod = 0):
3130
        return self.same_c_signature_as_resolved_type(
3131
            other_type.resolve(), as_cmethod)
3132

3133
    def same_c_signature_as_resolved_type(self, other_type, as_cmethod=False, as_pxd_definition=False,
3134
                                          exact_semantics=True):
3135
        # If 'exact_semantics' is false, allow any equivalent C signatures
3136
        # if the Cython semantics are compatible, i.e. the same or wider for 'other_type'.
3137

3138
        #print "CFuncType.same_c_signature_as_resolved_type:", \
3139
        #    self, other_type, "as_cmethod =", as_cmethod ###
3140
        if other_type is error_type:
3141
            return 1
3142
        if not other_type.is_cfunction:
3143
            return 0
3144
        if self.is_overridable != other_type.is_overridable:
3145
            return 0
3146
        nargs = len(self.args)
3147
        if nargs != len(other_type.args):
3148
            return 0
3149
        # When comparing C method signatures, the first argument
3150
        # is exempt from compatibility checking (the proper check
3151
        # is performed elsewhere).
3152
        for i in range(as_cmethod, nargs):
3153
            if not self.args[i].type.same_as(other_type.args[i].type):
3154
                return 0
3155
        if self.has_varargs != other_type.has_varargs:
3156
            return 0
3157
        if self.optional_arg_count != other_type.optional_arg_count:
3158
            return 0
3159
        if as_pxd_definition:
3160
            # A narrowing of the return type declared in the pxd is allowed.
3161
            if not self.return_type.subtype_of_resolved_type(other_type.return_type):
3162
                return 0
3163
        else:
3164
            if not self.return_type.same_as(other_type.return_type):
3165
                return 0
3166
        if not self.same_calling_convention_as(other_type):
3167
            return 0
3168
        if exact_semantics:
3169
            if self.exception_check != other_type.exception_check:
3170
                return 0
3171
            if not self._same_exception_value(other_type.exception_value):
3172
                return 0
3173
        elif not self._is_exception_compatible_with(other_type):
3174
            return 0
3175
        return 1
3176

3177
    def _same_exception_value(self, other_exc_value):
3178
        # Use fallback comparison as strings since we usually read exception values as strings.
3179
        if self.exception_value == other_exc_value or str(self.exception_value) == str(other_exc_value):
3180
            return 1
3181
        if self.exception_check != '+':
3182
            return 0
3183
        if not self.exception_value or not other_exc_value:
3184
            return 0
3185
        if self.exception_value.type != other_exc_value.type:
3186
            return 0
3187
        if self.exception_value.entry and other_exc_value.entry:
3188
            if self.exception_value.entry.cname != other_exc_value.entry.cname:
3189
                return 0
3190
        if self.exception_value.name != other_exc_value.name:
3191
            return 0
3192
        return 1
3193

3194
    def compatible_signature_with(self, other_type, as_cmethod = 0):
3195
        return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
3196

3197
    def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
3198
        #print "CFuncType.same_c_signature_as_resolved_type:", \
3199
        #    self, other_type, "as_cmethod =", as_cmethod ###
3200
        if other_type is error_type:
3201
            return 1
3202
        if not other_type.is_cfunction:
3203
            return 0
3204
        if not self.is_overridable and other_type.is_overridable:
3205
            return 0
3206
        nargs = len(self.args)
3207
        if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count:
3208
            return 0
3209
        if self.optional_arg_count < other_type.optional_arg_count:
3210
            return 0
3211
        # When comparing C method signatures, the first argument
3212
        # is exempt from compatibility checking (the proper check
3213
        # is performed elsewhere).
3214
        for i in range(as_cmethod, len(other_type.args)):
3215
            if not self.args[i].type.same_as(
3216
                    other_type.args[i].type):
3217
                return 0
3218
        if self.has_varargs != other_type.has_varargs:
3219
            return 0
3220
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
3221
            return 0
3222
        if not self.same_calling_convention_as(other_type):
3223
            return 0
3224
        if self.nogil != other_type.nogil:
3225
            return 0
3226
        if not self._is_exception_compatible_with(other_type):
3227
            return 0
3228
        self.original_sig = other_type.original_sig or other_type
3229
        return 1
3230

3231
    def _is_exception_compatible_with(self, other_type):
3232
        # narrower exception checks are ok, but prevent mismatches
3233
        if self.exception_check == '+' and other_type.exception_check != '+':
3234
            # must catch C++ exceptions if we raise them
3235
            return 0
3236
        if not other_type.exception_check or other_type.exception_value is not None:
3237
            # There's no problem if this type doesn't emit exceptions but the other type checks
3238
            if other_type.exception_check and not (self.exception_check or self.exception_value):
3239
                return 1
3240
            # if other does not *always* check exceptions, self must comply
3241
            if not self._same_exception_value(other_type.exception_value):
3242
                return 0
3243
            if self.exception_check and self.exception_check != other_type.exception_check:
3244
                # a redundant exception check doesn't make functions incompatible, but a missing one does
3245
                return 0
3246
        return 1
3247

3248
    def narrower_c_signature_than(self, other_type, as_cmethod = 0):
3249
        return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
3250

3251
    def narrower_c_signature_than_resolved_type(self, other_type, as_cmethod):
3252
        if other_type is error_type:
3253
            return 1
3254
        if not other_type.is_cfunction:
3255
            return 0
3256
        nargs = len(self.args)
3257
        if nargs != len(other_type.args):
3258
            return 0
3259
        for i in range(as_cmethod, nargs):
3260
            if not self.args[i].type.subtype_of_resolved_type(other_type.args[i].type):
3261
                return 0
3262
            else:
3263
                self.args[i].needs_type_test = other_type.args[i].needs_type_test \
3264
                        or not self.args[i].type.same_as(other_type.args[i].type)
3265
        if self.has_varargs != other_type.has_varargs:
3266
            return 0
3267
        if self.optional_arg_count != other_type.optional_arg_count:
3268
            return 0
3269
        if not self.return_type.subtype_of_resolved_type(other_type.return_type):
3270
            return 0
3271
        if not self.exception_check and other_type.exception_check:
3272
            # a redundant exception check doesn't make functions incompatible, but a missing one does
3273
            return 0
3274
        if not self._same_exception_value(other_type.exception_value):
3275
            return 0
3276
        return 1
3277

3278
    def same_calling_convention_as(self, other):
3279
        ## XXX Under discussion ...
3280
        ## callspec_words = ("__stdcall", "__cdecl", "__fastcall")
3281
        ## cs1 = self.calling_convention
3282
        ## cs2 = other.calling_convention
3283
        ## if (cs1 in callspec_words or
3284
        ##     cs2 in callspec_words):
3285
        ##     return cs1 == cs2
3286
        ## else:
3287
        ##     return True
3288
        sc1 = self.calling_convention == '__stdcall'
3289
        sc2 = other.calling_convention == '__stdcall'
3290
        return sc1 == sc2
3291

3292
    def same_as_resolved_type(self, other_type, as_cmethod=False):
3293
        return self.same_c_signature_as_resolved_type(other_type, as_cmethod=as_cmethod) \
3294
            and self.nogil == other_type.nogil
3295

3296
    def pointer_assignable_from_resolved_type(self, rhs_type):
3297
        # Accept compatible exception/nogil declarations for the RHS.
3298
        if rhs_type is error_type:
3299
            return 1
3300
        if not rhs_type.is_cfunction:
3301
            return 0
3302
        return rhs_type.same_c_signature_as_resolved_type(self, exact_semantics=False) \
3303
            and not (self.nogil and not rhs_type.nogil)
3304

3305
    def declaration_code(self, entity_code,
3306
                         for_display = 0, dll_linkage = None, pyrex = 0,
3307
                         with_calling_convention = 1):
3308
        arg_decl_list = []
3309
        for arg in self.args[:len(self.args)-self.optional_arg_count]:
3310
            arg_decl_list.append(
3311
                arg.type.declaration_code("", for_display, pyrex = pyrex))
3312
        if self.is_overridable:
3313
            arg_decl_list.append("int %s" % Naming.skip_dispatch_cname)
3314
        if self.optional_arg_count:
3315
            if self.op_arg_struct:
3316
                arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
3317
            else:
3318
                # op_arg_struct may not be initialized at this point if this class is being used
3319
                # to prepare a Python error message or similar.  In this case, just omit the args.
3320
                assert for_display
3321
        if self.has_varargs:
3322
            arg_decl_list.append("...")
3323
        arg_decl_code = ", ".join(arg_decl_list)
3324
        if not arg_decl_code and not pyrex:
3325
            arg_decl_code = "void"
3326
        trailer = ""
3327
        if (pyrex or for_display) and not self.return_type.is_pyobject:
3328
            if self.exception_value is not None and self.exception_check:
3329
                trailer = " except? %s" % self.exception_value
3330
            elif self.exception_value is not None and not self.exception_check:
3331
                trailer = " except %s" % self.exception_value
3332
            elif self.exception_value is None and not self.exception_check:
3333
                trailer = " noexcept"
3334
            elif self.exception_check == '+':
3335
                trailer = " except +"
3336
            elif self.exception_check and for_display:
3337
                # not spelled out by default, unless for human eyes
3338
                trailer = " except *"
3339
            if self.nogil:
3340
                trailer += " nogil"
3341
        if not with_calling_convention:
3342
            cc = ''
3343
        else:
3344
            cc = self.calling_convention_prefix()
3345
            if (not entity_code and cc) or entity_code.startswith("*"):
3346
                entity_code = "(%s%s)" % (cc, entity_code)
3347
                cc = ""
3348
        if self.is_const_method:
3349
            trailer += " const"
3350
        return self.return_type.declaration_code(
3351
            "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
3352
            for_display, dll_linkage, pyrex)
3353

3354
    def function_header_code(self, func_name, arg_code):
3355
        if self.is_const_method:
3356
            trailer = " const"
3357
        else:
3358
            trailer = ""
3359
        return "%s%s(%s)%s" % (self.calling_convention_prefix(),
3360
            func_name, arg_code, trailer)
3361

3362
    def signature_string(self):
3363
        s = self.empty_declaration_code()
3364
        return s
3365

3366
    def signature_cast_string(self):
3367
        s = self.declaration_code("(*)", with_calling_convention=False)
3368
        return '(%s)' % s
3369

3370
    def specialize(self, values):
3371
        result = CFuncType(self.return_type.specialize(values),
3372
                           [arg.specialize(values) for arg in self.args],
3373
                           has_varargs = self.has_varargs,
3374
                           exception_value = self.exception_value,
3375
                           exception_check = self.exception_check,
3376
                           calling_convention = self.calling_convention,
3377
                           nogil = self.nogil,
3378
                           with_gil = self.with_gil,
3379
                           is_overridable = self.is_overridable,
3380
                           optional_arg_count = self.optional_arg_count,
3381
                           is_const_method = self.is_const_method,
3382
                           is_static_method = self.is_static_method,
3383
                           templates = self.templates)
3384

3385
        result.from_fused = self.is_fused
3386
        return result
3387

3388
    def opt_arg_cname(self, arg_name):
3389
        return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
3390

3391
    # Methods that deal with Fused Types
3392
    # All but map_with_specific_entries should be called only on functions
3393
    # with fused types (and not on their corresponding specific versions).
3394

3395
    def get_all_specialized_permutations(self, fused_types=None):
3396
        """
3397
        Permute all the types. For every specific instance of a fused type, we
3398
        want all other specific instances of all other fused types.
3399

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

3406
        if fused_types is None:
3407
            fused_types = self.get_fused_types()
3408

3409
        return get_all_specialized_permutations(fused_types)
3410

3411
    def get_all_specialized_function_types(self):
3412
        """
3413
        Get all the specific function types of this one.
3414
        """
3415
        assert self.is_fused
3416

3417
        if self.entry.fused_cfunction:
3418
            return [n.type for n in self.entry.fused_cfunction.nodes]
3419
        elif self.cached_specialized_types is not None:
3420
            return self.cached_specialized_types
3421

3422
        result = []
3423
        permutations = self.get_all_specialized_permutations()
3424

3425
        new_cfunc_entries = []
3426
        for cname, fused_to_specific in permutations:
3427
            new_func_type = self.entry.type.specialize(fused_to_specific)
3428

3429
            if self.optional_arg_count:
3430
                # Remember, this method is set by CFuncDeclaratorNode
3431
                self.declare_opt_arg_struct(new_func_type, cname)
3432

3433
            new_entry = copy.deepcopy(self.entry)
3434
            new_func_type.specialize_entry(new_entry, cname)
3435

3436
            new_entry.type = new_func_type
3437
            new_func_type.entry = new_entry
3438
            result.append(new_func_type)
3439

3440
            new_cfunc_entries.append(new_entry)
3441

3442
        cfunc_entries = self.entry.scope.cfunc_entries
3443
        try:
3444
            cindex = cfunc_entries.index(self.entry)
3445
        except ValueError:
3446
            cfunc_entries.extend(new_cfunc_entries)
3447
        else:
3448
            cfunc_entries[cindex:cindex+1] = new_cfunc_entries
3449

3450
        self.cached_specialized_types = result
3451

3452
        return result
3453

3454
    def get_fused_types(self, result=None, seen=None, subtypes=None, include_function_return_type=False):
3455
        """Return fused types in the order they appear as parameter types"""
3456
        return super().get_fused_types(
3457
            result, seen,
3458
            # for function pointer types, we consider the result type; for plain function
3459
            # types we don't (because it must be derivable from the arguments)
3460
            subtypes=self.subtypes if include_function_return_type else ['args'])
3461

3462
    def specialize_entry(self, entry, cname):
3463
        assert not self.is_fused
3464
        specialize_entry(entry, cname)
3465

3466
    def can_coerce_to_pyobject(self, env):
3467
        # duplicating the decisions from create_to_py_utility_code() here avoids writing out unused code
3468
        if self.has_varargs or self.optional_arg_count:
3469
            return False
3470
        if self.to_py_function is not None:
3471
            return self.to_py_function
3472
        for arg in self.args:
3473
            if not arg.type.is_pyobject and not arg.type.can_coerce_to_pyobject(env):
3474
                return False
3475
        if not self.return_type.is_pyobject and not self.return_type.can_coerce_to_pyobject(env):
3476
            return False
3477
        return True
3478

3479
    def create_to_py_utility_code(self, env):
3480
        # FIXME: it seems we're trying to coerce in more cases than we should
3481
        if self.to_py_function is not None:
3482
            return self.to_py_function
3483
        if not self.can_coerce_to_pyobject(env):
3484
            return False
3485
        from .UtilityCode import CythonUtilityCode
3486

3487
        # include argument names into the c function name to ensure cname is unique
3488
        # between functions with identical types but different argument names
3489
        from .Symtab import punycodify_name
3490
        def arg_name_part(arg):
3491
            return "%s%s" % (len(arg.name), punycodify_name(arg.name)) if arg.name else "0"
3492
        arg_names = [ arg_name_part(arg) for arg in self.args ]
3493
        arg_names = cap_length("_".join(arg_names))
3494
        safe_typename = type_identifier(self, pyrex=True)
3495
        # Note that the length here is slightly bigger than twice the default cap in
3496
        # "cap_length" (since the length is capped in both arg_names and the type_identifier)
3497
        # but since this is significantly shorter than compilers should be able to handle,
3498
        # that is acceptable.
3499
        to_py_function = "__Pyx_CFunc_%s_to_py_%s" % (safe_typename, arg_names)
3500

3501
        for arg in self.args:
3502
            if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
3503
                return False
3504
        if not self.return_type.is_pyobject and not self.return_type.create_to_py_utility_code(env):
3505
            return False
3506

3507
        def declared_type(ctype):
3508
            type_displayname = str(ctype.declaration_code("", for_display=True))
3509
            if ctype.is_pyobject:
3510
                arg_ctype = type_name = type_displayname
3511
                if ctype.is_builtin_type:
3512
                    arg_ctype = ctype.name
3513
                elif not ctype.is_extension_type:
3514
                    type_name = 'object'
3515
                    type_displayname = None
3516
                else:
3517
                    type_displayname = repr(type_displayname)
3518
            elif ctype is c_bint_type:
3519
                type_name = arg_ctype = 'bint'
3520
            else:
3521
                type_name = arg_ctype = type_displayname
3522
                if ctype is c_double_type:
3523
                    type_displayname = 'float'
3524
                else:
3525
                    type_displayname = repr(type_displayname)
3526
            return type_name, arg_ctype, type_displayname
3527

3528
        class Arg:
3529
            def __init__(self, arg_name, arg_type):
3530
                self.name = arg_name
3531
                self.type = arg_type
3532
                self.type_cname, self.ctype, self.type_displayname = declared_type(arg_type)
3533

3534
        if self.return_type.is_void:
3535
            except_clause = 'except *'
3536
        elif self.return_type.is_pyobject:
3537
            except_clause = ''
3538
        elif self.exception_value is not None:
3539
            except_clause = ('except? %s' if self.exception_check else 'except %s') % self.exception_value
3540
        else:
3541
            except_clause = 'except *'
3542

3543
        context = {
3544
            'cname': to_py_function,
3545
            'args': [Arg(arg.name or 'arg%s' % ix, arg.type) for ix, arg in enumerate(self.args)],
3546
            'return_type': Arg('return', self.return_type),
3547
            'except_clause': except_clause,
3548
        }
3549
        # FIXME: directives come from first defining environment and do not adapt for reuse
3550
        env.use_utility_code(CythonUtilityCode.load(
3551
            "cfunc.to_py", "CConvert.pyx",
3552
            outer_module_scope=env.global_scope(),  # need access to types declared in module
3553
            context=context, compiler_directives=dict(env.global_scope().directives)))
3554
        self.to_py_function = to_py_function
3555
        return True
3556

3557

3558
def specialize_entry(entry, cname):
3559
    """
3560
    Specialize an entry of a copied fused function or method
3561
    """
3562
    entry.is_fused_specialized = True
3563
    entry.name = get_fused_cname(cname, entry.name)
3564

3565
    if entry.is_cmethod:
3566
        entry.cname = entry.name
3567
        if entry.is_inherited:
3568
            entry.cname = StringEncoding.EncodedString(
3569
                    "%s.%s" % (Naming.obj_base_cname, entry.cname))
3570
    else:
3571
        entry.cname = get_fused_cname(cname, entry.cname)
3572

3573
    if entry.func_cname:
3574
        entry.func_cname = get_fused_cname(cname, entry.func_cname)
3575
    if entry.final_func_cname:
3576
        entry.final_func_cname = get_fused_cname(cname, entry.final_func_cname)
3577

3578
def get_fused_cname(fused_cname, orig_cname):
3579
    """
3580
    Given the fused cname id and an original cname, return a specialized cname
3581
    """
3582
    assert fused_cname and orig_cname
3583
    return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix,
3584
                                                    fused_cname, orig_cname))
3585

3586
def unique(somelist):
3587
    seen = set()
3588
    result = []
3589
    for obj in somelist:
3590
        if obj not in seen:
3591
            result.append(obj)
3592
            seen.add(obj)
3593

3594
    return result
3595

3596
def get_all_specialized_permutations(fused_types):
3597
    return _get_all_specialized_permutations(unique(fused_types))
3598

3599
def _get_all_specialized_permutations(fused_types, id="", f2s=()):
3600
    fused_type, = fused_types[0].get_fused_types()
3601
    result = []
3602

3603
    for newid, specific_type in enumerate(fused_type.types):
3604
        # f2s = dict(f2s, **{ fused_type: specific_type })
3605
        f2s = dict(f2s)
3606
        f2s.update({ fused_type: specific_type })
3607

3608
        if id:
3609
            cname = '%s_%s' % (id, newid)
3610
        else:
3611
            cname = str(newid)
3612

3613
        if len(fused_types) > 1:
3614
            result.extend(_get_all_specialized_permutations(
3615
                                            fused_types[1:], cname, f2s))
3616
        else:
3617
            result.append((cname, f2s))
3618

3619
    return result
3620

3621
def specialization_signature_string(fused_compound_type, fused_to_specific):
3622
    """
3623
    Return the signature for a specialization of a fused type. e.g.
3624

3625
        floating[:] ->
3626
            'float' or 'double'
3627

3628
        cdef fused ft:
3629
            float[:]
3630
            double[:]
3631

3632
        ft ->
3633
            'float[:]' or 'double[:]'
3634

3635
        integral func(floating) ->
3636
            'int (*func)(float)' or ...
3637
    """
3638
    fused_types = fused_compound_type.get_fused_types()
3639
    if len(fused_types) == 1:
3640
        fused_type = fused_types[0]
3641
    else:
3642
        fused_type = fused_compound_type
3643

3644
    return fused_type.specialize(fused_to_specific).typeof_name()
3645

3646

3647
def get_specialized_types(type):
3648
    """
3649
    Return a list of specialized types in their declared order.
3650
    """
3651
    assert type.is_fused
3652

3653
    if isinstance(type, FusedType):
3654
        result = list(type.types)
3655
        for specialized_type in result:
3656
            specialized_type.specialization_string = specialized_type.typeof_name()
3657
    else:
3658
        result = []
3659
        for cname, f2s in get_all_specialized_permutations(type.get_fused_types()):
3660
            specialized_type = type.specialize(f2s)
3661
            specialized_type.specialization_string = (
3662
                            specialization_signature_string(type, f2s))
3663
            result.append(specialized_type)
3664

3665
    return result
3666

3667

3668
class CFuncTypeArg(BaseType):
3669
    #  name       string
3670
    #  cname      string
3671
    #  type       PyrexType
3672
    #  pos        source file position
3673

3674
    # FIXME: is this the right setup? should None be allowed here?
3675
    not_none = False
3676
    or_none = False
3677
    accept_none = True
3678
    accept_builtin_subtypes = False
3679
    annotation = None
3680

3681
    subtypes = ['type']
3682

3683
    def __init__(self, name, type, pos=None, cname=None, annotation=None):
3684
        self.name = name
3685
        if cname is not None:
3686
            self.cname = cname
3687
        else:
3688
            self.cname = Naming.var_prefix + name
3689
        if annotation is not None:
3690
            self.annotation = annotation
3691
        self.type = type
3692
        self.pos = pos
3693
        self.needs_type_test = False  # TODO: should these defaults be set in analyse_types()?
3694

3695
    def __repr__(self):
3696
        return "%s:%s" % (self.name, repr(self.type))
3697

3698
    def declaration_code(self, for_display = 0):
3699
        return self.type.declaration_code(self.cname, for_display)
3700

3701
    def specialize(self, values):
3702
        return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
3703

3704
    def is_forwarding_reference(self):
3705
        if self.type.is_rvalue_reference:
3706
            if (isinstance(self.type.ref_base_type, TemplatePlaceholderType)
3707
                    and not self.type.ref_base_type.is_cv_qualified):
3708
                return True
3709
        return False
3710

3711
class ToPyStructUtilityCode:
3712

3713
    requires = None
3714

3715
    def __init__(self, type, forward_decl, env):
3716
        self.type = type
3717
        self.header = "static PyObject* %s(%s)" % (type.to_py_function,
3718
                                                   type.declaration_code('s'))
3719
        self.forward_decl = forward_decl
3720
        self.env = env
3721

3722
    def __eq__(self, other):
3723
        return isinstance(other, ToPyStructUtilityCode) and self.header == other.header
3724

3725
    def __hash__(self):
3726
        return hash(self.header)
3727

3728
    def get_tree(self, **kwargs):
3729
        pass
3730

3731
    def put_code(self, output):
3732
        code = output['utility_code_def']
3733
        proto = output['utility_code_proto']
3734

3735
        code.putln("%s {" % self.header)
3736
        code.putln("PyObject* res;")
3737
        code.putln("PyObject* member;")
3738
        code.putln("res = __Pyx_PyDict_NewPresized(%d); if (unlikely(!res)) return NULL;" %
3739
                   len(self.type.scope.var_entries))
3740
        for member in self.type.scope.var_entries:
3741
            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
3742
            code.putln("%s; if (unlikely(!member)) goto bad;" % (
3743
                member.type.to_py_call_code('s.%s' % member.cname, 'member', member.type)))
3744
            code.putln("if (unlikely(PyDict_SetItem(res, %s, member) < 0)) goto bad;" % nameconst_cname)
3745
            code.putln("Py_DECREF(member);")
3746
        code.putln("return res;")
3747
        code.putln("bad:")
3748
        code.putln("Py_XDECREF(member);")
3749
        code.putln("Py_DECREF(res);")
3750
        code.putln("return NULL;")
3751
        code.putln("}")
3752

3753
        # This is a bit of a hack, we need a forward declaration
3754
        # due to the way things are ordered in the module...
3755
        if self.forward_decl:
3756
            proto.putln(self.type.empty_declaration_code() + ';')
3757
        proto.putln(self.header + ";")
3758

3759
    def inject_tree_and_scope_into(self, module_node):
3760
        pass
3761

3762

3763
class CStructOrUnionType(CType):
3764
    #  name          string
3765
    #  cname         string
3766
    #  kind          string              "struct" or "union"
3767
    #  scope         StructOrUnionScope, or None if incomplete
3768
    #  typedef_flag  boolean
3769
    #  packed        boolean
3770

3771
    # entry          Entry
3772

3773
    is_struct_or_union = 1
3774
    has_attributes = 1
3775
    exception_check = True
3776

3777
    def __init__(self, name, kind, scope, typedef_flag, cname, packed=False, in_cpp=False):
3778
        self.name = name
3779
        self.cname = cname
3780
        self.kind = kind
3781
        self.scope = scope
3782
        self.typedef_flag = typedef_flag
3783
        self.is_struct = kind == 'struct'
3784
        self.to_py_function = "%s_to_py_%s" % (
3785
            Naming.convert_func_prefix, self.specialization_name())
3786
        self.from_py_function = "%s_from_py_%s" % (
3787
            Naming.convert_func_prefix, self.specialization_name())
3788
        self.exception_check = True
3789
        self._convert_to_py_code = None
3790
        self._convert_from_py_code = None
3791
        self.packed = packed
3792
        self.needs_cpp_construction = self.is_struct and in_cpp
3793

3794
    def can_coerce_to_pyobject(self, env):
3795
        if self._convert_to_py_code is False:
3796
            return None  # tri-state-ish
3797

3798
        if env.outer_scope is None:
3799
            return False
3800

3801
        if self._convert_to_py_code is None:
3802
            is_union = not self.is_struct
3803
            unsafe_union_types = set()
3804
            safe_union_types = set()
3805
            for member in self.scope.var_entries:
3806
                member_type = member.type
3807
                if not member_type.can_coerce_to_pyobject(env):
3808
                    self.to_py_function = None
3809
                    self._convert_to_py_code = False
3810
                    return False
3811
                if is_union:
3812
                    if member_type.is_ptr or member_type.is_cpp_class:
3813
                        unsafe_union_types.add(member_type)
3814
                    else:
3815
                        safe_union_types.add(member_type)
3816

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

3823
        return True
3824

3825
    def create_to_py_utility_code(self, env):
3826
        if not self.can_coerce_to_pyobject(env):
3827
            return False
3828

3829
        if self._convert_to_py_code is None:
3830
            for member in self.scope.var_entries:
3831
                member.type.create_to_py_utility_code(env)
3832
            forward_decl = self.entry.visibility != 'extern' and not self.typedef_flag
3833
            self._convert_to_py_code = ToPyStructUtilityCode(self, forward_decl, env)
3834

3835
        env.use_utility_code(self._convert_to_py_code)
3836
        return True
3837

3838
    def can_coerce_from_pyobject(self, env):
3839
        if env.outer_scope is None or self._convert_from_py_code is False:
3840
            return False
3841
        for member in self.scope.var_entries:
3842
            if not member.type.can_coerce_from_pyobject(env):
3843
                return False
3844
        return True
3845

3846
    def create_from_py_utility_code(self, env):
3847
        if env.outer_scope is None:
3848
            return False
3849

3850
        if self._convert_from_py_code is False:
3851
            return None  # tri-state-ish
3852

3853
        if self._convert_from_py_code is None:
3854
            if not self.scope.var_entries:
3855
                # There are obviously missing fields; don't allow instantiation
3856
                # where absolutely no content is provided.
3857
                return False
3858

3859
            for member in self.scope.var_entries:
3860
                if not member.type.create_from_py_utility_code(env):
3861
                    self.from_py_function = None
3862
                    self._convert_from_py_code = False
3863
                    return False
3864

3865
            context = dict(
3866
                struct_type=self,
3867
                var_entries=self.scope.var_entries,
3868
                funcname=self.from_py_function,
3869
            )
3870
            env.use_utility_code(UtilityCode.load_cached("RaiseUnexpectedTypeError", "ObjectHandling.c"))
3871
            from .UtilityCode import CythonUtilityCode
3872
            self._convert_from_py_code = CythonUtilityCode.load(
3873
                "FromPyStructUtility" if self.is_struct else "FromPyUnionUtility",
3874
                "CConvert.pyx",
3875
                outer_module_scope=env.global_scope(),  # need access to types declared in module
3876
                context=context)
3877

3878
        env.use_utility_code(self._convert_from_py_code)
3879
        return True
3880

3881
    def __repr__(self):
3882
        return "<CStructOrUnionType %s %s%s>" % (
3883
            self.name, self.cname,
3884
            ("", " typedef")[self.typedef_flag])
3885

3886
    def declaration_code(self, entity_code,
3887
                         for_display=0, dll_linkage=None, pyrex=0):
3888
        if pyrex or for_display:
3889
            base_code = self.name
3890
        else:
3891
            if self.typedef_flag:
3892
                base_code = self.cname
3893
            else:
3894
                base_code = "%s %s" % (self.kind, self.cname)
3895
            base_code = public_decl(base_code, dll_linkage)
3896
        return self.base_declaration_code(base_code, entity_code)
3897

3898
    def __eq__(self, other):
3899
        try:
3900
            return (isinstance(other, CStructOrUnionType) and
3901
                    self.name == other.name)
3902
        except AttributeError:
3903
            return False
3904

3905
    def __lt__(self, other):
3906
        try:
3907
            return self.name < other.name
3908
        except AttributeError:
3909
            # this is arbitrary, but it makes sure we always have
3910
            # *some* kind of order
3911
            return False
3912

3913
    def __hash__(self):
3914
        return hash(self.cname) ^ hash(self.kind)
3915

3916
    def is_complete(self):
3917
        return self.scope is not None
3918

3919
    def attributes_known(self):
3920
        return self.is_complete()
3921

3922
    def can_be_complex(self):
3923
        # Does the struct consist of exactly two identical floats?
3924
        fields = self.scope.var_entries
3925
        if len(fields) != 2: return False
3926
        a, b = fields
3927
        return (a.type.is_float and b.type.is_float and
3928
                a.type.empty_declaration_code() ==
3929
                b.type.empty_declaration_code())
3930

3931
    def struct_nesting_depth(self):
3932
        child_depths = [x.type.struct_nesting_depth()
3933
                        for x in self.scope.var_entries]
3934
        return max(child_depths) + 1
3935

3936
    def cast_code(self, expr_code):
3937
        if self.is_struct:
3938
            return expr_code
3939
        return super().cast_code(expr_code)
3940

3941
cpp_string_conversions = ("std::string",)
3942

3943
builtin_cpp_conversions = {
3944
    # type                element template params
3945
    "std::pair":          2,
3946
    "std::vector":        1,
3947
    "std::list":          1,
3948
    "std::set":           1,
3949
    "std::unordered_set": 1,
3950
    "std::map":           2,
3951
    "std::unordered_map": 2,
3952
    "std::complex":       1,
3953
}
3954

3955
class CppClassType(CType):
3956
    #  name          string
3957
    #  cname         string
3958
    #  scope         CppClassScope
3959
    #  templates     [string] or None
3960

3961
    is_cpp_class = 1
3962
    has_attributes = 1
3963
    needs_cpp_construction = 1
3964
    exception_check = True
3965
    namespace = None
3966

3967
    # For struct-like declaration.
3968
    kind = "struct"
3969
    packed = False
3970
    typedef_flag = False
3971

3972
    subtypes = ['templates']
3973

3974
    def __init__(self, name, scope, cname, base_classes, templates=None, template_type=None):
3975
        self.name = name
3976
        self.cname = cname
3977
        self.scope = scope
3978
        self.base_classes = base_classes
3979
        self.operators = []
3980
        self.templates = templates
3981
        self.template_type = template_type
3982
        self.num_optional_templates = sum(is_optional_template_param(T) for T in templates or ())
3983
        if templates:
3984
            self.specializations = {tuple(zip(templates, templates)): self}
3985
        else:
3986
            self.specializations = {}
3987
        self.is_cpp_string = cname in cpp_string_conversions
3988

3989
    def use_conversion_utility(self, from_or_to):
3990
        pass
3991

3992
    def maybe_unordered(self):
3993
        if 'unordered' in self.cname:
3994
            return 'unordered_'
3995
        else:
3996
            return ''
3997

3998
    def can_coerce_from_pyobject(self, env):
3999
        if self.cname in builtin_cpp_conversions:
4000
            template_count = builtin_cpp_conversions[self.cname]
4001
            for ix, T in enumerate(self.templates or []):
4002
                if ix >= template_count:
4003
                    break
4004
                if T.is_pyobject or not T.can_coerce_from_pyobject(env):
4005
                    return False
4006
            return True
4007
        elif self.cname in cpp_string_conversions:
4008
            return True
4009
        return False
4010

4011
    def create_from_py_utility_code(self, env):
4012
        if self.from_py_function is not None:
4013
            return True
4014
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
4015
            X = "XYZABC"
4016
            tags = []
4017
            context = {}
4018
            for ix, T in enumerate(self.templates or []):
4019
                if ix >= builtin_cpp_conversions[self.cname]:
4020
                    break
4021
                if T.is_pyobject or not T.create_from_py_utility_code(env):
4022
                    return False
4023
                tags.append(T.specialization_name())
4024
                context[X[ix]] = T
4025

4026
            if self.cname in cpp_string_conversions:
4027
                cls = 'string'
4028
                tags = type_identifier(self),
4029
            else:
4030
                cls = self.cname[5:]
4031
            cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags))
4032
            context.update({
4033
                'cname': cname,
4034
                'maybe_unordered': self.maybe_unordered(),
4035
                'type': self.cname,
4036
            })
4037
            # Override directives that should not be inherited from user code.
4038
            from .UtilityCode import CythonUtilityCode
4039
            directives = CythonUtilityCode.filter_inherited_directives(env.directives)
4040
            env.use_utility_code(CythonUtilityCode.load(
4041
                cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx",
4042
                context=context, compiler_directives=directives))
4043
            self.from_py_function = cname
4044
            return True
4045

4046
    def can_coerce_to_pyobject(self, env):
4047
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
4048
            for ix, T in enumerate(self.templates or []):
4049
                if ix >= builtin_cpp_conversions[self.cname]:
4050
                    break
4051
                if T.is_pyobject or not T.can_coerce_to_pyobject(env):
4052
                    return False
4053
            return True
4054

4055

4056
    def create_to_py_utility_code(self, env):
4057
        if self.to_py_function is not None:
4058
            return True
4059
        if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions:
4060
            X = "XYZABC"
4061
            tags = []
4062
            context = {}
4063
            for ix, T in enumerate(self.templates or []):
4064
                if ix >= builtin_cpp_conversions[self.cname]:
4065
                    break
4066
                if not T.create_to_py_utility_code(env):
4067
                    return False
4068
                tags.append(T.specialization_name())
4069
                context[X[ix]] = T
4070

4071
            if self.cname in cpp_string_conversions:
4072
                cls = 'string'
4073
                prefix = 'PyObject_'  # gets specialised by explicit type casts in CoerceToPyTypeNode
4074
                tags = type_identifier(self),
4075
            else:
4076
                cls = self.cname[5:]
4077
                prefix = ''
4078
            cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags))
4079
            context.update({
4080
                'cname': cname,
4081
                'maybe_unordered': self.maybe_unordered(),
4082
                'type': self.cname,
4083
            })
4084
            from .UtilityCode import CythonUtilityCode
4085
            # Override directives that should not be inherited from user code.
4086
            directives = CythonUtilityCode.filter_inherited_directives(env.directives)
4087
            env.use_utility_code(CythonUtilityCode.load(
4088
                cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx",
4089
                context=context, compiler_directives=directives))
4090
            self.to_py_function = cname
4091
            return True
4092

4093
    def is_template_type(self):
4094
        return self.templates is not None and self.template_type is None
4095

4096
    def get_fused_types(self, result=None, seen=None, include_function_return_type=False):
4097
        if result is None:
4098
            result = []
4099
            seen = set()
4100
        if self.namespace:
4101
            self.namespace.get_fused_types(result, seen)
4102
        if self.templates:
4103
            for T in self.templates:
4104
                T.get_fused_types(result, seen)
4105
        return result
4106

4107
    def specialize_here(self, pos, env, template_values=None):
4108
        if not self.is_template_type():
4109
            error(pos, "'%s' type is not a template" % self)
4110
            return error_type
4111
        if len(self.templates) - self.num_optional_templates <= len(template_values) < len(self.templates):
4112
            num_defaults = len(self.templates) - len(template_values)
4113
            partial_specialization = self.declaration_code('', template_params=template_values)
4114
            # Most of the time we don't need to declare anything typed to these
4115
            # default template arguments, but when we do there's no way in C++
4116
            # to reference this directly.  However, it is common convention to
4117
            # provide a typedef in the template class that resolves to each
4118
            # template type.  For now, allow the user to specify this name as
4119
            # the template parameter.
4120
            # TODO: Allow typedefs in cpp classes and search for it in this
4121
            # classes scope as a concrete name we could use.
4122
            template_values = template_values + [
4123
                TemplatePlaceholderType(
4124
                    "%s::%s" % (partial_specialization, param.name), True)
4125
                for param in self.templates[-num_defaults:]]
4126
        if len(self.templates) != len(template_values):
4127
            error(pos, "%s templated type receives %d arguments, got %d" %
4128
                  (self.name, len(self.templates), len(template_values)))
4129
            return error_type
4130
        has_object_template_param = False
4131
        for value in template_values:
4132
            if value.is_pyobject or value.needs_refcounting:
4133
                has_object_template_param = True
4134
                type_description = "Python object" if value.is_pyobject else "Reference-counted"
4135
                error(pos,
4136
                      "%s type '%s' cannot be used as a template argument" % (
4137
                          type_description, value))
4138
        if has_object_template_param:
4139
            return error_type
4140
        return self.specialize(dict(zip(self.templates, template_values)))
4141

4142
    def specialize(self, values):
4143
        if not self.templates and not self.namespace:
4144
            return self
4145
        if self.templates is None:
4146
            self.templates = []
4147
        key = tuple(values.items())
4148
        if key in self.specializations:
4149
            return self.specializations[key]
4150
        template_values = [t.specialize(values) for t in self.templates]
4151
        specialized = self.specializations[key] = \
4152
            CppClassType(self.name, None, self.cname, [], template_values, template_type=self)
4153
        # Need to do these *after* self.specializations[key] is set
4154
        # to avoid infinite recursion on circular references.
4155
        specialized.base_classes = [b.specialize(values) for b in self.base_classes]
4156
        if self.namespace is not None:
4157
            specialized.namespace = self.namespace.specialize(values)
4158
        specialized.scope = self.scope.specialize(values, specialized)
4159
        if self.cname == 'std::vector':
4160
            # vector<bool> is special cased in the C++ standard, and its
4161
            # accessors do not necessarily return references to the underlying
4162
            # elements (which may be bit-packed).
4163
            # http://www.cplusplus.com/reference/vector/vector-bool/
4164
            # Here we pretend that the various methods return bool values
4165
            # (as the actual returned values are coercible to such, and
4166
            # we don't support call expressions as lvalues).
4167
            T = values.get(self.templates[0], None)
4168
            if T and not T.is_fused and T.empty_declaration_code() == 'bool':
4169
                for bit_ref_returner in ('at', 'back', 'front'):
4170
                    if bit_ref_returner in specialized.scope.entries:
4171
                        specialized.scope.entries[bit_ref_returner].type.return_type = T
4172
        return specialized
4173

4174
    def deduce_template_params(self, actual):
4175
        if actual.is_cv_qualified:
4176
            actual = actual.cv_base_type
4177
        if actual.is_reference:
4178
            actual = actual.ref_base_type
4179
        if self == actual:
4180
            return {}
4181
        elif actual.is_cpp_class:
4182
            self_template_type = self
4183
            while getattr(self_template_type, 'template_type', None):
4184
                self_template_type = self_template_type.template_type
4185
            def all_bases(cls):
4186
                yield cls
4187
                for parent in cls.base_classes:
4188
                    yield from all_bases(parent)
4189
            for actual_base in all_bases(actual):
4190
                template_type = actual_base
4191
                while getattr(template_type, 'template_type', None):
4192
                    template_type = template_type.template_type
4193
                    if (self_template_type.empty_declaration_code()
4194
                            == template_type.empty_declaration_code()):
4195
                        return reduce(
4196
                            merge_template_deductions,
4197
                            [formal_param.deduce_template_params(actual_param)
4198
                             for (formal_param, actual_param)
4199
                             in zip(self.templates, actual_base.templates)],
4200
                            {})
4201
        else:
4202
            return {}
4203

4204
    def declaration_code(self, entity_code,
4205
            for_display = 0, dll_linkage = None, pyrex = 0,
4206
            template_params = None):
4207
        if template_params is None:
4208
            template_params = self.templates
4209
        if self.templates:
4210
            template_strings = [param.declaration_code('', for_display, None, pyrex)
4211
                                for param in template_params
4212
                                if not is_optional_template_param(param) and not param.is_fused]
4213
            if for_display:
4214
                brackets = "[%s]"
4215
            else:
4216
                brackets = "<%s> "
4217
            templates = brackets % ",".join(template_strings)
4218
        else:
4219
            templates = ""
4220
        if pyrex or for_display:
4221
            base_code = "%s%s" % (self.name, templates)
4222
        else:
4223
            base_code = "%s%s" % (self.cname, templates)
4224
            if self.namespace is not None:
4225
                base_code = "%s::%s" % (self.namespace.empty_declaration_code(), base_code)
4226
            base_code = public_decl(base_code, dll_linkage)
4227
        return self.base_declaration_code(base_code, entity_code)
4228

4229
    def cpp_optional_declaration_code(self, entity_code, dll_linkage=None, template_params=None):
4230
        return "__Pyx_Optional_Type<%s> %s" % (
4231
                self.declaration_code("", False, dll_linkage, False,
4232
                                    template_params),
4233
                entity_code)
4234

4235
    def is_subclass(self, other_type):
4236
        if self.same_as_resolved_type(other_type):
4237
            return 1
4238
        for base_class in self.base_classes:
4239
            if base_class.is_subclass(other_type):
4240
                return 1
4241
        return 0
4242

4243
    def subclass_dist(self, super_type):
4244
        if self.same_as_resolved_type(super_type):
4245
            return 0
4246
        elif not self.base_classes:
4247
            return float('inf')
4248
        else:
4249
            return 1 + min(b.subclass_dist(super_type) for b in self.base_classes)
4250

4251
    def same_as_resolved_type(self, other_type):
4252
        if other_type.is_cpp_class:
4253
            if self == other_type:
4254
                return 1
4255
            # This messy logic is needed due to GH Issue #1852.
4256
            elif (self.cname == other_type.cname and
4257
                    (self.template_type and other_type.template_type
4258
                     or self.templates
4259
                     or other_type.templates)):
4260
                if self.templates == other_type.templates:
4261
                    return 1
4262
                for t1, t2 in zip(self.templates, other_type.templates):
4263
                    if is_optional_template_param(t1) and is_optional_template_param(t2):
4264
                        break
4265
                    if not t1.same_as_resolved_type(t2):
4266
                        return 0
4267
                return 1
4268
        return 0
4269

4270
    def assignable_from_resolved_type(self, other_type):
4271
        # TODO: handle operator=(...) here?
4272
        if other_type is error_type:
4273
            return True
4274
        elif other_type.is_cpp_class:
4275
            return other_type.is_subclass(self)
4276
        elif other_type.is_string and self.cname in cpp_string_conversions:
4277
            return True
4278

4279
    def attributes_known(self):
4280
        return self.scope is not None
4281

4282
    def find_cpp_operation_type(self, operator, operand_type=None):
4283
        operands = [self]
4284
        if operand_type is not None:
4285
            operands.append(operand_type)
4286
        # pos == None => no errors
4287
        operator_entry = self.scope.lookup_operator_for_types(None, operator, operands)
4288
        if not operator_entry:
4289
            return None
4290
        func_type = operator_entry.type
4291
        if func_type.is_ptr:
4292
            func_type = func_type.base_type
4293
        return func_type.return_type
4294

4295
    def get_constructor(self, pos):
4296
        constructor = self.scope.lookup('<init>')
4297
        if constructor is not None:
4298
            return constructor
4299

4300
        # Otherwise: automatically declare no-args default constructor.
4301
        # Make it "nogil" if the base classes allow it.
4302
        nogil = True
4303
        for base in self.base_classes:
4304
            base_constructor = base.scope.lookup('<init>')
4305
            if base_constructor and not base_constructor.type.nogil:
4306
                nogil = False
4307
                break
4308

4309
        func_type = CFuncType(self, [], exception_check='+', nogil=nogil)
4310
        return self.scope.declare_cfunction('<init>', func_type, pos)
4311

4312
    def check_nullary_constructor(self, pos, msg="stack allocated"):
4313
        constructor = self.scope.lookup('<init>')
4314
        if constructor is not None and best_match([], constructor.all_alternatives()) is None:
4315
            error(pos, "C++ class must have a nullary constructor to be %s" % msg)
4316

4317
    def cpp_optional_check_for_null_code(self, cname):
4318
        # only applies to c++ classes that are being declared as std::optional
4319
        return "(%s.has_value())" % cname
4320

4321

4322
class EnumMixin:
4323
    """
4324
    Common implementation details for C and C++ enums.
4325
    """
4326

4327
    def create_enum_to_py_utility_code(self, env):
4328
        from .UtilityCode import CythonUtilityCode
4329
        self.to_py_function = "__Pyx_Enum_%s_to_py" % type_identifier(self)
4330
        if self.entry.scope != env.global_scope():
4331
            module_name = self.entry.scope.qualified_name
4332
        else:
4333
            module_name = None
4334

4335
        directives = CythonUtilityCode.filter_inherited_directives(
4336
            env.global_scope().directives)
4337
        if any(value_entry.enum_int_value is None for value_entry in self.entry.enum_values):
4338
            # We're at a high risk of making a switch statement with equal values in
4339
            # (because we simply can't tell, and enums are often used like that).
4340
            # So turn off the switch optimization to be safe.
4341
            # (Note that for now Cython doesn't do the switch optimization for
4342
            # scoped enums anyway)
4343
            directives['optimize.use_switch'] = False
4344

4345
        if self.is_cpp_enum:
4346
            underlying_type_str = self.underlying_type.empty_declaration_code()
4347
        else:
4348
            underlying_type_str = "int"
4349

4350
        env.use_utility_code(CythonUtilityCode.load(
4351
            "EnumTypeToPy", "CpdefEnums.pyx",
4352
            context={"funcname": self.to_py_function,
4353
                    "name": self.name,
4354
                    "items": tuple(self.values),
4355
                    "underlying_type": underlying_type_str,
4356
                    "module_name": module_name,
4357
                    "is_flag": not self.is_cpp_enum,
4358
                    },
4359
            outer_module_scope=self.entry.scope,  # ensure that "name" is findable
4360
            compiler_directives = directives,
4361
        ))
4362

4363

4364
class CppScopedEnumType(CType, EnumMixin):
4365
    # name    string
4366
    # doc     string or None
4367
    # cname   string
4368

4369
    is_cpp_enum = True
4370

4371
    def __init__(self, name, cname, underlying_type, namespace=None, doc=None):
4372
        self.name = name
4373
        self.doc = doc
4374
        self.cname = cname
4375
        self.values = []
4376
        self.underlying_type = underlying_type
4377
        self.namespace = namespace
4378

4379
    def __str__(self):
4380
        return self.name
4381

4382
    def declaration_code(self, entity_code,
4383
                        for_display=0, dll_linkage=None, pyrex=0):
4384
        if pyrex or for_display:
4385
            type_name = self.name
4386
        else:
4387
            if self.namespace:
4388
                type_name = "%s::%s" % (
4389
                    self.namespace.empty_declaration_code(),
4390
                    self.cname
4391
                )
4392
            else:
4393
                type_name = "__PYX_ENUM_CLASS_DECL %s" % self.cname
4394
            type_name = public_decl(type_name, dll_linkage)
4395
        return self.base_declaration_code(type_name, entity_code)
4396

4397
    def create_from_py_utility_code(self, env):
4398
        if self.from_py_function:
4399
            return True
4400
        if self.underlying_type.create_from_py_utility_code(env):
4401
            self.from_py_function = '(%s)%s' % (
4402
                self.cname, self.underlying_type.from_py_function
4403
            )
4404
        return True
4405

4406
    def create_to_py_utility_code(self, env):
4407
        if self.to_py_function is not None:
4408
            return True
4409
        if self.entry.create_wrapper:
4410
            self.create_enum_to_py_utility_code(env)
4411
            return True
4412
        if self.underlying_type.create_to_py_utility_code(env):
4413
            # Using a C++11 lambda here, which is fine since
4414
            # scoped enums are a C++11 feature
4415
            self.to_py_function = '[](const %s& x){return %s((%s)x);}' % (
4416
                self.cname,
4417
                self.underlying_type.to_py_function,
4418
                self.underlying_type.empty_declaration_code()
4419
            )
4420
        return True
4421

4422
    def create_type_wrapper(self, env):
4423
        from .UtilityCode import CythonUtilityCode
4424
        rst = CythonUtilityCode.load(
4425
            "CppScopedEnumType", "CpdefEnums.pyx",
4426
            context={
4427
                "name": self.name,
4428
                "cname": self.cname.split("::")[-1],
4429
                "items": tuple(self.values),
4430
                "underlying_type": self.underlying_type.empty_declaration_code(),
4431
                "enum_doc": self.doc,
4432
                "static_modname": env.qualified_name,
4433
            },
4434
            outer_module_scope=env.global_scope())
4435

4436
        env.use_utility_code(rst)
4437

4438

4439
class TemplatePlaceholderType(CType):
4440

4441
    def __init__(self, name, optional=False):
4442
        self.name = name
4443
        self.optional = optional
4444

4445
    def declaration_code(self, entity_code,
4446
            for_display = 0, dll_linkage = None, pyrex = 0):
4447
        if entity_code:
4448
            return self.name + " " + entity_code
4449
        else:
4450
            return self.name
4451

4452
    def specialize(self, values):
4453
        if self in values:
4454
            return values[self]
4455
        else:
4456
            return self
4457

4458
    def deduce_template_params(self, actual):
4459
        return {self: actual}
4460

4461
    def same_as_resolved_type(self, other_type):
4462
        if isinstance(other_type, TemplatePlaceholderType):
4463
            return self.name == other_type.name
4464
        else:
4465
            return 0
4466

4467
    def __hash__(self):
4468
        return hash(self.name)
4469

4470
    def __eq__(self, other):
4471
        if isinstance(other, TemplatePlaceholderType):
4472
            return self.name == other.name
4473
        else:
4474
            return False
4475

4476
def is_optional_template_param(type):
4477
    return isinstance(type, TemplatePlaceholderType) and type.optional
4478

4479

4480
class CEnumType(CIntLike, CType, EnumMixin):
4481
    #  name           string
4482
    #  doc            string or None
4483
    #  cname          string or None
4484
    #  typedef_flag   boolean
4485
    #  values         [string], populated during declaration analysis
4486

4487
    is_enum = 1
4488
    signed = 1
4489
    rank = -1  # Ranks below any integer type
4490

4491
    def __init__(self, name, cname, typedef_flag, namespace=None, doc=None):
4492
        self.name = name
4493
        self.doc = doc
4494
        self.cname = cname
4495
        self.values = []
4496
        self.typedef_flag = typedef_flag
4497
        self.namespace = namespace
4498
        self.default_value = "(%s) 0" % self.empty_declaration_code()
4499

4500
    def __str__(self):
4501
        return self.name
4502

4503
    def __repr__(self):
4504
        return "<CEnumType %s %s%s>" % (self.name, self.cname,
4505
            ("", " typedef")[self.typedef_flag])
4506

4507
    def declaration_code(self, entity_code,
4508
            for_display = 0, dll_linkage = None, pyrex = 0):
4509
        if pyrex or for_display:
4510
            base_code = self.name
4511
        else:
4512
            if self.namespace:
4513
                base_code = "%s::%s" % (
4514
                    self.namespace.empty_declaration_code(), self.cname)
4515
            elif self.typedef_flag:
4516
                base_code = self.cname
4517
            else:
4518
                base_code = "enum %s" % self.cname
4519
            base_code = public_decl(base_code, dll_linkage)
4520
        return self.base_declaration_code(base_code, entity_code)
4521

4522
    def specialize(self, values):
4523
        if self.namespace:
4524
            namespace = self.namespace.specialize(values)
4525
            if namespace != self.namespace:
4526
                return CEnumType(
4527
                    self.name, self.cname, self.typedef_flag, namespace)
4528
        return self
4529

4530
    def create_type_wrapper(self, env):
4531
        from .UtilityCode import CythonUtilityCode
4532
        # Generate "int"-like conversion function
4533
        old_to_py_function = self.to_py_function
4534
        self.to_py_function = None
4535
        CIntLike.create_to_py_utility_code(self, env)
4536
        enum_to_pyint_func = self.to_py_function
4537
        self.to_py_function = old_to_py_function  # we don't actually want to overwrite this
4538

4539
        env.use_utility_code(CythonUtilityCode.load(
4540
            "EnumType", "CpdefEnums.pyx",
4541
            context={"name": self.name,
4542
                     "items": tuple(self.values),
4543
                     "enum_doc": self.doc,
4544
                     "enum_to_pyint_func": enum_to_pyint_func,
4545
                     "static_modname": env.qualified_name,
4546
                     },
4547
            outer_module_scope=env.global_scope()))
4548

4549
    def create_to_py_utility_code(self, env):
4550
        if self.to_py_function is not None:
4551
            return self.to_py_function
4552
        if not self.entry.create_wrapper:
4553
            return super().create_to_py_utility_code(env)
4554
        self.create_enum_to_py_utility_code(env)
4555
        return True
4556

4557

4558
class CTupleType(CType):
4559
    # components [PyrexType]
4560

4561
    is_ctuple = True
4562

4563
    subtypes = ['components']
4564

4565
    def __init__(self, cname, components):
4566
        self.cname = cname
4567
        self.components = components
4568
        self.size = len(components)
4569
        self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
4570
        self.from_py_function = "%s_from_py_%s" % (Naming.convert_func_prefix, self.cname)
4571
        self.exception_check = True
4572
        self._convert_to_py_code = None
4573
        self._convert_from_py_code = None
4574
        # equivalent_type must be set now because it isn't available at import time
4575
        from .Builtin import tuple_type
4576
        self.equivalent_type = tuple_type
4577

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

4581
    def declaration_code(self, entity_code,
4582
            for_display = 0, dll_linkage = None, pyrex = 0):
4583
        if pyrex or for_display:
4584
            return "%s %s" % (str(self), entity_code)
4585
        else:
4586
            return self.base_declaration_code(self.cname, entity_code)
4587

4588
    def can_coerce_to_pyobject(self, env):
4589
        for component in self.components:
4590
            if not component.can_coerce_to_pyobject(env):
4591
                return False
4592
        return True
4593

4594
    def can_coerce_from_pyobject(self, env):
4595
        for component in self.components:
4596
            if not component.can_coerce_from_pyobject(env):
4597
                return False
4598
        return True
4599

4600
    def create_to_py_utility_code(self, env):
4601
        if self._convert_to_py_code is False:
4602
            return None  # tri-state-ish
4603

4604
        if self._convert_to_py_code is None:
4605
            for component in self.components:
4606
                if not component.create_to_py_utility_code(env):
4607
                    self.to_py_function = None
4608
                    self._convert_to_py_code = False
4609
                    return False
4610

4611
            context = dict(
4612
                struct_type_decl=self.empty_declaration_code(),
4613
                components=self.components,
4614
                funcname=self.to_py_function,
4615
                size=len(self.components)
4616
            )
4617
            self._convert_to_py_code = TempitaUtilityCode.load(
4618
                "ToPyCTupleUtility", "TypeConversion.c", context=context)
4619

4620
        env.use_utility_code(self._convert_to_py_code)
4621
        return True
4622

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

4627
        if self._convert_from_py_code is None:
4628
            for component in self.components:
4629
                if not component.create_from_py_utility_code(env):
4630
                    self.from_py_function = None
4631
                    self._convert_from_py_code = False
4632
                    return False
4633

4634
            context = dict(
4635
                struct_type_decl=self.empty_declaration_code(),
4636
                components=self.components,
4637
                funcname=self.from_py_function,
4638
                size=len(self.components)
4639
            )
4640
            self._convert_from_py_code = TempitaUtilityCode.load(
4641
                "FromPyCTupleUtility", "TypeConversion.c", context=context)
4642

4643
        env.use_utility_code(self._convert_from_py_code)
4644
        return True
4645

4646
    def cast_code(self, expr_code):
4647
        return expr_code
4648

4649
    def specialize(self, values):
4650
        assert hasattr(self, "entry")
4651
        components = [c.specialize(values) for c in self.components]
4652
        new_entry = self.entry.scope.declare_tuple_type(self.entry.pos, components)
4653
        return new_entry.type
4654

4655

4656
def c_tuple_type(components):
4657
    components = tuple(components)
4658
    if any(c.is_fused for c in components):
4659
        # should never end up in code but should be unique
4660
        cname = f"<dummy fused ctuple {components!r}>"
4661
    else:
4662
        cname = Naming.ctuple_type_prefix + type_list_identifier(components)
4663
    tuple_type = CTupleType(cname, components)
4664
    return tuple_type
4665

4666

4667
class UnspecifiedType(PyrexType):
4668
    # Used as a placeholder until the type can be determined.
4669

4670
    is_unspecified = 1
4671

4672
    def declaration_code(self, entity_code,
4673
            for_display = 0, dll_linkage = None, pyrex = 0):
4674
        return "<unspecified>"
4675

4676
    def same_as_resolved_type(self, other_type):
4677
        return False
4678

4679

4680
class ErrorType(PyrexType):
4681
    # Used to prevent propagation of error messages.
4682

4683
    is_error = 1
4684
    exception_value = 0
4685
    exception_check = False
4686
    to_py_function = "dummy"
4687
    from_py_function = "dummy"
4688

4689
    def create_to_py_utility_code(self, env):
4690
        return True
4691

4692
    def create_from_py_utility_code(self, env):
4693
        return True
4694

4695
    def declaration_code(self, entity_code,
4696
            for_display = 0, dll_linkage = None, pyrex = 0):
4697
        return "<error>"
4698

4699
    def same_as_resolved_type(self, other_type):
4700
        return 1
4701

4702
    def error_condition(self, result_code):
4703
        return "dummy"
4704

4705

4706
class PythonTypeConstructorMixin:
4707
    """Used to help Cython interpret indexed types from the typing module (or similar)
4708
    """
4709
    modifier_name = None
4710

4711
    def set_python_type_constructor_name(self, name):
4712
        self.python_type_constructor_name = name
4713

4714
    def specialize_here(self, pos, env, template_values=None):
4715
        # for a lot of the typing classes it doesn't really matter what the template is
4716
        # (i.e. typing.Dict[int] is really just a dict)
4717
        return self
4718

4719
    def __repr__(self):
4720
        if self.base_type:
4721
            return "%s[%r]" % (self.name, self.base_type)
4722
        else:
4723
            return self.name
4724

4725
    def is_template_type(self):
4726
        return True
4727

4728

4729
class BuiltinTypeConstructorObjectType(BuiltinObjectType, PythonTypeConstructorMixin):
4730
    """
4731
    builtin types like list, dict etc which can be subscripted in annotations
4732
    """
4733
    def __init__(self, name, cname, objstruct_cname=None):
4734
        super().__init__(
4735
            name, cname, objstruct_cname=objstruct_cname)
4736
        self.set_python_type_constructor_name(name)
4737

4738

4739
class PythonTupleTypeConstructor(BuiltinTypeConstructorObjectType):
4740
    def specialize_here(self, pos, env, template_values=None):
4741
        if (template_values and None not in template_values and
4742
                not any(v.is_pyobject for v in template_values)):
4743
            entry = env.declare_tuple_type(pos, template_values)
4744
            if entry:
4745
                entry.used = True
4746
                return entry.type
4747
        return super().specialize_here(pos, env, template_values)
4748

4749

4750
class SpecialPythonTypeConstructor(PyObjectType, PythonTypeConstructorMixin):
4751
    """
4752
    For things like ClassVar, Optional, etc, which are not types and disappear during type analysis.
4753
    """
4754

4755
    def __init__(self, name):
4756
        super().__init__()
4757
        self.set_python_type_constructor_name(name)
4758
        self.modifier_name = name
4759

4760
    def __repr__(self):
4761
        return self.name
4762

4763
    def resolve(self):
4764
        return self
4765

4766
    def specialize_here(self, pos, env, template_values=None):
4767
        if len(template_values) != 1:
4768
            error(pos, "'%s' takes exactly one template argument." % self.name)
4769
            return error_type
4770
        if template_values[0] is None:
4771
            # FIXME: allowing unknown types for now since we don't recognise all Python types.
4772
            return None
4773
        # Replace this type with the actual 'template' argument.
4774
        return template_values[0].resolve()
4775

4776

4777
rank_to_type_name = (
4778
    "char",          # 0
4779
    "short",         # 1
4780
    "int",           # 2
4781
    "long",          # 3
4782
    "PY_LONG_LONG",  # 4
4783
    "float",         # 5
4784
    "double",        # 6
4785
    "long double",   # 7
4786
)
4787

4788
RANK_INT  = rank_to_type_name.index('int')
4789
RANK_LONG = rank_to_type_name.index('long')
4790
RANK_FLOAT = rank_to_type_name.index('float')
4791
UNSIGNED = 0
4792
SIGNED = 2
4793

4794
error_type =    ErrorType()
4795
unspecified_type = UnspecifiedType()
4796

4797
py_object_type = PyObjectType()
4798

4799
c_void_type =        CVoidType()
4800

4801
c_uchar_type =       CIntType(0, UNSIGNED)
4802
c_ushort_type =      CIntType(1, UNSIGNED)
4803
c_uint_type =        CIntType(2, UNSIGNED)
4804
c_ulong_type =       CIntType(3, UNSIGNED)
4805
c_ulonglong_type =   CIntType(4, UNSIGNED)
4806

4807
c_char_type =        CIntType(0)
4808
c_short_type =       CIntType(1)
4809
c_int_type =         CIntType(2)
4810
c_long_type =        CIntType(3)
4811
c_longlong_type =    CIntType(4)
4812

4813
c_schar_type =       CIntType(0, SIGNED)
4814
c_sshort_type =      CIntType(1, SIGNED)
4815
c_sint_type =        CIntType(2, SIGNED)
4816
c_slong_type =       CIntType(3, SIGNED)
4817
c_slonglong_type =   CIntType(4, SIGNED)
4818

4819
c_float_type =       CFloatType(5, math_h_modifier='f')
4820
c_double_type =      CFloatType(6)
4821
c_longdouble_type =  CFloatType(7, math_h_modifier='l')
4822

4823
c_float_complex_type =      CComplexType(c_float_type)
4824
c_double_complex_type =     CComplexType(c_double_type)
4825
c_longdouble_complex_type = CComplexType(c_longdouble_type)
4826

4827
soft_complex_type = SoftCComplexType()
4828

4829
c_anon_enum_type =   CAnonEnumType(-1)
4830
c_returncode_type =  CReturnCodeType(RANK_INT)
4831
c_bint_type =        CBIntType(RANK_INT)
4832
c_py_unicode_type =  CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
4833
c_py_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
4834
c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
4835
c_py_ssize_t_type =  CPySSizeTType(RANK_LONG+0.5, SIGNED)
4836
c_ssize_t_type =     CSSizeTType(RANK_LONG+0.5, SIGNED)
4837
c_size_t_type =      CSizeTType(RANK_LONG+0.5, UNSIGNED)
4838
c_ptrdiff_t_type =   CPtrdiffTType(RANK_LONG+0.75, SIGNED)
4839

4840
c_null_ptr_type =     CNullPtrType(c_void_type)
4841
c_void_ptr_type =     CPtrType(c_void_type)
4842
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
4843
c_char_ptr_type =     CPtrType(c_char_type)
4844
c_const_char_ptr_type = CPtrType(CConstType(c_char_type))
4845
c_uchar_ptr_type =    CPtrType(c_uchar_type)
4846
c_const_uchar_ptr_type = CPtrType(CConstType(c_uchar_type))
4847
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
4848
c_int_ptr_type =      CPtrType(c_int_type)
4849
c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
4850
c_const_py_unicode_ptr_type = CPtrType(CConstType(c_py_unicode_type))
4851
c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
4852
c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
4853
c_size_t_ptr_type =  CPtrType(c_size_t_type)
4854

4855
# GIL state
4856
c_gilstate_type = CEnumType("PyGILState_STATE", "PyGILState_STATE", True)
4857
c_threadstate_type = CStructOrUnionType("PyThreadState", "struct", None, 1, "PyThreadState")
4858
c_threadstate_ptr_type = CPtrType(c_threadstate_type)
4859

4860
# PEP-539 "Py_tss_t" type
4861
c_pytss_t_type = CPyTSSTType()
4862

4863
# Py3.10+ "PySendResult" for "am_send" slot functions: ["PYGEN_RETURN", "PYGEN_ERROR", "PYGEN_NEXT"]
4864
PySendResult_type = CEnumType("PySendResult", "__Pyx_PySendResult", typedef_flag=True)
4865
py_objptr_type = CPtrType(CStructOrUnionType(
4866
    "PyObject", "struct", scope=None, typedef_flag=True, cname="PyObject"))
4867

4868
# the Py_buffer type is defined in Builtin.py
4869
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
4870
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
4871

4872
# Not sure whether the unsigned versions and 'long long' should be in there
4873
# long long requires C99 and might be slow, and would always get preferred
4874
# when specialization happens through calling and not indexing
4875
cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type],
4876
                             name="integral")
4877
# Omitting long double as it might be slow
4878
cy_floating_type = FusedType([c_float_type, c_double_type], name="floating")
4879
cy_numeric_type = FusedType([c_short_type,
4880
                             c_int_type,
4881
                             c_long_type,
4882
                             c_float_type,
4883
                             c_double_type,
4884
                             c_float_complex_type,
4885
                             c_double_complex_type], name="numeric")
4886

4887
# buffer-related structs
4888
c_buf_diminfo_type =  CStructOrUnionType("__Pyx_Buf_DimInfo", "struct",
4889
                                      None, 1, "__Pyx_Buf_DimInfo")
4890
c_pyx_buffer_type = CStructOrUnionType("__Pyx_Buffer", "struct", None, 1, "__Pyx_Buffer")
4891
c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type)
4892
c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct",
4893
                                      None, 1, "__Pyx_LocalBuf_ND")
4894

4895
cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
4896
                                      None, 0, "__pyx_memoryview_obj")
4897

4898
memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct",
4899
                                          None, 1, "__Pyx_memviewslice")
4900

4901
fixed_sign_int_types = {
4902
    "bint":       (1, c_bint_type),
4903
    "Py_UNICODE": (0, c_py_unicode_type),
4904
    "Py_UCS4":    (0, c_py_ucs4_type),
4905
    "Py_hash_t":  (2, c_py_hash_t_type),
4906
    "Py_ssize_t": (2, c_py_ssize_t_type),
4907
    "ssize_t":    (2, c_ssize_t_type),
4908
    "size_t":     (0, c_size_t_type),
4909
    "ptrdiff_t":  (2, c_ptrdiff_t_type),
4910
}
4911

4912
modifiers_and_name_to_type = {
4913
    #(signed, longness, name) : type
4914
    (0,  0, "char"): c_uchar_type,
4915
    (1,  0, "char"): c_char_type,
4916
    (2,  0, "char"): c_schar_type,
4917

4918
    (0, -1, "int"): c_ushort_type,
4919
    (0,  0, "int"): c_uint_type,
4920
    (0,  1, "int"): c_ulong_type,
4921
    (0,  2, "int"): c_ulonglong_type,
4922

4923
    (1, -1, "int"): c_short_type,
4924
    (1,  0, "int"): c_int_type,
4925
    (1,  1, "int"): c_long_type,
4926
    (1,  2, "int"): c_longlong_type,
4927

4928
    (2, -1, "int"): c_sshort_type,
4929
    (2,  0, "int"): c_sint_type,
4930
    (2,  1, "int"): c_slong_type,
4931
    (2,  2, "int"): c_slonglong_type,
4932

4933
    (1,  0, "float"):  c_float_type,
4934
    (1,  0, "double"): c_double_type,
4935
    (1,  1, "double"): c_longdouble_type,
4936

4937
    (1,  0, "complex"):  c_double_complex_type,  # C: float, Python: double => Python wins
4938
    (1,  0, "floatcomplex"):  c_float_complex_type,
4939
    (1,  0, "doublecomplex"): c_double_complex_type,
4940
    (1,  1, "doublecomplex"): c_longdouble_complex_type,
4941

4942
    #
4943
    (1,  0, "void"): c_void_type,
4944
    (1,  0, "Py_tss_t"): c_pytss_t_type,
4945

4946
    (1,  0, "object"): py_object_type,
4947
}
4948

4949
modifiers_and_name_to_type.update({
4950
    (signed, 0, name): tp
4951
    for name, (signed, tp) in fixed_sign_int_types.items()
4952
})
4953

4954
def is_promotion(src_type, dst_type):
4955
    # It's hard to find a hard definition of promotion, but empirical
4956
    # evidence suggests that the below is all that's allowed.
4957
    if src_type.is_numeric:
4958
        if dst_type.same_as(c_int_type):
4959
            unsigned = (not src_type.signed)
4960
            return (src_type.is_enum or
4961
                    (src_type.is_int and
4962
                     unsigned + src_type.rank < dst_type.rank))
4963
        elif dst_type.same_as(c_double_type):
4964
            return src_type.is_float and src_type.rank <= dst_type.rank
4965
    return False
4966

4967
def best_match(arg_types, functions, pos=None, env=None, args=None):
4968
    """
4969
    Given a list args of arguments and a list of functions, choose one
4970
    to call which seems to be the "best" fit for this list of arguments.
4971
    This function is used, e.g., when deciding which overloaded method
4972
    to dispatch for C++ classes.
4973

4974
    We first eliminate functions based on arity, and if only one
4975
    function has the correct arity, we return it. Otherwise, we weight
4976
    functions based on how much work must be done to convert the
4977
    arguments, with the following priorities:
4978
      * identical types or pointers to identical types
4979
      * promotions
4980
      * non-Python types
4981
    That is, we prefer functions where no arguments need converted,
4982
    and failing that, functions where only promotions are required, and
4983
    so on.
4984

4985
    If no function is deemed a good fit, or if two or more functions have
4986
    the same weight, we return None (as there is no best match). If pos
4987
    is not None, we also generate an error.
4988
    """
4989
    # TODO: args should be a list of types, not a list of Nodes.
4990
    actual_nargs = len(arg_types)
4991

4992
    candidates = []
4993
    errors = []
4994
    for func in functions:
4995
        error_mesg = ""
4996
        func_type = func.type
4997
        if func_type.is_ptr:
4998
            func_type = func_type.base_type
4999
        # Check function type
5000
        if not func_type.is_cfunction:
5001
            if not func_type.is_error and pos is not None:
5002
                error_mesg = "Calling non-function type '%s'" % func_type
5003
            errors.append((func, error_mesg))
5004
            continue
5005
        # Check no. of args
5006
        max_nargs = len(func_type.args)
5007
        min_nargs = max_nargs - func_type.optional_arg_count
5008
        if actual_nargs < min_nargs or (not func_type.has_varargs and actual_nargs > max_nargs):
5009
            if max_nargs == min_nargs and not func_type.has_varargs:
5010
                expectation = max_nargs
5011
            elif actual_nargs < min_nargs:
5012
                expectation = "at least %s" % min_nargs
5013
            else:
5014
                expectation = "at most %s" % max_nargs
5015
            error_mesg = "Call with wrong number of arguments (expected %s, got %s)" \
5016
                         % (expectation, actual_nargs)
5017
            errors.append((func, error_mesg))
5018
            continue
5019
        if func_type.templates:
5020
            # For any argument/parameter pair A/P, if P is a forwarding reference,
5021
            # use lvalue-reference-to-A for deduction in place of A when the
5022
            # function call argument is an lvalue. See:
5023
            # https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_function_call
5024
            arg_types_for_deduction = list(arg_types)
5025
            if func.type.is_cfunction and args:
5026
                for i, formal_arg in enumerate(func.type.args):
5027
                    if formal_arg.is_forwarding_reference():
5028
                        if args[i].is_lvalue():
5029
                            arg_types_for_deduction[i] = c_ref_type(arg_types[i])
5030
            deductions = reduce(
5031
                merge_template_deductions,
5032
                [pattern.type.deduce_template_params(actual) for (pattern, actual) in zip(func_type.args, arg_types_for_deduction)],
5033
                {})
5034
            if deductions is None:
5035
                errors.append((func, "Unable to deduce type parameters for %s given (%s)" % (
5036
                    func_type, ', '.join(map(str, arg_types_for_deduction)))))
5037
            elif len(deductions) < len(func_type.templates):
5038
                errors.append((func, "Unable to deduce type parameter %s" % (
5039
                    ", ".join([param.name for param in func_type.templates if param not in deductions]))))
5040
            else:
5041
                type_list = [deductions[param] for param in func_type.templates]
5042
                from .Symtab import Entry
5043
                specialization = Entry(
5044
                    name = func.name + "[%s]" % ",".join([str(t) for t in type_list]),
5045
                    cname = func.cname + "<%s>" % ",".join([t.empty_declaration_code() for t in type_list]),
5046
                    type = func_type.specialize(deductions),
5047
                    pos = func.pos)
5048
                candidates.append((specialization, specialization.type))
5049
        else:
5050
            candidates.append((func, func_type))
5051

5052
    # Optimize the most common case of no overloading...
5053
    if len(candidates) == 1:
5054
        return candidates[0][0]
5055
    elif not candidates:
5056
        if pos is not None and errors:
5057
            if len(errors) == 1 or len({msg for _, msg in errors}) == 1:
5058
                _, errmsg = errors[0]
5059
                error(pos, errmsg)
5060
            else:
5061
                error(pos, f"no suitable method found (candidates: {len(functions)})")
5062
        return None
5063

5064
    possibilities = []
5065
    bad_types = []
5066
    needed_coercions = {}
5067

5068
    for index, (func, func_type) in enumerate(candidates):
5069
        score = [0,0,0,0,0,0,0]
5070
        for i in range(min(actual_nargs, len(func_type.args))):
5071
            src_type = arg_types[i]
5072
            dst_type = func_type.args[i].type
5073

5074
            assignable = dst_type.assignable_from(src_type)
5075

5076
            # Now take care of unprefixed string literals. So when you call a cdef
5077
            # function that takes a char *, the coercion will mean that the
5078
            # type will simply become bytes. We need to do this coercion
5079
            # manually for overloaded and fused functions
5080
            if not assignable:
5081
                c_src_type = None
5082
                if src_type.is_pyobject:
5083
                    if src_type.is_builtin_type and src_type.name == 'str' and dst_type.resolve().is_string:
5084
                        c_src_type = dst_type.resolve()
5085
                    else:
5086
                        c_src_type = src_type.default_coerced_ctype()
5087
                elif src_type.is_pythran_expr:
5088
                        c_src_type = src_type.org_buffer
5089

5090
                if c_src_type is not None:
5091
                    assignable = dst_type.assignable_from(c_src_type)
5092
                    if assignable:
5093
                        src_type = c_src_type
5094
                        needed_coercions[func] = (i, dst_type)
5095

5096
            if assignable:
5097
                if src_type == dst_type or dst_type.same_as(src_type):
5098
                    pass  # score 0
5099
                elif func_type.is_strict_signature:
5100
                    break  # exact match requested but not found
5101
                elif is_promotion(src_type, dst_type):
5102
                    score[2] += 1
5103
                elif ((src_type.is_int and dst_type.is_int) or
5104
                      (src_type.is_float and dst_type.is_float)):
5105
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
5106
                                    (src_type.rank + (not src_type.signed))) + 1
5107
                elif dst_type.is_ptr and src_type.is_ptr:
5108
                    if dst_type.base_type == c_void_type:
5109
                        score[4] += 1
5110
                    elif src_type.base_type.is_cpp_class and src_type.base_type.is_subclass(dst_type.base_type):
5111
                        score[6] += src_type.base_type.subclass_dist(dst_type.base_type)
5112
                    else:
5113
                        score[5] += 1
5114
                elif not src_type.is_pyobject:
5115
                    score[1] += 1
5116
                else:
5117
                    score[0] += 1
5118
            else:
5119
                error_mesg = "Invalid conversion from '%s' to '%s'" % (src_type, dst_type)
5120
                bad_types.append((func, error_mesg))
5121
                break
5122
        else:
5123
            possibilities.append((score, index, func))  # so we can sort it
5124

5125
    if possibilities:
5126
        possibilities.sort()
5127
        if len(possibilities) > 1:
5128
            score1 = possibilities[0][0]
5129
            score2 = possibilities[1][0]
5130
            if score1 == score2:
5131
                if pos is not None:
5132
                    error(pos, "ambiguous overloaded method")
5133
                return None
5134

5135
        function = possibilities[0][-1]
5136

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

5141
        return function
5142

5143
    if pos is not None:
5144
        if len(bad_types) == 1:
5145
            error(pos, bad_types[0][1])
5146
        else:
5147
            error(pos, "no suitable method found")
5148

5149
    return None
5150

5151

5152
def merge_template_deductions(a, b):
5153
    # Used to reduce lists of deduced template mappings into one mapping.
5154
    if a is None or b is None:
5155
        return None
5156
    add_if_missing = a.setdefault
5157
    for param, value in b.items():
5158
        if add_if_missing(param, value) != value:
5159
            # Found mismatch, cannot merge.
5160
            return None
5161
    return a
5162

5163

5164
def widest_numeric_type(type1, type2):
5165
    """Given two numeric types, return the narrowest type encompassing both of them.
5166
    """
5167
    if type1.is_reference:
5168
        type1 = type1.ref_base_type
5169
    if type2.is_reference:
5170
        type2 = type2.ref_base_type
5171
    if type1.is_cv_qualified:
5172
        type1 = type1.cv_base_type
5173
    if type2.is_cv_qualified:
5174
        type2 = type2.cv_base_type
5175
    if type1 == type2:
5176
        widest_type = type1
5177
    elif type1.is_complex or type2.is_complex:
5178
        def real_type(ntype):
5179
            if ntype.is_complex:
5180
                return ntype.real_type
5181
            return ntype
5182
        widest_type = CComplexType(
5183
            widest_numeric_type(
5184
                real_type(type1),
5185
                real_type(type2)))
5186
        if type1 is soft_complex_type or type2 is soft_complex_type:
5187
            type1_is_other_complex = type1 is not soft_complex_type and type1.is_complex
5188
            type2_is_other_complex = type2 is not soft_complex_type and type2.is_complex
5189
            if (not type1_is_other_complex and not type2_is_other_complex and
5190
                    widest_type.real_type == soft_complex_type.real_type):
5191
                # ensure we can do an actual "is" comparison
5192
                # (this possibly goes slightly wrong when mixing long double and soft complex)
5193
                widest_type = soft_complex_type
5194
    elif type1.is_enum and type2.is_enum:
5195
        widest_type = c_int_type
5196
    elif type1.rank < type2.rank:
5197
        widest_type = type2
5198
    elif type1.rank > type2.rank:
5199
        widest_type = type1
5200
    elif type1.signed < type2.signed:
5201
        widest_type = type1
5202
    elif type1.signed > type2.signed:
5203
        widest_type = type2
5204
    elif type1.is_typedef > type2.is_typedef:
5205
        widest_type = type1
5206
    else:
5207
        widest_type = type2
5208
    return widest_type
5209

5210

5211
def result_type_of_builtin_operation(builtin_type, type2):
5212
    """
5213
    Try to find a suitable (C) result type for a binary operation with a known builtin type.
5214
    """
5215
    if builtin_type.name == 'float':
5216
        if type2.is_numeric:
5217
            return widest_numeric_type(c_double_type, type2)
5218
        elif type2.is_builtin_type and type2.name in ('int', 'float'):
5219
            return c_double_type
5220
        elif type2.is_builtin_type and type2.name == 'complex':
5221
            return type2
5222
    elif builtin_type.name == 'int':
5223
        if type2 == builtin_type or type2.is_int:
5224
            return builtin_type
5225
        elif type2.is_float or type2.is_builtin_type and type2.name == 'float':
5226
            return c_double_type
5227
        elif type2.is_builtin_type and type2.name == 'complex':
5228
            return type2
5229
    elif builtin_type.name == 'complex':
5230
        if type2 == builtin_type or type2.is_complex:
5231
            return CComplexType(widest_numeric_type(c_double_type, type2.real_type))
5232
        elif type2.is_numeric:
5233
            return CComplexType(widest_numeric_type(c_double_type, type2))
5234
        elif type2.is_builtin_type and type2.name in ('int', 'float', 'complex'):
5235
            return CComplexType(c_double_type)
5236

5237
    return None
5238

5239

5240
def numeric_type_fits(small_type, large_type):
5241
    return widest_numeric_type(small_type, large_type) == large_type
5242

5243

5244
def independent_spanning_type(type1, type2):
5245
    # Return a type assignable independently from both type1 and
5246
    # type2, but do not require any interoperability between the two.
5247
    # For example, in "True * 2", it is safe to assume an integer
5248
    # result type (so spanning_type() will do the right thing),
5249
    # whereas "x = True or 2" must evaluate to a type that can hold
5250
    # both a boolean value and an integer, so this function works
5251
    # better.
5252
    if type1.is_reference ^ type2.is_reference:
5253
        if type1.is_reference:
5254
            type1 = type1.ref_base_type
5255
        else:
5256
            type2 = type2.ref_base_type
5257

5258
    resolved_type1 = type1.resolve()
5259
    resolved_type2 = type2.resolve()
5260
    if resolved_type1 == resolved_type2:
5261
        return type1
5262
    elif ((resolved_type1 is c_bint_type or resolved_type2 is c_bint_type)
5263
            and (type1.is_numeric and type2.is_numeric)):
5264
        # special case: if one of the results is a bint and the other
5265
        # is another C integer, we must prevent returning a numeric
5266
        # type so that we do not lose the ability to coerce to a
5267
        # Python bool if we have to.
5268
        return py_object_type
5269

5270
    span_type = _spanning_type(type1, type2)
5271
    if span_type is None:
5272
        return error_type
5273
    return span_type
5274

5275
def spanning_type(type1, type2):
5276
    # Return a type assignable from both type1 and type2, or
5277
    # py_object_type if no better type is found.  Assumes that the
5278
    # code that calls this will try a coercion afterwards, which will
5279
    # fail if the types cannot actually coerce to a py_object_type.
5280
    if type1 == type2:
5281
        return type1
5282
    elif type1 is py_object_type or type2 is py_object_type:
5283
        return py_object_type
5284
    elif type1 is c_py_unicode_type or type2 is c_py_unicode_type:
5285
        # Py_UNICODE behaves more like a string than an int
5286
        return py_object_type
5287
    span_type = _spanning_type(type1, type2)
5288
    if span_type is None:
5289
        return py_object_type
5290
    return span_type
5291

5292

5293
def _spanning_type(type1, type2):
5294
    if type1.is_numeric and type2.is_numeric:
5295
        return widest_numeric_type(type1, type2)
5296
    elif type1.is_builtin_type:
5297
        return result_type_of_builtin_operation(type1, type2) or py_object_type
5298
    elif type2.is_builtin_type:
5299
        return result_type_of_builtin_operation(type2, type1) or py_object_type
5300
    elif type1.is_extension_type and type2.is_extension_type:
5301
        return widest_extension_type(type1, type2)
5302
    elif type1.is_pyobject or type2.is_pyobject:
5303
        return py_object_type
5304
    elif type1.assignable_from(type2):
5305
        if type1.is_extension_type and type1.typeobj_is_imported():
5306
            # external types are unsafe, so we use PyObject instead
5307
            return py_object_type
5308
        return type1
5309
    elif type2.assignable_from(type1):
5310
        if type2.is_extension_type and type2.typeobj_is_imported():
5311
            # external types are unsafe, so we use PyObject instead
5312
            return py_object_type
5313
        return type2
5314
    elif type1.is_ptr and type2.is_ptr:
5315
        if type1.base_type.is_cpp_class and type2.base_type.is_cpp_class:
5316
            common_base = widest_cpp_type(type1.base_type, type2.base_type)
5317
            if common_base:
5318
                return CPtrType(common_base)
5319
        # incompatible pointers, void* will do as a result
5320
        return c_void_ptr_type
5321
    else:
5322
        return None
5323

5324
def widest_extension_type(type1, type2):
5325
    if type1.typeobj_is_imported() or type2.typeobj_is_imported():
5326
        return py_object_type
5327
    while True:
5328
        if type1.subtype_of(type2):
5329
            return type2
5330
        elif type2.subtype_of(type1):
5331
            return type1
5332
        type1, type2 = type1.base_type, type2.base_type
5333
        if type1 is None or type2 is None:
5334
            return py_object_type
5335

5336
def widest_cpp_type(type1, type2):
5337
    @cached_function
5338
    def bases(type):
5339
        all = set()
5340
        for base in type.base_classes:
5341
            all.add(base)
5342
            all.update(bases(base))
5343
        return all
5344
    common_bases = bases(type1).intersection(bases(type2))
5345
    common_bases_bases = reduce(set.union, [bases(b) for b in common_bases], set())
5346
    candidates = [b for b in common_bases if b not in common_bases_bases]
5347
    if len(candidates) == 1:
5348
        return candidates[0]
5349
    else:
5350
        # Fall back to void* for now.
5351
        return None
5352

5353

5354
def simple_c_type(signed, longness, name):
5355
    # Find type descriptor for simple type given name and modifiers.
5356
    # Returns None if arguments don't make sense.
5357
    return modifiers_and_name_to_type.get((signed, longness, name))
5358

5359
def parse_basic_type(name):
5360
    base = None
5361
    if name.startswith('p_'):
5362
        base = parse_basic_type(name[2:])
5363
    elif name.startswith('p'):
5364
        base = parse_basic_type(name[1:])
5365
    elif name.endswith('*'):
5366
        base = parse_basic_type(name[:-1])
5367
    if base:
5368
        return CPtrType(base)
5369
    #
5370
    if name in fixed_sign_int_types:
5371
        return fixed_sign_int_types[name][1]
5372
    basic_type = simple_c_type(1, 0, name)
5373
    if basic_type:
5374
        return basic_type
5375
    #
5376
    if name.startswith('u'):
5377
        name = name[1:]
5378
        signed = 0
5379
    elif (name.startswith('s') and
5380
          not name.startswith('short')):
5381
        name = name[1:]
5382
        signed = 2
5383
    else:
5384
        signed = 1
5385

5386
    # We parse both (cy) 'long long' and (py) 'longlong' style names here.
5387
    longness = 0
5388
    while name.startswith(('long', 'short')):
5389
        if name.startswith('long'):
5390
            name = name[4:].lstrip()
5391
            longness += 1
5392
        else:
5393
            name = name[5:].lstrip()
5394
            longness -= 1
5395
    if longness != 0 and not name:
5396
        name = 'int'  # long/short [int]
5397

5398
    return simple_c_type(signed, longness, name)
5399

5400

5401
def _construct_type_from_base(cls, base_type, *args):
5402
    if base_type is error_type:
5403
        return error_type
5404
    return cls(base_type, *args)
5405

5406
def c_array_type(base_type, size):
5407
    # Construct a C array type.
5408
    return _construct_type_from_base(CArrayType, base_type, size)
5409

5410
def c_ptr_type(base_type):
5411
    # Construct a C pointer type.
5412
    if base_type.is_reference:
5413
        base_type = base_type.ref_base_type
5414
    return _construct_type_from_base(CPtrType, base_type)
5415

5416
def c_ref_type(base_type):
5417
    # Construct a C reference type
5418
    return _construct_type_from_base(CReferenceType, base_type)
5419

5420
def cpp_rvalue_ref_type(base_type):
5421
    # Construct a C++ rvalue reference type
5422
    return _construct_type_from_base(CppRvalueReferenceType, base_type)
5423

5424
def c_const_type(base_type):
5425
    # Construct a C const type.
5426
    return _construct_type_from_base(CConstType, base_type)
5427

5428
def c_const_or_volatile_type(base_type, is_const, is_volatile):
5429
    # Construct a C const/volatile type.
5430
    return _construct_type_from_base(CConstOrVolatileType, base_type, is_const, is_volatile)
5431

5432

5433
def same_type(type1, type2):
5434
    return type1.same_as(type2)
5435

5436
def assignable_from(type1, type2):
5437
    return type1.assignable_from(type2)
5438

5439
def typecast(to_type, from_type, expr_code):
5440
    #  Return expr_code cast to a C type which can be
5441
    #  assigned to to_type, assuming its existing C type
5442
    #  is from_type.
5443
    if (to_type is from_type or
5444
            (not to_type.is_pyobject and assignable_from(to_type, from_type))):
5445
        return expr_code
5446
    elif (to_type is py_object_type and from_type and
5447
            from_type.is_builtin_type and from_type.name != 'type'):
5448
        # no cast needed, builtins are PyObject* already
5449
        return expr_code
5450
    else:
5451
        #print "typecast: to", to_type, "from", from_type ###
5452
        return to_type.cast_code(expr_code)
5453

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

5457
_special_type_characters = {
5458
    '__': '__dunder',
5459
    'const ': '__const_',
5460
    ' ': '__space_',
5461
    '*': '__ptr',
5462
    '&': '__ref',
5463
    '&&': '__fwref',
5464
    '[': '__lArr',
5465
    ']': '__rArr',
5466
    '<': '__lAng',
5467
    '>': '__rAng',
5468
    '(': '__lParen',
5469
    ')': '__rParen',
5470
    ',': '__comma_',
5471
    '...': '__EL',
5472
    '::': '__in_',
5473
    ':': '__D',
5474
}
5475

5476
_escape_special_type_characters = partial(re.compile(
5477
    # join substrings in reverse order to put longer matches first, e.g. "::" before ":"
5478
    " ?(%s) ?" % "|".join(re.escape(s) for s in sorted(_special_type_characters, reverse=True))
5479
).sub, lambda match: _special_type_characters[match.group(1)])
5480

5481
def type_identifier(type, pyrex=False):
5482
    scope = None
5483
    decl = type.empty_declaration_code(pyrex=pyrex)
5484
    entry = getattr(type, "entry", None)
5485
    if entry and entry.scope:
5486
        scope = entry.scope
5487
    return type_identifier_from_declaration(decl, scope=scope)
5488

5489
_type_identifier_cache = {}
5490
def type_identifier_from_declaration(decl, scope = None):
5491
    key = (decl, scope)
5492
    safe = _type_identifier_cache.get(key)
5493
    if safe is None:
5494
        safe = decl
5495
        if scope:
5496
            safe = scope.mangle(prefix="", name=safe)
5497
        safe = re.sub(' +', ' ', safe)
5498
        safe = re.sub(' ?([^a-zA-Z0-9_]) ?', r'\1', safe)
5499
        safe = _escape_special_type_characters(safe)
5500
        safe = cap_length(re.sub('[^a-zA-Z0-9_]', lambda x: '__%X' % ord(x.group(0)), safe))
5501
        _type_identifier_cache[key] = safe
5502
    return safe
5503

5504
def cap_length(s, max_len=63):
5505
    if len(s) <= max_len:
5506
        return s
5507
    hash_prefix = hashlib.sha256(s.encode('ascii')).hexdigest()[:6]
5508
    return '%s__%s__etc' % (hash_prefix, s[:max_len-17])
5509

5510
def write_noexcept_performance_hint(pos, env,
5511
                                    function_name=None, void_return=False, is_call=False,
5512
                                    is_from_pxd=False):
5513
    if function_name:
5514
        # we need it escaped everywhere we use it
5515
        function_name = "'%s'" % function_name
5516
    if is_call:
5517
        on_what = "after calling %s " % (function_name or 'function')
5518
    elif function_name:
5519
        on_what = "on %s " % function_name
5520
    else:
5521
        on_what =''
5522
    msg = (
5523
        "Exception check %swill always require the GIL to be acquired."
5524
    ) % on_what
5525
    the_function = function_name if function_name else "the function"
5526
    if is_call and not function_name:
5527
        the_function = the_function + " you are calling"
5528
    solutions = ["Declare %s as 'noexcept' if you control the definition and "
5529
                 "you're sure you don't want the function to raise exceptions."
5530
                                % the_function]
5531
    if void_return:
5532
        solutions.append(
5533
            "Use an 'int' return type on %s to allow an error code to be returned." %
5534
            the_function)
5535
    if is_from_pxd and not void_return:
5536
        solutions.append(
5537
            "Declare any exception value explicitly for functions in pxd files.")
5538
    if len(solutions) == 1:
5539
        msg = "%s %s" % (msg, solutions[0])
5540
    else:
5541
        solutions = ["\t%s. %s" % (i+1, s) for i, s in enumerate(solutions)]
5542
        msg = "%s\nPossible solutions:\n%s" % (msg, "\n".join(solutions))
5543
    performance_hint(pos, msg, env)
5544

5545
def remove_cv_ref(tp, remove_fakeref=False):
5546
    # named by analogy with c++ std::remove_cv_ref
5547
    last_tp = None
5548
    # The while-loop is probably unnecessary, but I'm not confident
5549
    # of the order or how careful we are prevent nesting.
5550
    while tp != last_tp:
5551
        last_tp = tp
5552
        if tp.is_cv_qualified:
5553
            tp = tp.cv_base_type
5554
        if tp.is_reference and (not tp.is_fake_reference or remove_fakeref):
5555
            tp = tp.ref_base_type
5556
    return tp
5557

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.