1# 2# Cython/Python language types 3# 4 5from __future__ import absolute_import 6 7import copy 8import hashlib 9import re 10 11try: 12 reduce 13except NameError: 14 from functools import reduce 15 16from Cython.Utils import cached_function 17from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode 18from . import StringEncoding 19from . import Naming 20 21from .Errors import error, warning 22 23 24class BaseType(object): 25 # 26 # Base class for all Cython types including pseudo-types. 27 28 # List of attribute names of any subtypes 29 subtypes = [] 30 _empty_declaration = None 31 _specialization_name = None 32 default_format_spec = None 33 34 def can_coerce_to_pyobject(self, env): 35 return False 36 37 def can_coerce_from_pyobject(self, env): 38 return False 39 40 def can_coerce_to_pystring(self, env, format_spec=None): 41 return False 42 43 def convert_to_pystring(self, cvalue, code, format_spec=None): 44 raise NotImplementedError("C types that support string formatting must override this method") 45 46 def cast_code(self, expr_code): 47 return "((%s)%s)" % (self.empty_declaration_code(), expr_code) 48 49 def empty_declaration_code(self): 50 if self._empty_declaration is None: 51 self._empty_declaration = self.declaration_code('') 52 return self._empty_declaration 53 54 def specialization_name(self): 55 if self._specialization_name is None: 56 # This is not entirely robust. 57 common_subs = (self.empty_declaration_code() 58 .replace("unsigned ", "unsigned_") 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): 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) 92 else: 93 for subtype in list_or_subtype: 94 subtype.get_fused_types(result, seen) 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 http://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 163class 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_const boolean Is a C const type. 180 # is_cfunction boolean Is a C function type 181 # is_struct_or_union boolean Is a C struct or union type 182 # is_struct boolean Is a C struct type 183 # is_enum boolean Is a C enum type 184 # is_typedef boolean Is a typedef type 185 # is_string boolean Is a C char * type 186 # is_pyunicode_ptr boolean Is a C PyUNICODE * type 187 # is_cpp_string boolean Is a C++ std::string type 188 # is_unicode_char boolean Is either Py_UCS4 or Py_UNICODE 189 # is_returncode boolean Is used only to signal exceptions 190 # is_error boolean Is the dummy error type 191 # is_buffer boolean Is buffer access type 192 # is_pythran_expr boolean Is Pythran expr 193 # is_numpy_buffer boolean Is Numpy array buffer 194 # has_attributes boolean Has C dot-selectable attributes 195 # default_value string Initial value that can be assigned before first user assignment. 196 # declaration_value string The value statically assigned on declaration (if any). 197 # entry Entry The Entry for this type 198 # 199 # declaration_code(entity_code, 200 # for_display = 0, dll_linkage = None, pyrex = 0) 201 # Returns a code fragment for the declaration of an entity 202 # of this type, given a code fragment for the entity. 203 # * If for_display, this is for reading by a human in an error 204 # message; otherwise it must be valid C code. 205 # * If dll_linkage is not None, it must be 'DL_EXPORT' or 206 # 'DL_IMPORT', and will be added to the base type part of 207 # the declaration. 208 # * If pyrex = 1, this is for use in a 'cdef extern' 209 # statement of a Cython include file. 210 # 211 # assignable_from(src_type) 212 # Tests whether a variable of this type can be 213 # assigned a value of type src_type. 214 # 215 # same_as(other_type) 216 # Tests whether this type represents the same type 217 # as other_type. 218 # 219 # as_argument_type(): 220 # Coerces array and C function types into pointer type for use as 221 # a formal argument type. 222 # 223 224 is_pyobject = 0 225 is_unspecified = 0 226 is_extension_type = 0 227 is_final_type = 0 228 is_builtin_type = 0 229 is_numeric = 0 230 is_int = 0 231 is_float = 0 232 is_complex = 0 233 is_void = 0 234 is_array = 0 235 is_ptr = 0 236 is_null_ptr = 0 237 is_reference = 0 238 is_const = 0 239 is_cfunction = 0 240 is_struct_or_union = 0 241 is_cpp_class = 0 242 is_cpp_string = 0 243 is_struct = 0 244 is_enum = 0 245 is_typedef = 0 246 is_string = 0 247 is_pyunicode_ptr = 0 248 is_unicode_char = 0 249 is_returncode = 0 250 is_error = 0 251 is_buffer = 0 252 is_ctuple = 0 253 is_memoryviewslice = 0 254 is_pythran_expr = 0 255 is_numpy_buffer = 0 256 has_attributes = 0 257 default_value = "" 258 declaration_value = "" 259 260 def resolve(self): 261 # If a typedef, returns the base type. 262 return self 263 264 def specialize(self, values): 265 # TODO(danilo): Override wherever it makes sense. 266 return self 267 268 def literal_code(self, value): 269 # Returns a C code fragment representing a literal 270 # value of this type. 271 return str(value) 272 273 def __str__(self): 274 return self.declaration_code("", for_display = 1).strip() 275 276 def same_as(self, other_type, **kwds): 277 return self.same_as_resolved_type(other_type.resolve(), **kwds) 278 279 def same_as_resolved_type(self, other_type): 280 return self == other_type or other_type is error_type 281 282 def subtype_of(self, other_type): 283 return self.subtype_of_resolved_type(other_type.resolve()) 284 285 def subtype_of_resolved_type(self, other_type): 286 return self.same_as(other_type) 287 288 def assignable_from(self, src_type): 289 return self.assignable_from_resolved_type(src_type.resolve()) 290 291 def assignable_from_resolved_type(self, src_type): 292 return self.same_as(src_type) 293 294 def as_argument_type(self): 295 return self 296 297 def is_complete(self): 298 # A type is incomplete if it is an unsized array, 299 # a struct whose attributes are not defined, etc. 300 return 1 301 302 def is_simple_buffer_dtype(self): 303 return (self.is_int or self.is_float or self.is_complex or self.is_pyobject or 304 self.is_extension_type or self.is_ptr) 305 306 def struct_nesting_depth(self): 307 # Returns the number levels of nested structs. This is 308 # used for constructing a stack for walking the run-time 309 # type information of the struct. 310 return 1 311 312 def global_init_code(self, entry, code): 313 # abstract 314 pass 315 316 def needs_nonecheck(self): 317 return 0 318 319 def _assign_from_py_code(self, source_code, result_code, error_pos, code, 320 from_py_function=None, error_condition=None, extra_args=None): 321 args = ', ' + ', '.join('%s' % arg for arg in extra_args) if extra_args else '' 322 convert_call = "%s(%s%s)" % ( 323 from_py_function or self.from_py_function, 324 source_code, 325 args, 326 ) 327 if self.is_enum: 328 convert_call = typecast(self, c_long_type, convert_call) 329 return '%s = %s; %s' % ( 330 result_code, 331 convert_call, 332 code.error_goto_if(error_condition or self.error_condition(result_code), error_pos)) 333 334 335def public_decl(base_code, dll_linkage): 336 if dll_linkage: 337 return "%s(%s)" % (dll_linkage, base_code.replace(',', ' __PYX_COMMA ')) 338 else: 339 return base_code 340 341def create_typedef_type(name, base_type, cname, is_external=0, namespace=None): 342 is_fused = base_type.is_fused 343 if base_type.is_complex or is_fused: 344 if is_external: 345 if is_fused: 346 msg = "Fused" 347 else: 348 msg = "Complex" 349 350 raise ValueError("%s external typedefs not supported" % msg) 351 352 return base_type 353 else: 354 return CTypedefType(name, base_type, cname, is_external, namespace) 355 356 357class CTypedefType(BaseType): 358 # 359 # Pseudo-type defined with a ctypedef statement in a 360 # 'cdef extern from' block. 361 # Delegates most attribute lookups to the base type. 362 # (Anything not defined here or in the BaseType is delegated.) 363 # 364 # qualified_name string 365 # typedef_name string 366 # typedef_cname string 367 # typedef_base_type PyrexType 368 # typedef_is_external bool 369 370 is_typedef = 1 371 typedef_is_external = 0 372 373 to_py_utility_code = None 374 from_py_utility_code = None 375 376 subtypes = ['typedef_base_type'] 377 378 def __init__(self, name, base_type, cname, is_external=0, namespace=None): 379 assert not base_type.is_complex 380 self.typedef_name = name 381 self.typedef_cname = cname 382 self.typedef_base_type = base_type 383 self.typedef_is_external = is_external 384 self.typedef_namespace = namespace 385 386 def invalid_value(self): 387 return self.typedef_base_type.invalid_value() 388 389 def resolve(self): 390 return self.typedef_base_type.resolve() 391 392 def declaration_code(self, entity_code, 393 for_display = 0, dll_linkage = None, pyrex = 0): 394 if pyrex or for_display: 395 base_code = self.typedef_name 396 else: 397 base_code = public_decl(self.typedef_cname, dll_linkage) 398 if self.typedef_namespace is not None and not pyrex: 399 base_code = "%s::%s" % (self.typedef_namespace.empty_declaration_code(), base_code) 400 return self.base_declaration_code(base_code, entity_code) 401 402 def as_argument_type(self): 403 return self 404 405 def cast_code(self, expr_code): 406 # If self is really an array (rather than pointer), we can't cast. 407 # For example, the gmp mpz_t. 408 if self.typedef_base_type.is_array: 409 base_type = self.typedef_base_type.base_type 410 return CPtrType(base_type).cast_code(expr_code) 411 else: 412 return BaseType.cast_code(self, expr_code) 413 414 def specialize(self, values): 415 base_type = self.typedef_base_type.specialize(values) 416 namespace = self.typedef_namespace.specialize(values) if self.typedef_namespace else None 417 if base_type is self.typedef_base_type and namespace is self.typedef_namespace: 418 return self 419 else: 420 return create_typedef_type(self.typedef_name, base_type, self.typedef_cname, 421 0, namespace) 422 423 def __repr__(self): 424 return "<CTypedefType %s>" % self.typedef_cname 425 426 def __str__(self): 427 return self.typedef_name 428 429 def _create_utility_code(self, template_utility_code, 430 template_function_name): 431 type_name = type_identifier(self.typedef_cname) 432 utility_code = template_utility_code.specialize( 433 type = self.typedef_cname, 434 TypeName = type_name) 435 function_name = template_function_name % type_name 436 return utility_code, function_name 437 438 def create_to_py_utility_code(self, env): 439 if self.typedef_is_external: 440 if not self.to_py_utility_code: 441 base_type = self.typedef_base_type 442 if type(base_type) is CIntType: 443 self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name() 444 env.use_utility_code(TempitaUtilityCode.load_cached( 445 "CIntToPy", "TypeConversion.c", 446 context={"TYPE": self.empty_declaration_code(), 447 "TO_PY_FUNCTION": self.to_py_function})) 448 return True 449 elif base_type.is_float: 450 pass # XXX implement! 451 elif base_type.is_complex: 452 pass # XXX implement! 453 pass 454 elif base_type.is_cpp_string: 455 cname = "__pyx_convert_PyObject_string_to_py_%s" % type_identifier(self) 456 context = { 457 'cname': cname, 458 'type': self.typedef_cname, 459 } 460 from .UtilityCode import CythonUtilityCode 461 env.use_utility_code(CythonUtilityCode.load( 462 "string.to_py", "CppConvert.pyx", context=context)) 463 self.to_py_function = cname 464 return True 465 if self.to_py_utility_code: 466 env.use_utility_code(self.to_py_utility_code) 467 return True 468 # delegation 469 return self.typedef_base_type.create_to_py_utility_code(env) 470 471 def create_from_py_utility_code(self, env): 472 if self.typedef_is_external: 473 if not self.from_py_utility_code: 474 base_type = self.typedef_base_type 475 if type(base_type) is CIntType: 476 self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name() 477 env.use_utility_code(TempitaUtilityCode.load_cached( 478 "CIntFromPy", "TypeConversion.c", 479 context={"TYPE": self.empty_declaration_code(), 480 "FROM_PY_FUNCTION": self.from_py_function})) 481 return True 482 elif base_type.is_float: 483 pass # XXX implement! 484 elif base_type.is_complex: 485 pass # XXX implement! 486 elif base_type.is_cpp_string: 487 cname = '__pyx_convert_string_from_py_%s' % type_identifier(self) 488 context = { 489 'cname': cname, 490 'type': self.typedef_cname, 491 } 492 from .UtilityCode import CythonUtilityCode 493 env.use_utility_code(CythonUtilityCode.load( 494 "string.from_py", "CppConvert.pyx", context=context)) 495 self.from_py_function = cname 496 return True 497 if self.from_py_utility_code: 498 env.use_utility_code(self.from_py_utility_code) 499 return True 500 # delegation 501 return self.typedef_base_type.create_from_py_utility_code(env) 502 503 def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None): 504 if to_py_function is None: 505 to_py_function = self.to_py_function 506 return self.typedef_base_type.to_py_call_code( 507 source_code, result_code, result_type, to_py_function) 508 509 def from_py_call_code(self, source_code, result_code, error_pos, code, 510 from_py_function=None, error_condition=None): 511 return self.typedef_base_type.from_py_call_code( 512 source_code, result_code, error_pos, code, 513 from_py_function or self.from_py_function, 514 error_condition or self.error_condition(result_code) 515 ) 516 517 def overflow_check_binop(self, binop, env, const_rhs=False): 518 env.use_utility_code(UtilityCode.load("Common", "Overflow.c")) 519 type = self.empty_declaration_code() 520 name = self.specialization_name() 521 if binop == "lshift": 522 env.use_utility_code(TempitaUtilityCode.load_cached( 523 "LeftShift", "Overflow.c", 524 context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed})) 525 else: 526 if const_rhs: 527 binop += "_const" 528 _load_overflow_base(env) 529 env.use_utility_code(TempitaUtilityCode.load_cached( 530 "SizeCheck", "Overflow.c", 531 context={'TYPE': type, 'NAME': name})) 532 env.use_utility_code(TempitaUtilityCode.load_cached( 533 "Binop", "Overflow.c", 534 context={'TYPE': type, 'NAME': name, 'BINOP': binop})) 535 return "__Pyx_%s_%s_checking_overflow" % (binop, name) 536 537 def error_condition(self, result_code): 538 if self.typedef_is_external: 539 if self.exception_value: 540 condition = "(%s == %s)" % ( 541 result_code, self.cast_code(self.exception_value)) 542 if self.exception_check: 543 condition += " && PyErr_Occurred()" 544 return condition 545 # delegation 546 return self.typedef_base_type.error_condition(result_code) 547 548 def __getattr__(self, name): 549 return getattr(self.typedef_base_type, name) 550 551 def py_type_name(self): 552 return self.typedef_base_type.py_type_name() 553 554 def can_coerce_to_pyobject(self, env): 555 return self.typedef_base_type.can_coerce_to_pyobject(env) 556 557 def can_coerce_from_pyobject(self, env): 558 return self.typedef_base_type.can_coerce_from_pyobject(env) 559 560 561class MemoryViewSliceType(PyrexType): 562 563 is_memoryviewslice = 1 564 565 has_attributes = 1 566 scope = None 567 568 # These are special cased in Defnode 569 from_py_function = None 570 to_py_function = None 571 572 exception_value = None 573 exception_check = True 574 575 subtypes = ['dtype'] 576 577 def __init__(self, base_dtype, axes): 578 """ 579 MemoryViewSliceType(base, axes) 580 581 Base is the C base type; axes is a list of (access, packing) strings, 582 where access is one of 'full', 'direct' or 'ptr' and packing is one of 583 'contig', 'strided' or 'follow'. There is one (access, packing) tuple 584 for each dimension. 585 586 the access specifiers determine whether the array data contains 587 pointers that need to be dereferenced along that axis when 588 retrieving/setting: 589 590 'direct' -- No pointers stored in this dimension. 591 'ptr' -- Pointer stored in this dimension. 592 'full' -- Check along this dimension, don't assume either. 593 594 the packing specifiers specify how the array elements are layed-out 595 in memory. 596 597 'contig' -- The data is contiguous in memory along this dimension. 598 At most one dimension may be specified as 'contig'. 599 'strided' -- The data isn't contiguous along this dimension. 600 'follow' -- Used for C/Fortran contiguous arrays, a 'follow' dimension 601 has its stride automatically computed from extents of the other 602 dimensions to ensure C or Fortran memory layout. 603 604 C-contiguous memory has 'direct' as the access spec, 'contig' as the 605 *last* axis' packing spec and 'follow' for all other packing specs. 606 607 Fortran-contiguous memory has 'direct' as the access spec, 'contig' as 608 the *first* axis' packing spec and 'follow' for all other packing 609 specs. 610 """ 611 from . import Buffer, MemoryView 612 613 self.dtype = base_dtype 614 self.axes = axes 615 self.ndim = len(axes) 616 self.flags = MemoryView.get_buf_flags(self.axes) 617 618 self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes) 619 assert not (self.is_c_contig and self.is_f_contig) 620 621 self.mode = MemoryView.get_mode(axes) 622 self.writable_needed = False 623 624 if not self.dtype.is_fused: 625 self.dtype_name = Buffer.mangle_dtype_name(self.dtype) 626 627 def __hash__(self): 628 return hash(self.__class__) ^ hash(self.dtype) ^ hash(tuple(self.axes)) 629 630 def __eq__(self, other): 631 if isinstance(other, BaseType): 632 return self.same_as_resolved_type(other) 633 else: 634 return False 635 636 def same_as_resolved_type(self, other_type): 637 return ((other_type.is_memoryviewslice and 638 #self.writable_needed == other_type.writable_needed and # FIXME: should be only uni-directional 639 self.dtype.same_as(other_type.dtype) and 640 self.axes == other_type.axes) or 641 other_type is error_type) 642 643 def needs_nonecheck(self): 644 return True 645 646 def is_complete(self): 647 # incomplete since the underlying struct doesn't have a cython.memoryview object. 648 return 0 649 650 def declaration_code(self, entity_code, 651 for_display = 0, dll_linkage = None, pyrex = 0): 652 # XXX: we put these guards in for now... 653 assert not pyrex 654 assert not dll_linkage 655 from . import MemoryView 656 base_code = str(self) if for_display else MemoryView.memviewslice_cname 657 return self.base_declaration_code( 658 base_code, 659 entity_code) 660 661 def attributes_known(self): 662 if self.scope is None: 663 from . import Symtab 664 665 self.scope = scope = Symtab.CClassScope( 666 'mvs_class_'+self.specialization_suffix(), 667 None, 668 visibility='extern') 669 670 scope.parent_type = self 671 scope.directives = {} 672 673 scope.declare_var('_data', c_char_ptr_type, None, 674 cname='data', is_cdef=1) 675 676 return True 677 678 def declare_attribute(self, attribute, env, pos): 679 from . import MemoryView, Options 680 681 scope = self.scope 682 683 if attribute == 'shape': 684 scope.declare_var('shape', 685 c_array_type(c_py_ssize_t_type, 686 Options.buffer_max_dims), 687 pos, 688 cname='shape', 689 is_cdef=1) 690 691 elif attribute == 'strides': 692 scope.declare_var('strides', 693 c_array_type(c_py_ssize_t_type, 694 Options.buffer_max_dims), 695 pos, 696 cname='strides', 697 is_cdef=1) 698 699 elif attribute == 'suboffsets': 700 scope.declare_var('suboffsets', 701 c_array_type(c_py_ssize_t_type, 702 Options.buffer_max_dims), 703 pos, 704 cname='suboffsets', 705 is_cdef=1) 706 707 elif attribute in ("copy", "copy_fortran"): 708 ndim = len(self.axes) 709 710 follow_dim = [('direct', 'follow')] 711 contig_dim = [('direct', 'contig')] 712 to_axes_c = follow_dim * (ndim - 1) + contig_dim 713 to_axes_f = contig_dim + follow_dim * (ndim -1) 714 715 dtype = self.dtype 716 if dtype.is_const: 717 dtype = dtype.const_base_type 718 719 to_memview_c = MemoryViewSliceType(dtype, to_axes_c) 720 to_memview_f = MemoryViewSliceType(dtype, to_axes_f) 721 722 for to_memview, cython_name in [(to_memview_c, "copy"), 723 (to_memview_f, "copy_fortran")]: 724 copy_func_type = CFuncType( 725 to_memview, 726 [CFuncTypeArg("memviewslice", self, None)]) 727 copy_cname = MemoryView.copy_c_or_fortran_cname(to_memview) 728 729 entry = scope.declare_cfunction( 730 cython_name, 731 copy_func_type, pos=pos, defining=1, 732 cname=copy_cname) 733 734 utility = MemoryView.get_copy_new_utility(pos, self, to_memview) 735 env.use_utility_code(utility) 736 737 MemoryView.use_cython_array_utility_code(env) 738 739 elif attribute in ("is_c_contig", "is_f_contig"): 740 # is_c_contig and is_f_contig functions 741 for (c_or_f, cython_name) in (('C', 'is_c_contig'), ('F', 'is_f_contig')): 742 743 is_contig_name = MemoryView.get_is_contig_func_name(c_or_f, self.ndim) 744 745 cfunctype = CFuncType( 746 return_type=c_bint_type, 747 args=[CFuncTypeArg("memviewslice", self, None)], 748 exception_value="-1", 749 ) 750 751 entry = scope.declare_cfunction(cython_name, 752 cfunctype, 753 pos=pos, 754 defining=1, 755 cname=is_contig_name) 756 757 entry.utility_code_definition = MemoryView.get_is_contig_utility(c_or_f, self.ndim) 758 759 return True 760 761 def get_entry(self, node, cname=None, type=None): 762 from . import MemoryView, Symtab 763 764 if cname is None: 765 assert node.is_simple() or node.is_temp or node.is_elemental 766 cname = node.result() 767 768 if type is None: 769 type = node.type 770 771 entry = Symtab.Entry(cname, cname, type, node.pos) 772 return MemoryView.MemoryViewSliceBufferEntry(entry) 773 774 def conforms_to(self, dst, broadcast=False, copying=False): 775 """ 776 Returns True if src conforms to dst, False otherwise. 777 778 If conformable, the types are the same, the ndims are equal, and each axis spec is conformable. 779 780 Any packing/access spec is conformable to itself. 781 782 'direct' and 'ptr' are conformable to 'full'. 783 'contig' and 'follow' are conformable to 'strided'. 784 Any other combo is not conformable. 785 """ 786 from . import MemoryView 787 788 src = self 789 790 #if not copying and self.writable_needed and not dst.writable_needed: 791 # return False 792 793 src_dtype, dst_dtype = src.dtype, dst.dtype 794 if dst_dtype.is_const: 795 # Requesting read-only views is always ok => consider only the non-const base type. 796 dst_dtype = dst_dtype.const_base_type 797 if src_dtype.is_const: 798 # When assigning between read-only views, compare only the non-const base types. 799 src_dtype = src_dtype.const_base_type 800 elif copying and src_dtype.is_const: 801 # Copying by value => ignore const on source. 802 src_dtype = src_dtype.const_base_type 803 804 if src_dtype != dst_dtype: 805 return False 806 807 if src.ndim != dst.ndim: 808 if broadcast: 809 src, dst = MemoryView.broadcast_types(src, dst) 810 else: 811 return False 812 813 for src_spec, dst_spec in zip(src.axes, dst.axes): 814 src_access, src_packing = src_spec 815 dst_access, dst_packing = dst_spec 816 if src_access != dst_access and dst_access != 'full': 817 return False 818 if src_packing != dst_packing and dst_packing != 'strided' and not copying: 819 return False 820 821 return True 822 823 def valid_dtype(self, dtype, i=0): 824 """ 825 Return whether type dtype can be used as the base type of a 826 memoryview slice. 827 828 We support structs, numeric types and objects 829 """ 830 if dtype.is_complex and dtype.real_type.is_int: 831 return False 832 833 if dtype.is_struct and dtype.kind == 'struct': 834 for member in dtype.scope.var_entries: 835 if not self.valid_dtype(member.type): 836 return False 837 838 return True 839 840 return ( 841 dtype.is_error or 842 # Pointers are not valid (yet) 843 # (dtype.is_ptr and valid_memslice_dtype(dtype.base_type)) or 844 (dtype.is_array and i < 8 and self.valid_dtype(dtype.base_type, i + 1)) or 845 dtype.is_numeric or 846 dtype.is_pyobject or 847 dtype.is_fused or # accept this as it will be replaced by specializations later 848 (dtype.is_typedef and self.valid_dtype(dtype.typedef_base_type)) 849 ) 850 851 def validate_memslice_dtype(self, pos): 852 if not self.valid_dtype(self.dtype): 853 error(pos, "Invalid base type for memoryview slice: %s" % self.dtype) 854 855 def assert_direct_dims(self, pos): 856 for access, packing in self.axes: 857 if access != 'direct': 858 error(pos, "All dimensions must be direct") 859 return False 860 return True 861 862 def transpose(self, pos): 863 if not self.assert_direct_dims(pos): 864 return error_type 865 return MemoryViewSliceType(self.dtype, self.axes[::-1]) 866 867 def specialization_name(self): 868 return '%s_%s' % ( 869 super(MemoryViewSliceType,self).specialization_name(), 870 self.specialization_suffix()) 871 872 def specialization_suffix(self): 873 return "%s_%s" % (self.axes_to_name(), self.dtype_name) 874 875 def can_coerce_to_pyobject(self, env): 876 return True 877 878 def can_coerce_from_pyobject(self, env): 879 return True 880 881 def check_for_null_code(self, cname): 882 return cname + '.memview' 883 884 def create_from_py_utility_code(self, env): 885 from . import MemoryView, Buffer 886 887 # We don't have 'code', so use a LazyUtilityCode with a callback. 888 def lazy_utility_callback(code): 889 context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype) 890 return TempitaUtilityCode.load( 891 "ObjectToMemviewSlice", "MemoryView_C.c", context=context) 892 893 env.use_utility_code(MemoryView.memviewslice_init_code) 894 env.use_utility_code(LazyUtilityCode(lazy_utility_callback)) 895 896 if self.is_c_contig: 897 c_or_f_flag = "__Pyx_IS_C_CONTIG" 898 elif self.is_f_contig: 899 c_or_f_flag = "__Pyx_IS_F_CONTIG" 900 else: 901 c_or_f_flag = "0" 902 903 suffix = self.specialization_suffix() 904 funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix 905 906 context = dict( 907 MemoryView.context, 908 buf_flag = self.flags, 909 ndim = self.ndim, 910 axes_specs = ', '.join(self.axes_to_code()), 911 dtype_typedecl = self.dtype.empty_declaration_code(), 912 struct_nesting_depth = self.dtype.struct_nesting_depth(), 913 c_or_f_flag = c_or_f_flag, 914 funcname = funcname, 915 ) 916 917 self.from_py_function = funcname 918 return True 919 920 def from_py_call_code(self, source_code, result_code, error_pos, code, 921 from_py_function=None, error_condition=None): 922 # NOTE: auto-detection of readonly buffers is disabled: 923 # writable = self.writable_needed or not self.dtype.is_const 924 writable = not self.dtype.is_const 925 return self._assign_from_py_code( 926 source_code, result_code, error_pos, code, from_py_function, error_condition, 927 extra_args=['PyBUF_WRITABLE' if writable else '0']) 928 929 def create_to_py_utility_code(self, env): 930 self._dtype_to_py_func, self._dtype_from_py_func = self.dtype_object_conversion_funcs(env) 931 return True 932 933 def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None): 934 assert self._dtype_to_py_func 935 assert self._dtype_from_py_func 936 937 to_py_func = "(PyObject *(*)(char *)) " + self._dtype_to_py_func 938 from_py_func = "(int (*)(char *, PyObject *)) " + self._dtype_from_py_func 939 940 tup = (result_code, source_code, self.ndim, to_py_func, from_py_func, self.dtype.is_pyobject) 941 return "%s = __pyx_memoryview_fromslice(%s, %s, %s, %s, %d);" % tup 942 943 def dtype_object_conversion_funcs(self, env): 944 get_function = "__pyx_memview_get_%s" % self.dtype_name 945 set_function = "__pyx_memview_set_%s" % self.dtype_name 946 947 context = dict( 948 get_function = get_function, 949 set_function = set_function, 950 ) 951 952 if self.dtype.is_pyobject: 953 utility_name = "MemviewObjectToObject" 954 else: 955 self.dtype.create_to_py_utility_code(env) 956 to_py_function = self.dtype.to_py_function 957 958 from_py_function = None 959 if not self.dtype.is_const: 960 self.dtype.create_from_py_utility_code(env) 961 from_py_function = self.dtype.from_py_function 962 963 if not (to_py_function or from_py_function): 964 return "NULL", "NULL" 965 if not to_py_function: 966 get_function = "NULL" 967 if not from_py_function: 968 set_function = "NULL" 969 970 utility_name = "MemviewDtypeToObject" 971 error_condition = (self.dtype.error_condition('value') or 972 'PyErr_Occurred()') 973 context.update( 974 to_py_function=to_py_function, 975 from_py_function=from_py_function, 976 dtype=self.dtype.empty_declaration_code(), 977 error_condition=error_condition, 978 ) 979 980 utility = TempitaUtilityCode.load_cached( 981 utility_name, "MemoryView_C.c", context=context) 982 env.use_utility_code(utility) 983 return get_function, set_function 984 985 def axes_to_code(self): 986 """Return a list of code constants for each axis""" 987 from . import MemoryView 988 d = MemoryView._spec_to_const 989 return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes] 990 991 def axes_to_name(self): 992 """Return an abbreviated name for our axes""" 993 from . import MemoryView 994 d = MemoryView._spec_to_abbrev 995 return "".join(["%s%s" % (d[a], d[p]) for a, p in self.axes]) 996 997 def error_condition(self, result_code): 998 return "!%s.memview" % result_code 999 1000 def __str__(self): 1001 from . import MemoryView 1002 1003 axes_code_list = [] 1004 for idx, (access, packing) in enumerate(self.axes): 1005 flag = MemoryView.get_memoryview_flag(access, packing) 1006 if flag == "strided": 1007 axes_code_list.append(":") 1008 else: 1009 if flag == 'contiguous': 1010 have_follow = [p for a, p in self.axes[idx - 1:idx + 2] 1011 if p == 'follow'] 1012 if have_follow or self.ndim == 1: 1013 flag = '1' 1014 1015 axes_code_list.append("::" + flag) 1016 1017 if self.dtype.is_pyobject: 1018 dtype_name = self.dtype.name 1019 else: 1020 dtype_name = self.dtype 1021 1022 return "%s[%s]" % (dtype_name, ", ".join(axes_code_list)) 1023 1024 def specialize(self, values): 1025 """This does not validate the base type!!""" 1026 dtype = self.dtype.specialize(values) 1027 if dtype is not self.dtype: 1028 return MemoryViewSliceType(dtype, self.axes) 1029 1030 return self 1031 1032 def cast_code(self, expr_code): 1033 return expr_code 1034 1035 1036class BufferType(BaseType): 1037 # 1038 # Delegates most attribute lookups to the base type. 1039 # (Anything not defined here or in the BaseType is delegated.) 1040 # 1041 # dtype PyrexType 1042 # ndim int 1043 # mode str 1044 # negative_indices bool 1045 # cast bool 1046 # is_buffer bool 1047 # writable bool 1048 1049 is_buffer = 1 1050 writable = True 1051 1052 subtypes = ['dtype'] 1053 1054 def __init__(self, base, dtype, ndim, mode, negative_indices, cast): 1055 self.base = base 1056 self.dtype = dtype 1057 self.ndim = ndim 1058 self.buffer_ptr_type = CPtrType(dtype) 1059 self.mode = mode 1060 self.negative_indices = negative_indices 1061 self.cast = cast 1062 self.is_numpy_buffer = self.base.name == "ndarray" 1063 1064 def can_coerce_to_pyobject(self,env): 1065 return True 1066 1067 def can_coerce_from_pyobject(self,env): 1068 return True 1069 1070 def as_argument_type(self): 1071 return self 1072 1073 def specialize(self, values): 1074 dtype = self.dtype.specialize(values) 1075 if dtype is not self.dtype: 1076 return BufferType(self.base, dtype, self.ndim, self.mode, 1077 self.negative_indices, self.cast) 1078 return self 1079 1080 def get_entry(self, node): 1081 from . import Buffer 1082 assert node.is_name 1083 return Buffer.BufferEntry(node.entry) 1084 1085 def __getattr__(self, name): 1086 return getattr(self.base, name) 1087 1088 def __repr__(self): 1089 return "<BufferType %r>" % self.base 1090 1091 def __str__(self): 1092 # avoid ', ', as fused functions split the signature string on ', ' 1093 cast_str = '' 1094 if self.cast: 1095 cast_str = ',cast=True' 1096 1097 return "%s[%s,ndim=%d%s]" % (self.base, self.dtype, self.ndim, 1098 cast_str) 1099 1100 def assignable_from(self, other_type): 1101 if other_type.is_buffer: 1102 return (self.same_as(other_type, compare_base=False) and 1103 self.base.assignable_from(other_type.base)) 1104 1105 return self.base.assignable_from(other_type) 1106 1107 def same_as(self, other_type, compare_base=True): 1108 if not other_type.is_buffer: 1109 return other_type.same_as(self.base) 1110 1111 return (self.dtype.same_as(other_type.dtype) and 1112 self.ndim == other_type.ndim and 1113 self.mode == other_type.mode and 1114 self.cast == other_type.cast and 1115 (not compare_base or self.base.same_as(other_type.base))) 1116 1117 1118class PyObjectType(PyrexType): 1119 # 1120 # Base class for all Python object types (reference-counted). 1121 # 1122 # buffer_defaults dict or None Default options for bu 1123 1124 name = "object" 1125 is_pyobject = 1 1126 default_value = "0" 1127 declaration_value = "0" 1128 buffer_defaults = None 1129 is_extern = False 1130 is_subclassed = False 1131 is_gc_simple = False 1132 1133 def __str__(self): 1134 return "Python object" 1135 1136 def __repr__(self): 1137 return "<PyObjectType>" 1138 1139 def can_coerce_to_pyobject(self, env): 1140 return True 1141 1142 def can_coerce_from_pyobject(self, env): 1143 return True 1144 1145 def default_coerced_ctype(self): 1146 """The default C type that this Python type coerces to, or None.""" 1147 return None 1148 1149 def assignable_from(self, src_type): 1150 # except for pointers, conversion will be attempted 1151 return not src_type.is_ptr or src_type.is_string or src_type.is_pyunicode_ptr 1152 1153 def declaration_code(self, entity_code, 1154 for_display = 0, dll_linkage = None, pyrex = 0): 1155 if pyrex or for_display: 1156 base_code = "object" 1157 else: 1158 base_code = public_decl("PyObject", dll_linkage) 1159 entity_code = "*%s" % entity_code 1160 return self.base_declaration_code(base_code, entity_code) 1161 1162 def as_pyobject(self, cname): 1163 if (not self.is_complete()) or self.is_extension_type: 1164 return "(PyObject *)" + cname 1165 else: 1166 return cname 1167 1168 def py_type_name(self): 1169 return "object" 1170 1171 def __lt__(self, other): 1172 """ 1173 Make sure we sort highest, as instance checking on py_type_name 1174 ('object') is always true 1175 """ 1176 return False 1177 1178 def global_init_code(self, entry, code): 1179 code.put_init_var_to_py_none(entry, nanny=False) 1180 1181 def check_for_null_code(self, cname): 1182 return cname 1183 1184 1185builtin_types_that_cannot_create_refcycles = set([ 1186 'bool', 'int', 'long', 'float', 'complex', 1187 'bytearray', 'bytes', 'unicode', 'str', 'basestring' 1188]) 1189 1190 1191class BuiltinObjectType(PyObjectType): 1192 # objstruct_cname string Name of PyObject struct 1193 1194 is_builtin_type = 1 1195 has_attributes = 1 1196 base_type = None 1197 module_name = '__builtin__' 1198 require_exact = 1 1199 1200 # fields that let it look like an extension type 1201 vtabslot_cname = None 1202 vtabstruct_cname = None 1203 vtabptr_cname = None 1204 typedef_flag = True 1205 is_external = True 1206 decl_type = 'PyObject' 1207 1208 def __init__(self, name, cname, objstruct_cname=None): 1209 self.name = name 1210 self.cname = cname 1211 self.typeptr_cname = "(&%s)" % cname 1212 self.objstruct_cname = objstruct_cname 1213 self.is_gc_simple = name in builtin_types_that_cannot_create_refcycles 1214 if name == 'type': 1215 # Special case the type type, as many C API calls (and other 1216 # libraries) actually expect a PyTypeObject* for type arguments. 1217 self.decl_type = objstruct_cname 1218 if name == 'Exception': 1219 self.require_exact = 0 1220 1221 def set_scope(self, scope): 1222 self.scope = scope 1223 if scope: 1224 scope.parent_type = self 1225 1226 def __str__(self): 1227 return "%s object" % self.name 1228 1229 def __repr__(self): 1230 return "<%s>"% self.cname 1231 1232 def default_coerced_ctype(self): 1233 if self.name in ('bytes', 'bytearray'): 1234 return c_char_ptr_type 1235 elif self.name == 'bool': 1236 return c_bint_type 1237 elif self.name == 'float': 1238 return c_double_type 1239 return None 1240 1241 def assignable_from(self, src_type): 1242 if isinstance(src_type, BuiltinObjectType): 1243 if self.name == 'basestring': 1244 return src_type.name in ('str', 'unicode', 'basestring') 1245 else: 1246 return src_type.name == self.name 1247 elif src_type.is_extension_type: 1248 # FIXME: This is an ugly special case that we currently 1249 # keep supporting. It allows users to specify builtin 1250 # types as external extension types, while keeping them 1251 # compatible with the real builtin types. We already 1252 # generate a warning for it. Big TODO: remove! 1253 return (src_type.module_name == '__builtin__' and 1254 src_type.name == self.name) 1255 else: 1256 return True 1257 1258 def typeobj_is_available(self): 1259 return True 1260 1261 def attributes_known(self): 1262 return True 1263 1264 def subtype_of(self, type): 1265 return type.is_pyobject and type.assignable_from(self) 1266 1267 def type_check_function(self, exact=True): 1268 type_name = self.name 1269 if type_name == 'str': 1270 type_check = 'PyString_Check' 1271 elif type_name == 'basestring': 1272 type_check = '__Pyx_PyBaseString_Check' 1273 elif type_name == 'Exception': 1274 type_check = '__Pyx_PyException_Check' 1275 elif type_name == 'bytearray': 1276 type_check = 'PyByteArray_Check' 1277 elif type_name == 'frozenset': 1278 type_check = 'PyFrozenSet_Check' 1279 else: 1280 type_check = 'Py%s_Check' % type_name.capitalize() 1281 if exact and type_name not in ('bool', 'slice', 'Exception'): 1282 type_check += 'Exact' 1283 return type_check 1284 1285 def isinstance_code(self, arg): 1286 return '%s(%s)' % (self.type_check_function(exact=False), arg) 1287 1288 def type_test_code(self, arg, notnone=False, exact=True): 1289 type_check = self.type_check_function(exact=exact) 1290 check = 'likely(%s(%s))' % (type_check, arg) 1291 if not notnone: 1292 check += '||((%s) == Py_None)' % arg 1293 if self.name == 'basestring': 1294 name = '(PY_MAJOR_VERSION < 3 ? "basestring" : "str")' 1295 space_for_name = 16 1296 else: 1297 name = '"%s"' % self.name 1298 # avoid wasting too much space but limit number of different format strings 1299 space_for_name = (len(self.name) // 16 + 1) * 16 1300 error = '(PyErr_Format(PyExc_TypeError, "Expected %%.%ds, got %%.200s", %s, Py_TYPE(%s)->tp_name), 0)' % ( 1301 space_for_name, name, arg) 1302 return check + '||' + error 1303 1304 def declaration_code(self, entity_code, 1305 for_display = 0, dll_linkage = None, pyrex = 0): 1306 if pyrex or for_display: 1307 base_code = self.name 1308 else: 1309 base_code = public_decl(self.decl_type, dll_linkage) 1310 entity_code = "*%s" % entity_code 1311 return self.base_declaration_code(base_code, entity_code) 1312 1313 def as_pyobject(self, cname): 1314 if self.decl_type == 'PyObject': 1315 return cname 1316 else: 1317 return "(PyObject *)" + cname 1318 1319 def cast_code(self, expr_code, to_object_struct = False): 1320 return "((%s*)%s)" % ( 1321 to_object_struct and self.objstruct_cname or self.decl_type, # self.objstruct_cname may be None 1322 expr_code) 1323 1324 def py_type_name(self): 1325 return self.name 1326 1327 1328 1329class PyExtensionType(PyObjectType): 1330 # 1331 # A Python extension type. 1332 # 1333 # name string 1334 # scope CClassScope Attribute namespace 1335 # visibility string 1336 # typedef_flag boolean 1337 # base_type PyExtensionType or None 1338 # module_name string or None Qualified name of defining module 1339 # objstruct_cname string Name of PyObject struct 1340 # objtypedef_cname string Name of PyObject struct typedef 1341 # typeobj_cname string or None C code fragment referring to type object 1342 # typeptr_cname string or None Name of pointer to external type object 1343 # vtabslot_cname string Name of C method table member 1344 # vtabstruct_cname string Name of C method table struct 1345 # vtabptr_cname string Name of pointer to C method table 1346 # vtable_cname string Name of C method table definition 1347 # early_init boolean Whether to initialize early (as opposed to during module execution). 1348 # defered_declarations [thunk] Used to declare class hierarchies in order 1349 # check_size 'warn', 'error', 'ignore' What to do if tp_basicsize does not match 1350 1351 is_extension_type = 1 1352 has_attributes = 1 1353 early_init = 1 1354 1355 objtypedef_cname = None 1356 1357 def __init__(self, name, typedef_flag, base_type, is_external=0, check_size=None): 1358 self.name = name 1359 self.scope = None 1360 self.typedef_flag = typedef_flag 1361 if base_type is not None: 1362 base_type.is_subclassed = True 1363 self.base_type = base_type 1364 self.module_name = None 1365 self.objstruct_cname = None 1366 self.typeobj_cname = None 1367 self.typeptr_cname = None 1368 self.vtabslot_cname = None 1369 self.vtabstruct_cname = None 1370 self.vtabptr_cname = None 1371 self.vtable_cname = None 1372 self.is_external = is_external 1373 self.check_size = check_size or 'warn' 1374 self.defered_declarations = [] 1375 1376 def set_scope(self, scope): 1377 self.scope = scope 1378 if scope: 1379 scope.parent_type = self 1380 1381 def needs_nonecheck(self): 1382 return True 1383 1384 def subtype_of_resolved_type(self, other_type): 1385 if other_type.is_extension_type or other_type.is_builtin_type: 1386 return self is other_type or ( 1387 self.base_type and self.base_type.subtype_of(other_type)) 1388 else: 1389 return other_type is py_object_type 1390 1391 def typeobj_is_available(self): 1392 # Do we have a pointer to the type object? 1393 return self.typeptr_cname 1394 1395 def typeobj_is_imported(self): 1396 # If we don't know the C name of the type object but we do 1397 # know which module it's defined in, it will be imported. 1398 return self.typeobj_cname is None and self.module_name is not None 1399 1400 def assignable_from(self, src_type): 1401 if self == src_type: 1402 return True 1403 if isinstance(src_type, PyExtensionType): 1404 if src_type.base_type is not None: 1405 return self.assignable_from(src_type.base_type) 1406 if isinstance(src_type, BuiltinObjectType): 1407 # FIXME: This is an ugly special case that we currently 1408 # keep supporting. It allows users to specify builtin 1409 # types as external extension types, while keeping them 1410 # compatible with the real builtin types. We already 1411 # generate a warning for it. Big TODO: remove! 1412 return (self.module_name == '__builtin__' and 1413 self.name == src_type.name) 1414 return False 1415 1416 def declaration_code(self, entity_code, 1417 for_display = 0, dll_linkage = None, pyrex = 0, deref = 0): 1418 if pyrex or for_display: 1419 base_code = self.name 1420 else: 1421 if self.typedef_flag: 1422 objstruct = self.objstruct_cname 1423 else: 1424 objstruct = "struct %s" % self.objstruct_cname 1425 base_code = public_decl(objstruct, dll_linkage) 1426 if deref: 1427 assert not entity_code 1428 else: 1429 entity_code = "*%s" % entity_code 1430 return self.base_declaration_code(base_code, entity_code) 1431 1432 def type_test_code(self, py_arg, notnone=False): 1433 1434 none_check = "((%s) == Py_None)" % py_arg 1435 type_check = "likely(__Pyx_TypeTest(%s, %s))" % ( 1436 py_arg, self.typeptr_cname) 1437 if notnone: 1438 return type_check 1439 else: 1440 return "likely(%s || %s)" % (none_check, type_check) 1441 1442 def attributes_known(self): 1443 return self.scope is not None 1444 1445 def __str__(self): 1446 return self.name 1447 1448 def __repr__(self): 1449 return "<PyExtensionType %s%s>" % (self.scope.class_name, 1450 ("", " typedef")[self.typedef_flag]) 1451 1452 def py_type_name(self): 1453 if not self.module_name: 1454 return self.name 1455 1456 return "__import__(%r, None, None, ['']).%s" % (self.module_name, 1457 self.name) 1458 1459class CType(PyrexType): 1460 # 1461 # Base class for all C types (non-reference-counted). 1462 # 1463 # to_py_function string C function for converting to Python object 1464 # from_py_function string C function for constructing from Python object 1465 # 1466 1467 to_py_function = None 1468 from_py_function = None 1469 exception_value = None 1470 exception_check = 1 1471 1472 def create_to_py_utility_code(self, env): 1473 return self.to_py_function is not None 1474 1475 def create_from_py_utility_code(self, env): 1476 return self.from_py_function is not None 1477 1478 def can_coerce_to_pyobject(self, env): 1479 return self.create_to_py_utility_code(env) 1480 1481 def can_coerce_from_pyobject(self, env): 1482 return self.create_from_py_utility_code(env) 1483 1484 def error_condition(self, result_code): 1485 conds = [] 1486 if self.is_string or self.is_pyunicode_ptr: 1487 conds.append("(!%s)" % result_code) 1488 elif self.exception_value is not None: 1489 conds.append("(%s == (%s)%s)" % (result_code, self.sign_and_name(), self.exception_value)) 1490 if self.exception_check: 1491 conds.append("PyErr_Occurred()") 1492 if len(conds) > 0: 1493 return " && ".join(conds) 1494 else: 1495 return 0 1496 1497 def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None): 1498 func = self.to_py_function if to_py_function is None else to_py_function 1499 assert func 1500 if self.is_string or self.is_cpp_string: 1501 if result_type.is_builtin_type: 1502 result_type_name = result_type.name 1503 if result_type_name in ('bytes', 'str', 'unicode'): 1504 func = func.replace("Object", result_type_name.title(), 1) 1505 elif result_type_name == 'bytearray': 1506 func = func.replace("Object", "ByteArray", 1) 1507 return '%s = %s(%s)' % ( 1508 result_code, 1509 func, 1510 source_code or 'NULL') 1511 1512 def from_py_call_code(self, source_code, result_code, error_pos, code, 1513 from_py_function=None, error_condition=None): 1514 return self._assign_from_py_code( 1515 source_code, result_code, error_pos, code, from_py_function, error_condition) 1516 1517 1518 1519class PythranExpr(CType): 1520 # Pythran object of a given type 1521 1522 to_py_function = "__Pyx_pythran_to_python" 1523 is_pythran_expr = True 1524 writable = True 1525 has_attributes = 1 1526 1527 def __init__(self, pythran_type, org_buffer=None): 1528 self.org_buffer = org_buffer 1529 self.pythran_type = pythran_type 1530 self.name = self.pythran_type 1531 self.cname = self.pythran_type 1532 self.from_py_function = "from_python<%s>" % (self.pythran_type) 1533 self.scope = None 1534 1535 def declaration_code(self, entity_code, for_display=0, dll_linkage=None, pyrex=0): 1536 assert not pyrex 1537 return "%s %s" % (self.cname, entity_code) 1538 1539 def attributes_known(self): 1540 if self.scope is None: 1541 from . import Symtab 1542 # FIXME: fake C scope, might be better represented by a struct or C++ class scope 1543 self.scope = scope = Symtab.CClassScope('', None, visibility="extern") 1544 scope.parent_type = self 1545 scope.directives = {} 1546 scope.declare_var("shape", CPtrType(c_long_type), None, cname="_shape", is_cdef=True) 1547 scope.declare_var("ndim", c_long_type, None, cname="value", is_cdef=True) 1548 1549 return True 1550 1551 def __eq__(self, other): 1552 return isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type 1553 1554 def __ne__(self, other): 1555 return not (isinstance(other, PythranExpr) and self.pythran_type == other.pythran_type) 1556 1557 def __hash__(self): 1558 return hash(self.pythran_type) 1559 1560 1561class CConstType(BaseType): 1562 1563 is_const = 1 1564 1565 def __init__(self, const_base_type): 1566 self.const_base_type = const_base_type 1567 if const_base_type.has_attributes and const_base_type.scope is not None: 1568 from . import Symtab 1569 self.scope = Symtab.CConstScope(const_base_type.scope) 1570 1571 def __repr__(self): 1572 return "<CConstType %s>" % repr(self.const_base_type) 1573 1574 def __str__(self): 1575 return self.declaration_code("", for_display=1) 1576 1577 def declaration_code(self, entity_code, 1578 for_display = 0, dll_linkage = None, pyrex = 0): 1579 if for_display or pyrex: 1580 return "const " + self.const_base_type.declaration_code(entity_code, for_display, dll_linkage, pyrex) 1581 else: 1582 return self.const_base_type.declaration_code("const %s" % entity_code, for_display, dll_linkage, pyrex) 1583 1584 def specialize(self, values): 1585 base_type = self.const_base_type.specialize(values) 1586 if base_type == self.const_base_type: 1587 return self 1588 else: 1589 return CConstType(base_type) 1590 1591 def deduce_template_params(self, actual): 1592 return self.const_base_type.deduce_template_params(actual) 1593 1594 def can_coerce_to_pyobject(self, env): 1595 return self.const_base_type.can_coerce_to_pyobject(env) 1596 1597 def can_coerce_from_pyobject(self, env): 1598 return self.const_base_type.can_coerce_from_pyobject(env) 1599 1600 def create_to_py_utility_code(self, env): 1601 if self.const_base_type.create_to_py_utility_code(env): 1602 self.to_py_function = self.const_base_type.to_py_function 1603 return True 1604 1605 def same_as_resolved_type(self, other_type): 1606 if other_type.is_const: 1607 return self.const_base_type.same_as_resolved_type(other_type.const_base_type) 1608 # Accept const LHS <- non-const RHS. 1609 return self.const_base_type.same_as_resolved_type(other_type) 1610 1611 def __getattr__(self, name): 1612 return getattr(self.const_base_type, name) 1613 1614 1615class FusedType(CType): 1616 """ 1617 Represents a Fused Type. All it needs to do is keep track of the types 1618 it aggregates, as it will be replaced with its specific version wherever 1619 needed. 1620 1621 See http://wiki.cython.org/enhancements/fusedtypes 1622 1623 types [PyrexType] is the list of types to be fused 1624 name str the name of the ctypedef 1625 """ 1626 1627 is_fused = 1 1628 exception_check = 0 1629 1630 def __init__(self, types, name=None): 1631 # Use list rather than set to preserve order (list should be short). 1632 flattened_types = [] 1633 for t in types: 1634 if t.is_fused: 1635 # recursively merge in subtypes 1636 for subtype in t.types: 1637 if subtype not in flattened_types: 1638 flattened_types.append(subtype) 1639 elif t not in flattened_types: 1640 flattened_types.append(t) 1641 self.types = flattened_types 1642 self.name = name 1643 1644 def declaration_code(self, entity_code, for_display = 0, 1645 dll_linkage = None, pyrex = 0): 1646 if pyrex or for_display: 1647 return self.name 1648 1649 raise Exception("This may never happen, please report a bug") 1650 1651 def __repr__(self): 1652 return 'FusedType(name=%r)' % self.name 1653 1654 def specialize(self, values): 1655 return values[self] 1656 1657 def get_fused_types(self, result=None, seen=None): 1658 if result is None: 1659 return [self] 1660 1661 if self not in seen: 1662 result.append(self) 1663 seen.add(self) 1664 1665 1666class CVoidType(CType): 1667 # 1668 # C "void" type 1669 # 1670 1671 is_void = 1 1672 to_py_function = "__Pyx_void_to_None" 1673 1674 def __repr__(self): 1675 return "<CVoidType>" 1676 1677 def declaration_code(self, entity_code, 1678 for_display = 0, dll_linkage = None, pyrex = 0): 1679 if pyrex or for_display: 1680 base_code = "void" 1681 else: 1682 base_code = public_decl("void", dll_linkage) 1683 return self.base_declaration_code(base_code, entity_code) 1684 1685 def is_complete(self): 1686 return 0 1687 1688class InvisibleVoidType(CVoidType): 1689 # 1690 # For use with C++ constructors and destructors return types. 1691 # Acts like void, but does not print out a declaration. 1692 # 1693 def declaration_code(self, entity_code, 1694 for_display = 0, dll_linkage = None, pyrex = 0): 1695 if pyrex or for_display: 1696 base_code = "[void]" 1697 else: 1698 base_code = public_decl("", dll_linkage) 1699 return self.base_declaration_code(base_code, entity_code) 1700 1701 1702class CNumericType(CType): 1703 # 1704 # Base class for all C numeric types. 1705 # 1706 # rank integer Relative size 1707 # signed integer 0 = unsigned, 1 = unspecified, 2 = explicitly signed 1708 # 1709 1710 is_numeric = 1 1711 default_value = "0" 1712 has_attributes = True 1713 scope = None 1714 1715 sign_words = ("unsigned ", "", "signed ") 1716 1717 def __init__(self, rank, signed = 1): 1718 self.rank = rank 1719 if rank > 0 and signed == SIGNED: 1720 # Signed is meaningless for anything but char, and complicates 1721 # type promotion. 1722 signed = 1 1723 self.signed = signed 1724 1725 def sign_and_name(self): 1726 s = self.sign_words[self.signed] 1727 n = rank_to_type_name[self.rank] 1728 return s + n 1729 1730 def __repr__(self): 1731 return "<CNumericType %s>" % self.sign_and_name() 1732 1733 def declaration_code(self, entity_code, 1734 for_display = 0, dll_linkage = None, pyrex = 0): 1735 type_name = self.sign_and_name() 1736 if pyrex or for_display: 1737 base_code = type_name.replace('PY_LONG_LONG', 'long long') 1738 else: 1739 base_code = public_decl(type_name, dll_linkage) 1740 return self.base_declaration_code(base_code, entity_code) 1741 1742 def attributes_known(self): 1743 if self.scope is None: 1744 from . import Symtab 1745 self.scope = scope = Symtab.CClassScope( 1746 '', 1747 None, 1748 visibility="extern") 1749 scope.parent_type = self 1750 scope.directives = {} 1751 scope.declare_cfunction( 1752 "conjugate", 1753 CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True), 1754 pos=None, 1755 defining=1, 1756 cname=" ") 1757 return True 1758 1759 def __lt__(self, other): 1760 """Sort based on rank, preferring signed over unsigned""" 1761 if other.is_numeric: 1762 return self.rank > other.rank and self.signed >= other.signed 1763 1764 # Prefer numeric types over others 1765 return True 1766 1767 def py_type_name(self): 1768 if self.rank <= 4: 1769 return "(int, long)" 1770 return "float" 1771 1772 1773class ForbidUseClass: 1774 def __repr__(self): 1775 raise RuntimeError() 1776 def __str__(self): 1777 raise RuntimeError() 1778ForbidUse = ForbidUseClass() 1779 1780 1781class CIntLike(object): 1782 """Mixin for shared behaviour of C integers and enums. 1783 """ 1784 to_py_function = None 1785 from_py_function = None 1786 to_pyunicode_utility = None 1787 default_format_spec = 'd' 1788 1789 def can_coerce_to_pyobject(self, env): 1790 return True 1791 1792 def can_coerce_from_pyobject(self, env): 1793 return True 1794 1795 def create_to_py_utility_code(self, env): 1796 if type(self).to_py_function is None: 1797 self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name() 1798 env.use_utility_code(TempitaUtilityCode.load_cached( 1799 "CIntToPy", "TypeConversion.c", 1800 context={"TYPE": self.empty_declaration_code(), 1801 "TO_PY_FUNCTION": self.to_py_function})) 1802 return True 1803 1804 def create_from_py_utility_code(self, env): 1805 if type(self).from_py_function is None: 1806 self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name() 1807 env.use_utility_code(TempitaUtilityCode.load_cached( 1808 "CIntFromPy", "TypeConversion.c", 1809 context={"TYPE": self.empty_declaration_code(), 1810 "FROM_PY_FUNCTION": self.from_py_function})) 1811 return True 1812 1813 @staticmethod 1814 def _parse_format(format_spec): 1815 padding = ' ' 1816 if not format_spec: 1817 return ('d', 0, padding) 1818 format_type = format_spec[-1] 1819 if format_type in ('o', 'd', 'x', 'X'): 1820 prefix = format_spec[:-1] 1821 elif format_type.isdigit(): 1822 format_type = 'd' 1823 prefix = format_spec 1824 else: 1825 return (None, 0, padding) 1826 if not prefix: 1827 return (format_type, 0, padding) 1828 if prefix[0] == '-': 1829 prefix = prefix[1:] 1830 if prefix and prefix[0] == '0': 1831 padding = '0' 1832 prefix = prefix.lstrip('0') 1833 if prefix.isdigit(): 1834 return (format_type, int(prefix), padding) 1835 return (None, 0, padding) 1836 1837 def can_coerce_to_pystring(self, env, format_spec=None): 1838 format_type, width, padding = self._parse_format(format_spec) 1839 return format_type is not None and width <= 2**30 1840 1841 def convert_to_pystring(self, cvalue, code, format_spec=None): 1842 if self.to_pyunicode_utility is None: 1843 utility_code_name = "__Pyx_PyUnicode_From_" + self.specialization_name() 1844 to_pyunicode_utility = TempitaUtilityCode.load_cached( 1845 "CIntToPyUnicode", "TypeConversion.c", 1846 context={"TYPE": self.empty_declaration_code(), 1847 "TO_PY_FUNCTION": utility_code_name}) 1848 self.to_pyunicode_utility = (utility_code_name, to_pyunicode_utility) 1849 else: 1850 utility_code_name, to_pyunicode_utility = self.to_pyunicode_utility 1851 code.globalstate.use_utility_code(to_pyunicode_utility) 1852 format_type, width, padding_char = self._parse_format(format_spec) 1853 return "%s(%s, %d, '%s', '%s')" % (utility_code_name, cvalue, width, padding_char, format_type) 1854 1855 1856class CIntType(CIntLike, CNumericType): 1857 1858 is_int = 1 1859 typedef_flag = 0 1860 exception_value = -1 1861 1862 def get_to_py_type_conversion(self): 1863 if self.rank < list(rank_to_type_name).index('int'): 1864 # This assumes sizeof(short) < sizeof(int) 1865 return "PyInt_FromLong" 1866 else: 1867 # Py{Int|Long}_From[Unsigned]Long[Long] 1868 Prefix = "Int" 1869 SignWord = "" 1870 TypeName = "Long" 1871 if not self.signed: 1872 Prefix = "Long" 1873 SignWord = "Unsigned" 1874 if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'): 1875 Prefix = "Long" 1876 TypeName = "LongLong" 1877 return "Py%s_From%s%s" % (Prefix, SignWord, TypeName) 1878 1879 def assignable_from_resolved_type(self, src_type): 1880 return src_type.is_int or src_type.is_enum or src_type is error_type 1881 1882 def invalid_value(self): 1883 if rank_to_type_name[int(self.rank)] == 'char': 1884 return "'?'" 1885 else: 1886 # We do not really know the size of the type, so return 1887 # a 32-bit literal and rely on casting to final type. It will 1888 # be negative for signed ints, which is good. 1889 return "0xbad0bad0" 1890 1891 def overflow_check_binop(self, binop, env, const_rhs=False): 1892 env.use_utility_code(UtilityCode.load("Common", "Overflow.c")) 1893 type = self.empty_declaration_code() 1894 name = self.specialization_name() 1895 if binop == "lshift": 1896 env.use_utility_code(TempitaUtilityCode.load_cached( 1897 "LeftShift", "Overflow.c", 1898 context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed})) 1899 else: 1900 if const_rhs: 1901 binop += "_const" 1902 if type in ('int', 'long', 'long long'): 1903 env.use_utility_code(TempitaUtilityCode.load_cached( 1904 "BaseCaseSigned", "Overflow.c", 1905 context={'INT': type, 'NAME': name})) 1906 elif type in ('unsigned int', 'unsigned long', 'unsigned long long'): 1907 env.use_utility_code(TempitaUtilityCode.load_cached( 1908 "BaseCaseUnsigned", "Overflow.c", 1909 context={'UINT': type, 'NAME': name})) 1910 elif self.rank <= 1: 1911 # sizeof(short) < sizeof(int) 1912 return "__Pyx_%s_%s_no_overflow" % (binop, name) 1913 else: 1914 _load_overflow_base(env) 1915 env.use_utility_code(TempitaUtilityCode.load_cached( 1916 "SizeCheck", "Overflow.c", 1917 context={'TYPE': type, 'NAME': name})) 1918 env.use_utility_code(TempitaUtilityCode.load_cached( 1919 "Binop", "Overflow.c", 1920 context={'TYPE': type, 'NAME': name, 'BINOP': binop})) 1921 return "__Pyx_%s_%s_checking_overflow" % (binop, name) 1922 1923 1924def _load_overflow_base(env): 1925 env.use_utility_code(UtilityCode.load("Common", "Overflow.c")) 1926 for type in ('int', 'long', 'long long'): 1927 env.use_utility_code(TempitaUtilityCode.load_cached( 1928 "BaseCaseSigned", "Overflow.c", 1929 context={'INT': type, 'NAME': type.replace(' ', '_')})) 1930 for type in ('unsigned int', 'unsigned long', 'unsigned long long'): 1931 env.use_utility_code(TempitaUtilityCode.load_cached( 1932 "BaseCaseUnsigned", "Overflow.c", 1933 context={'UINT': type, 'NAME': type.replace(' ', '_')})) 1934 1935 1936class CAnonEnumType(CIntType): 1937 1938 is_enum = 1 1939 1940 def sign_and_name(self): 1941 return 'int' 1942 1943 1944class CReturnCodeType(CIntType): 1945 1946 to_py_function = "__Pyx_Owned_Py_None" 1947 1948 is_returncode = True 1949 exception_check = False 1950 default_format_spec = '' 1951 1952 def can_coerce_to_pystring(self, env, format_spec=None): 1953 return not format_spec 1954 1955 def convert_to_pystring(self, cvalue, code, format_spec=None): 1956 return "__Pyx_NewRef(%s)" % code.globalstate.get_py_string_const(StringEncoding.EncodedString("None")).cname 1957 1958 1959class CBIntType(CIntType): 1960 1961 to_py_function = "__Pyx_PyBool_FromLong" 1962 from_py_function = "__Pyx_PyObject_IsTrue" 1963 exception_check = 1 # for C++ bool 1964 default_format_spec = '' 1965 1966 def can_coerce_to_pystring(self, env, format_spec=None): 1967 return not format_spec or super(CBIntType, self).can_coerce_to_pystring(env, format_spec) 1968 1969 def convert_to_pystring(self, cvalue, code, format_spec=None): 1970 if format_spec: 1971 return super(CBIntType, self).convert_to_pystring(cvalue, code, format_spec) 1972 # NOTE: no caching here as the string constant cnames depend on the current module 1973 utility_code_name = "__Pyx_PyUnicode_FromBInt_" + self.specialization_name() 1974 to_pyunicode_utility = TempitaUtilityCode.load_cached( 1975 "CBIntToPyUnicode", "TypeConversion.c", context={ 1976 "TRUE_CONST": code.globalstate.get_py_string_const(StringEncoding.EncodedString("True")).cname, 1977 "FALSE_CONST": code.globalstate.get_py_string_const(StringEncoding.EncodedString("False")).cname, 1978 "TO_PY_FUNCTION": utility_code_name, 1979 }) 1980 code.globalstate.use_utility_code(to_pyunicode_utility) 1981 return "%s(%s)" % (utility_code_name, cvalue) 1982 1983 def declaration_code(self, entity_code, 1984 for_display = 0, dll_linkage = None, pyrex = 0): 1985 if for_display: 1986 base_code = 'bool' 1987 elif pyrex: 1988 base_code = 'bint' 1989 else: 1990 base_code = public_decl('int', dll_linkage) 1991 return self.base_declaration_code(base_code, entity_code) 1992 1993 def __repr__(self): 1994 return "<CNumericType bint>" 1995 1996 def __str__(self): 1997 return 'bint' 1998 1999 def py_type_name(self): 2000 return "bool" 2001 2002 2003class CPyUCS4IntType(CIntType): 2004 # Py_UCS4 2005 2006 is_unicode_char = True 2007 2008 # Py_UCS4 coerces from and to single character unicode strings (or 2009 # at most two characters on 16bit Unicode builds), but we also 2010 # allow Python integers as input. The value range for Py_UCS4 2011 # is 0..1114111, which is checked when converting from an integer 2012 # value. 2013 2014 to_py_function = "PyUnicode_FromOrdinal" 2015 from_py_function = "__Pyx_PyObject_AsPy_UCS4" 2016 2017 def can_coerce_to_pystring(self, env, format_spec=None): 2018 return False # does the right thing anyway 2019 2020 def create_from_py_utility_code(self, env): 2021 env.use_utility_code(UtilityCode.load_cached("ObjectAsUCS4", "TypeConversion.c")) 2022 return True 2023 2024 def sign_and_name(self): 2025 return "Py_UCS4" 2026 2027 2028class CPyUnicodeIntType(CIntType): 2029 # Py_UNICODE 2030 2031 is_unicode_char = True 2032 2033 # Py_UNICODE coerces from and to single character unicode strings, 2034 # but we also allow Python integers as input. The value range for 2035 # Py_UNICODE is 0..1114111, which is checked when converting from 2036 # an integer value. 2037 2038 to_py_function = "PyUnicode_FromOrdinal" 2039 from_py_function = "__Pyx_PyObject_AsPy_UNICODE" 2040 2041 def can_coerce_to_pystring(self, env, format_spec=None): 2042 return False # does the right thing anyway 2043 2044 def create_from_py_utility_code(self, env): 2045 env.use_utility_code(UtilityCode.load_cached("ObjectAsPyUnicode", "TypeConversion.c")) 2046 return True 2047 2048 def sign_and_name(self): 2049 return "Py_UNICODE" 2050 2051 2052class CPyHashTType(CIntType): 2053 2054 to_py_function = "__Pyx_PyInt_FromHash_t" 2055 from_py_function = "__Pyx_PyInt_AsHash_t" 2056 2057 def sign_and_name(self): 2058 return "Py_hash_t" 2059 2060class CPySSizeTType(CIntType): 2061 2062 to_py_function = "PyInt_FromSsize_t" 2063 from_py_function = "__Pyx_PyIndex_AsSsize_t" 2064 2065 def sign_and_name(self): 2066 return "Py_ssize_t" 2067 2068class CSSizeTType(CIntType): 2069 2070 to_py_function = "PyInt_FromSsize_t" 2071 from_py_function = "PyInt_AsSsize_t" 2072 2073 def sign_and_name(self): 2074 return "Py_ssize_t" 2075 2076class CSizeTType(CIntType): 2077 2078 to_py_function = "__Pyx_PyInt_FromSize_t" 2079 2080 def sign_and_name(self): 2081 return "size_t" 2082 2083class CPtrdiffTType(CIntType): 2084 2085 def sign_and_name(self): 2086 return "ptrdiff_t" 2087 2088 2089class CFloatType(CNumericType): 2090 2091 is_float = 1 2092 to_py_function = "PyFloat_FromDouble" 2093 from_py_function = "__pyx_PyFloat_AsDouble" 2094 2095 exception_value = -1 2096 2097 def __init__(self, rank, math_h_modifier = ''): 2098 CNumericType.__init__(self, rank, 1) 2099 self.math_h_modifier = math_h_modifier 2100 if rank == RANK_FLOAT: 2101 self.from_py_function = "__pyx_PyFloat_AsFloat" 2102 2103 def assignable_from_resolved_type(self, src_type): 2104 return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type 2105 2106 def invalid_value(self): 2107 return Naming.PYX_NAN 2108 2109class CComplexType(CNumericType): 2110 2111 is_complex = 1 2112 to_py_function = "__pyx_PyComplex_FromComplex" 2113 has_attributes = 1 2114 scope = None 2115 2116 def __init__(self, real_type): 2117 while real_type.is_typedef and not real_type.typedef_is_external: 2118 real_type = real_type.typedef_base_type 2119 self.funcsuffix = "_%s" % real_type.specialization_name() 2120 if real_type.is_float: 2121 self.math_h_modifier = real_type.math_h_modifier 2122 else: 2123 self.math_h_modifier = "_UNUSED" 2124 2125 self.real_type = real_type 2126 CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed) 2127 self.binops = {} 2128 self.from_parts = "%s_from_parts" % self.specialization_name() 2129 self.default_value = "%s(0, 0)" % self.from_parts 2130 2131 def __eq__(self, other): 2132 if isinstance(self, CComplexType) and isinstance(other, CComplexType): 2133 return self.real_type == other.real_type 2134 else: 2135 return False 2136 2137 def __ne__(self, other): 2138 if isinstance(self, CComplexType) and isinstance(other, CComplexType): 2139 return self.real_type != other.real_type 2140 else: 2141 return True 2142 2143 def __lt__(self, other): 2144 if isinstance(self, CComplexType) and isinstance(other, CComplexType): 2145 return self.real_type < other.real_type 2146 else: 2147 # this is arbitrary, but it makes sure we always have 2148 # *some* kind of order 2149 return False 2150 2151 def __hash__(self): 2152 return ~hash(self.real_type) 2153 2154 def declaration_code(self, entity_code, 2155 for_display = 0, dll_linkage = None, pyrex = 0): 2156 if pyrex or for_display: 2157 real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex) 2158 base_code = "%s complex" % real_code 2159 else: 2160 base_code = public_decl(self.sign_and_name(), dll_linkage) 2161 return self.base_declaration_code(base_code, entity_code) 2162 2163 def sign_and_name(self): 2164 real_type_name = self.real_type.specialization_name() 2165 real_type_name = real_type_name.replace('long__double','long_double') 2166 real_type_name = real_type_name.replace('PY_LONG_LONG','long_long') 2167 return Naming.type_prefix + real_type_name + "_complex" 2168 2169 def assignable_from(self, src_type): 2170 # Temporary hack/feature disabling, see #441 2171 if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef 2172 and src_type.typedef_is_external): 2173 return False 2174 elif src_type.is_pyobject: 2175 return True 2176 else: 2177 return super(CComplexType, self).assignable_from(src_type) 2178 2179 def assignable_from_resolved_type(self, src_type): 2180 return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type) 2181 or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type) 2182 or src_type is error_type) 2183 2184 def attributes_known(self): 2185 if self.scope is None: 2186 from . import Symtab 2187 self.scope = scope = Symtab.CClassScope( 2188 '', 2189 None, 2190 visibility="extern") 2191 scope.parent_type = self 2192 scope.directives = {} 2193 scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True) 2194 scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True) 2195 scope.declare_cfunction( 2196 "conjugate", 2197 CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True), 2198 pos=None, 2199 defining=1, 2200 cname="__Pyx_c_conj%s" % self.funcsuffix) 2201 2202 return True 2203 2204 def _utility_code_context(self): 2205 return { 2206 'type': self.empty_declaration_code(), 2207 'type_name': self.specialization_name(), 2208 'real_type': self.real_type.empty_declaration_code(), 2209 'func_suffix': self.funcsuffix, 2210 'm': self.math_h_modifier, 2211 'is_float': int(self.real_type.is_float) 2212 } 2213 2214 def create_declaration_utility_code(self, env): 2215 # This must always be run, because a single CComplexType instance can be shared 2216 # across multiple compilations (the one created in the module scope) 2217 env.use_utility_code(UtilityCode.load_cached('Header', 'Complex.c')) 2218 env.use_utility_code(UtilityCode.load_cached('RealImag', 'Complex.c')) 2219 env.use_utility_code(TempitaUtilityCode.load_cached( 2220 'Declarations', 'Complex.c', self._utility_code_context())) 2221 env.use_utility_code(TempitaUtilityCode.load_cached( 2222 'Arithmetic', 'Complex.c', self._utility_code_context())) 2223 return True 2224 2225 def can_coerce_to_pyobject(self, env): 2226 return True 2227 2228 def can_coerce_from_pyobject(self, env): 2229 return True 2230 2231 def create_to_py_utility_code(self, env): 2232 env.use_utility_code(UtilityCode.load_cached('ToPy', 'Complex.c')) 2233 return True 2234 2235 def create_from_py_utility_code(self, env): 2236 env.use_utility_code(TempitaUtilityCode.load_cached( 2237 'FromPy', 'Complex.c', self._utility_code_context())) 2238 self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name() 2239 return True 2240 2241 def lookup_op(self, nargs, op): 2242 try: 2243 return self.binops[nargs, op] 2244 except KeyError: 2245 pass 2246 try: 2247 op_name = complex_ops[nargs, op] 2248 self.binops[nargs, op] = func_name = "__Pyx_c_%s%s" % (op_name, self.funcsuffix) 2249 return func_name 2250 except KeyError: 2251 return None 2252 2253 def unary_op(self, op): 2254 return self.lookup_op(1, op) 2255 2256 def binary_op(self, op): 2257 return self.lookup_op(2, op) 2258 2259 def py_type_name(self): 2260 return "complex" 2261 2262 def cast_code(self, expr_code): 2263 return expr_code 2264 2265complex_ops = { 2266 (1, '-'): 'neg', 2267 (1, 'zero'): 'is_zero', 2268 (2, '+'): 'sum', 2269 (2, '-'): 'diff', 2270 (2, '*'): 'prod', 2271 (2, '/'): 'quot', 2272 (2, '**'): 'pow', 2273 (2, '=='): 'eq', 2274} 2275 2276 2277class CPyTSSTType(CType): 2278 # 2279 # PEP-539 "Py_tss_t" type 2280 # 2281 2282 declaration_value = "Py_tss_NEEDS_INIT" 2283 2284 def __repr__(self): 2285 return "<Py_tss_t>" 2286 2287 def declaration_code(self, entity_code, 2288 for_display=0, dll_linkage=None, pyrex=0): 2289 if pyrex or for_display: 2290 base_code = "Py_tss_t" 2291 else: 2292 base_code = public_decl("Py_tss_t", dll_linkage) 2293 return self.base_declaration_code(base_code, entity_code) 2294 2295 2296class CPointerBaseType(CType): 2297 # common base type for pointer/array types 2298 # 2299 # base_type CType Reference type 2300 2301 subtypes = ['base_type'] 2302 2303 def __init__(self, base_type): 2304 self.base_type = base_type 2305 if base_type.is_const: 2306 base_type = base_type.const_base_type 2307 for char_type in (c_char_type, c_uchar_type, c_schar_type): 2308 if base_type.same_as(char_type): 2309 self.is_string = 1 2310 break 2311 else: 2312 if base_type.same_as(c_py_unicode_type): 2313 self.is_pyunicode_ptr = 1 2314 2315 if self.is_string and not base_type.is_error: 2316 if base_type.signed == 2: 2317 self.to_py_function = "__Pyx_PyObject_FromCString" 2318 if self.is_ptr: 2319 self.from_py_function = "__Pyx_PyObject_As%sSString" 2320 elif base_type.signed: 2321 self.to_py_function = "__Pyx_PyObject_FromString" 2322 if self.is_ptr: 2323 self.from_py_function = "__Pyx_PyObject_As%sString" 2324 else: 2325 self.to_py_function = "__Pyx_PyObject_FromCString" 2326 if self.is_ptr: 2327 self.from_py_function = "__Pyx_PyObject_As%sUString" 2328 if self.is_ptr: 2329 self.from_py_function %= '' if self.base_type.is_const else 'Writable' 2330 self.exception_value = "NULL" 2331 elif self.is_pyunicode_ptr and not base_type.is_error: 2332 self.to_py_function = "__Pyx_PyUnicode_FromUnicode" 2333 if self.is_ptr: 2334 self.from_py_function = "__Pyx_PyUnicode_AsUnicode" 2335 self.exception_value = "NULL" 2336 2337 def py_type_name(self): 2338 if self.is_string: 2339 return "bytes" 2340 elif self.is_pyunicode_ptr: 2341 return "unicode" 2342 else: 2343 return super(CPointerBaseType, self).py_type_name() 2344 2345 def literal_code(self, value): 2346 if self.is_string: 2347 assert isinstance(value, str) 2348 return '"%s"' % StringEncoding.escape_byte_string(value) 2349 2350 2351class CArrayType(CPointerBaseType): 2352 # base_type CType Element type 2353 # size integer or None Number of elements 2354 2355 is_array = 1 2356 to_tuple_function = None 2357 2358 def __init__(self, base_type, size): 2359 super(CArrayType, self).__init__(base_type) 2360 self.size = size 2361 2362 def __eq__(self, other): 2363 if isinstance(other, CType) and other.is_array and self.size == other.size: 2364 return self.base_type.same_as(other.base_type) 2365 return False 2366 2367 def __hash__(self): 2368 return hash(self.base_type) + 28 # arbitrarily chosen offset 2369 2370 def __repr__(self): 2371 return "<CArrayType %s %s>" % (self.size, repr(self.base_type)) 2372 2373 def same_as_resolved_type(self, other_type): 2374 return ((other_type.is_array and 2375 self.base_type.same_as(other_type.base_type)) 2376 or other_type is error_type) 2377 2378 def assignable_from_resolved_type(self, src_type): 2379 # C arrays are assigned by value, either Python containers or C arrays/pointers 2380 if src_type.is_pyobject: 2381 return True 2382 if src_type.is_ptr or src_type.is_array: 2383 return self.base_type.assignable_from(src_type.base_type) 2384 return False 2385 2386 def element_ptr_type(self): 2387 return c_ptr_type(self.base_type) 2388 2389 def declaration_code(self, entity_code, 2390 for_display = 0, dll_linkage = None, pyrex = 0): 2391 if self.size is not None: 2392 dimension_code = self.size 2393 else: 2394 dimension_code = "" 2395 if entity_code.startswith("*"): 2396 entity_code = "(%s)" % entity_code 2397 return self.base_type.declaration_code( 2398 "%s[%s]" % (entity_code, dimension_code), 2399 for_display, dll_linkage, pyrex) 2400 2401 def as_argument_type(self): 2402 return c_ptr_type(self.base_type) 2403 2404 def is_complete(self): 2405 return self.size is not None 2406 2407 def specialize(self, values): 2408 base_type = self.base_type.specialize(values) 2409 if base_type == self.base_type: 2410 return self 2411 else: 2412 return CArrayType(base_type, self.size) 2413 2414 def deduce_template_params(self, actual): 2415 if isinstance(actual, CArrayType): 2416 return self.base_type.deduce_template_params(actual.base_type) 2417 else: 2418 return {} 2419 2420 def can_coerce_to_pyobject(self, env): 2421 return self.base_type.can_coerce_to_pyobject(env) 2422 2423 def can_coerce_from_pyobject(self, env): 2424 return self.base_type.can_coerce_from_pyobject(env) 2425 2426 def create_to_py_utility_code(self, env): 2427 if self.to_py_function is not None: 2428 return self.to_py_function 2429 if not self.base_type.create_to_py_utility_code(env): 2430 return False 2431 2432 safe_typename = self.base_type.specialization_name() 2433 to_py_function = "__Pyx_carray_to_py_%s" % safe_typename 2434 to_tuple_function = "__Pyx_carray_to_tuple_%s" % safe_typename 2435 2436 from .UtilityCode import CythonUtilityCode 2437 context = { 2438 'cname': to_py_function, 2439 'to_tuple_cname': to_tuple_function, 2440 'base_type': self.base_type, 2441 } 2442 env.use_utility_code(CythonUtilityCode.load( 2443 "carray.to_py", "CConvert.pyx", 2444 outer_module_scope=env.global_scope(), # need access to types declared in module 2445 context=context, compiler_directives=dict(env.global_scope().directives))) 2446 self.to_tuple_function = to_tuple_function 2447 self.to_py_function = to_py_function 2448 return True 2449 2450 def to_py_call_code(self, source_code, result_code, result_type, to_py_function=None): 2451 func = self.to_py_function if to_py_function is None else to_py_function 2452 if self.is_string or self.is_pyunicode_ptr: 2453 return '%s = %s(%s)' % ( 2454 result_code, 2455 func, 2456 source_code) 2457 target_is_tuple = result_type.is_builtin_type and result_type.name == 'tuple' 2458 return '%s = %s(%s, %s)' % ( 2459 result_code, 2460 self.to_tuple_function if target_is_tuple else func, 2461 source_code, 2462 self.size) 2463 2464 def create_from_py_utility_code(self, env): 2465 if self.from_py_function is not None: 2466 return self.from_py_function 2467 if not self.base_type.create_from_py_utility_code(env): 2468 return False 2469 2470 from_py_function = "__Pyx_carray_from_py_%s" % self.base_type.specialization_name() 2471 2472 from .UtilityCode import CythonUtilityCode 2473 context = { 2474 'cname': from_py_function, 2475 'base_type': self.base_type, 2476 } 2477 env.use_utility_code(CythonUtilityCode.load( 2478 "carray.from_py", "CConvert.pyx", 2479 outer_module_scope=env.global_scope(), # need access to types declared in module 2480 context=context, compiler_directives=dict(env.global_scope().directives))) 2481 self.from_py_function = from_py_function 2482 return True 2483 2484 def from_py_call_code(self, source_code, result_code, error_pos, code, 2485 from_py_function=None, error_condition=None): 2486 assert not error_condition, '%s: %s' % (error_pos, error_condition) 2487 call_code = "%s(%s, %s, %s)" % ( 2488 from_py_function or self.from_py_function, 2489 source_code, result_code, self.size) 2490 return code.error_goto_if_neg(call_code, error_pos) 2491 2492 2493class CPtrType(CPointerBaseType): 2494 # base_type CType Reference type 2495 2496 is_ptr = 1 2497 default_value = "0" 2498 2499 def __hash__(self): 2500 return hash(self.base_type) + 27 # arbitrarily chosen offset 2501 2502 def __eq__(self, other): 2503 if isinstance(other, CType) and other.is_ptr: 2504 return self.base_type.same_as(other.base_type) 2505 return False 2506 2507 def __ne__(self, other): 2508 return not (self == other) 2509 2510 def __repr__(self): 2511 return "<CPtrType %s>" % repr(self.base_type) 2512 2513 def same_as_resolved_type(self, other_type): 2514 return ((other_type.is_ptr and 2515 self.base_type.same_as(other_type.base_type)) 2516 or other_type is error_type) 2517 2518 def declaration_code(self, entity_code, 2519 for_display = 0, dll_linkage = None, pyrex = 0): 2520 #print "CPtrType.declaration_code: pointer to", self.base_type ### 2521 return self.base_type.declaration_code( 2522 "*%s" % entity_code, 2523 for_display, dll_linkage, pyrex) 2524 2525 def assignable_from_resolved_type(self, other_type): 2526 if other_type is error_type: 2527 return 1 2528 if other_type.is_null_ptr: 2529 return 1 2530 if self.base_type.is_const: 2531 self = CPtrType(self.base_type.const_base_type) 2532 if self.base_type.is_cfunction: 2533 if other_type.is_ptr: 2534 other_type = other_type.base_type.resolve() 2535 if other_type.is_cfunction: 2536 return self.base_type.pointer_assignable_from_resolved_type(other_type) 2537 else: 2538 return 0 2539 if (self.base_type.is_cpp_class and other_type.is_ptr 2540 and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)): 2541 return 1 2542 if other_type.is_array or other_type.is_ptr: 2543 return self.base_type.is_void or self.base_type.same_as(other_type.base_type) 2544 return 0 2545 2546 def specialize(self, values): 2547 base_type = self.base_type.specialize(values) 2548 if base_type == self.base_type: 2549 return self 2550 else: 2551 return CPtrType(base_type) 2552 2553 def deduce_template_params(self, actual): 2554 if isinstance(actual, CPtrType): 2555 return self.base_type.deduce_template_params(actual.base_type) 2556 else: 2557 return {} 2558 2559 def invalid_value(self): 2560 return "1" 2561 2562 def find_cpp_operation_type(self, operator, operand_type=None): 2563 if self.base_type.is_cpp_class: 2564 return self.base_type.find_cpp_operation_type(operator, operand_type) 2565 return None 2566 2567 2568class CNullPtrType(CPtrType): 2569 2570 is_null_ptr = 1 2571 2572 2573class CReferenceType(BaseType): 2574 2575 is_reference = 1 2576 is_fake_reference = 0 2577 2578 def __init__(self, base_type): 2579 self.ref_base_type = base_type 2580 2581 def __repr__(self): 2582 return "<CReferenceType %s>" % repr(self.ref_base_type) 2583 2584 def __str__(self): 2585 return "%s &" % self.ref_base_type 2586 2587 def declaration_code(self, entity_code, 2588 for_display = 0, dll_linkage = None, pyrex = 0): 2589 #print "CReferenceType.declaration_code: pointer to", self.base_type ### 2590 return self.ref_base_type.declaration_code( 2591 "&%s" % entity_code, 2592 for_display, dll_linkage, pyrex) 2593 2594 def specialize(self, values): 2595 base_type = self.ref_base_type.specialize(values) 2596 if base_type == self.ref_base_type: 2597 return self 2598 else: 2599 return type(self)(base_type) 2600 2601 def deduce_template_params(self, actual): 2602 return self.ref_base_type.deduce_template_params(actual) 2603 2604 def __getattr__(self, name): 2605 return getattr(self.ref_base_type, name) 2606 2607 2608class CFakeReferenceType(CReferenceType): 2609 2610 is_fake_reference = 1 2611 2612 def __repr__(self): 2613 return "<CFakeReferenceType %s>" % repr(self.ref_base_type) 2614 2615 def __str__(self): 2616 return "%s [&]" % self.ref_base_type 2617 2618 def declaration_code(self, entity_code, 2619 for_display = 0, dll_linkage = None, pyrex = 0): 2620 #print "CReferenceType.declaration_code: pointer to", self.base_type ### 2621 return "__Pyx_FakeReference<%s> %s" % (self.ref_base_type.empty_declaration_code(), entity_code) 2622 2623 2624class CFuncType(CType): 2625 # return_type CType 2626 # args [CFuncTypeArg] 2627 # has_varargs boolean 2628 # exception_value string 2629 # exception_check boolean True if PyErr_Occurred check needed 2630 # calling_convention string Function calling convention 2631 # nogil boolean Can be called without gil 2632 # with_gil boolean Acquire gil around function body 2633 # templates [string] or None 2634 # cached_specialized_types [CFuncType] cached specialized versions of the CFuncType if defined in a pxd 2635 # from_fused boolean Indicates whether this is a specialized 2636 # C function 2637 # is_strict_signature boolean function refuses to accept coerced arguments 2638 # (used for optimisation overrides) 2639 # is_const_method boolean 2640 # is_static_method boolean 2641 2642 is_cfunction = 1 2643 original_sig = None 2644 cached_specialized_types = None 2645 from_fused = False 2646 is_const_method = False 2647 2648 subtypes = ['return_type', 'args'] 2649 2650 def __init__(self, return_type, args, has_varargs = 0, 2651 exception_value = None, exception_check = 0, calling_convention = "", 2652 nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0, 2653 is_const_method = False, is_static_method=False, 2654 templates = None, is_strict_signature = False): 2655 self.return_type = return_type 2656 self.args = args 2657 self.has_varargs = has_varargs 2658 self.optional_arg_count = optional_arg_count 2659 self.exception_value = exception_value 2660 self.exception_check = exception_check 2661 self.calling_convention = calling_convention 2662 self.nogil = nogil 2663 self.with_gil = with_gil 2664 self.is_overridable = is_overridable 2665 self.is_const_method = is_const_method 2666 self.is_static_method = is_static_method 2667 self.templates = templates 2668 self.is_strict_signature = is_strict_signature 2669 2670 def __repr__(self): 2671 arg_reprs = list(map(repr, self.args)) 2672 if self.has_varargs: 2673 arg_reprs.append("...") 2674 if self.exception_value: 2675 except_clause = " %r" % self.exception_value 2676 else: 2677 except_clause = "" 2678 if self.exception_check: 2679 except_clause += "?" 2680 return "<CFuncType %s %s[%s]%s>" % ( 2681 repr(self.return_type), 2682 self.calling_convention_prefix(), 2683 ",".join(arg_reprs), 2684 except_clause) 2685 2686 def with_with_gil(self, with_gil): 2687 if with_gil == self.with_gil: 2688 return self 2689 else: 2690 return CFuncType( 2691 self.return_type, self.args, self.has_varargs, 2692 self.exception_value, self.exception_check, 2693 self.calling_convention, self.nogil, 2694 with_gil, 2695 self.is_overridable, self.optional_arg_count, 2696 self.is_const_method, self.is_static_method, 2697 self.templates, self.is_strict_signature) 2698 2699 def calling_convention_prefix(self): 2700 cc = self.calling_convention 2701 if cc: 2702 return cc + " " 2703 else: 2704 return "" 2705 2706 def as_argument_type(self): 2707 return c_ptr_type(self) 2708 2709 def same_c_signature_as(self, other_type, as_cmethod = 0): 2710 return self.same_c_signature_as_resolved_type( 2711 other_type.resolve(), as_cmethod) 2712 2713 def same_c_signature_as_resolved_type(self, other_type, as_cmethod=False, as_pxd_definition=False, 2714 exact_semantics=True): 2715 # If 'exact_semantics' is false, allow any equivalent C signatures 2716 # if the Cython semantics are compatible, i.e. the same or wider for 'other_type'. 2717 2718 #print "CFuncType.same_c_signature_as_resolved_type:", \ 2719 # self, other_type, "as_cmethod =", as_cmethod ### 2720 if other_type is error_type: 2721 return 1 2722 if not other_type.is_cfunction: 2723 return 0 2724 if self.is_overridable != other_type.is_overridable: 2725 return 0 2726 nargs = len(self.args) 2727 if nargs != len(other_type.args): 2728 return 0 2729 # When comparing C method signatures, the first argument 2730 # is exempt from compatibility checking (the proper check 2731 # is performed elsewhere). 2732 for i in range(as_cmethod, nargs): 2733 if not self.args[i].type.same_as(other_type.args[i].type): 2734 return 0 2735 if self.has_varargs != other_type.has_varargs: 2736 return 0 2737 if self.optional_arg_count != other_type.optional_arg_count: 2738 return 0 2739 if as_pxd_definition: 2740 # A narrowing of the return type declared in the pxd is allowed. 2741 if not self.return_type.subtype_of_resolved_type(other_type.return_type): 2742 return 0 2743 else: 2744 if not self.return_type.same_as(other_type.return_type): 2745 return 0 2746 if not self.same_calling_convention_as(other_type): 2747 return 0 2748 if exact_semantics: 2749 if self.exception_check != other_type.exception_check: 2750 return 0 2751 if not self._same_exception_value(other_type.exception_value): 2752 return 0 2753 elif not self._is_exception_compatible_with(other_type): 2754 return 0 2755 return 1 2756 2757 def _same_exception_value(self, other_exc_value): 2758 if self.exception_value == other_exc_value: 2759 return 1 2760 if self.exception_check != '+': 2761 return 0 2762 if not self.exception_value or not other_exc_value: 2763 return 0 2764 if self.exception_value.type != other_exc_value.type: 2765 return 0 2766 if self.exception_value.entry and other_exc_value.entry: 2767 if self.exception_value.entry.cname != other_exc_value.entry.cname: 2768 return 0 2769 if self.exception_value.name != other_exc_value.name: 2770 return 0 2771 return 1 2772 2773 def compatible_signature_with(self, other_type, as_cmethod = 0): 2774 return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod) 2775 2776 def compatible_signature_with_resolved_type(self, other_type, as_cmethod): 2777 #print "CFuncType.same_c_signature_as_resolved_type:", \ 2778 # self, other_type, "as_cmethod =", as_cmethod ### 2779 if other_type is error_type: 2780 return 1 2781 if not other_type.is_cfunction: 2782 return 0 2783 if not self.is_overridable and other_type.is_overridable: 2784 return 0 2785 nargs = len(self.args) 2786 if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count: 2787 return 0 2788 if self.optional_arg_count < other_type.optional_arg_count: 2789 return 0 2790 # When comparing C method signatures, the first argument 2791 # is exempt from compatibility checking (the proper check 2792 # is performed elsewhere). 2793 for i in range(as_cmethod, len(other_type.args)): 2794 if not self.args[i].type.same_as( 2795 other_type.args[i].type): 2796 return 0 2797 if self.has_varargs != other_type.has_varargs: 2798 return 0 2799 if not self.return_type.subtype_of_resolved_type(other_type.return_type): 2800 return 0 2801 if not self.same_calling_convention_as(other_type): 2802 return 0 2803 if self.nogil != other_type.nogil: 2804 return 0 2805 if not self._is_exception_compatible_with(other_type): 2806 return 0 2807 self.original_sig = other_type.original_sig or other_type 2808 return 1 2809 2810 def _is_exception_compatible_with(self, other_type): 2811 # narrower exception checks are ok, but prevent mismatches 2812 if self.exception_check == '+' and other_type.exception_check != '+': 2813 # must catch C++ exceptions if we raise them 2814 return 0 2815 if not other_type.exception_check or other_type.exception_value is not None: 2816 # if other does not *always* check exceptions, self must comply 2817 if not self._same_exception_value(other_type.exception_value): 2818 return 0 2819 if self.exception_check and self.exception_check != other_type.exception_check: 2820 # a redundant exception check doesn't make functions incompatible, but a missing one does 2821 return 0 2822 return 1 2823 2824 def narrower_c_signature_than(self, other_type, as_cmethod = 0): 2825 return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod) 2826 2827 def narrower_c_signature_than_resolved_type(self, other_type, as_cmethod): 2828 if other_type is error_type: 2829 return 1 2830 if not other_type.is_cfunction: 2831 return 0 2832 nargs = len(self.args) 2833 if nargs != len(other_type.args): 2834 return 0 2835 for i in range(as_cmethod, nargs): 2836 if not self.args[i].type.subtype_of_resolved_type(other_type.args[i].type): 2837 return 0 2838 else: 2839 self.args[i].needs_type_test = other_type.args[i].needs_type_test \ 2840 or not self.args[i].type.same_as(other_type.args[i].type) 2841 if self.has_varargs != other_type.has_varargs: 2842 return 0 2843 if self.optional_arg_count != other_type.optional_arg_count: 2844 return 0 2845 if not self.return_type.subtype_of_resolved_type(other_type.return_type): 2846 return 0 2847 if not self.exception_check and other_type.exception_check: 2848 # a redundant exception check doesn't make functions incompatible, but a missing one does 2849 return 0 2850 if not self._same_exception_value(other_type.exception_value): 2851 return 0 2852 return 1 2853 2854 def same_calling_convention_as(self, other): 2855 ## XXX Under discussion ... 2856 ## callspec_words = ("__stdcall", "__cdecl", "__fastcall") 2857 ## cs1 = self.calling_convention 2858 ## cs2 = other.calling_convention 2859 ## if (cs1 in callspec_words or 2860 ## cs2 in callspec_words): 2861 ## return cs1 == cs2 2862 ## else: 2863 ## return True 2864 sc1 = self.calling_convention == '__stdcall' 2865 sc2 = other.calling_convention == '__stdcall' 2866 return sc1 == sc2 2867 2868 def same_as_resolved_type(self, other_type, as_cmethod=False): 2869 return self.same_c_signature_as_resolved_type(other_type, as_cmethod=as_cmethod) \ 2870 and self.nogil == other_type.nogil 2871 2872 def pointer_assignable_from_resolved_type(self, rhs_type): 2873 # Accept compatible exception/nogil declarations for the RHS. 2874 if rhs_type is error_type: 2875 return 1 2876 if not rhs_type.is_cfunction: 2877 return 0 2878 return rhs_type.same_c_signature_as_resolved_type(self, exact_semantics=False) \ 2879 and not (self.nogil and not rhs_type.nogil) 2880 2881 def declaration_code(self, entity_code, 2882 for_display = 0, dll_linkage = None, pyrex = 0, 2883 with_calling_convention = 1): 2884 arg_decl_list = [] 2885 for arg in self.args[:len(self.args)-self.optional_arg_count]: 2886 arg_decl_list.append( 2887 arg.type.declaration_code("", for_display, pyrex = pyrex)) 2888 if self.is_overridable: 2889 arg_decl_list.append("int %s" % Naming.skip_dispatch_cname) 2890 if self.optional_arg_count: 2891 arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname)) 2892 if self.has_varargs: 2893 arg_decl_list.append("...") 2894 arg_decl_code = ", ".join(arg_decl_list) 2895 if not arg_decl_code and not pyrex: 2896 arg_decl_code = "void" 2897 trailer = "" 2898 if (pyrex or for_display) and not self.return_type.is_pyobject: 2899 if self.exception_value and self.exception_check: 2900 trailer = " except? %s" % self.exception_value 2901 elif self.exception_value: 2902 trailer = " except %s" % self.exception_value 2903 elif self.exception_check == '+': 2904 trailer = " except +" 2905 elif self.exception_check and for_display: 2906 # not spelled out by default, unless for human eyes 2907 trailer = " except *" 2908 if self.nogil: 2909 trailer += " nogil" 2910 if not with_calling_convention: 2911 cc = '' 2912 else: 2913 cc = self.calling_convention_prefix() 2914 if (not entity_code and cc) or entity_code.startswith("*"): 2915 entity_code = "(%s%s)" % (cc, entity_code) 2916 cc = "" 2917 if self.is_const_method: 2918 trailer += " const" 2919 return self.return_type.declaration_code( 2920 "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer), 2921 for_display, dll_linkage, pyrex) 2922 2923 def function_header_code(self, func_name, arg_code): 2924 if self.is_const_method: 2925 trailer = " const" 2926 else: 2927 trailer = "" 2928 return "%s%s(%s)%s" % (self.calling_convention_prefix(), 2929 func_name, arg_code, trailer) 2930 2931 def signature_string(self): 2932 s = self.empty_declaration_code() 2933 return s 2934 2935 def signature_cast_string(self): 2936 s = self.declaration_code("(*)", with_calling_convention=False) 2937 return '(%s)' % s 2938 2939 def specialize(self, values): 2940 result = CFuncType(self.return_type.specialize(values), 2941 [arg.specialize(values) for arg in self.args], 2942 has_varargs = self.has_varargs, 2943 exception_value = self.exception_value, 2944 exception_check = self.exception_check, 2945 calling_convention = self.calling_convention, 2946 nogil = self.nogil, 2947 with_gil = self.with_gil, 2948 is_overridable = self.is_overridable, 2949 optional_arg_count = self.optional_arg_count, 2950 is_const_method = self.is_const_method, 2951 is_static_method = self.is_static_method, 2952 templates = self.templates) 2953 2954 result.from_fused = self.is_fused 2955 return result 2956 2957 def opt_arg_cname(self, arg_name): 2958 return self.op_arg_struct.base_type.scope.lookup(arg_name).cname 2959 2960 # Methods that deal with Fused Types 2961 # All but map_with_specific_entries should be called only on functions 2962 # with fused types (and not on their corresponding specific versions). 2963 2964 def get_all_specialized_permutations(self, fused_types=None): 2965 """ 2966 Permute all the types. For every specific instance of a fused type, we 2967 want all other specific instances of all other fused types. 2968 2969 It returns an iterable of two-tuples of the cname that should prefix 2970 the cname of the function, and a dict mapping any fused types to their 2971 respective specific types. 2972 """ 2973 assert self.is_fused 2974 2975 if fused_types is None: 2976 fused_types = self.get_fused_types() 2977 2978 return get_all_specialized_permutations(fused_types) 2979 2980 def get_all_specialized_function_types(self): 2981 """ 2982 Get all the specific function types of this one. 2983 """ 2984 assert self.is_fused 2985 2986 if self.entry.fused_cfunction: 2987 return [n.type for n in self.entry.fused_cfunction.nodes] 2988 elif self.cached_specialized_types is not None: 2989 return self.cached_specialized_types 2990 2991 result = [] 2992 permutations = self.get_all_specialized_permutations() 2993 2994 new_cfunc_entries = [] 2995 for cname, fused_to_specific in permutations: 2996 new_func_type = self.entry.type.specialize(fused_to_specific) 2997 2998 if self.optional_arg_count: 2999 # Remember, this method is set by CFuncDeclaratorNode 3000 self.declare_opt_arg_struct(new_func_type, cname) 3001 3002 new_entry = copy.deepcopy(self.entry) 3003 new_func_type.specialize_entry(new_entry, cname) 3004 3005 new_entry.type = new_func_type 3006 new_func_type.entry = new_entry 3007 result.append(new_func_type) 3008 3009 new_cfunc_entries.append(new_entry) 3010 3011 cfunc_entries = self.entry.scope.cfunc_entries 3012 try: 3013 cindex = cfunc_entries.index(self.entry) 3014 except ValueError: 3015 cfunc_entries.extend(new_cfunc_entries) 3016 else: 3017 cfunc_entries[cindex:cindex+1] = new_cfunc_entries 3018 3019 self.cached_specialized_types = result 3020 3021 return result 3022 3023 def get_fused_types(self, result=None, seen=None, subtypes=None): 3024 """Return fused types in the order they appear as parameter types""" 3025 return super(CFuncType, self).get_fused_types(result, seen, 3026 subtypes=['args']) 3027 3028 def specialize_entry(self, entry, cname): 3029 assert not self.is_fused 3030 specialize_entry(entry, cname) 3031 3032 def can_coerce_to_pyobject(self, env): 3033 # duplicating the decisions from create_to_py_utility_code() here avoids writing out unused code 3034 if self.has_varargs or self.optional_arg_count: 3035 return False 3036 if self.to_py_function is not None: 3037 return self.to_py_function 3038 for arg in self.args: 3039 if not arg.type.is_pyobject and not arg.type.can_coerce_to_pyobject(env): 3040 return False 3041 if not self.return_type.is_pyobject and not self.return_type.can_coerce_to_pyobject(env): 3042 return False 3043 return True 3044 3045 def create_to_py_utility_code(self, env): 3046 # FIXME: it seems we're trying to coerce in more cases than we should 3047 if self.to_py_function is not None: 3048 return self.to_py_function 3049 if not self.can_coerce_to_pyobject(env): 3050 return False 3051 from .UtilityCode import CythonUtilityCode 3052 safe_typename = re.sub('[^a-zA-Z0-9]', '__', self.declaration_code("", pyrex=1)) 3053 to_py_function = "__Pyx_CFunc_%s_to_py" % safe_typename 3054 3055 for arg in self.args: 3056 if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env): 3057 return False 3058 if not self.return_type.is_pyobject and not self.return_type.create_to_py_utility_code(env): 3059 return False 3060 3061 def declared_type(ctype): 3062 type_displayname = str(ctype.declaration_code("", for_display=True)) 3063 if ctype.is_pyobject: 3064 arg_ctype = type_name = type_displayname 3065 if ctype.is_builtin_type: 3066 arg_ctype = ctype.name 3067 elif not ctype.is_extension_type: 3068 type_name = 'object' 3069 type_displayname = None 3070 else: 3071 type_displayname = repr(type_displayname) 3072 elif ctype is c_bint_type: 3073 type_name = arg_ctype = 'bint' 3074 else: 3075 type_name = arg_ctype = type_displayname 3076 if ctype is c_double_type: 3077 type_displayname = 'float' 3078 else: 3079 type_displayname = repr(type_displayname) 3080 return type_name, arg_ctype, type_displayname 3081 3082 class Arg(object): 3083 def __init__(self, arg_name, arg_type): 3084 self.name = arg_name 3085 self.type = arg_type 3086 self.type_cname, self.ctype, self.type_displayname = declared_type(arg_type) 3087 3088 if self.return_type.is_void: 3089 except_clause = 'except *' 3090 elif self.return_type.is_pyobject: 3091 except_clause = '' 3092 elif self.exception_value: 3093 except_clause = ('except? %s' if self.exception_check else 'except %s') % self.exception_value 3094 else: 3095 except_clause = 'except *' 3096 3097 context = { 3098 'cname': to_py_function, 3099 'args': [Arg(arg.name or 'arg%s' % ix, arg.type) for ix, arg in enumerate(self.args)], 3100 'return_type': Arg('return', self.return_type), 3101 'except_clause': except_clause, 3102 } 3103 # FIXME: directives come from first defining environment and do not adapt for reuse 3104 env.use_utility_code(CythonUtilityCode.load( 3105 "cfunc.to_py", "CConvert.pyx", 3106 outer_module_scope=env.global_scope(), # need access to types declared in module 3107 context=context, compiler_directives=dict(env.global_scope().directives))) 3108 self.to_py_function = to_py_function 3109 return True 3110 3111 3112def specialize_entry(entry, cname): 3113 """ 3114 Specialize an entry of a copied fused function or method 3115 """ 3116 entry.is_fused_specialized = True 3117 entry.name = get_fused_cname(cname, entry.name) 3118 3119 if entry.is_cmethod: 3120 entry.cname = entry.name 3121 if entry.is_inherited: 3122 entry.cname = StringEncoding.EncodedString( 3123 "%s.%s" % (Naming.obj_base_cname, entry.cname)) 3124 else: 3125 entry.cname = get_fused_cname(cname, entry.cname) 3126 3127 if entry.func_cname: 3128 entry.func_cname = get_fused_cname(cname, entry.func_cname) 3129 3130def get_fused_cname(fused_cname, orig_cname): 3131 """ 3132 Given the fused cname id and an original cname, return a specialized cname 3133 """ 3134 assert fused_cname and orig_cname 3135 return StringEncoding.EncodedString('%s%s%s' % (Naming.fused_func_prefix, 3136 fused_cname, orig_cname)) 3137 3138def unique(somelist): 3139 seen = set() 3140 result = [] 3141 for obj in somelist: 3142 if obj not in seen: 3143 result.append(obj) 3144 seen.add(obj) 3145 3146 return result 3147 3148def get_all_specialized_permutations(fused_types): 3149 return _get_all_specialized_permutations(unique(fused_types)) 3150 3151def _get_all_specialized_permutations(fused_types, id="", f2s=()): 3152 fused_type, = fused_types[0].get_fused_types() 3153 result = [] 3154 3155 for newid, specific_type in enumerate(fused_type.types): 3156 # f2s = dict(f2s, **{ fused_type: specific_type }) 3157 f2s = dict(f2s) 3158 f2s.update({ fused_type: specific_type }) 3159 3160 if id: 3161 cname = '%s_%s' % (id, newid) 3162 else: 3163 cname = str(newid) 3164 3165 if len(fused_types) > 1: 3166 result.extend(_get_all_specialized_permutations( 3167 fused_types[1:], cname, f2s)) 3168 else: 3169 result.append((cname, f2s)) 3170 3171 return result 3172 3173def specialization_signature_string(fused_compound_type, fused_to_specific): 3174 """ 3175 Return the signature for a specialization of a fused type. e.g. 3176 3177 floating[:] -> 3178 'float' or 'double' 3179 3180 cdef fused ft: 3181 float[:] 3182 double[:] 3183 3184 ft -> 3185 'float[:]' or 'double[:]' 3186 3187 integral func(floating) -> 3188 'int (*func)(float)' or ... 3189 """ 3190 fused_types = fused_compound_type.get_fused_types() 3191 if len(fused_types) == 1: 3192 fused_type = fused_types[0] 3193 else: 3194 fused_type = fused_compound_type 3195 3196 return fused_type.specialize(fused_to_specific).typeof_name() 3197 3198 3199def get_specialized_types(type): 3200 """ 3201 Return a list of specialized types in their declared order. 3202 """ 3203 assert type.is_fused 3204 3205 if isinstance(type, FusedType): 3206 result = list(type.types) 3207 for specialized_type in result: 3208 specialized_type.specialization_string = specialized_type.typeof_name() 3209 else: 3210 result = [] 3211 for cname, f2s in get_all_specialized_permutations(type.get_fused_types()): 3212 specialized_type = type.specialize(f2s) 3213 specialized_type.specialization_string = ( 3214 specialization_signature_string(type, f2s)) 3215 result.append(specialized_type) 3216 3217 return result 3218 3219 3220class CFuncTypeArg(BaseType): 3221 # name string 3222 # cname string 3223 # type PyrexType 3224 # pos source file position 3225 3226 # FIXME: is this the right setup? should None be allowed here? 3227 not_none = False 3228 or_none = False 3229 accept_none = True 3230 accept_builtin_subtypes = False 3231 annotation = None 3232 3233 subtypes = ['type'] 3234 3235 def __init__(self, name, type, pos, cname=None, annotation=None): 3236 self.name = name 3237 if cname is not None: 3238 self.cname = cname 3239 else: 3240 self.cname = Naming.var_prefix + name 3241 if annotation is not None: 3242 self.annotation = annotation 3243 self.type = type 3244 self.pos = pos 3245 self.needs_type_test = False # TODO: should these defaults be set in analyse_types()? 3246 3247 def __repr__(self): 3248 return "%s:%s" % (self.name, repr(self.type)) 3249 3250 def declaration_code(self, for_display = 0): 3251 return self.type.declaration_code(self.cname, for_display) 3252 3253 def specialize(self, values): 3254 return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname) 3255 3256 3257class ToPyStructUtilityCode(object): 3258 3259 requires = None 3260 3261 def __init__(self, type, forward_decl, env): 3262 self.type = type 3263 self.header = "static PyObject* %s(%s)" % (type.to_py_function, 3264 type.declaration_code('s')) 3265 self.forward_decl = forward_decl 3266 self.env = env 3267 3268 def __eq__(self, other): 3269 return isinstance(other, ToPyStructUtilityCode) and self.header == other.header 3270 3271 def __hash__(self): 3272 return hash(self.header) 3273 3274 def get_tree(self, **kwargs): 3275 pass 3276 3277 def put_code(self, output): 3278 code = output['utility_code_def'] 3279 proto = output['utility_code_proto'] 3280 3281 code.putln("%s {" % self.header) 3282 code.putln("PyObject* res;") 3283 code.putln("PyObject* member;") 3284 code.putln("res = __Pyx_PyDict_NewPresized(%d); if (unlikely(!res)) return NULL;" % 3285 len(self.type.scope.var_entries)) 3286 for member in self.type.scope.var_entries: 3287 nameconst_cname = code.get_py_string_const(member.name, identifier=True) 3288 code.putln("%s; if (unlikely(!member)) goto bad;" % ( 3289 member.type.to_py_call_code('s.%s' % member.cname, 'member', member.type))) 3290 code.putln("if (unlikely(PyDict_SetItem(res, %s, member) < 0)) goto bad;" % nameconst_cname) 3291 code.putln("Py_DECREF(member);") 3292 code.putln("return res;") 3293 code.putln("bad:") 3294 code.putln("Py_XDECREF(member);") 3295 code.putln("Py_DECREF(res);") 3296 code.putln("return NULL;") 3297 code.putln("}") 3298 3299 # This is a bit of a hack, we need a forward declaration 3300 # due to the way things are ordered in the module... 3301 if self.forward_decl: 3302 proto.putln(self.type.empty_declaration_code() + ';') 3303 proto.putln(self.header + ";") 3304 3305 def inject_tree_and_scope_into(self, module_node): 3306 pass 3307 3308 3309class CStructOrUnionType(CType): 3310 # name string 3311 # cname string 3312 # kind string "struct" or "union" 3313 # scope StructOrUnionScope, or None if incomplete 3314 # typedef_flag boolean 3315 # packed boolean 3316 3317 # entry Entry 3318 3319 is_struct_or_union = 1 3320 has_attributes = 1 3321 exception_check = True 3322 3323 def __init__(self, name, kind, scope, typedef_flag, cname, packed=False): 3324 self.name = name 3325 self.cname = cname 3326 self.kind = kind 3327 self.scope = scope 3328 self.typedef_flag = typedef_flag 3329 self.is_struct = kind == 'struct' 3330 self.to_py_function = "%s_to_py_%s" % ( 3331 Naming.convert_func_prefix, self.specialization_name()) 3332 self.from_py_function = "%s_from_py_%s" % ( 3333 Naming.convert_func_prefix, self.specialization_name()) 3334 self.exception_check = True 3335 self._convert_to_py_code = None 3336 self._convert_from_py_code = None 3337 self.packed = packed 3338 3339 def can_coerce_to_pyobject(self, env): 3340 if self._convert_to_py_code is False: 3341 return None # tri-state-ish 3342 3343 if env.outer_scope is None: 3344 return False 3345 3346 if self._convert_to_py_code is None: 3347 is_union = not self.is_struct 3348 unsafe_union_types = set() 3349 safe_union_types = set() 3350 for member in self.scope.var_entries: 3351 member_type = member.type 3352 if not member_type.can_coerce_to_pyobject(env): 3353 self.to_py_function = None 3354 self._convert_to_py_code = False 3355 return False 3356 if is_union: 3357 if member_type.is_ptr or member_type.is_cpp_class: 3358 unsafe_union_types.add(member_type) 3359 else: 3360 safe_union_types.add(member_type) 3361 3362 if unsafe_union_types and (safe_union_types or len(unsafe_union_types) > 1): 3363 # unsafe mix of safe and unsafe to convert types 3364 self.from_py_function = None 3365 self._convert_from_py_code = False 3366 return False 3367 3368 return True 3369 3370 def create_to_py_utility_code(self, env): 3371 if not self.can_coerce_to_pyobject(env): 3372 return False 3373 3374 if self._convert_to_py_code is None: 3375 for member in self.scope.var_entries: 3376 member.type.create_to_py_utility_code(env) 3377 forward_decl = self.entry.visibility != 'extern' and not self.typedef_flag 3378 self._convert_to_py_code = ToPyStructUtilityCode(self, forward_decl, env) 3379 3380 env.use_utility_code(self._convert_to_py_code) 3381 return True 3382 3383 def can_coerce_from_pyobject(self, env): 3384 if env.outer_scope is None or self._convert_from_py_code is False: 3385 return False 3386 for member in self.scope.var_entries: 3387 if not member.type.can_coerce_from_pyobject(env): 3388 return False 3389 return True 3390 3391 def create_from_py_utility_code(self, env): 3392 if env.outer_scope is None: 3393 return False 3394 3395 if self._convert_from_py_code is False: 3396 return None # tri-state-ish 3397 3398 if self._convert_from_py_code is None: 3399 if not self.scope.var_entries: 3400 # There are obviously missing fields; don't allow instantiation 3401 # where absolutely no content is provided. 3402 return False 3403 3404 for member in self.scope.var_entries: 3405 if not member.type.create_from_py_utility_code(env): 3406 self.from_py_function = None 3407 self._convert_from_py_code = False 3408 return False 3409 3410 context = dict( 3411 struct_type=self, 3412 var_entries=self.scope.var_entries, 3413 funcname=self.from_py_function, 3414 ) 3415 from .UtilityCode import CythonUtilityCode 3416 self._convert_from_py_code = CythonUtilityCode.load( 3417 "FromPyStructUtility" if self.is_struct else "FromPyUnionUtility", 3418 "CConvert.pyx", 3419 outer_module_scope=env.global_scope(), # need access to types declared in module 3420 context=context) 3421 3422 env.use_utility_code(self._convert_from_py_code) 3423 return True 3424 3425 def __repr__(self): 3426 return "<CStructOrUnionType %s %s%s>" % ( 3427 self.name, self.cname, 3428 ("", " typedef")[self.typedef_flag]) 3429 3430 def declaration_code(self, entity_code, 3431 for_display=0, dll_linkage=None, pyrex=0): 3432 if pyrex or for_display: 3433 base_code = self.name 3434 else: 3435 if self.typedef_flag: 3436 base_code = self.cname 3437 else: 3438 base_code = "%s %s" % (self.kind, self.cname) 3439 base_code = public_decl(base_code, dll_linkage) 3440 return self.base_declaration_code(base_code, entity_code) 3441 3442 def __eq__(self, other): 3443 try: 3444 return (isinstance(other, CStructOrUnionType) and 3445 self.name == other.name) 3446 except AttributeError: 3447 return False 3448 3449 def __lt__(self, other): 3450 try: 3451 return self.name < other.name 3452 except AttributeError: 3453 # this is arbitrary, but it makes sure we always have 3454 # *some* kind of order 3455 return False 3456 3457 def __hash__(self): 3458 return hash(self.cname) ^ hash(self.kind) 3459 3460 def is_complete(self): 3461 return self.scope is not None 3462 3463 def attributes_known(self): 3464 return self.is_complete() 3465 3466 def can_be_complex(self): 3467 # Does the struct consist of exactly two identical floats? 3468 fields = self.scope.var_entries 3469 if len(fields) != 2: return False 3470 a, b = fields 3471 return (a.type.is_float and b.type.is_float and 3472 a.type.empty_declaration_code() == 3473 b.type.empty_declaration_code()) 3474 3475 def struct_nesting_depth(self): 3476 child_depths = [x.type.struct_nesting_depth() 3477 for x in self.scope.var_entries] 3478 return max(child_depths) + 1 3479 3480 def cast_code(self, expr_code): 3481 if self.is_struct: 3482 return expr_code 3483 return super(CStructOrUnionType, self).cast_code(expr_code) 3484 3485cpp_string_conversions = ("std::string",) 3486 3487builtin_cpp_conversions = { 3488 # type element template params 3489 "std::pair": 2, 3490 "std::vector": 1, 3491 "std::list": 1, 3492 "std::set": 1, 3493 "std::unordered_set": 1, 3494 "std::map": 2, 3495 "std::unordered_map": 2, 3496 "std::complex": 1, 3497} 3498 3499class CppClassType(CType): 3500 # name string 3501 # cname string 3502 # scope CppClassScope 3503 # templates [string] or None 3504 3505 is_cpp_class = 1 3506 has_attributes = 1 3507 exception_check = True 3508 namespace = None 3509 3510 # For struct-like declaration. 3511 kind = "struct" 3512 packed = False 3513 typedef_flag = False 3514 3515 subtypes = ['templates'] 3516 3517 def __init__(self, name, scope, cname, base_classes, templates=None, template_type=None): 3518 self.name = name 3519 self.cname = cname 3520 self.scope = scope 3521 self.base_classes = base_classes 3522 self.operators = [] 3523 self.templates = templates 3524 self.template_type = template_type 3525 self.num_optional_templates = sum(is_optional_template_param(T) for T in templates or ()) 3526 if templates: 3527 self.specializations = {tuple(zip(templates, templates)): self} 3528 else: 3529 self.specializations = {} 3530 self.is_cpp_string = cname in cpp_string_conversions 3531 3532 def use_conversion_utility(self, from_or_to): 3533 pass 3534 3535 def maybe_unordered(self): 3536 if 'unordered' in self.cname: 3537 return 'unordered_' 3538 else: 3539 return '' 3540 3541 def can_coerce_from_pyobject(self, env): 3542 if self.cname in builtin_cpp_conversions: 3543 template_count = builtin_cpp_conversions[self.cname] 3544 for ix, T in enumerate(self.templates or []): 3545 if ix >= template_count: 3546 break 3547 if T.is_pyobject or not T.can_coerce_from_pyobject(env): 3548 return False 3549 return True 3550 elif self.cname in cpp_string_conversions: 3551 return True 3552 return False 3553 3554 def create_from_py_utility_code(self, env): 3555 if self.from_py_function is not None: 3556 return True 3557 if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions: 3558 X = "XYZABC" 3559 tags = [] 3560 context = {} 3561 for ix, T in enumerate(self.templates or []): 3562 if ix >= builtin_cpp_conversions[self.cname]: 3563 break 3564 if T.is_pyobject or not T.create_from_py_utility_code(env): 3565 return False 3566 tags.append(T.specialization_name()) 3567 context[X[ix]] = T 3568 3569 if self.cname in cpp_string_conversions: 3570 cls = 'string' 3571 tags = type_identifier(self), 3572 else: 3573 cls = self.cname[5:] 3574 cname = '__pyx_convert_%s_from_py_%s' % (cls, '__and_'.join(tags)) 3575 context.update({ 3576 'cname': cname, 3577 'maybe_unordered': self.maybe_unordered(), 3578 'type': self.cname, 3579 }) 3580 from .UtilityCode import CythonUtilityCode 3581 env.use_utility_code(CythonUtilityCode.load( 3582 cls.replace('unordered_', '') + ".from_py", "CppConvert.pyx", 3583 context=context, compiler_directives=env.directives)) 3584 self.from_py_function = cname 3585 return True 3586 3587 def can_coerce_to_pyobject(self, env): 3588 if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions: 3589 for ix, T in enumerate(self.templates or []): 3590 if ix >= builtin_cpp_conversions[self.cname]: 3591 break 3592 if T.is_pyobject or not T.can_coerce_to_pyobject(env): 3593 return False 3594 return True 3595 3596 3597 def create_to_py_utility_code(self, env): 3598 if self.to_py_function is not None: 3599 return True 3600 if self.cname in builtin_cpp_conversions or self.cname in cpp_string_conversions: 3601 X = "XYZABC" 3602 tags = [] 3603 context = {} 3604 for ix, T in enumerate(self.templates or []): 3605 if ix >= builtin_cpp_conversions[self.cname]: 3606 break 3607 if not T.create_to_py_utility_code(env): 3608 return False 3609 tags.append(T.specialization_name()) 3610 context[X[ix]] = T 3611 3612 if self.cname in cpp_string_conversions: 3613 cls = 'string' 3614 prefix = 'PyObject_' # gets specialised by explicit type casts in CoerceToPyTypeNode 3615 tags = type_identifier(self), 3616 else: 3617 cls = self.cname[5:] 3618 prefix = '' 3619 cname = "__pyx_convert_%s%s_to_py_%s" % (prefix, cls, "____".join(tags)) 3620 context.update({ 3621 'cname': cname, 3622 'maybe_unordered': self.maybe_unordered(), 3623 'type': self.cname, 3624 }) 3625 from .UtilityCode import CythonUtilityCode 3626 env.use_utility_code(CythonUtilityCode.load( 3627 cls.replace('unordered_', '') + ".to_py", "CppConvert.pyx", 3628 context=context, compiler_directives=env.directives)) 3629 self.to_py_function = cname 3630 return True 3631 3632 def is_template_type(self): 3633 return self.templates is not None and self.template_type is None 3634 3635 def get_fused_types(self, result=None, seen=None): 3636 if result is None: 3637 result = [] 3638 seen = set() 3639 if self.namespace: 3640 self.namespace.get_fused_types(result, seen) 3641 if self.templates: 3642 for T in self.templates: 3643 T.get_fused_types(result, seen) 3644 return result 3645 3646 def specialize_here(self, pos, template_values=None): 3647 if not self.is_template_type(): 3648 error(pos, "'%s' type is not a template" % self) 3649 return error_type 3650 if len(self.templates) - self.num_optional_templates <= len(template_values) < len(self.templates): 3651 num_defaults = len(self.templates) - len(template_values) 3652 partial_specialization = self.declaration_code('', template_params=template_values) 3653 # Most of the time we don't need to declare anything typed to these 3654 # default template arguments, but when we do there's no way in C++ 3655 # to reference this directly. However, it is common convention to 3656 # provide a typedef in the template class that resolves to each 3657 # template type. For now, allow the user to specify this name as 3658 # the template parameter. 3659 # TODO: Allow typedefs in cpp classes and search for it in this 3660 # classes scope as a concrete name we could use. 3661 template_values = template_values + [ 3662 TemplatePlaceholderType( 3663 "%s::%s" % (partial_specialization, param.name), True) 3664 for param in self.templates[-num_defaults:]] 3665 if len(self.templates) != len(template_values): 3666 error(pos, "%s templated type receives %d arguments, got %d" % 3667 (self.name, len(self.templates), len(template_values))) 3668 return error_type 3669 has_object_template_param = False 3670 for value in template_values: 3671 if value.is_pyobject: 3672 has_object_template_param = True 3673 error(pos, 3674 "Python object type '%s' cannot be used as a template argument" % value) 3675 if has_object_template_param: 3676 return error_type 3677 return self.specialize(dict(zip(self.templates, template_values))) 3678 3679 def specialize(self, values): 3680 if not self.templates and not self.namespace: 3681 return self 3682 if self.templates is None: 3683 self.templates = [] 3684 key = tuple(values.items()) 3685 if key in self.specializations: 3686 return self.specializations[key] 3687 template_values = [t.specialize(values) for t in self.templates] 3688 specialized = self.specializations[key] = \ 3689 CppClassType(self.name, None, self.cname, [], template_values, template_type=self) 3690 # Need to do these *after* self.specializations[key] is set 3691 # to avoid infinite recursion on circular references. 3692 specialized.base_classes = [b.specialize(values) for b in self.base_classes] 3693 if self.namespace is not None: 3694 specialized.namespace = self.namespace.specialize(values) 3695 specialized.scope = self.scope.specialize(values, specialized) 3696 if self.cname == 'std::vector': 3697 # vector<bool> is special cased in the C++ standard, and its 3698 # accessors do not necessarily return references to the underlying 3699 # elements (which may be bit-packed). 3700 # http://www.cplusplus.com/reference/vector/vector-bool/ 3701 # Here we pretend that the various methods return bool values 3702 # (as the actual returned values are coercable to such, and 3703 # we don't support call expressions as lvalues). 3704 T = values.get(self.templates[0], None) 3705 if T and not T.is_fused and T.empty_declaration_code() == 'bool': 3706 for bit_ref_returner in ('at', 'back', 'front'): 3707 if bit_ref_returner in specialized.scope.entries: 3708 specialized.scope.entries[bit_ref_returner].type.return_type = T 3709 return specialized 3710 3711 def deduce_template_params(self, actual): 3712 if actual.is_const: 3713 actual = actual.const_base_type 3714 if actual.is_reference: 3715 actual = actual.ref_base_type 3716 if self == actual: 3717 return {} 3718 elif actual.is_cpp_class: 3719 self_template_type = self 3720 while getattr(self_template_type, 'template_type', None): 3721 self_template_type = self_template_type.template_type 3722 def all_bases(cls): 3723 yield cls 3724 for parent in cls.base_classes: 3725 for base in all_bases(parent): 3726 yield base 3727 for actual_base in all_bases(actual): 3728 template_type = actual_base 3729 while getattr(template_type, 'template_type', None): 3730 template_type = template_type.template_type 3731 if (self_template_type.empty_declaration_code() 3732 == template_type.empty_declaration_code()): 3733 return reduce( 3734 merge_template_deductions, 3735 [formal_param.deduce_template_params(actual_param) 3736 for (formal_param, actual_param) 3737 in zip(self.templates, actual_base.templates)], 3738 {}) 3739 else: 3740 return {} 3741 3742 def declaration_code(self, entity_code, 3743 for_display = 0, dll_linkage = None, pyrex = 0, 3744 template_params = None): 3745 if template_params is None: 3746 template_params = self.templates 3747 if self.templates: 3748 template_strings = [param.declaration_code('', for_display, None, pyrex) 3749 for param in template_params 3750 if not is_optional_template_param(param) and not param.is_fused] 3751 if for_display: 3752 brackets = "[%s]" 3753 else: 3754 brackets = "<%s> " 3755 templates = brackets % ",".join(template_strings) 3756 else: 3757 templates = "" 3758 if pyrex or for_display: 3759 base_code = "%s%s" % (self.name, templates) 3760 else: 3761 base_code = "%s%s" % (self.cname, templates) 3762 if self.namespace is not None: 3763 base_code = "%s::%s" % (self.namespace.empty_declaration_code(), base_code) 3764 base_code = public_decl(base_code, dll_linkage) 3765 return self.base_declaration_code(base_code, entity_code) 3766 3767 def is_subclass(self, other_type): 3768 if self.same_as_resolved_type(other_type): 3769 return 1 3770 for base_class in self.base_classes: 3771 if base_class.is_subclass(other_type): 3772 return 1 3773 return 0 3774 3775 def subclass_dist(self, super_type): 3776 if self.same_as_resolved_type(super_type): 3777 return 0 3778 elif not self.base_classes: 3779 return float('inf') 3780 else: 3781 return 1 + min(b.subclass_dist(super_type) for b in self.base_classes) 3782 3783 def same_as_resolved_type(self, other_type): 3784 if other_type.is_cpp_class: 3785 if self == other_type: 3786 return 1 3787 # This messy logic is needed due to GH Issue #1852. 3788 elif (self.cname == other_type.cname and 3789 (self.template_type and other_type.template_type 3790 or self.templates 3791 or other_type.templates)): 3792 if self.templates == other_type.templates: 3793 return 1 3794 for t1, t2 in zip(self.templates, other_type.templates): 3795 if is_optional_template_param(t1) and is_optional_template_param(t2): 3796 break 3797 if not t1.same_as_resolved_type(t2): 3798 return 0 3799 return 1 3800 return 0 3801 3802 def assignable_from_resolved_type(self, other_type): 3803 # TODO: handle operator=(...) here? 3804 if other_type is error_type: 3805 return True 3806 elif other_type.is_cpp_class: 3807 return other_type.is_subclass(self) 3808 elif other_type.is_string and self.cname in cpp_string_conversions: 3809 return True 3810 3811 def attributes_known(self): 3812 return self.scope is not None 3813 3814 def find_cpp_operation_type(self, operator, operand_type=None): 3815 operands = [self] 3816 if operand_type is not None: 3817 operands.append(operand_type) 3818 # pos == None => no errors 3819 operator_entry = self.scope.lookup_operator_for_types(None, operator, operands) 3820 if not operator_entry: 3821 return None 3822 func_type = operator_entry.type 3823 if func_type.is_ptr: 3824 func_type = func_type.base_type 3825 return func_type.return_type 3826 3827 def get_constructor(self, pos): 3828 constructor = self.scope.lookup('<init>') 3829 if constructor is not None: 3830 return constructor 3831 3832 # Otherwise: automatically declare no-args default constructor. 3833 # Make it "nogil" if the base classes allow it. 3834 nogil = True 3835 for base in self.base_classes: 3836 base_constructor = base.scope.lookup('<init>') 3837 if base_constructor and not base_constructor.type.nogil: 3838 nogil = False 3839 break 3840 3841 func_type = CFuncType(self, [], exception_check='+', nogil=nogil) 3842 return self.scope.declare_cfunction(u'<init>', func_type, pos) 3843 3844 def check_nullary_constructor(self, pos, msg="stack allocated"): 3845 constructor = self.scope.lookup(u'<init>') 3846 if constructor is not None and best_match([], constructor.all_alternatives()) is None: 3847 error(pos, "C++ class must have a nullary constructor to be %s" % msg) 3848 3849 3850class TemplatePlaceholderType(CType): 3851 3852 def __init__(self, name, optional=False): 3853 self.name = name 3854 self.optional = optional 3855 3856 def declaration_code(self, entity_code, 3857 for_display = 0, dll_linkage = None, pyrex = 0): 3858 if entity_code: 3859 return self.name + " " + entity_code 3860 else: 3861 return self.name 3862 3863 def specialize(self, values): 3864 if self in values: 3865 return values[self] 3866 else: 3867 return self 3868 3869 def deduce_template_params(self, actual): 3870 return {self: actual} 3871 3872 def same_as_resolved_type(self, other_type): 3873 if isinstance(other_type, TemplatePlaceholderType): 3874 return self.name == other_type.name 3875 else: 3876 return 0 3877 3878 def __hash__(self): 3879 return hash(self.name) 3880 3881 def __cmp__(self, other): 3882 if isinstance(other, TemplatePlaceholderType): 3883 return cmp(self.name, other.name) 3884 else: 3885 return cmp(type(self), type(other)) 3886 3887 def __eq__(self, other): 3888 if isinstance(other, TemplatePlaceholderType): 3889 return self.name == other.name 3890 else: 3891 return False 3892 3893def is_optional_template_param(type): 3894 return isinstance(type, TemplatePlaceholderType) and type.optional 3895 3896 3897class CEnumType(CIntLike, CType): 3898 # name string 3899 # cname string or None 3900 # typedef_flag boolean 3901 # values [string], populated during declaration analysis 3902 3903 is_enum = 1 3904 signed = 1 3905 rank = -1 # Ranks below any integer type 3906 3907 def __init__(self, name, cname, typedef_flag, namespace=None): 3908 self.name = name 3909 self.cname = cname 3910 self.values = [] 3911 self.typedef_flag = typedef_flag 3912 self.namespace = namespace 3913 self.default_value = "(%s) 0" % self.empty_declaration_code() 3914 3915 def __str__(self): 3916 return self.name 3917 3918 def __repr__(self): 3919 return "<CEnumType %s %s%s>" % (self.name, self.cname, 3920 ("", " typedef")[self.typedef_flag]) 3921 3922 def declaration_code(self, entity_code, 3923 for_display = 0, dll_linkage = None, pyrex = 0): 3924 if pyrex or for_display: 3925 base_code = self.name 3926 else: 3927 if self.namespace: 3928 base_code = "%s::%s" % ( 3929 self.namespace.empty_declaration_code(), self.cname) 3930 elif self.typedef_flag: 3931 base_code = self.cname 3932 else: 3933 base_code = "enum %s" % self.cname 3934 base_code = public_decl(base_code, dll_linkage) 3935 return self.base_declaration_code(base_code, entity_code) 3936 3937 def specialize(self, values): 3938 if self.namespace: 3939 namespace = self.namespace.specialize(values) 3940 if namespace != self.namespace: 3941 return CEnumType( 3942 self.name, self.cname, self.typedef_flag, namespace) 3943 return self 3944 3945 def create_type_wrapper(self, env): 3946 from .UtilityCode import CythonUtilityCode 3947 env.use_utility_code(CythonUtilityCode.load( 3948 "EnumType", "CpdefEnums.pyx", 3949 context={"name": self.name, 3950 "items": tuple(self.values)}, 3951 outer_module_scope=env.global_scope())) 3952 3953 3954class CTupleType(CType): 3955 # components [PyrexType] 3956 3957 is_ctuple = True 3958 3959 def __init__(self, cname, components): 3960 self.cname = cname 3961 self.components = components 3962 self.size = len(components) 3963 self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname) 3964 self.from_py_function = "%s_from_py_%s" % (Naming.convert_func_prefix, self.cname) 3965 self.exception_check = True 3966 self._convert_to_py_code = None 3967 self._convert_from_py_code = None 3968 3969 def __str__(self): 3970 return "(%s)" % ", ".join(str(c) for c in self.components) 3971 3972 def declaration_code(self, entity_code, 3973 for_display = 0, dll_linkage = None, pyrex = 0): 3974 if pyrex or for_display: 3975 return str(self) 3976 else: 3977 return self.base_declaration_code(self.cname, entity_code) 3978 3979 def can_coerce_to_pyobject(self, env): 3980 for component in self.components: 3981 if not component.can_coerce_to_pyobject(env): 3982 return False 3983 return True 3984 3985 def can_coerce_from_pyobject(self, env): 3986 for component in self.components: 3987 if not component.can_coerce_from_pyobject(env): 3988 return False 3989 return True 3990 3991 def create_to_py_utility_code(self, env): 3992 if self._convert_to_py_code is False: 3993 return None # tri-state-ish 3994 3995 if self._convert_to_py_code is None: 3996 for component in self.components: 3997 if not component.create_to_py_utility_code(env): 3998 self.to_py_function = None 3999 self._convert_to_py_code = False 4000 return False 4001 4002 context = dict( 4003 struct_type_decl=self.empty_declaration_code(), 4004 components=self.components, 4005 funcname=self.to_py_function, 4006 size=len(self.components) 4007 ) 4008 self._convert_to_py_code = TempitaUtilityCode.load( 4009 "ToPyCTupleUtility", "TypeConversion.c", context=context) 4010 4011 env.use_utility_code(self._convert_to_py_code) 4012 return True 4013 4014 def create_from_py_utility_code(self, env): 4015 if self._convert_from_py_code is False: 4016 return None # tri-state-ish 4017 4018 if self._convert_from_py_code is None: 4019 for component in self.components: 4020 if not component.create_from_py_utility_code(env): 4021 self.from_py_function = None 4022 self._convert_from_py_code = False 4023 return False 4024 4025 context = dict( 4026 struct_type_decl=self.empty_declaration_code(), 4027 components=self.components, 4028 funcname=self.from_py_function, 4029 size=len(self.components) 4030 ) 4031 self._convert_from_py_code = TempitaUtilityCode.load( 4032 "FromPyCTupleUtility", "TypeConversion.c", context=context) 4033 4034 env.use_utility_code(self._convert_from_py_code) 4035 return True 4036 4037 def cast_code(self, expr_code): 4038 return expr_code 4039 4040 4041def c_tuple_type(components): 4042 components = tuple(components) 4043 cname = Naming.ctuple_type_prefix + type_list_identifier(components) 4044 tuple_type = CTupleType(cname, components) 4045 return tuple_type 4046 4047 4048class UnspecifiedType(PyrexType): 4049 # Used as a placeholder until the type can be determined. 4050 4051 is_unspecified = 1 4052 4053 def declaration_code(self, entity_code, 4054 for_display = 0, dll_linkage = None, pyrex = 0): 4055 return "<unspecified>" 4056 4057 def same_as_resolved_type(self, other_type): 4058 return False 4059 4060 4061class ErrorType(PyrexType): 4062 # Used to prevent propagation of error messages. 4063 4064 is_error = 1 4065 exception_value = "0" 4066 exception_check = 0 4067 to_py_function = "dummy" 4068 from_py_function = "dummy" 4069 4070 def create_to_py_utility_code(self, env): 4071 return True 4072 4073 def create_from_py_utility_code(self, env): 4074 return True 4075 4076 def declaration_code(self, entity_code, 4077 for_display = 0, dll_linkage = None, pyrex = 0): 4078 return "<error>" 4079 4080 def same_as_resolved_type(self, other_type): 4081 return 1 4082 4083 def error_condition(self, result_code): 4084 return "dummy" 4085 4086 4087rank_to_type_name = ( 4088 "char", # 0 4089 "short", # 1 4090 "int", # 2 4091 "long", # 3 4092 "PY_LONG_LONG", # 4 4093 "float", # 5 4094 "double", # 6 4095 "long double", # 7 4096) 4097 4098_rank_to_type_name = list(rank_to_type_name) 4099RANK_INT = _rank_to_type_name.index('int') 4100RANK_LONG = _rank_to_type_name.index('long') 4101RANK_FLOAT = _rank_to_type_name.index('float') 4102UNSIGNED = 0 4103SIGNED = 2 4104 4105error_type = ErrorType() 4106unspecified_type = UnspecifiedType() 4107 4108py_object_type = PyObjectType() 4109 4110c_void_type = CVoidType() 4111 4112c_uchar_type = CIntType(0, UNSIGNED) 4113c_ushort_type = CIntType(1, UNSIGNED) 4114c_uint_type = CIntType(2, UNSIGNED) 4115c_ulong_type = CIntType(3, UNSIGNED) 4116c_ulonglong_type = CIntType(4, UNSIGNED) 4117 4118c_char_type = CIntType(0) 4119c_short_type = CIntType(1) 4120c_int_type = CIntType(2) 4121c_long_type = CIntType(3) 4122c_longlong_type = CIntType(4) 4123 4124c_schar_type = CIntType(0, SIGNED) 4125c_sshort_type = CIntType(1, SIGNED) 4126c_sint_type = CIntType(2, SIGNED) 4127c_slong_type = CIntType(3, SIGNED) 4128c_slonglong_type = CIntType(4, SIGNED) 4129 4130c_float_type = CFloatType(5, math_h_modifier='f') 4131c_double_type = CFloatType(6) 4132c_longdouble_type = CFloatType(7, math_h_modifier='l') 4133 4134c_float_complex_type = CComplexType(c_float_type) 4135c_double_complex_type = CComplexType(c_double_type) 4136c_longdouble_complex_type = CComplexType(c_longdouble_type) 4137 4138c_anon_enum_type = CAnonEnumType(-1) 4139c_returncode_type = CReturnCodeType(RANK_INT) 4140c_bint_type = CBIntType(RANK_INT) 4141c_py_unicode_type = CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED) 4142c_py_ucs4_type = CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED) 4143c_py_hash_t_type = CPyHashTType(RANK_LONG+0.5, SIGNED) 4144c_py_ssize_t_type = CPySSizeTType(RANK_LONG+0.5, SIGNED) 4145c_ssize_t_type = CSSizeTType(RANK_LONG+0.5, SIGNED) 4146c_size_t_type = CSizeTType(RANK_LONG+0.5, UNSIGNED) 4147c_ptrdiff_t_type = CPtrdiffTType(RANK_LONG+0.75, SIGNED) 4148 4149c_null_ptr_type = CNullPtrType(c_void_type) 4150c_void_ptr_type = CPtrType(c_void_type) 4151c_void_ptr_ptr_type = CPtrType(c_void_ptr_type) 4152c_char_ptr_type = CPtrType(c_char_type) 4153c_const_char_ptr_type = CPtrType(CConstType(c_char_type)) 4154c_uchar_ptr_type = CPtrType(c_uchar_type) 4155c_const_uchar_ptr_type = CPtrType(CConstType(c_uchar_type)) 4156c_char_ptr_ptr_type = CPtrType(c_char_ptr_type) 4157c_int_ptr_type = CPtrType(c_int_type) 4158c_py_unicode_ptr_type = CPtrType(c_py_unicode_type) 4159c_const_py_unicode_ptr_type = CPtrType(CConstType(c_py_unicode_type)) 4160c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type) 4161c_ssize_t_ptr_type = CPtrType(c_ssize_t_type) 4162c_size_t_ptr_type = CPtrType(c_size_t_type) 4163 4164# GIL state 4165c_gilstate_type = CEnumType("PyGILState_STATE", "PyGILState_STATE", True) 4166c_threadstate_type = CStructOrUnionType("PyThreadState", "struct", None, 1, "PyThreadState") 4167c_threadstate_ptr_type = CPtrType(c_threadstate_type) 4168 4169# PEP-539 "Py_tss_t" type 4170c_pytss_t_type = CPyTSSTType() 4171 4172# the Py_buffer type is defined in Builtin.py 4173c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer") 4174c_py_buffer_ptr_type = CPtrType(c_py_buffer_type) 4175 4176# Not sure whether the unsigned versions and 'long long' should be in there 4177# long long requires C99 and might be slow, and would always get preferred 4178# when specialization happens through calling and not indexing 4179cy_integral_type = FusedType([c_short_type, c_int_type, c_long_type], 4180 name="integral") 4181# Omitting long double as it might be slow 4182cy_floating_type = FusedType([c_float_type, c_double_type], name="floating") 4183cy_numeric_type = FusedType([c_short_type, 4184 c_int_type, 4185 c_long_type, 4186 c_float_type, 4187 c_double_type, 4188 c_float_complex_type, 4189 c_double_complex_type], name="numeric") 4190 4191# buffer-related structs 4192c_buf_diminfo_type = CStructOrUnionType("__Pyx_Buf_DimInfo", "struct", 4193 None, 1, "__Pyx_Buf_DimInfo") 4194c_pyx_buffer_type = CStructOrUnionType("__Pyx_Buffer", "struct", None, 1, "__Pyx_Buffer") 4195c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type) 4196c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct", 4197 None, 1, "__Pyx_LocalBuf_ND") 4198 4199cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct", 4200 None, 0, "__pyx_memoryview_obj") 4201 4202memoryviewslice_type = CStructOrUnionType("memoryviewslice", "struct", 4203 None, 1, "__Pyx_memviewslice") 4204 4205modifiers_and_name_to_type = { 4206 #(signed, longness, name) : type 4207 (0, 0, "char"): c_uchar_type, 4208 (1, 0, "char"): c_char_type, 4209 (2, 0, "char"): c_schar_type, 4210 4211 (0, -1, "int"): c_ushort_type, 4212 (0, 0, "int"): c_uint_type, 4213 (0, 1, "int"): c_ulong_type, 4214 (0, 2, "int"): c_ulonglong_type, 4215 4216 (1, -1, "int"): c_short_type, 4217 (1, 0, "int"): c_int_type, 4218 (1, 1, "int"): c_long_type, 4219 (1, 2, "int"): c_longlong_type, 4220 4221 (2, -1, "int"): c_sshort_type, 4222 (2, 0, "int"): c_sint_type, 4223 (2, 1, "int"): c_slong_type, 4224 (2, 2, "int"): c_slonglong_type, 4225 4226 (1, 0, "float"): c_float_type, 4227 (1, 0, "double"): c_double_type, 4228 (1, 1, "double"): c_longdouble_type, 4229 4230 (1, 0, "complex"): c_double_complex_type, # C: float, Python: double => Python wins 4231 (1, 0, "floatcomplex"): c_float_complex_type, 4232 (1, 0, "doublecomplex"): c_double_complex_type, 4233 (1, 1, "doublecomplex"): c_longdouble_complex_type, 4234 4235 # 4236 (1, 0, "void"): c_void_type, 4237 (1, 0, "Py_tss_t"): c_pytss_t_type, 4238 4239 (1, 0, "bint"): c_bint_type, 4240 (0, 0, "Py_UNICODE"): c_py_unicode_type, 4241 (0, 0, "Py_UCS4"): c_py_ucs4_type, 4242 (2, 0, "Py_hash_t"): c_py_hash_t_type, 4243 (2, 0, "Py_ssize_t"): c_py_ssize_t_type, 4244 (2, 0, "ssize_t") : c_ssize_t_type, 4245 (0, 0, "size_t") : c_size_t_type, 4246 (2, 0, "ptrdiff_t") : c_ptrdiff_t_type, 4247 4248 (1, 0, "object"): py_object_type, 4249} 4250 4251def is_promotion(src_type, dst_type): 4252 # It's hard to find a hard definition of promotion, but empirical 4253 # evidence suggests that the below is all that's allowed. 4254 if src_type.is_numeric: 4255 if dst_type.same_as(c_int_type): 4256 unsigned = (not src_type.signed) 4257 return (src_type.is_enum or 4258 (src_type.is_int and 4259 unsigned + src_type.rank < dst_type.rank)) 4260 elif dst_type.same_as(c_double_type): 4261 return src_type.is_float and src_type.rank <= dst_type.rank 4262 return False 4263 4264def best_match(arg_types, functions, pos=None, env=None, args=None): 4265 """ 4266 Given a list args of arguments and a list of functions, choose one 4267 to call which seems to be the "best" fit for this list of arguments. 4268 This function is used, e.g., when deciding which overloaded method 4269 to dispatch for C++ classes. 4270 4271 We first eliminate functions based on arity, and if only one 4272 function has the correct arity, we return it. Otherwise, we weight 4273 functions based on how much work must be done to convert the 4274 arguments, with the following priorities: 4275 * identical types or pointers to identical types 4276 * promotions 4277 * non-Python types 4278 That is, we prefer functions where no arguments need converted, 4279 and failing that, functions where only promotions are required, and 4280 so on. 4281 4282 If no function is deemed a good fit, or if two or more functions have 4283 the same weight, we return None (as there is no best match). If pos 4284 is not None, we also generate an error. 4285 """ 4286 # TODO: args should be a list of types, not a list of Nodes. 4287 actual_nargs = len(arg_types) 4288 4289 candidates = [] 4290 errors = [] 4291 for func in functions: 4292 error_mesg = "" 4293 func_type = func.type 4294 if func_type.is_ptr: 4295 func_type = func_type.base_type 4296 # Check function type 4297 if not func_type.is_cfunction: 4298 if not func_type.is_error and pos is not None: 4299 error_mesg = "Calling non-function type '%s'" % func_type 4300 errors.append((func, error_mesg)) 4301 continue 4302 # Check no. of args 4303 max_nargs = len(func_type.args) 4304 min_nargs = max_nargs - func_type.optional_arg_count 4305 if actual_nargs < min_nargs or \ 4306 (not func_type.has_varargs and actual_nargs > max_nargs): 4307 if max_nargs == min_nargs and not func_type.has_varargs: 4308 expectation = max_nargs 4309 elif actual_nargs < min_nargs: 4310 expectation = "at least %s" % min_nargs 4311 else: 4312 expectation = "at most %s" % max_nargs 4313 error_mesg = "Call with wrong number of arguments (expected %s, got %s)" \ 4314 % (expectation, actual_nargs) 4315 errors.append((func, error_mesg)) 4316 continue 4317 if func_type.templates: 4318 deductions = reduce( 4319 merge_template_deductions, 4320 [pattern.type.deduce_template_params(actual) for (pattern, actual) in zip(func_type.args, arg_types)], 4321 {}) 4322 if deductions is None: 4323 errors.append((func, "Unable to deduce type parameters for %s given (%s)" % (func_type, ', '.join(map(str, arg_types))))) 4324 elif len(deductions) < len(func_type.templates): 4325 errors.append((func, "Unable to deduce type parameter %s" % ( 4326 ", ".join([param.name for param in set(func_type.templates) - set(deductions.keys())])))) 4327 else: 4328 type_list = [deductions[param] for param in func_type.templates] 4329 from .Symtab import Entry 4330 specialization = Entry( 4331 name = func.name + "[%s]" % ",".join([str(t) for t in type_list]), 4332 cname = func.cname + "<%s>" % ",".join([t.empty_declaration_code() for t in type_list]), 4333 type = func_type.specialize(deductions), 4334 pos = func.pos) 4335 candidates.append((specialization, specialization.type)) 4336 else: 4337 candidates.append((func, func_type)) 4338 4339 # Optimize the most common case of no overloading... 4340 if len(candidates) == 1: 4341 return candidates[0][0] 4342 elif len(candidates) == 0: 4343 if pos is not None: 4344 func, errmsg = errors[0] 4345 if len(errors) == 1 or [1 for func, e in errors if e == errmsg]: 4346 error(pos, errmsg) 4347 else: 4348 error(pos, "no suitable method found") 4349 return None 4350 4351 possibilities = [] 4352 bad_types = [] 4353 needed_coercions = {} 4354 4355 for index, (func, func_type) in enumerate(candidates): 4356 score = [0,0,0,0,0,0,0] 4357 for i in range(min(actual_nargs, len(func_type.args))): 4358 src_type = arg_types[i] 4359 dst_type = func_type.args[i].type 4360 4361 assignable = dst_type.assignable_from(src_type) 4362 4363 # Now take care of unprefixed string literals. So when you call a cdef 4364 # function that takes a char *, the coercion will mean that the 4365 # type will simply become bytes. We need to do this coercion 4366 # manually for overloaded and fused functions 4367 if not assignable: 4368 c_src_type = None 4369 if src_type.is_pyobject: 4370 if src_type.is_builtin_type and src_type.name == 'str' and dst_type.resolve().is_string: 4371 c_src_type = dst_type.resolve() 4372 else: 4373 c_src_type = src_type.default_coerced_ctype() 4374 elif src_type.is_pythran_expr: 4375 c_src_type = src_type.org_buffer 4376 4377 if c_src_type is not None: 4378 assignable = dst_type.assignable_from(c_src_type) 4379 if assignable: 4380 src_type = c_src_type 4381 needed_coercions[func] = (i, dst_type) 4382 4383 if assignable: 4384 if src_type == dst_type or dst_type.same_as(src_type): 4385 pass # score 0 4386 elif func_type.is_strict_signature: 4387 break # exact match requested but not found 4388 elif is_promotion(src_type, dst_type): 4389 score[2] += 1 4390 elif ((src_type.is_int and dst_type.is_int) or 4391 (src_type.is_float and dst_type.is_float)): 4392 score[2] += abs(dst_type.rank + (not dst_type.signed) - 4393 (src_type.rank + (not src_type.signed))) + 1 4394 elif dst_type.is_ptr and src_type.is_ptr: 4395 if dst_type.base_type == c_void_type: 4396 score[4] += 1 4397 elif src_type.base_type.is_cpp_class and src_type.base_type.is_subclass(dst_type.base_type): 4398 score[6] += src_type.base_type.subclass_dist(dst_type.base_type) 4399 else: 4400 score[5] += 1 4401 elif not src_type.is_pyobject: 4402 score[1] += 1 4403 else: 4404 score[0] += 1 4405 else: 4406 error_mesg = "Invalid conversion from '%s' to '%s'" % (src_type, dst_type) 4407 bad_types.append((func, error_mesg)) 4408 break 4409 else: 4410 possibilities.append((score, index, func)) # so we can sort it 4411 4412 if possibilities: 4413 possibilities.sort() 4414 if len(possibilities) > 1: 4415 score1 = possibilities[0][0] 4416 score2 = possibilities[1][0] 4417 if score1 == score2: 4418 if pos is not None: 4419 error(pos, "ambiguous overloaded method") 4420 return None 4421 4422 function = possibilities[0][-1] 4423 4424 if function in needed_coercions and env: 4425 arg_i, coerce_to_type = needed_coercions[function] 4426 args[arg_i] = args[arg_i].coerce_to(coerce_to_type, env) 4427 4428 return function 4429 4430 if pos is not None: 4431 if len(bad_types) == 1: 4432 error(pos, bad_types[0][1]) 4433 else: 4434 error(pos, "no suitable method found") 4435 4436 return None 4437 4438def merge_template_deductions(a, b): 4439 if a is None or b is None: 4440 return None 4441 all = a 4442 for param, value in b.items(): 4443 if param in all: 4444 if a[param] != b[param]: 4445 return None 4446 else: 4447 all[param] = value 4448 return all 4449 4450 4451def widest_numeric_type(type1, type2): 4452 """Given two numeric types, return the narrowest type encompassing both of them. 4453 """ 4454 if type1.is_reference: 4455 type1 = type1.ref_base_type 4456 if type2.is_reference: 4457 type2 = type2.ref_base_type 4458 if type1.is_const: 4459 type1 = type1.const_base_type 4460 if type2.is_const: 4461 type2 = type2.const_base_type 4462 if type1 == type2: 4463 widest_type = type1 4464 elif type1.is_complex or type2.is_complex: 4465 def real_type(ntype): 4466 if ntype.is_complex: 4467 return ntype.real_type 4468 return ntype 4469 widest_type = CComplexType( 4470 widest_numeric_type( 4471 real_type(type1), 4472 real_type(type2))) 4473 elif type1.is_enum and type2.is_enum: 4474 widest_type = c_int_type 4475 elif type1.rank < type2.rank: 4476 widest_type = type2 4477 elif type1.rank > type2.rank: 4478 widest_type = type1 4479 elif type1.signed < type2.signed: 4480 widest_type = type1 4481 elif type1.signed > type2.signed: 4482 widest_type = type2 4483 elif type1.is_typedef > type2.is_typedef: 4484 widest_type = type1 4485 else: 4486 widest_type = type2 4487 return widest_type 4488 4489 4490def numeric_type_fits(small_type, large_type): 4491 return widest_numeric_type(small_type, large_type) == large_type 4492 4493 4494def independent_spanning_type(type1, type2): 4495 # Return a type assignable independently from both type1 and 4496 # type2, but do not require any interoperability between the two. 4497 # For example, in "True * 2", it is safe to assume an integer 4498 # result type (so spanning_type() will do the right thing), 4499 # whereas "x = True or 2" must evaluate to a type that can hold 4500 # both a boolean value and an integer, so this function works 4501 # better. 4502 if type1.is_reference ^ type2.is_reference: 4503 if type1.is_reference: 4504 type1 = type1.ref_base_type 4505 else: 4506 type2 = type2.ref_base_type 4507 if type1 == type2: 4508 return type1 4509 elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric): 4510 # special case: if one of the results is a bint and the other 4511 # is another C integer, we must prevent returning a numeric 4512 # type so that we do not lose the ability to coerce to a 4513 # Python bool if we have to. 4514 return py_object_type 4515 span_type = _spanning_type(type1, type2) 4516 if span_type is None: 4517 return error_type 4518 return span_type 4519 4520def spanning_type(type1, type2): 4521 # Return a type assignable from both type1 and type2, or 4522 # py_object_type if no better type is found. Assumes that the 4523 # code that calls this will try a coercion afterwards, which will 4524 # fail if the types cannot actually coerce to a py_object_type. 4525 if type1 == type2: 4526 return type1 4527 elif type1 is py_object_type or type2 is py_object_type: 4528 return py_object_type 4529 elif type1 is c_py_unicode_type or type2 is c_py_unicode_type: 4530 # Py_UNICODE behaves more like a string than an int 4531 return py_object_type 4532 span_type = _spanning_type(type1, type2) 4533 if span_type is None: 4534 return py_object_type 4535 return span_type 4536 4537def _spanning_type(type1, type2): 4538 if type1.is_numeric and type2.is_numeric: 4539 return widest_numeric_type(type1, type2) 4540 elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric: 4541 return widest_numeric_type(c_double_type, type2) 4542 elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric: 4543 return widest_numeric_type(type1, c_double_type) 4544 elif type1.is_extension_type and type2.is_extension_type: 4545 return widest_extension_type(type1, type2) 4546 elif type1.is_pyobject or type2.is_pyobject: 4547 return py_object_type 4548 elif type1.assignable_from(type2): 4549 if type1.is_extension_type and type1.typeobj_is_imported(): 4550 # external types are unsafe, so we use PyObject instead 4551 return py_object_type 4552 return type1 4553 elif type2.assignable_from(type1): 4554 if type2.is_extension_type and type2.typeobj_is_imported(): 4555 # external types are unsafe, so we use PyObject instead 4556 return py_object_type 4557 return type2 4558 elif type1.is_ptr and type2.is_ptr: 4559 if type1.base_type.is_cpp_class and type2.base_type.is_cpp_class: 4560 common_base = widest_cpp_type(type1.base_type, type2.base_type) 4561 if common_base: 4562 return CPtrType(common_base) 4563 # incompatible pointers, void* will do as a result 4564 return c_void_ptr_type 4565 else: 4566 return None 4567 4568def widest_extension_type(type1, type2): 4569 if type1.typeobj_is_imported() or type2.typeobj_is_imported(): 4570 return py_object_type 4571 while True: 4572 if type1.subtype_of(type2): 4573 return type2 4574 elif type2.subtype_of(type1): 4575 return type1 4576 type1, type2 = type1.base_type, type2.base_type 4577 if type1 is None or type2 is None: 4578 return py_object_type 4579 4580def widest_cpp_type(type1, type2): 4581 @cached_function 4582 def bases(type): 4583 all = set() 4584 for base in type.base_classes: 4585 all.add(base) 4586 all.update(bases(base)) 4587 return all 4588 common_bases = bases(type1).intersection(bases(type2)) 4589 common_bases_bases = reduce(set.union, [bases(b) for b in common_bases], set()) 4590 candidates = [b for b in common_bases if b not in common_bases_bases] 4591 if len(candidates) == 1: 4592 return candidates[0] 4593 else: 4594 # Fall back to void* for now. 4595 return None 4596 4597 4598def simple_c_type(signed, longness, name): 4599 # Find type descriptor for simple type given name and modifiers. 4600 # Returns None if arguments don't make sense. 4601 return modifiers_and_name_to_type.get((signed, longness, name)) 4602 4603def parse_basic_type(name): 4604 base = None 4605 if name.startswith('p_'): 4606 base = parse_basic_type(name[2:]) 4607 elif name.startswith('p'): 4608 base = parse_basic_type(name[1:]) 4609 elif name.endswith('*'): 4610 base = parse_basic_type(name[:-1]) 4611 if base: 4612 return CPtrType(base) 4613 # 4614 basic_type = simple_c_type(1, 0, name) 4615 if basic_type: 4616 return basic_type 4617 # 4618 signed = 1 4619 longness = 0 4620 if name == 'Py_UNICODE': 4621 signed = 0 4622 elif name == 'Py_UCS4': 4623 signed = 0 4624 elif name == 'Py_hash_t': 4625 signed = 2 4626 elif name == 'Py_ssize_t': 4627 signed = 2 4628 elif name == 'ssize_t': 4629 signed = 2 4630 elif name == 'size_t': 4631 signed = 0 4632 else: 4633 if name.startswith('u'): 4634 name = name[1:] 4635 signed = 0 4636 elif (name.startswith('s') and 4637 not name.startswith('short')): 4638 name = name[1:] 4639 signed = 2 4640 longness = 0 4641 while name.startswith('short'): 4642 name = name.replace('short', '', 1).strip() 4643 longness -= 1 4644 while name.startswith('long'): 4645 name = name.replace('long', '', 1).strip() 4646 longness += 1 4647 if longness != 0 and not name: 4648 name = 'int' 4649 return simple_c_type(signed, longness, name) 4650 4651def c_array_type(base_type, size): 4652 # Construct a C array type. 4653 if base_type is error_type: 4654 return error_type 4655 else: 4656 return CArrayType(base_type, size) 4657 4658def c_ptr_type(base_type): 4659 # Construct a C pointer type. 4660 if base_type is error_type: 4661 return error_type 4662 elif base_type.is_reference: 4663 return CPtrType(base_type.ref_base_type) 4664 else: 4665 return CPtrType(base_type) 4666 4667def c_ref_type(base_type): 4668 # Construct a C reference type 4669 if base_type is error_type: 4670 return error_type 4671 else: 4672 return CReferenceType(base_type) 4673 4674def c_const_type(base_type): 4675 # Construct a C const type. 4676 if base_type is error_type: 4677 return error_type 4678 else: 4679 return CConstType(base_type) 4680 4681def same_type(type1, type2): 4682 return type1.same_as(type2) 4683 4684def assignable_from(type1, type2): 4685 return type1.assignable_from(type2) 4686 4687def typecast(to_type, from_type, expr_code): 4688 # Return expr_code cast to a C type which can be 4689 # assigned to to_type, assuming its existing C type 4690 # is from_type. 4691 if (to_type is from_type or 4692 (not to_type.is_pyobject and assignable_from(to_type, from_type))): 4693 return expr_code 4694 elif (to_type is py_object_type and from_type and 4695 from_type.is_builtin_type and from_type.name != 'type'): 4696 # no cast needed, builtins are PyObject* already 4697 return expr_code 4698 else: 4699 #print "typecast: to", to_type, "from", from_type ### 4700 return to_type.cast_code(expr_code) 4701 4702def type_list_identifier(types): 4703 return cap_length('__and_'.join(type_identifier(type) for type in types)) 4704 4705_type_identifier_cache = {} 4706def type_identifier(type): 4707 decl = type.empty_declaration_code() 4708 safe = _type_identifier_cache.get(decl) 4709 if safe is None: 4710 safe = decl 4711 safe = re.sub(' +', ' ', safe) 4712 safe = re.sub(' ([^a-zA-Z0-9_])', r'\1', safe) 4713 safe = re.sub('([^a-zA-Z0-9_]) ', r'\1', safe) 4714 safe = (safe.replace('__', '__dunder') 4715 .replace('const ', '__const_') 4716 .replace(' ', '__space_') 4717 .replace('*', '__ptr') 4718 .replace('&', '__ref') 4719 .replace('[', '__lArr') 4720 .replace(']', '__rArr') 4721 .replace('<', '__lAng') 4722 .replace('>', '__rAng') 4723 .replace('(', '__lParen') 4724 .replace(')', '__rParen') 4725 .replace(',', '__comma_') 4726 .replace('::', '__in_')) 4727 safe = cap_length(re.sub('[^a-zA-Z0-9_]', lambda x: '__%X' % ord(x.group(0)), safe)) 4728 _type_identifier_cache[decl] = safe 4729 return safe 4730 4731def cap_length(s, max_prefix=63, max_len=1024): 4732 if len(s) <= max_prefix: 4733 return s 4734 hash_prefix = hashlib.sha256(s.encode('ascii')).hexdigest()[:6] 4735 return '%s__%s__etc' % (hash_prefix, s[:max_len-17]) 4736