1 # 2 # Parse tree nodes for expressions 3 # 4 5 import cython 6 cython.declare(error=object, warning=object, warn_once=object, InternalError=object, 7 CompileError=object, UtilityCode=object, TempitaUtilityCode=object, 8 StringEncoding=object, operator=object, 9 Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object, 10 list_type=object, tuple_type=object, set_type=object, dict_type=object, 11 unicode_type=object, str_type=object, bytes_type=object, type_type=object, 12 Builtin=object, Symtab=object, Utils=object, find_coercion_error=object, 13 debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object, 14 bytearray_type=object, slice_type=object) 15 16 import sys 17 import copy 18 import operator 19 20 from Errors import error, warning, warn_once, InternalError, CompileError 21 from Errors import hold_errors, release_errors, held_errors, report_error 22 from Code import UtilityCode, TempitaUtilityCode 23 import StringEncoding 24 import Naming 25 import Nodes 26 from Nodes import Node 27 import PyrexTypes 28 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \ 29 unspecified_type 30 import TypeSlots 31 from Builtin import list_type, tuple_type, set_type, dict_type, type_type, \ 32 unicode_type, str_type, bytes_type, bytearray_type, basestring_type, slice_type 33 import Builtin 34 import Symtab 35 from Cython import Utils 36 from Annotate import AnnotationItem 37 from Cython.Compiler import Future 38 from Cython.Debugging import print_call_chain 39 from DebugFlags import debug_disposal_code, debug_temp_alloc, \ 40 debug_coercion 41 42 try: 43 from __builtin__ import basestring 44 except ImportError: 45 basestring = str # Python 3 46 47 try: 48 from builtins import bytes 49 except ImportError: 50 bytes = str # Python 2 51 52 53 class NotConstant(object): 54 _obj = None 55 56 def __new__(cls): 57 if NotConstant._obj is None: 58 NotConstant._obj = super(NotConstant, cls).__new__(cls) 59 60 return NotConstant._obj 61 62 def __repr__(self): 63 return "<NOT CONSTANT>" 64 65 not_a_constant = NotConstant() 66 constant_value_not_set = object() 67 68 # error messages when coercing from key[0] to key[1] 69 coercion_error_dict = { 70 # string related errors 71 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.", 72 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.", 73 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.", 74 (Builtin.unicode_type, PyrexTypes.c_uchar_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.", 75 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required", 76 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.", 77 (Builtin.bytes_type, Builtin.basestring_type) : "Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3.", 78 (Builtin.bytes_type, PyrexTypes.c_py_unicode_ptr_type) : "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.", 79 (Builtin.basestring_type, Builtin.bytes_type) : "Cannot convert 'basestring' object to bytes implicitly. This is not portable.", 80 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')", 81 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.", 82 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).", 83 (Builtin.str_type, PyrexTypes.c_uchar_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).", 84 (Builtin.str_type, PyrexTypes.c_py_unicode_ptr_type) : "'str' objects do not support coercion to C types (use 'unicode'?).", 85 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required", 86 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required", 87 } 88 89 def find_coercion_error(type_tuple, default, env): 90 err = coercion_error_dict.get(type_tuple) 91 if err is None: 92 return default 93 elif ((PyrexTypes.c_char_ptr_type in type_tuple or PyrexTypes.c_uchar_ptr_type in type_tuple) 94 and env.directives['c_string_encoding']): 95 if type_tuple[1].is_pyobject: 96 return default 97 elif env.directives['c_string_encoding'] in ('ascii', 'default'): 98 return default 99 else: 100 return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple[0].name 101 else: 102 return err 103 104 105 def default_str_type(env): 106 return { 107 'bytes': bytes_type, 108 'bytearray': bytearray_type, 109 'str': str_type, 110 'unicode': unicode_type 111 }.get(env.directives['c_string_type']) 112 113 114 def check_negative_indices(*nodes): 115 """ 116 Raise a warning on nodes that are known to have negative numeric values. 117 Used to find (potential) bugs inside of "wraparound=False" sections. 118 """ 119 for node in nodes: 120 if (node is None 121 or not isinstance(node.constant_result, (int, float, long))): 122 continue 123 if node.constant_result < 0: 124 warning(node.pos, 125 "the result of using negative indices inside of " 126 "code sections marked as 'wraparound=False' is " 127 "undefined", level=1) 128 129 130 def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None): 131 if not seq_node.is_sequence_constructor: 132 if seq_type is None: 133 seq_type = seq_node.infer_type(env) 134 if seq_type is tuple_type: 135 # tuples are immutable => we can safely follow assignments 136 if seq_node.cf_state and len(seq_node.cf_state) == 1: 137 try: 138 seq_node = seq_node.cf_state[0].rhs 139 except AttributeError: 140 pass 141 if seq_node is not None and seq_node.is_sequence_constructor: 142 if index_node is not None and index_node.has_constant_result(): 143 try: 144 item = seq_node.args[index_node.constant_result] 145 except (ValueError, TypeError, IndexError): 146 pass 147 else: 148 return item.infer_type(env) 149 # if we're lucky, all items have the same type 150 item_types = set([item.infer_type(env) for item in seq_node.args]) 151 if len(item_types) == 1: 152 return item_types.pop() 153 return None 154 155 156 class ExprNode(Node): 157 # subexprs [string] Class var holding names of subexpr node attrs 158 # type PyrexType Type of the result 159 # result_code string Code fragment 160 # result_ctype string C type of result_code if different from type 161 # is_temp boolean Result is in a temporary variable 162 # is_sequence_constructor 163 # boolean Is a list or tuple constructor expression 164 # is_starred boolean Is a starred expression (e.g. '*a') 165 # saved_subexpr_nodes 166 # [ExprNode or [ExprNode or None] or None] 167 # Cached result of subexpr_nodes() 168 # use_managed_ref boolean use ref-counted temps/assignments/etc. 169 # result_is_used boolean indicates that the result will be dropped and the 170 # result_code/temp_result can safely be set to None 171 172 result_ctype = None 173 type = None 174 temp_code = None 175 old_temp = None # error checker for multiple frees etc. 176 use_managed_ref = True # can be set by optimisation transforms 177 result_is_used = True 178 179 # The Analyse Expressions phase for expressions is split 180 # into two sub-phases: 181 # 182 # Analyse Types 183 # Determines the result type of the expression based 184 # on the types of its sub-expressions, and inserts 185 # coercion nodes into the expression tree where needed. 186 # Marks nodes which will need to have temporary variables 187 # allocated. 188 # 189 # Allocate Temps 190 # Allocates temporary variables where needed, and fills 191 # in the result_code field of each node. 192 # 193 # ExprNode provides some convenience routines which 194 # perform both of the above phases. These should only 195 # be called from statement nodes, and only when no 196 # coercion nodes need to be added around the expression 197 # being analysed. In that case, the above two phases 198 # should be invoked separately. 199 # 200 # Framework code in ExprNode provides much of the common 201 # processing for the various phases. It makes use of the 202 # 'subexprs' class attribute of ExprNodes, which should 203 # contain a list of the names of attributes which can 204 # hold sub-nodes or sequences of sub-nodes. 205 # 206 # The framework makes use of a number of abstract methods. 207 # Their responsibilities are as follows. 208 # 209 # Declaration Analysis phase 210 # 211 # analyse_target_declaration 212 # Called during the Analyse Declarations phase to analyse 213 # the LHS of an assignment or argument of a del statement. 214 # Nodes which cannot be the LHS of an assignment need not 215 # implement it. 216 # 217 # Expression Analysis phase 218 # 219 # analyse_types 220 # - Call analyse_types on all sub-expressions. 221 # - Check operand types, and wrap coercion nodes around 222 # sub-expressions where needed. 223 # - Set the type of this node. 224 # - If a temporary variable will be required for the 225 # result, set the is_temp flag of this node. 226 # 227 # analyse_target_types 228 # Called during the Analyse Types phase to analyse 229 # the LHS of an assignment or argument of a del 230 # statement. Similar responsibilities to analyse_types. 231 # 232 # target_code 233 # Called by the default implementation of allocate_target_temps. 234 # Should return a C lvalue for assigning to the node. The default 235 # implementation calls calculate_result_code. 236 # 237 # check_const 238 # - Check that this node and its subnodes form a 239 # legal constant expression. If so, do nothing, 240 # otherwise call not_const. 241 # 242 # The default implementation of check_const 243 # assumes that the expression is not constant. 244 # 245 # check_const_addr 246 # - Same as check_const, except check that the 247 # expression is a C lvalue whose address is 248 # constant. Otherwise, call addr_not_const. 249 # 250 # The default implementation of calc_const_addr 251 # assumes that the expression is not a constant 252 # lvalue. 253 # 254 # Code Generation phase 255 # 256 # generate_evaluation_code 257 # - Call generate_evaluation_code for sub-expressions. 258 # - Perform the functions of generate_result_code 259 # (see below). 260 # - If result is temporary, call generate_disposal_code 261 # on all sub-expressions. 262 # 263 # A default implementation of generate_evaluation_code 264 # is provided which uses the following abstract methods: 265 # 266 # generate_result_code 267 # - Generate any C statements necessary to calculate 268 # the result of this node from the results of its 269 # sub-expressions. 270 # 271 # calculate_result_code 272 # - Should return a C code fragment evaluating to the 273 # result. This is only called when the result is not 274 # a temporary. 275 # 276 # generate_assignment_code 277 # Called on the LHS of an assignment. 278 # - Call generate_evaluation_code for sub-expressions. 279 # - Generate code to perform the assignment. 280 # - If the assignment absorbed a reference, call 281 # generate_post_assignment_code on the RHS, 282 # otherwise call generate_disposal_code on it. 283 # 284 # generate_deletion_code 285 # Called on an argument of a del statement. 286 # - Call generate_evaluation_code for sub-expressions. 287 # - Generate code to perform the deletion. 288 # - Call generate_disposal_code on all sub-expressions. 289 # 290 # 291 292 is_sequence_constructor = 0 293 is_string_literal = 0 294 is_attribute = 0 295 is_subscript = 0 296 297 saved_subexpr_nodes = None 298 is_temp = 0 299 is_target = 0 300 is_starred = 0 301 302 constant_result = constant_value_not_set 303 304 # whether this node with a memoryview type should be broadcast 305 memslice_broadcast = False 306 307 child_attrs = property(fget=operator.attrgetter('subexprs')) 308 309 def not_implemented(self, method_name): 310 print_call_chain(method_name, "not implemented") ### 311 raise InternalError( 312 "%s.%s not implemented" % 313 (self.__class__.__name__, method_name)) 314 315 def is_lvalue(self): 316 return 0 317 318 def is_addressable(self): 319 return self.is_lvalue() and not self.type.is_memoryviewslice 320 321 def is_ephemeral(self): 322 # An ephemeral node is one whose result is in 323 # a Python temporary and we suspect there are no 324 # other references to it. Certain operations are 325 # disallowed on such values, since they are 326 # likely to result in a dangling pointer. 327 return self.type.is_pyobject and self.is_temp 328 329 def subexpr_nodes(self): 330 # Extract a list of subexpression nodes based 331 # on the contents of the subexprs class attribute. 332 nodes = [] 333 for name in self.subexprs: 334 item = getattr(self, name) 335 if item is not None: 336 if type(item) is list: 337 nodes.extend(item) 338 else: 339 nodes.append(item) 340 return nodes 341 342 def result(self): 343 if self.is_temp: 344 return self.temp_code 345 else: 346 return self.calculate_result_code() 347 348 def result_as(self, type = None): 349 # Return the result code cast to the specified C type. 350 if (self.is_temp and self.type.is_pyobject and 351 type != py_object_type): 352 # Allocated temporaries are always PyObject *, which may not 353 # reflect the actual type (e.g. an extension type) 354 return typecast(type, py_object_type, self.result()) 355 return typecast(type, self.ctype(), self.result()) 356 357 def py_result(self): 358 # Return the result code cast to PyObject *. 359 return self.result_as(py_object_type) 360 361 def ctype(self): 362 # Return the native C type of the result (i.e. the 363 # C type of the result_code expression). 364 return self.result_ctype or self.type 365 366 def get_constant_c_result_code(self): 367 # Return the constant value of this node as a result code 368 # string, or None if the node is not constant. This method 369 # can be called when the constant result code is required 370 # before the code generation phase. 371 # 372 # The return value is a string that can represent a simple C 373 # value, a constant C name or a constant C expression. If the 374 # node type depends on Python code, this must return None. 375 return None 376 377 def calculate_constant_result(self): 378 # Calculate the constant compile time result value of this 379 # expression and store it in ``self.constant_result``. Does 380 # nothing by default, thus leaving ``self.constant_result`` 381 # unknown. If valid, the result can be an arbitrary Python 382 # value. 383 # 384 # This must only be called when it is assured that all 385 # sub-expressions have a valid constant_result value. The 386 # ConstantFolding transform will do this. 387 pass 388 389 def has_constant_result(self): 390 return self.constant_result is not constant_value_not_set and \ 391 self.constant_result is not not_a_constant 392 393 def compile_time_value(self, denv): 394 # Return value of compile-time expression, or report error. 395 error(self.pos, "Invalid compile-time expression") 396 397 def compile_time_value_error(self, e): 398 error(self.pos, "Error in compile-time expression: %s: %s" % ( 399 e.__class__.__name__, e)) 400 401 # ------------- Declaration Analysis ---------------- 402 403 def analyse_target_declaration(self, env): 404 error(self.pos, "Cannot assign to or delete this") 405 406 # ------------- Expression Analysis ---------------- 407 408 def analyse_const_expression(self, env): 409 # Called during the analyse_declarations phase of a 410 # constant expression. Analyses the expression's type, 411 # checks whether it is a legal const expression, 412 # and determines its value. 413 node = self.analyse_types(env) 414 node.check_const() 415 return node 416 417 def analyse_expressions(self, env): 418 # Convenience routine performing both the Type 419 # Analysis and Temp Allocation phases for a whole 420 # expression. 421 return self.analyse_types(env) 422 423 def analyse_target_expression(self, env, rhs): 424 # Convenience routine performing both the Type 425 # Analysis and Temp Allocation phases for the LHS of 426 # an assignment. 427 return self.analyse_target_types(env) 428 429 def analyse_boolean_expression(self, env): 430 # Analyse expression and coerce to a boolean. 431 node = self.analyse_types(env) 432 bool = node.coerce_to_boolean(env) 433 return bool 434 435 def analyse_temp_boolean_expression(self, env): 436 # Analyse boolean expression and coerce result into 437 # a temporary. This is used when a branch is to be 438 # performed on the result and we won't have an 439 # opportunity to ensure disposal code is executed 440 # afterwards. By forcing the result into a temporary, 441 # we ensure that all disposal has been done by the 442 # time we get the result. 443 node = self.analyse_types(env) 444 return node.coerce_to_boolean(env).coerce_to_simple(env) 445 446 # --------------- Type Inference ----------------- 447 448 def type_dependencies(self, env): 449 # Returns the list of entries whose types must be determined 450 # before the type of self can be inferred. 451 if hasattr(self, 'type') and self.type is not None: 452 return () 453 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ()) 454 455 def infer_type(self, env): 456 # Attempt to deduce the type of self. 457 # Differs from analyse_types as it avoids unnecessary 458 # analysis of subexpressions, but can assume everything 459 # in self.type_dependencies() has been resolved. 460 if hasattr(self, 'type') and self.type is not None: 461 return self.type 462 elif hasattr(self, 'entry') and self.entry is not None: 463 return self.entry.type 464 else: 465 self.not_implemented("infer_type") 466 467 def nonlocally_immutable(self): 468 # Returns whether this variable is a safe reference, i.e. 469 # can't be modified as part of globals or closures. 470 return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction 471 472 # --------------- Type Analysis ------------------ 473 474 def analyse_as_module(self, env): 475 # If this node can be interpreted as a reference to a 476 # cimported module, return its scope, else None. 477 return None 478 479 def analyse_as_type(self, env): 480 # If this node can be interpreted as a reference to a 481 # type, return that type, else None. 482 return None 483 484 def analyse_as_extension_type(self, env): 485 # If this node can be interpreted as a reference to an 486 # extension type or builtin type, return its type, else None. 487 return None 488 489 def analyse_types(self, env): 490 self.not_implemented("analyse_types") 491 492 def analyse_target_types(self, env): 493 return self.analyse_types(env) 494 495 def nogil_check(self, env): 496 # By default, any expression based on Python objects is 497 # prevented in nogil environments. Subtypes must override 498 # this if they can work without the GIL. 499 if self.type and self.type.is_pyobject: 500 self.gil_error() 501 502 def gil_assignment_check(self, env): 503 if env.nogil and self.type.is_pyobject: 504 error(self.pos, "Assignment of Python object not allowed without gil") 505 506 def check_const(self): 507 self.not_const() 508 return False 509 510 def not_const(self): 511 error(self.pos, "Not allowed in a constant expression") 512 513 def check_const_addr(self): 514 self.addr_not_const() 515 return False 516 517 def addr_not_const(self): 518 error(self.pos, "Address is not constant") 519 520 # ----------------- Result Allocation ----------------- 521 522 def result_in_temp(self): 523 # Return true if result is in a temporary owned by 524 # this node or one of its subexpressions. Overridden 525 # by certain nodes which can share the result of 526 # a subnode. 527 return self.is_temp 528 529 def target_code(self): 530 # Return code fragment for use as LHS of a C assignment. 531 return self.calculate_result_code() 532 533 def calculate_result_code(self): 534 self.not_implemented("calculate_result_code") 535 536 # def release_target_temp(self, env): 537 # # Release temporaries used by LHS of an assignment. 538 # self.release_subexpr_temps(env) 539 540 def allocate_temp_result(self, code): 541 if self.temp_code: 542 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos)) 543 type = self.type 544 if not type.is_void: 545 if type.is_pyobject: 546 type = PyrexTypes.py_object_type 547 self.temp_code = code.funcstate.allocate_temp( 548 type, manage_ref=self.use_managed_ref) 549 else: 550 self.temp_code = None 551 552 def release_temp_result(self, code): 553 if not self.temp_code: 554 if not self.result_is_used: 555 # not used anyway, so ignore if not set up 556 return 557 if self.old_temp: 558 raise RuntimeError("temp %s released multiple times in %s" % ( 559 self.old_temp, self.__class__.__name__)) 560 else: 561 raise RuntimeError("no temp, but release requested in %s" % ( 562 self.__class__.__name__)) 563 code.funcstate.release_temp(self.temp_code) 564 self.old_temp = self.temp_code 565 self.temp_code = None 566 567 # ---------------- Code Generation ----------------- 568 569 def make_owned_reference(self, code): 570 """ 571 If result is a pyobject, make sure we own a reference to it. 572 If the result is in a temp, it is already a new reference. 573 """ 574 if self.type.is_pyobject and not self.result_in_temp(): 575 code.put_incref(self.result(), self.ctype()) 576 577 def make_owned_memoryviewslice(self, code): 578 """ 579 Make sure we own the reference to this memoryview slice. 580 """ 581 if not self.result_in_temp(): 582 code.put_incref_memoryviewslice(self.result(), 583 have_gil=self.in_nogil_context) 584 585 def generate_evaluation_code(self, code): 586 # Generate code to evaluate this node and 587 # its sub-expressions, and dispose of any 588 # temporary results of its sub-expressions. 589 self.generate_subexpr_evaluation_code(code) 590 591 code.mark_pos(self.pos) 592 if self.is_temp: 593 self.allocate_temp_result(code) 594 595 self.generate_result_code(code) 596 if self.is_temp: 597 # If we are temp we do not need to wait until this node is disposed 598 # before disposing children. 599 self.generate_subexpr_disposal_code(code) 600 self.free_subexpr_temps(code) 601 602 def generate_subexpr_evaluation_code(self, code): 603 for node in self.subexpr_nodes(): 604 node.generate_evaluation_code(code) 605 606 def generate_result_code(self, code): 607 self.not_implemented("generate_result_code") 608 609 def generate_disposal_code(self, code): 610 if self.is_temp: 611 if self.result(): 612 if self.type.is_pyobject: 613 code.put_decref_clear(self.result(), self.ctype()) 614 elif self.type.is_memoryviewslice: 615 code.put_xdecref_memoryviewslice( 616 self.result(), have_gil=not self.in_nogil_context) 617 else: 618 # Already done if self.is_temp 619 self.generate_subexpr_disposal_code(code) 620 621 def generate_subexpr_disposal_code(self, code): 622 # Generate code to dispose of temporary results 623 # of all sub-expressions. 624 for node in self.subexpr_nodes(): 625 node.generate_disposal_code(code) 626 627 def generate_post_assignment_code(self, code): 628 if self.is_temp: 629 if self.type.is_pyobject: 630 code.putln("%s = 0;" % self.result()) 631 elif self.type.is_memoryviewslice: 632 code.putln("%s.memview = NULL;" % self.result()) 633 code.putln("%s.data = NULL;" % self.result()) 634 else: 635 self.generate_subexpr_disposal_code(code) 636 637 def generate_assignment_code(self, rhs, code): 638 # Stub method for nodes which are not legal as 639 # the LHS of an assignment. An error will have 640 # been reported earlier. 641 pass 642 643 def generate_deletion_code(self, code, ignore_nonexisting=False): 644 # Stub method for nodes that are not legal as 645 # the argument of a del statement. An error 646 # will have been reported earlier. 647 pass 648 649 def free_temps(self, code): 650 if self.is_temp: 651 if not self.type.is_void: 652 self.release_temp_result(code) 653 else: 654 self.free_subexpr_temps(code) 655 656 def free_subexpr_temps(self, code): 657 for sub in self.subexpr_nodes(): 658 sub.free_temps(code) 659 660 def generate_function_definitions(self, env, code): 661 pass 662 663 # ---------------- Annotation --------------------- 664 665 def annotate(self, code): 666 for node in self.subexpr_nodes(): 667 node.annotate(code) 668 669 # ----------------- Coercion ---------------------- 670 671 def coerce_to(self, dst_type, env): 672 # Coerce the result so that it can be assigned to 673 # something of type dst_type. If processing is necessary, 674 # wraps this node in a coercion node and returns that. 675 # Otherwise, returns this node unchanged. 676 # 677 # This method is called during the analyse_expressions 678 # phase of the src_node's processing. 679 # 680 # Note that subclasses that override this (especially 681 # ConstNodes) must not (re-)set their own .type attribute 682 # here. Since expression nodes may turn up in different 683 # places in the tree (e.g. inside of CloneNodes in cascaded 684 # assignments), this method must return a new node instance 685 # if it changes the type. 686 # 687 src = self 688 src_type = self.type 689 690 if self.check_for_coercion_error(dst_type, env): 691 return self 692 693 if dst_type.is_reference and not src_type.is_reference: 694 dst_type = dst_type.ref_base_type 695 696 if src_type.is_const: 697 src_type = src_type.const_base_type 698 699 if src_type.is_fused or dst_type.is_fused: 700 # See if we are coercing a fused function to a pointer to a 701 # specialized function 702 if (src_type.is_cfunction and not dst_type.is_fused and 703 dst_type.is_ptr and dst_type.base_type.is_cfunction): 704 705 dst_type = dst_type.base_type 706 707 for signature in src_type.get_all_specialized_function_types(): 708 if signature.same_as(dst_type): 709 src.type = signature 710 src.entry = src.type.entry 711 src.entry.used = True 712 return self 713 714 if src_type.is_fused: 715 error(self.pos, "Type is not specialized") 716 else: 717 error(self.pos, "Cannot coerce to a type that is not specialized") 718 719 self.type = error_type 720 return self 721 722 if self.coercion_type is not None: 723 # This is purely for error checking purposes! 724 node = NameNode(self.pos, name='', type=self.coercion_type) 725 node.coerce_to(dst_type, env) 726 727 if dst_type.is_memoryviewslice: 728 import MemoryView 729 if not src.type.is_memoryviewslice: 730 if src.type.is_pyobject: 731 src = CoerceToMemViewSliceNode(src, dst_type, env) 732 elif src.type.is_array: 733 src = CythonArrayNode.from_carray(src, env).coerce_to( 734 dst_type, env) 735 elif not src_type.is_error: 736 error(self.pos, 737 "Cannot convert '%s' to memoryviewslice" % 738 (src_type,)) 739 elif not MemoryView.src_conforms_to_dst( 740 src.type, dst_type, broadcast=self.memslice_broadcast): 741 if src.type.dtype.same_as(dst_type.dtype): 742 msg = "Memoryview '%s' not conformable to memoryview '%s'." 743 tup = src.type, dst_type 744 else: 745 msg = "Different base types for memoryviews (%s, %s)" 746 tup = src.type.dtype, dst_type.dtype 747 748 error(self.pos, msg % tup) 749 750 elif dst_type.is_pyobject: 751 if not src.type.is_pyobject: 752 if dst_type is bytes_type and src.type.is_int: 753 src = CoerceIntToBytesNode(src, env) 754 else: 755 src = CoerceToPyTypeNode(src, env, type=dst_type) 756 if not src.type.subtype_of(dst_type): 757 if src.constant_result is not None: 758 src = PyTypeTestNode(src, dst_type, env) 759 elif src.type.is_pyobject: 760 src = CoerceFromPyTypeNode(dst_type, src, env) 761 elif (dst_type.is_complex 762 and src_type != dst_type 763 and dst_type.assignable_from(src_type)): 764 src = CoerceToComplexNode(src, dst_type, env) 765 else: # neither src nor dst are py types 766 # Added the string comparison, since for c types that 767 # is enough, but Cython gets confused when the types are 768 # in different pxi files. 769 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)): 770 self.fail_assignment(dst_type) 771 return src 772 773 def fail_assignment(self, dst_type): 774 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type)) 775 776 def check_for_coercion_error(self, dst_type, env, fail=False, default=None): 777 if fail and not default: 778 default = "Cannot assign type '%(FROM)s' to '%(TO)s'" 779 message = find_coercion_error((self.type, dst_type), default, env) 780 if message is not None: 781 error(self.pos, message % {'FROM': self.type, 'TO': dst_type}) 782 return True 783 if fail: 784 self.fail_assignment(dst_type) 785 return True 786 return False 787 788 def coerce_to_pyobject(self, env): 789 return self.coerce_to(PyrexTypes.py_object_type, env) 790 791 def coerce_to_boolean(self, env): 792 # Coerce result to something acceptable as 793 # a boolean value. 794 795 # if it's constant, calculate the result now 796 if self.has_constant_result(): 797 bool_value = bool(self.constant_result) 798 return BoolNode(self.pos, value=bool_value, 799 constant_result=bool_value) 800 801 type = self.type 802 if type.is_enum or type.is_error: 803 return self 804 elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float: 805 return CoerceToBooleanNode(self, env) 806 else: 807 error(self.pos, "Type '%s' not acceptable as a boolean" % type) 808 return self 809 810 def coerce_to_integer(self, env): 811 # If not already some C integer type, coerce to longint. 812 if self.type.is_int: 813 return self 814 else: 815 return self.coerce_to(PyrexTypes.c_long_type, env) 816 817 def coerce_to_temp(self, env): 818 # Ensure that the result is in a temporary. 819 if self.result_in_temp(): 820 return self 821 else: 822 return CoerceToTempNode(self, env) 823 824 def coerce_to_simple(self, env): 825 # Ensure that the result is simple (see is_simple). 826 if self.is_simple(): 827 return self 828 else: 829 return self.coerce_to_temp(env) 830 831 def is_simple(self): 832 # A node is simple if its result is something that can 833 # be referred to without performing any operations, e.g. 834 # a constant, local var, C global var, struct member 835 # reference, or temporary. 836 return self.result_in_temp() 837 838 def may_be_none(self): 839 if self.type and not (self.type.is_pyobject or 840 self.type.is_memoryviewslice): 841 return False 842 if self.has_constant_result(): 843 return self.constant_result is not None 844 return True 845 846 def as_cython_attribute(self): 847 return None 848 849 def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()): 850 # Wraps the node in a NoneCheckNode if it is not known to be 851 # not-None (e.g. because it is a Python literal). 852 if self.may_be_none(): 853 return NoneCheckNode(self, error, message, format_args) 854 else: 855 return self 856 857 @classmethod 858 def from_node(cls, node, **kwargs): 859 """Instantiate this node class from another node, properly 860 copying over all attributes that one would forget otherwise. 861 """ 862 attributes = "cf_state cf_maybe_null cf_is_null constant_result".split() 863 for attr_name in attributes: 864 if attr_name in kwargs: 865 continue 866 try: 867 value = getattr(node, attr_name) 868 except AttributeError: 869 pass 870 else: 871 kwargs[attr_name] = value 872 return cls(node.pos, **kwargs) 873 874 875 class AtomicExprNode(ExprNode): 876 # Abstract base class for expression nodes which have 877 # no sub-expressions. 878 879 subexprs = [] 880 881 # Override to optimize -- we know we have no children 882 def generate_subexpr_evaluation_code(self, code): 883 pass 884 def generate_subexpr_disposal_code(self, code): 885 pass 886 887 class PyConstNode(AtomicExprNode): 888 # Abstract base class for constant Python values. 889 890 is_literal = 1 891 type = py_object_type 892 893 def is_simple(self): 894 return 1 895 896 def may_be_none(self): 897 return False 898 899 def analyse_types(self, env): 900 return self 901 902 def calculate_result_code(self): 903 return self.value 904 905 def generate_result_code(self, code): 906 pass 907 908 909 class NoneNode(PyConstNode): 910 # The constant value None 911 912 is_none = 1 913 value = "Py_None" 914 915 constant_result = None 916 917 nogil_check = None 918 919 def compile_time_value(self, denv): 920 return None 921 922 def may_be_none(self): 923 return True 924 925 926 class EllipsisNode(PyConstNode): 927 # '...' in a subscript list. 928 929 value = "Py_Ellipsis" 930 931 constant_result = Ellipsis 932 933 def compile_time_value(self, denv): 934 return Ellipsis 935 936 937 class ConstNode(AtomicExprNode): 938 # Abstract base type for literal constant nodes. 939 # 940 # value string C code fragment 941 942 is_literal = 1 943 nogil_check = None 944 945 def is_simple(self): 946 return 1 947 948 def nonlocally_immutable(self): 949 return 1 950 951 def may_be_none(self): 952 return False 953 954 def analyse_types(self, env): 955 return self # Types are held in class variables 956 957 def check_const(self): 958 return True 959 960 def get_constant_c_result_code(self): 961 return self.calculate_result_code() 962 963 def calculate_result_code(self): 964 return str(self.value) 965 966 def generate_result_code(self, code): 967 pass 968 969 970 class BoolNode(ConstNode): 971 type = PyrexTypes.c_bint_type 972 # The constant value True or False 973 974 def calculate_constant_result(self): 975 self.constant_result = self.value 976 977 def compile_time_value(self, denv): 978 return self.value 979 980 def calculate_result_code(self): 981 if self.type.is_pyobject: 982 return self.value and 'Py_True' or 'Py_False' 983 else: 984 return str(int(self.value)) 985 986 def coerce_to(self, dst_type, env): 987 if dst_type.is_pyobject and self.type.is_int: 988 return BoolNode( 989 self.pos, value=self.value, 990 constant_result=self.constant_result, 991 type=Builtin.bool_type) 992 if dst_type.is_int and self.type.is_pyobject: 993 return BoolNode( 994 self.pos, value=self.value, 995 constant_result=self.constant_result, 996 type=PyrexTypes.c_bint_type) 997 return ConstNode.coerce_to(self, dst_type, env) 998 999 1000 class NullNode(ConstNode): 1001 type = PyrexTypes.c_null_ptr_type 1002 value = "NULL" 1003 constant_result = 0 1004 1005 def get_constant_c_result_code(self): 1006 return self.value 1007 1008 1009 class CharNode(ConstNode): 1010 type = PyrexTypes.c_char_type 1011 1012 def calculate_constant_result(self): 1013 self.constant_result = ord(self.value) 1014 1015 def compile_time_value(self, denv): 1016 return ord(self.value) 1017 1018 def calculate_result_code(self): 1019 return "'%s'" % StringEncoding.escape_char(self.value) 1020 1021 1022 class IntNode(ConstNode): 1023 1024 # unsigned "" or "U" 1025 # longness "" or "L" or "LL" 1026 # is_c_literal True/False/None creator considers this a C integer literal 1027 1028 unsigned = "" 1029 longness = "" 1030 is_c_literal = None # unknown 1031 1032 def __init__(self, pos, **kwds): 1033 ExprNode.__init__(self, pos, **kwds) 1034 if 'type' not in kwds: 1035 self.type = self.find_suitable_type_for_value() 1036 1037 def find_suitable_type_for_value(self): 1038 if self.constant_result is constant_value_not_set: 1039 try: 1040 self.calculate_constant_result() 1041 except ValueError: 1042 pass 1043 # we ignore 'is_c_literal = True' and instead map signed 32bit 1044 # integers as C long values 1045 if self.is_c_literal or \ 1046 self.constant_result in (constant_value_not_set, not_a_constant) or \ 1047 self.unsigned or self.longness == 'LL': 1048 # clearly a C literal 1049 rank = (self.longness == 'LL') and 2 or 1 1050 suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"] 1051 if self.type: 1052 suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type) 1053 else: 1054 # C literal or Python literal - split at 32bit boundary 1055 if -2**31 <= self.constant_result < 2**31: 1056 if self.type and self.type.is_int: 1057 suitable_type = self.type 1058 else: 1059 suitable_type = PyrexTypes.c_long_type 1060 else: 1061 suitable_type = PyrexTypes.py_object_type 1062 return suitable_type 1063 1064 def coerce_to(self, dst_type, env): 1065 if self.type is dst_type: 1066 return self 1067 elif dst_type.is_float: 1068 if self.has_constant_result(): 1069 return FloatNode(self.pos, value='%d.0' % int(self.constant_result), type=dst_type, 1070 constant_result=float(self.constant_result)) 1071 else: 1072 return FloatNode(self.pos, value=self.value, type=dst_type, 1073 constant_result=not_a_constant) 1074 if dst_type.is_numeric and not dst_type.is_complex: 1075 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1076 type = dst_type, is_c_literal = True, 1077 unsigned=self.unsigned, longness=self.longness) 1078 return node 1079 elif dst_type.is_pyobject: 1080 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1081 type = PyrexTypes.py_object_type, is_c_literal = False, 1082 unsigned=self.unsigned, longness=self.longness) 1083 else: 1084 # FIXME: not setting the type here to keep it working with 1085 # complex numbers. Should they be special cased? 1086 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1087 unsigned=self.unsigned, longness=self.longness) 1088 # We still need to perform normal coerce_to processing on the 1089 # result, because we might be coercing to an extension type, 1090 # in which case a type test node will be needed. 1091 return ConstNode.coerce_to(node, dst_type, env) 1092 1093 def coerce_to_boolean(self, env): 1094 return IntNode( 1095 self.pos, value=self.value, 1096 constant_result=self.constant_result, 1097 type=PyrexTypes.c_bint_type, 1098 unsigned=self.unsigned, longness=self.longness) 1099 1100 def generate_evaluation_code(self, code): 1101 if self.type.is_pyobject: 1102 # pre-allocate a Python version of the number 1103 plain_integer_string = str(Utils.str_to_number(self.value)) 1104 self.result_code = code.get_py_int(plain_integer_string, self.longness) 1105 else: 1106 self.result_code = self.get_constant_c_result_code() 1107 1108 def get_constant_c_result_code(self): 1109 return self.value_as_c_integer_string() + self.unsigned + self.longness 1110 1111 def value_as_c_integer_string(self): 1112 value = self.value 1113 if len(value) > 2: 1114 # convert C-incompatible Py3 oct/bin notations 1115 if value[1] in 'oO': 1116 value = value[0] + value[2:] # '0o123' => '0123' 1117 elif value[1] in 'bB': 1118 value = int(value[2:], 2) 1119 return str(value) 1120 1121 def calculate_result_code(self): 1122 return self.result_code 1123 1124 def calculate_constant_result(self): 1125 self.constant_result = Utils.str_to_number(self.value) 1126 1127 def compile_time_value(self, denv): 1128 return Utils.str_to_number(self.value) 1129 1130 1131 class FloatNode(ConstNode): 1132 type = PyrexTypes.c_double_type 1133 1134 def calculate_constant_result(self): 1135 self.constant_result = float(self.value) 1136 1137 def compile_time_value(self, denv): 1138 return float(self.value) 1139 1140 def coerce_to(self, dst_type, env): 1141 if dst_type.is_pyobject and self.type.is_float: 1142 return FloatNode( 1143 self.pos, value=self.value, 1144 constant_result=self.constant_result, 1145 type=Builtin.float_type) 1146 if dst_type.is_float and self.type.is_pyobject: 1147 return FloatNode( 1148 self.pos, value=self.value, 1149 constant_result=self.constant_result, 1150 type=dst_type) 1151 return ConstNode.coerce_to(self, dst_type, env) 1152 1153 def calculate_result_code(self): 1154 return self.result_code 1155 1156 def get_constant_c_result_code(self): 1157 strval = self.value 1158 assert isinstance(strval, (str, unicode)) 1159 cmpval = repr(float(strval)) 1160 if cmpval == 'nan': 1161 return "(Py_HUGE_VAL * 0)" 1162 elif cmpval == 'inf': 1163 return "Py_HUGE_VAL" 1164 elif cmpval == '-inf': 1165 return "(-Py_HUGE_VAL)" 1166 else: 1167 return strval 1168 1169 def generate_evaluation_code(self, code): 1170 c_value = self.get_constant_c_result_code() 1171 if self.type.is_pyobject: 1172 self.result_code = code.get_py_float(self.value, c_value) 1173 else: 1174 self.result_code = c_value 1175 1176 1177 class BytesNode(ConstNode): 1178 # A char* or bytes literal 1179 # 1180 # value BytesLiteral 1181 1182 is_string_literal = True 1183 # start off as Python 'bytes' to support len() in O(1) 1184 type = bytes_type 1185 1186 def calculate_constant_result(self): 1187 self.constant_result = self.value 1188 1189 def as_sliced_node(self, start, stop, step=None): 1190 value = StringEncoding.BytesLiteral(self.value[start:stop:step]) 1191 value.encoding = self.value.encoding 1192 return BytesNode( 1193 self.pos, value=value, constant_result=value) 1194 1195 def compile_time_value(self, denv): 1196 return self.value 1197 1198 def analyse_as_type(self, env): 1199 type = PyrexTypes.parse_basic_type(self.value) 1200 if type is not None: 1201 return type 1202 from TreeFragment import TreeFragment 1203 pos = (self.pos[0], self.pos[1], self.pos[2]-7) 1204 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos) 1205 sizeof_node = declaration.root.stats[0].expr 1206 sizeof_node = sizeof_node.analyse_types(env) 1207 if isinstance(sizeof_node, SizeofTypeNode): 1208 return sizeof_node.arg_type 1209 1210 def can_coerce_to_char_literal(self): 1211 return len(self.value) == 1 1212 1213 def coerce_to_boolean(self, env): 1214 # This is special because testing a C char* for truth directly 1215 # would yield the wrong result. 1216 bool_value = bool(self.value) 1217 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) 1218 1219 def coerce_to(self, dst_type, env): 1220 if self.type == dst_type: 1221 return self 1222 if dst_type.is_int: 1223 if not self.can_coerce_to_char_literal(): 1224 error(self.pos, "Only single-character string literals can be coerced into ints.") 1225 return self 1226 if dst_type.is_unicode_char: 1227 error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.") 1228 return self 1229 return CharNode(self.pos, value=self.value, 1230 constant_result=ord(self.value)) 1231 1232 node = BytesNode(self.pos, value=self.value, 1233 constant_result=self.constant_result) 1234 if dst_type.is_pyobject: 1235 if dst_type in (py_object_type, Builtin.bytes_type): 1236 node.type = Builtin.bytes_type 1237 else: 1238 self.check_for_coercion_error(dst_type, env, fail=True) 1239 return node 1240 elif dst_type == PyrexTypes.c_char_ptr_type: 1241 node.type = dst_type 1242 return node 1243 elif dst_type == PyrexTypes.c_uchar_ptr_type: 1244 node.type = PyrexTypes.c_char_ptr_type 1245 return CastNode(node, PyrexTypes.c_uchar_ptr_type) 1246 elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type): 1247 node.type = dst_type 1248 return node 1249 1250 # We still need to perform normal coerce_to processing on the 1251 # result, because we might be coercing to an extension type, 1252 # in which case a type test node will be needed. 1253 return ConstNode.coerce_to(node, dst_type, env) 1254 1255 def generate_evaluation_code(self, code): 1256 if self.type.is_pyobject: 1257 self.result_code = code.get_py_string_const(self.value) 1258 else: 1259 self.result_code = code.get_string_const(self.value) 1260 1261 def get_constant_c_result_code(self): 1262 return None # FIXME 1263 1264 def calculate_result_code(self): 1265 return self.result_code 1266 1267 1268 class UnicodeNode(ConstNode): 1269 # A Py_UNICODE* or unicode literal 1270 # 1271 # value EncodedString 1272 # bytes_value BytesLiteral the literal parsed as bytes string 1273 # ('-3' unicode literals only) 1274 1275 is_string_literal = True 1276 bytes_value = None 1277 type = unicode_type 1278 1279 def calculate_constant_result(self): 1280 self.constant_result = self.value 1281 1282 def as_sliced_node(self, start, stop, step=None): 1283 if StringEncoding.string_contains_surrogates(self.value[:stop]): 1284 # this is unsafe as it may give different results 1285 # in different runtimes 1286 return None 1287 value = StringEncoding.EncodedString(self.value[start:stop:step]) 1288 value.encoding = self.value.encoding 1289 if self.bytes_value is not None: 1290 bytes_value = StringEncoding.BytesLiteral( 1291 self.bytes_value[start:stop:step]) 1292 bytes_value.encoding = self.bytes_value.encoding 1293 else: 1294 bytes_value = None 1295 return UnicodeNode( 1296 self.pos, value=value, bytes_value=bytes_value, 1297 constant_result=value) 1298 1299 def coerce_to(self, dst_type, env): 1300 if dst_type is self.type: 1301 pass 1302 elif dst_type.is_unicode_char: 1303 if not self.can_coerce_to_char_literal(): 1304 error(self.pos, 1305 "Only single-character Unicode string literals or " 1306 "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.") 1307 return self 1308 int_value = ord(self.value) 1309 return IntNode(self.pos, type=dst_type, value=str(int_value), 1310 constant_result=int_value) 1311 elif not dst_type.is_pyobject: 1312 if dst_type.is_string and self.bytes_value is not None: 1313 # special case: '-3' enforced unicode literal used in a 1314 # C char* context 1315 return BytesNode(self.pos, value=self.bytes_value 1316 ).coerce_to(dst_type, env) 1317 if dst_type.is_pyunicode_ptr: 1318 node = UnicodeNode(self.pos, value=self.value) 1319 node.type = dst_type 1320 return node 1321 error(self.pos, 1322 "Unicode literals do not support coercion to C types other " 1323 "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* " 1324 "(for strings).") 1325 elif dst_type not in (py_object_type, Builtin.basestring_type): 1326 self.check_for_coercion_error(dst_type, env, fail=True) 1327 return self 1328 1329 def can_coerce_to_char_literal(self): 1330 return len(self.value) == 1 1331 ## or (len(self.value) == 2 1332 ## and (0xD800 <= self.value[0] <= 0xDBFF) 1333 ## and (0xDC00 <= self.value[1] <= 0xDFFF)) 1334 1335 def coerce_to_boolean(self, env): 1336 bool_value = bool(self.value) 1337 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) 1338 1339 def contains_surrogates(self): 1340 return StringEncoding.string_contains_surrogates(self.value) 1341 1342 def generate_evaluation_code(self, code): 1343 if self.type.is_pyobject: 1344 if self.contains_surrogates(): 1345 # surrogates are not really portable and cannot be 1346 # decoded by the UTF-8 codec in Py3.3 1347 self.result_code = code.get_py_const(py_object_type, 'ustring') 1348 data_cname = code.get_pyunicode_ptr_const(self.value) 1349 code = code.get_cached_constants_writer() 1350 code.mark_pos(self.pos) 1351 code.putln( 1352 "%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNICODE))-1); %s" % ( 1353 self.result_code, 1354 data_cname, 1355 data_cname, 1356 code.error_goto_if_null(self.result_code, self.pos))) 1357 code.putln("#if CYTHON_PEP393_ENABLED") 1358 code.put_error_if_neg( 1359 self.pos, "PyUnicode_READY(%s)" % self.result_code) 1360 code.putln("#endif") 1361 else: 1362 self.result_code = code.get_py_string_const(self.value) 1363 else: 1364 self.result_code = code.get_pyunicode_ptr_const(self.value) 1365 1366 def calculate_result_code(self): 1367 return self.result_code 1368 1369 def compile_time_value(self, env): 1370 return self.value 1371 1372 1373 class StringNode(PyConstNode): 1374 # A Python str object, i.e. a byte string in Python 2.x and a 1375 # unicode string in Python 3.x 1376 # 1377 # value BytesLiteral (or EncodedString with ASCII content) 1378 # unicode_value EncodedString or None 1379 # is_identifier boolean 1380 1381 type = str_type 1382 is_string_literal = True 1383 is_identifier = None 1384 unicode_value = None 1385 1386 def calculate_constant_result(self): 1387 if self.unicode_value is not None: 1388 # only the Unicode value is portable across Py2/3 1389 self.constant_result = self.unicode_value 1390 1391 def as_sliced_node(self, start, stop, step=None): 1392 value = type(self.value)(self.value[start:stop:step]) 1393 value.encoding = self.value.encoding 1394 if self.unicode_value is not None: 1395 if StringEncoding.string_contains_surrogates(self.unicode_value[:stop]): 1396 # this is unsafe as it may give different results in different runtimes 1397 return None 1398 unicode_value = StringEncoding.EncodedString( 1399 self.unicode_value[start:stop:step]) 1400 else: 1401 unicode_value = None 1402 return StringNode( 1403 self.pos, value=value, unicode_value=unicode_value, 1404 constant_result=value, is_identifier=self.is_identifier) 1405 1406 def coerce_to(self, dst_type, env): 1407 if dst_type is not py_object_type and not str_type.subtype_of(dst_type): 1408 # if dst_type is Builtin.bytes_type: 1409 # # special case: bytes = 'str literal' 1410 # return BytesNode(self.pos, value=self.value) 1411 if not dst_type.is_pyobject: 1412 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env) 1413 if dst_type is not Builtin.basestring_type: 1414 self.check_for_coercion_error(dst_type, env, fail=True) 1415 return self 1416 1417 def can_coerce_to_char_literal(self): 1418 return not self.is_identifier and len(self.value) == 1 1419 1420 def generate_evaluation_code(self, code): 1421 self.result_code = code.get_py_string_const( 1422 self.value, identifier=self.is_identifier, is_str=True, 1423 unicode_value=self.unicode_value) 1424 1425 def get_constant_c_result_code(self): 1426 return None 1427 1428 def calculate_result_code(self): 1429 return self.result_code 1430 1431 def compile_time_value(self, env): 1432 return self.value 1433 1434 1435 class IdentifierStringNode(StringNode): 1436 # A special str value that represents an identifier (bytes in Py2, 1437 # unicode in Py3). 1438 is_identifier = True 1439 1440 1441 class ImagNode(AtomicExprNode): 1442 # Imaginary number literal 1443 # 1444 # value float imaginary part 1445 1446 type = PyrexTypes.c_double_complex_type 1447 1448 def calculate_constant_result(self): 1449 self.constant_result = complex(0.0, self.value) 1450 1451 def compile_time_value(self, denv): 1452 return complex(0.0, self.value) 1453 1454 def analyse_types(self, env): 1455 self.type.create_declaration_utility_code(env) 1456 return self 1457 1458 def may_be_none(self): 1459 return False 1460 1461 def coerce_to(self, dst_type, env): 1462 if self.type is dst_type: 1463 return self 1464 node = ImagNode(self.pos, value=self.value) 1465 if dst_type.is_pyobject: 1466 node.is_temp = 1 1467 node.type = PyrexTypes.py_object_type 1468 # We still need to perform normal coerce_to processing on the 1469 # result, because we might be coercing to an extension type, 1470 # in which case a type test node will be needed. 1471 return AtomicExprNode.coerce_to(node, dst_type, env) 1472 1473 gil_message = "Constructing complex number" 1474 1475 def calculate_result_code(self): 1476 if self.type.is_pyobject: 1477 return self.result() 1478 else: 1479 return "%s(0, %r)" % (self.type.from_parts, float(self.value)) 1480 1481 def generate_result_code(self, code): 1482 if self.type.is_pyobject: 1483 code.putln( 1484 "%s = PyComplex_FromDoubles(0.0, %r); %s" % ( 1485 self.result(), 1486 float(self.value), 1487 code.error_goto_if_null(self.result(), self.pos))) 1488 code.put_gotref(self.py_result()) 1489 1490 1491 class NewExprNode(AtomicExprNode): 1492 1493 # C++ new statement 1494 # 1495 # cppclass node c++ class to create 1496 1497 type = None 1498 1499 def infer_type(self, env): 1500 type = self.cppclass.analyse_as_type(env) 1501 if type is None or not type.is_cpp_class: 1502 error(self.pos, "new operator can only be applied to a C++ class") 1503 self.type = error_type 1504 return 1505 self.cpp_check(env) 1506 constructor = type.scope.lookup(u'<init>') 1507 if constructor is None: 1508 func_type = PyrexTypes.CFuncType(type, [], exception_check='+') 1509 type.scope.declare_cfunction(u'<init>', func_type, self.pos) 1510 constructor = type.scope.lookup(u'<init>') 1511 self.class_type = type 1512 self.entry = constructor 1513 self.type = constructor.type 1514 return self.type 1515 1516 def analyse_types(self, env): 1517 if self.type is None: 1518 self.infer_type(env) 1519 return self 1520 1521 def may_be_none(self): 1522 return False 1523 1524 def generate_result_code(self, code): 1525 pass 1526 1527 def calculate_result_code(self): 1528 return "new " + self.class_type.declaration_code("") 1529 1530 1531 class NameNode(AtomicExprNode): 1532 # Reference to a local or global variable name. 1533 # 1534 # name string Python name of the variable 1535 # entry Entry Symbol table entry 1536 # type_entry Entry For extension type names, the original type entry 1537 # cf_is_null boolean Is uninitialized before this node 1538 # cf_maybe_null boolean Maybe uninitialized before this node 1539 # allow_null boolean Don't raise UnboundLocalError 1540 # nogil boolean Whether it is used in a nogil context 1541 1542 is_name = True 1543 is_cython_module = False 1544 cython_attribute = None 1545 lhs_of_first_assignment = False # TODO: remove me 1546 is_used_as_rvalue = 0 1547 entry = None 1548 type_entry = None 1549 cf_maybe_null = True 1550 cf_is_null = False 1551 allow_null = False 1552 nogil = False 1553 inferred_type = None 1554 1555 def as_cython_attribute(self): 1556 return self.cython_attribute 1557 1558 def type_dependencies(self, env): 1559 if self.entry is None: 1560 self.entry = env.lookup(self.name) 1561 if self.entry is not None and self.entry.type.is_unspecified: 1562 return (self,) 1563 else: 1564 return () 1565 1566 def infer_type(self, env): 1567 if self.entry is None: 1568 self.entry = env.lookup(self.name) 1569 if self.entry is None or self.entry.type is unspecified_type: 1570 if self.inferred_type is not None: 1571 return self.inferred_type 1572 return py_object_type 1573 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \ 1574 self.name == self.entry.type.name: 1575 # Unfortunately the type attribute of type objects 1576 # is used for the pointer to the type they represent. 1577 return type_type 1578 elif self.entry.type.is_cfunction: 1579 if self.entry.scope.is_builtin_scope: 1580 # special case: optimised builtin functions must be treated as Python objects 1581 return py_object_type 1582 else: 1583 # special case: referring to a C function must return its pointer 1584 return PyrexTypes.CPtrType(self.entry.type) 1585 else: 1586 # If entry is inferred as pyobject it's safe to use local 1587 # NameNode's inferred_type. 1588 if self.entry.type.is_pyobject and self.inferred_type: 1589 # Overflow may happen if integer 1590 if not (self.inferred_type.is_int and self.entry.might_overflow): 1591 return self.inferred_type 1592 return self.entry.type 1593 1594 def compile_time_value(self, denv): 1595 try: 1596 return denv.lookup(self.name) 1597 except KeyError: 1598 error(self.pos, "Compile-time name '%s' not defined" % self.name) 1599 1600 def get_constant_c_result_code(self): 1601 if not self.entry or self.entry.type.is_pyobject: 1602 return None 1603 return self.entry.cname 1604 1605 def coerce_to(self, dst_type, env): 1606 # If coercing to a generic pyobject and this is a builtin 1607 # C function with a Python equivalent, manufacture a NameNode 1608 # referring to the Python builtin. 1609 #print "NameNode.coerce_to:", self.name, dst_type ### 1610 if dst_type is py_object_type: 1611 entry = self.entry 1612 if entry and entry.is_cfunction: 1613 var_entry = entry.as_variable 1614 if var_entry: 1615 if var_entry.is_builtin and var_entry.is_const: 1616 var_entry = env.declare_builtin(var_entry.name, self.pos) 1617 node = NameNode(self.pos, name = self.name) 1618 node.entry = var_entry 1619 node.analyse_rvalue_entry(env) 1620 return node 1621 1622 return super(NameNode, self).coerce_to(dst_type, env) 1623 1624 def analyse_as_module(self, env): 1625 # Try to interpret this as a reference to a cimported module. 1626 # Returns the module scope, or None. 1627 entry = self.entry 1628 if not entry: 1629 entry = env.lookup(self.name) 1630 if entry and entry.as_module: 1631 return entry.as_module 1632 return None 1633 1634 def analyse_as_type(self, env): 1635 if self.cython_attribute: 1636 type = PyrexTypes.parse_basic_type(self.cython_attribute) 1637 else: 1638 type = PyrexTypes.parse_basic_type(self.name) 1639 if type: 1640 return type 1641 entry = self.entry 1642 if not entry: 1643 entry = env.lookup(self.name) 1644 if entry and entry.is_type: 1645 return entry.type 1646 else: 1647 return None 1648 1649 def analyse_as_extension_type(self, env): 1650 # Try to interpret this as a reference to an extension type. 1651 # Returns the extension type, or None. 1652 entry = self.entry 1653 if not entry: 1654 entry = env.lookup(self.name) 1655 if entry and entry.is_type: 1656 if entry.type.is_extension_type or entry.type.is_builtin_type: 1657 return entry.type 1658 return None 1659 1660 def analyse_target_declaration(self, env): 1661 if not self.entry: 1662 self.entry = env.lookup_here(self.name) 1663 if not self.entry: 1664 if env.directives['warn.undeclared']: 1665 warning(self.pos, "implicit declaration of '%s'" % self.name, 1) 1666 if env.directives['infer_types'] != False: 1667 type = unspecified_type 1668 else: 1669 type = py_object_type 1670 self.entry = env.declare_var(self.name, type, self.pos) 1671 if self.entry.is_declared_generic: 1672 self.result_ctype = py_object_type 1673 1674 def analyse_types(self, env): 1675 self.initialized_check = env.directives['initializedcheck'] 1676 if self.entry is None: 1677 self.entry = env.lookup(self.name) 1678 if not self.entry: 1679 self.entry = env.declare_builtin(self.name, self.pos) 1680 if not self.entry: 1681 self.type = PyrexTypes.error_type 1682 return self 1683 entry = self.entry 1684 if entry: 1685 entry.used = 1 1686 if entry.type.is_buffer: 1687 import Buffer 1688 Buffer.used_buffer_aux_vars(entry) 1689 self.analyse_rvalue_entry(env) 1690 return self 1691 1692 def analyse_target_types(self, env): 1693 self.analyse_entry(env, is_target=True) 1694 1695 if (not self.is_lvalue() and self.entry.is_cfunction and 1696 self.entry.fused_cfunction and self.entry.as_variable): 1697 # We need this for the fused 'def' TreeFragment 1698 self.entry = self.entry.as_variable 1699 self.type = self.entry.type 1700 1701 if self.type.is_const: 1702 error(self.pos, "Assignment to const '%s'" % self.name) 1703 if self.type.is_reference: 1704 error(self.pos, "Assignment to reference '%s'" % self.name) 1705 if not self.is_lvalue(): 1706 error(self.pos, "Assignment to non-lvalue '%s'" 1707 % self.name) 1708 self.type = PyrexTypes.error_type 1709 self.entry.used = 1 1710 if self.entry.type.is_buffer: 1711 import Buffer 1712 Buffer.used_buffer_aux_vars(self.entry) 1713 return self 1714 1715 def analyse_rvalue_entry(self, env): 1716 #print "NameNode.analyse_rvalue_entry:", self.name ### 1717 #print "Entry:", self.entry.__dict__ ### 1718 self.analyse_entry(env) 1719 entry = self.entry 1720 1721 if entry.is_declared_generic: 1722 self.result_ctype = py_object_type 1723 1724 if entry.is_pyglobal or entry.is_builtin: 1725 if entry.is_builtin and entry.is_const: 1726 self.is_temp = 0 1727 else: 1728 self.is_temp = 1 1729 1730 self.is_used_as_rvalue = 1 1731 elif entry.type.is_memoryviewslice: 1732 self.is_temp = False 1733 self.is_used_as_rvalue = True 1734 self.use_managed_ref = True 1735 return self 1736 1737 def nogil_check(self, env): 1738 self.nogil = True 1739 if self.is_used_as_rvalue: 1740 entry = self.entry 1741 if entry.is_builtin: 1742 if not entry.is_const: # cached builtins are ok 1743 self.gil_error() 1744 elif entry.is_pyglobal: 1745 self.gil_error() 1746 elif self.entry.type.is_memoryviewslice: 1747 if self.cf_is_null or self.cf_maybe_null: 1748 import MemoryView 1749 MemoryView.err_if_nogil_initialized_check(self.pos, env) 1750 1751 gil_message = "Accessing Python global or builtin" 1752 1753 def analyse_entry(self, env, is_target=False): 1754 #print "NameNode.analyse_entry:", self.name ### 1755 self.check_identifier_kind() 1756 entry = self.entry 1757 type = entry.type 1758 if (not is_target and type.is_pyobject and self.inferred_type and 1759 self.inferred_type.is_builtin_type): 1760 # assume that type inference is smarter than the static entry 1761 type = self.inferred_type 1762 self.type = type 1763 1764 def check_identifier_kind(self): 1765 # Check that this is an appropriate kind of name for use in an 1766 # expression. Also finds the variable entry associated with 1767 # an extension type. 1768 entry = self.entry 1769 if entry.is_type and entry.type.is_extension_type: 1770 self.type_entry = entry 1771 if not (entry.is_const or entry.is_variable 1772 or entry.is_builtin or entry.is_cfunction 1773 or entry.is_cpp_class): 1774 if self.entry.as_variable: 1775 self.entry = self.entry.as_variable 1776 else: 1777 error(self.pos, 1778 "'%s' is not a constant, variable or function identifier" % self.name) 1779 1780 def is_simple(self): 1781 # If it's not a C variable, it'll be in a temp. 1782 return 1 1783 1784 def may_be_none(self): 1785 if self.cf_state and self.type and (self.type.is_pyobject or 1786 self.type.is_memoryviewslice): 1787 # gard against infinite recursion on self-dependencies 1788 if getattr(self, '_none_checking', False): 1789 # self-dependency - either this node receives a None 1790 # value from *another* node, or it can not reference 1791 # None at this point => safe to assume "not None" 1792 return False 1793 self._none_checking = True 1794 # evaluate control flow state to see if there were any 1795 # potential None values assigned to the node so far 1796 may_be_none = False 1797 for assignment in self.cf_state: 1798 if assignment.rhs.may_be_none(): 1799 may_be_none = True 1800 break 1801 del self._none_checking 1802 return may_be_none 1803 return super(NameNode, self).may_be_none() 1804 1805 def nonlocally_immutable(self): 1806 if ExprNode.nonlocally_immutable(self): 1807 return True 1808 entry = self.entry 1809 if not entry or entry.in_closure: 1810 return False 1811 return entry.is_local or entry.is_arg or entry.is_builtin or entry.is_readonly 1812 1813 def calculate_target_results(self, env): 1814 pass 1815 1816 def check_const(self): 1817 entry = self.entry 1818 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin): 1819 self.not_const() 1820 return False 1821 return True 1822 1823 def check_const_addr(self): 1824 entry = self.entry 1825 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin): 1826 self.addr_not_const() 1827 return False 1828 return True 1829 1830 def is_lvalue(self): 1831 return self.entry.is_variable and \ 1832 not self.entry.type.is_array and \ 1833 not self.entry.is_readonly 1834 1835 def is_addressable(self): 1836 return self.entry.is_variable and not self.type.is_memoryviewslice 1837 1838 def is_ephemeral(self): 1839 # Name nodes are never ephemeral, even if the 1840 # result is in a temporary. 1841 return 0 1842 1843 def calculate_result_code(self): 1844 entry = self.entry 1845 if not entry: 1846 return "<error>" # There was an error earlier 1847 return entry.cname 1848 1849 def generate_result_code(self, code): 1850 assert hasattr(self, 'entry') 1851 entry = self.entry 1852 if entry is None: 1853 return # There was an error earlier 1854 if entry.is_builtin and entry.is_const: 1855 return # Lookup already cached 1856 elif entry.is_pyclass_attr: 1857 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 1858 interned_cname = code.intern_identifier(self.entry.name) 1859 if entry.is_builtin: 1860 namespace = Naming.builtins_cname 1861 else: # entry.is_pyglobal 1862 namespace = entry.scope.namespace_cname 1863 if not self.cf_is_null: 1864 code.putln( 1865 '%s = PyObject_GetItem(%s, %s);' % ( 1866 self.result(), 1867 namespace, 1868 interned_cname)) 1869 code.putln('if (unlikely(!%s)) {' % self.result()) 1870 code.putln('PyErr_Clear();') 1871 code.globalstate.use_utility_code( 1872 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) 1873 code.putln( 1874 '%s = __Pyx_GetModuleGlobalName(%s);' % ( 1875 self.result(), 1876 interned_cname)) 1877 if not self.cf_is_null: 1878 code.putln("}") 1879 code.putln(code.error_goto_if_null(self.result(), self.pos)) 1880 code.put_gotref(self.py_result()) 1881 1882 elif entry.is_builtin: 1883 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 1884 interned_cname = code.intern_identifier(self.entry.name) 1885 code.globalstate.use_utility_code( 1886 UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c")) 1887 code.putln( 1888 '%s = __Pyx_GetBuiltinName(%s); %s' % ( 1889 self.result(), 1890 interned_cname, 1891 code.error_goto_if_null(self.result(), self.pos))) 1892 code.put_gotref(self.py_result()) 1893 1894 elif entry.is_pyglobal: 1895 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 1896 interned_cname = code.intern_identifier(self.entry.name) 1897 if entry.scope.is_module_scope: 1898 code.globalstate.use_utility_code( 1899 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) 1900 code.putln( 1901 '%s = __Pyx_GetModuleGlobalName(%s); %s' % ( 1902 self.result(), 1903 interned_cname, 1904 code.error_goto_if_null(self.result(), self.pos))) 1905 else: 1906 # FIXME: is_pyglobal is also used for class namespace 1907 code.globalstate.use_utility_code( 1908 UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c")) 1909 code.putln( 1910 '%s = __Pyx_GetNameInClass(%s, %s); %s' % ( 1911 self.result(), 1912 entry.scope.namespace_cname, 1913 interned_cname, 1914 code.error_goto_if_null(self.result(), self.pos))) 1915 code.put_gotref(self.py_result()) 1916 1917 elif entry.is_local or entry.in_closure or entry.from_closure or entry.type.is_memoryviewslice: 1918 # Raise UnboundLocalError for objects and memoryviewslices 1919 raise_unbound = ( 1920 (self.cf_maybe_null or self.cf_is_null) and not self.allow_null) 1921 null_code = entry.type.check_for_null_code(entry.cname) 1922 1923 memslice_check = entry.type.is_memoryviewslice and self.initialized_check 1924 1925 if null_code and raise_unbound and (entry.type.is_pyobject or memslice_check): 1926 code.put_error_if_unbound(self.pos, entry, self.in_nogil_context) 1927 1928 def generate_assignment_code(self, rhs, code): 1929 #print "NameNode.generate_assignment_code:", self.name ### 1930 entry = self.entry 1931 if entry is None: 1932 return # There was an error earlier 1933 1934 if (self.entry.type.is_ptr and isinstance(rhs, ListNode) 1935 and not self.lhs_of_first_assignment and not rhs.in_module_scope): 1936 error(self.pos, "Literal list must be assigned to pointer at time of declaration") 1937 1938 # is_pyglobal seems to be True for module level-globals only. 1939 # We use this to access class->tp_dict if necessary. 1940 if entry.is_pyglobal: 1941 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 1942 interned_cname = code.intern_identifier(self.entry.name) 1943 namespace = self.entry.scope.namespace_cname 1944 if entry.is_member: 1945 # if the entry is a member we have to cheat: SetAttr does not work 1946 # on types, so we create a descriptor which is then added to tp_dict 1947 setter = 'PyDict_SetItem' 1948 namespace = '%s->tp_dict' % namespace 1949 elif entry.scope.is_module_scope: 1950 setter = 'PyDict_SetItem' 1951 namespace = Naming.moddict_cname 1952 elif entry.is_pyclass_attr: 1953 setter = 'PyObject_SetItem' 1954 else: 1955 assert False, repr(entry) 1956 code.put_error_if_neg( 1957 self.pos, 1958 '%s(%s, %s, %s)' % ( 1959 setter, 1960 namespace, 1961 interned_cname, 1962 rhs.py_result())) 1963 if debug_disposal_code: 1964 print("NameNode.generate_assignment_code:") 1965 print("...generating disposal code for %s" % rhs) 1966 rhs.generate_disposal_code(code) 1967 rhs.free_temps(code) 1968 if entry.is_member: 1969 # in Py2.6+, we need to invalidate the method cache 1970 code.putln("PyType_Modified(%s);" % 1971 entry.scope.parent_type.typeptr_cname) 1972 else: 1973 if self.type.is_memoryviewslice: 1974 self.generate_acquire_memoryviewslice(rhs, code) 1975 1976 elif self.type.is_buffer: 1977 # Generate code for doing the buffer release/acquisition. 1978 # This might raise an exception in which case the assignment (done 1979 # below) will not happen. 1980 # 1981 # The reason this is not in a typetest-like node is because the 1982 # variables that the acquired buffer info is stored to is allocated 1983 # per entry and coupled with it. 1984 self.generate_acquire_buffer(rhs, code) 1985 assigned = False 1986 if self.type.is_pyobject: 1987 #print "NameNode.generate_assignment_code: to", self.name ### 1988 #print "...from", rhs ### 1989 #print "...LHS type", self.type, "ctype", self.ctype() ### 1990 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ### 1991 if self.use_managed_ref: 1992 rhs.make_owned_reference(code) 1993 is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure 1994 if is_external_ref: 1995 if not self.cf_is_null: 1996 if self.cf_maybe_null: 1997 code.put_xgotref(self.py_result()) 1998 else: 1999 code.put_gotref(self.py_result()) 2000 assigned = True 2001 if entry.is_cglobal: 2002 code.put_decref_set( 2003 self.result(), rhs.result_as(self.ctype())) 2004 else: 2005 if not self.cf_is_null: 2006 if self.cf_maybe_null: 2007 code.put_xdecref_set( 2008 self.result(), rhs.result_as(self.ctype())) 2009 else: 2010 code.put_decref_set( 2011 self.result(), rhs.result_as(self.ctype())) 2012 else: 2013 assigned = False 2014 if is_external_ref: 2015 code.put_giveref(rhs.py_result()) 2016 if not self.type.is_memoryviewslice: 2017 if not assigned: 2018 code.putln('%s = %s;' % ( 2019 self.result(), rhs.result_as(self.ctype()))) 2020 if debug_disposal_code: 2021 print("NameNode.generate_assignment_code:") 2022 print("...generating post-assignment code for %s" % rhs) 2023 rhs.generate_post_assignment_code(code) 2024 elif rhs.result_in_temp(): 2025 rhs.generate_post_assignment_code(code) 2026 2027 rhs.free_temps(code) 2028 2029 def generate_acquire_memoryviewslice(self, rhs, code): 2030 """ 2031 Slices, coercions from objects, return values etc are new references. 2032 We have a borrowed reference in case of dst = src 2033 """ 2034 import MemoryView 2035 2036 MemoryView.put_acquire_memoryviewslice( 2037 lhs_cname=self.result(), 2038 lhs_type=self.type, 2039 lhs_pos=self.pos, 2040 rhs=rhs, 2041 code=code, 2042 have_gil=not self.in_nogil_context, 2043 first_assignment=self.cf_is_null) 2044 2045 def generate_acquire_buffer(self, rhs, code): 2046 # rhstmp is only used in case the rhs is a complicated expression leading to 2047 # the object, to avoid repeating the same C expression for every reference 2048 # to the rhs. It does NOT hold a reference. 2049 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp 2050 if pretty_rhs: 2051 rhstmp = rhs.result_as(self.ctype()) 2052 else: 2053 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False) 2054 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) 2055 2056 import Buffer 2057 Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry, 2058 is_initialized=not self.lhs_of_first_assignment, 2059 pos=self.pos, code=code) 2060 2061 if not pretty_rhs: 2062 code.putln("%s = 0;" % rhstmp) 2063 code.funcstate.release_temp(rhstmp) 2064 2065 def generate_deletion_code(self, code, ignore_nonexisting=False): 2066 if self.entry is None: 2067 return # There was an error earlier 2068 elif self.entry.is_pyclass_attr: 2069 namespace = self.entry.scope.namespace_cname 2070 interned_cname = code.intern_identifier(self.entry.name) 2071 if ignore_nonexisting: 2072 key_error_code = 'PyErr_Clear(); else' 2073 else: 2074 # minor hack: fake a NameError on KeyError 2075 key_error_code = ( 2076 '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' % 2077 self.entry.name) 2078 code.putln( 2079 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {' 2080 ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s' 2081 ' %s ' 2082 '}' % (namespace, interned_cname, 2083 key_error_code, 2084 code.error_goto(self.pos))) 2085 elif self.entry.is_pyglobal: 2086 code.globalstate.use_utility_code( 2087 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 2088 interned_cname = code.intern_identifier(self.entry.name) 2089 del_code = '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( 2090 Naming.module_cname, interned_cname) 2091 if ignore_nonexisting: 2092 code.putln('if (unlikely(%s < 0)) { if (likely(PyErr_ExceptionMatches(PyExc_AttributeError))) PyErr_Clear(); else %s }' % ( 2093 del_code, 2094 code.error_goto(self.pos))) 2095 else: 2096 code.put_error_if_neg(self.pos, del_code) 2097 elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice: 2098 if not self.cf_is_null: 2099 if self.cf_maybe_null and not ignore_nonexisting: 2100 code.put_error_if_unbound(self.pos, self.entry) 2101 2102 if self.entry.type.is_pyobject: 2103 if self.entry.in_closure: 2104 # generator 2105 if ignore_nonexisting and self.cf_maybe_null: 2106 code.put_xgotref(self.result()) 2107 else: 2108 code.put_gotref(self.result()) 2109 if ignore_nonexisting and self.cf_maybe_null: 2110 code.put_xdecref(self.result(), self.ctype()) 2111 else: 2112 code.put_decref(self.result(), self.ctype()) 2113 code.putln('%s = NULL;' % self.result()) 2114 else: 2115 code.put_xdecref_memoryviewslice(self.entry.cname, 2116 have_gil=not self.nogil) 2117 else: 2118 error(self.pos, "Deletion of C names not supported") 2119 2120 def annotate(self, code): 2121 if hasattr(self, 'is_called') and self.is_called: 2122 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1) 2123 if self.type.is_pyobject: 2124 style, text = 'py_call', 'python function (%s)' 2125 else: 2126 style, text = 'c_call', 'c function (%s)' 2127 code.annotate(pos, AnnotationItem(style, text % self.type, size=len(self.name))) 2128 2129 class BackquoteNode(ExprNode): 2130 # `expr` 2131 # 2132 # arg ExprNode 2133 2134 type = py_object_type 2135 2136 subexprs = ['arg'] 2137 2138 def analyse_types(self, env): 2139 self.arg = self.arg.analyse_types(env) 2140 self.arg = self.arg.coerce_to_pyobject(env) 2141 self.is_temp = 1 2142 return self 2143 2144 gil_message = "Backquote expression" 2145 2146 def calculate_constant_result(self): 2147 self.constant_result = repr(self.arg.constant_result) 2148 2149 def generate_result_code(self, code): 2150 code.putln( 2151 "%s = PyObject_Repr(%s); %s" % ( 2152 self.result(), 2153 self.arg.py_result(), 2154 code.error_goto_if_null(self.result(), self.pos))) 2155 code.put_gotref(self.py_result()) 2156 2157 2158 class ImportNode(ExprNode): 2159 # Used as part of import statement implementation. 2160 # Implements result = 2161 # __import__(module_name, globals(), None, name_list, level) 2162 # 2163 # module_name StringNode dotted name of module. Empty module 2164 # name means importing the parent package according 2165 # to level 2166 # name_list ListNode or None list of names to be imported 2167 # level int relative import level: 2168 # -1: attempt both relative import and absolute import; 2169 # 0: absolute import; 2170 # >0: the number of parent directories to search 2171 # relative to the current module. 2172 # None: decide the level according to language level and 2173 # directives 2174 2175 type = py_object_type 2176 2177 subexprs = ['module_name', 'name_list'] 2178 2179 def analyse_types(self, env): 2180 if self.level is None: 2181 if (env.directives['py2_import'] or 2182 Future.absolute_import not in env.global_scope().context.future_directives): 2183 self.level = -1 2184 else: 2185 self.level = 0 2186 module_name = self.module_name.analyse_types(env) 2187 self.module_name = module_name.coerce_to_pyobject(env) 2188 if self.name_list: 2189 name_list = self.name_list.analyse_types(env) 2190 self.name_list = name_list.coerce_to_pyobject(env) 2191 self.is_temp = 1 2192 env.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c")) 2193 return self 2194 2195 gil_message = "Python import" 2196 2197 def generate_result_code(self, code): 2198 if self.name_list: 2199 name_list_code = self.name_list.py_result() 2200 else: 2201 name_list_code = "0" 2202 code.putln( 2203 "%s = __Pyx_Import(%s, %s, %d); %s" % ( 2204 self.result(), 2205 self.module_name.py_result(), 2206 name_list_code, 2207 self.level, 2208 code.error_goto_if_null(self.result(), self.pos))) 2209 code.put_gotref(self.py_result()) 2210 2211 2212 class IteratorNode(ExprNode): 2213 # Used as part of for statement implementation. 2214 # 2215 # Implements result = iter(sequence) 2216 # 2217 # sequence ExprNode 2218 2219 type = py_object_type 2220 iter_func_ptr = None 2221 counter_cname = None 2222 cpp_iterator_cname = None 2223 reversed = False # currently only used for list/tuple types (see Optimize.py) 2224 2225 subexprs = ['sequence'] 2226 2227 def analyse_types(self, env): 2228 self.sequence = self.sequence.analyse_types(env) 2229 if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \ 2230 not self.sequence.type.is_string: 2231 # C array iteration will be transformed later on 2232 self.type = self.sequence.type 2233 elif self.sequence.type.is_cpp_class: 2234 self.analyse_cpp_types(env) 2235 else: 2236 self.sequence = self.sequence.coerce_to_pyobject(env) 2237 if self.sequence.type is list_type or \ 2238 self.sequence.type is tuple_type: 2239 self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable") 2240 self.is_temp = 1 2241 return self 2242 2243 gil_message = "Iterating over Python object" 2244 2245 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( 2246 PyrexTypes.py_object_type, [ 2247 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), 2248 ])) 2249 2250 def type_dependencies(self, env): 2251 return self.sequence.type_dependencies(env) 2252 2253 def infer_type(self, env): 2254 sequence_type = self.sequence.infer_type(env) 2255 if sequence_type.is_array or sequence_type.is_ptr: 2256 return sequence_type 2257 elif sequence_type.is_cpp_class: 2258 begin = sequence_type.scope.lookup("begin") 2259 if begin is not None: 2260 return begin.type.return_type 2261 elif sequence_type.is_pyobject: 2262 return sequence_type 2263 return py_object_type 2264 2265 def analyse_cpp_types(self, env): 2266 sequence_type = self.sequence.type 2267 if sequence_type.is_ptr: 2268 sequence_type = sequence_type.base_type 2269 begin = sequence_type.scope.lookup("begin") 2270 end = sequence_type.scope.lookup("end") 2271 if (begin is None 2272 or not begin.type.is_cfunction 2273 or begin.type.args): 2274 error(self.pos, "missing begin() on %s" % self.sequence.type) 2275 self.type = error_type 2276 return 2277 if (end is None 2278 or not end.type.is_cfunction 2279 or end.type.args): 2280 error(self.pos, "missing end() on %s" % self.sequence.type) 2281 self.type = error_type 2282 return 2283 iter_type = begin.type.return_type 2284 if iter_type.is_cpp_class: 2285 if env.lookup_operator_for_types( 2286 self.pos, 2287 "!=", 2288 [iter_type, end.type.return_type]) is None: 2289 error(self.pos, "missing operator!= on result of begin() on %s" % self.sequence.type) 2290 self.type = error_type 2291 return 2292 if env.lookup_operator_for_types(self.pos, '++', [iter_type]) is None: 2293 error(self.pos, "missing operator++ on result of begin() on %s" % self.sequence.type) 2294 self.type = error_type 2295 return 2296 if env.lookup_operator_for_types(self.pos, '*', [iter_type]) is None: 2297 error(self.pos, "missing operator* on result of begin() on %s" % self.sequence.type) 2298 self.type = error_type 2299 return 2300 self.type = iter_type 2301 elif iter_type.is_ptr: 2302 if not (iter_type == end.type.return_type): 2303 error(self.pos, "incompatible types for begin() and end()") 2304 self.type = iter_type 2305 else: 2306 error(self.pos, "result type of begin() on %s must be a C++ class or pointer" % self.sequence.type) 2307 self.type = error_type 2308 return 2309 2310 def generate_result_code(self, code): 2311 sequence_type = self.sequence.type 2312 if sequence_type.is_cpp_class: 2313 if self.sequence.is_name: 2314 # safe: C++ won't allow you to reassign to class references 2315 begin_func = "%s.begin" % self.sequence.result() 2316 else: 2317 sequence_type = PyrexTypes.c_ptr_type(sequence_type) 2318 self.cpp_iterator_cname = code.funcstate.allocate_temp(sequence_type, manage_ref=False) 2319 code.putln("%s = &%s;" % (self.cpp_iterator_cname, self.sequence.result())) 2320 begin_func = "%s->begin" % self.cpp_iterator_cname 2321 # TODO: Limit scope. 2322 code.putln("%s = %s();" % (self.result(), begin_func)) 2323 return 2324 if sequence_type.is_array or sequence_type.is_ptr: 2325 raise InternalError("for in carray slice not transformed") 2326 is_builtin_sequence = sequence_type is list_type or \ 2327 sequence_type is tuple_type 2328 if not is_builtin_sequence: 2329 # reversed() not currently optimised (see Optimize.py) 2330 assert not self.reversed, "internal error: reversed() only implemented for list/tuple objects" 2331 self.may_be_a_sequence = not sequence_type.is_builtin_type 2332 if self.may_be_a_sequence: 2333 code.putln( 2334 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % ( 2335 self.sequence.py_result(), 2336 self.sequence.py_result())) 2337 if is_builtin_sequence or self.may_be_a_sequence: 2338 self.counter_cname = code.funcstate.allocate_temp( 2339 PyrexTypes.c_py_ssize_t_type, manage_ref=False) 2340 if self.reversed: 2341 if sequence_type is list_type: 2342 init_value = 'PyList_GET_SIZE(%s) - 1' % self.result() 2343 else: 2344 init_value = 'PyTuple_GET_SIZE(%s) - 1' % self.result() 2345 else: 2346 init_value = '0' 2347 code.putln( 2348 "%s = %s; __Pyx_INCREF(%s); %s = %s;" % ( 2349 self.result(), 2350 self.sequence.py_result(), 2351 self.result(), 2352 self.counter_cname, 2353 init_value 2354 )) 2355 if not is_builtin_sequence: 2356 self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) 2357 if self.may_be_a_sequence: 2358 code.putln("%s = NULL;" % self.iter_func_ptr) 2359 code.putln("} else {") 2360 code.put("%s = -1; " % self.counter_cname) 2361 code.putln("%s = PyObject_GetIter(%s); %s" % ( 2362 self.result(), 2363 self.sequence.py_result(), 2364 code.error_goto_if_null(self.result(), self.pos))) 2365 code.put_gotref(self.py_result()) 2366 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (self.iter_func_ptr, self.py_result())) 2367 if self.may_be_a_sequence: 2368 code.putln("}") 2369 2370 def generate_next_sequence_item(self, test_name, result_name, code): 2371 assert self.counter_cname, "internal error: counter_cname temp not prepared" 2372 final_size = 'Py%s_GET_SIZE(%s)' % (test_name, self.py_result()) 2373 if self.sequence.is_sequence_constructor: 2374 item_count = len(self.sequence.args) 2375 if self.sequence.mult_factor is None: 2376 final_size = item_count 2377 elif isinstance(self.sequence.mult_factor.constant_result, (int, long)): 2378 final_size = item_count * self.sequence.mult_factor.constant_result 2379 code.putln("if (%s >= %s) break;" % (self.counter_cname, final_size)) 2380 if self.reversed: 2381 inc_dec = '--' 2382 else: 2383 inc_dec = '++' 2384 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") 2385 code.putln( 2386 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % ( 2387 result_name, 2388 test_name, 2389 self.py_result(), 2390 self.counter_cname, 2391 result_name, 2392 self.counter_cname, 2393 inc_dec, 2394 # use the error label to avoid C compiler warnings if we only use it below 2395 code.error_goto_if_neg('0', self.pos) 2396 )) 2397 code.putln("#else") 2398 code.putln( 2399 "%s = PySequence_ITEM(%s, %s); %s%s; %s" % ( 2400 result_name, 2401 self.py_result(), 2402 self.counter_cname, 2403 self.counter_cname, 2404 inc_dec, 2405 code.error_goto_if_null(result_name, self.pos))) 2406 code.putln("#endif") 2407 2408 def generate_iter_next_result_code(self, result_name, code): 2409 sequence_type = self.sequence.type 2410 if self.reversed: 2411 code.putln("if (%s < 0) break;" % self.counter_cname) 2412 if sequence_type.is_cpp_class: 2413 if self.cpp_iterator_cname: 2414 end_func = "%s->end" % self.cpp_iterator_cname 2415 else: 2416 end_func = "%s.end" % self.sequence.result() 2417 # TODO: Cache end() call? 2418 code.putln("if (!(%s != %s())) break;" % ( 2419 self.result(), 2420 end_func)) 2421 code.putln("%s = *%s;" % ( 2422 result_name, 2423 self.result())) 2424 code.putln("++%s;" % self.result()) 2425 return 2426 elif sequence_type is list_type: 2427 self.generate_next_sequence_item('List', result_name, code) 2428 return 2429 elif sequence_type is tuple_type: 2430 self.generate_next_sequence_item('Tuple', result_name, code) 2431 return 2432 2433 if self.may_be_a_sequence: 2434 for test_name in ('List', 'Tuple'): 2435 code.putln("if (!%s && Py%s_CheckExact(%s)) {" % ( 2436 self.iter_func_ptr, test_name, self.py_result())) 2437 self.generate_next_sequence_item(test_name, result_name, code) 2438 code.put("} else ") 2439 2440 code.putln("{") 2441 code.putln( 2442 "%s = %s(%s);" % ( 2443 result_name, 2444 self.iter_func_ptr, 2445 self.py_result())) 2446 code.putln("if (unlikely(!%s)) {" % result_name) 2447 code.putln("PyObject* exc_type = PyErr_Occurred();") 2448 code.putln("if (exc_type) {") 2449 code.putln("if (likely(exc_type == PyExc_StopIteration ||" 2450 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();") 2451 code.putln("else %s" % code.error_goto(self.pos)) 2452 code.putln("}") 2453 code.putln("break;") 2454 code.putln("}") 2455 code.put_gotref(result_name) 2456 code.putln("}") 2457 2458 def free_temps(self, code): 2459 if self.counter_cname: 2460 code.funcstate.release_temp(self.counter_cname) 2461 if self.iter_func_ptr: 2462 code.funcstate.release_temp(self.iter_func_ptr) 2463 self.iter_func_ptr = None 2464 if self.cpp_iterator_cname: 2465 code.funcstate.release_temp(self.cpp_iterator_cname) 2466 ExprNode.free_temps(self, code) 2467 2468 2469 class NextNode(AtomicExprNode): 2470 # Used as part of for statement implementation. 2471 # Implements result = iterator.next() 2472 # Created during analyse_types phase. 2473 # The iterator is not owned by this node. 2474 # 2475 # iterator IteratorNode 2476 2477 def __init__(self, iterator): 2478 AtomicExprNode.__init__(self, iterator.pos) 2479 self.iterator = iterator 2480 2481 def type_dependencies(self, env): 2482 return self.iterator.type_dependencies(env) 2483 2484 def infer_type(self, env, iterator_type = None): 2485 if iterator_type is None: 2486 iterator_type = self.iterator.infer_type(env) 2487 if iterator_type.is_ptr or iterator_type.is_array: 2488 return iterator_type.base_type 2489 elif iterator_type.is_cpp_class: 2490 item_type = env.lookup_operator_for_types(self.pos, "*", [iterator_type]).type.return_type 2491 if item_type.is_reference: 2492 item_type = item_type.ref_base_type 2493 if item_type.is_const: 2494 item_type = item_type.const_base_type 2495 return item_type 2496 else: 2497 # Avoid duplication of complicated logic. 2498 fake_index_node = IndexNode( 2499 self.pos, 2500 base=self.iterator.sequence, 2501 index=IntNode(self.pos, value='PY_SSIZE_T_MAX', 2502 type=PyrexTypes.c_py_ssize_t_type)) 2503 return fake_index_node.infer_type(env) 2504 2505 def analyse_types(self, env): 2506 self.type = self.infer_type(env, self.iterator.type) 2507 self.is_temp = 1 2508 return self 2509 2510 def generate_result_code(self, code): 2511 self.iterator.generate_iter_next_result_code(self.result(), code) 2512 2513 2514 class WithExitCallNode(ExprNode): 2515 # The __exit__() call of a 'with' statement. Used in both the 2516 # except and finally clauses. 2517 2518 # with_stat WithStatNode the surrounding 'with' statement 2519 # args TupleNode or ResultStatNode the exception info tuple 2520 2521 subexprs = ['args'] 2522 test_if_run = True 2523 2524 def analyse_types(self, env): 2525 self.args = self.args.analyse_types(env) 2526 self.type = PyrexTypes.c_bint_type 2527 self.is_temp = True 2528 return self 2529 2530 def generate_evaluation_code(self, code): 2531 if self.test_if_run: 2532 # call only if it was not already called (and decref-cleared) 2533 code.putln("if (%s) {" % self.with_stat.exit_var) 2534 2535 self.args.generate_evaluation_code(code) 2536 result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False) 2537 2538 code.mark_pos(self.pos) 2539 code.globalstate.use_utility_code(UtilityCode.load_cached( 2540 "PyObjectCall", "ObjectHandling.c")) 2541 code.putln("%s = __Pyx_PyObject_Call(%s, %s, NULL);" % ( 2542 result_var, 2543 self.with_stat.exit_var, 2544 self.args.result())) 2545 code.put_decref_clear(self.with_stat.exit_var, type=py_object_type) 2546 self.args.generate_disposal_code(code) 2547 self.args.free_temps(code) 2548 2549 code.putln(code.error_goto_if_null(result_var, self.pos)) 2550 code.put_gotref(result_var) 2551 if self.result_is_used: 2552 self.allocate_temp_result(code) 2553 code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var)) 2554 code.put_decref_clear(result_var, type=py_object_type) 2555 if self.result_is_used: 2556 code.put_error_if_neg(self.pos, self.result()) 2557 code.funcstate.release_temp(result_var) 2558 if self.test_if_run: 2559 code.putln("}") 2560 2561 2562 class ExcValueNode(AtomicExprNode): 2563 # Node created during analyse_types phase 2564 # of an ExceptClauseNode to fetch the current 2565 # exception value. 2566 2567 type = py_object_type 2568 2569 def __init__(self, pos): 2570 ExprNode.__init__(self, pos) 2571 2572 def set_var(self, var): 2573 self.var = var 2574 2575 def calculate_result_code(self): 2576 return self.var 2577 2578 def generate_result_code(self, code): 2579 pass 2580 2581 def analyse_types(self, env): 2582 return self 2583 2584 2585 class TempNode(ExprNode): 2586 # Node created during analyse_types phase 2587 # of some nodes to hold a temporary value. 2588 # 2589 # Note: One must call "allocate" and "release" on 2590 # the node during code generation to get/release the temp. 2591 # This is because the temp result is often used outside of 2592 # the regular cycle. 2593 2594 subexprs = [] 2595 2596 def __init__(self, pos, type, env=None): 2597 ExprNode.__init__(self, pos) 2598 self.type = type 2599 if type.is_pyobject: 2600 self.result_ctype = py_object_type 2601 self.is_temp = 1 2602 2603 def analyse_types(self, env): 2604 return self 2605 2606 def analyse_target_declaration(self, env): 2607 pass 2608 2609 def generate_result_code(self, code): 2610 pass 2611 2612 def allocate(self, code): 2613 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True) 2614 2615 def release(self, code): 2616 code.funcstate.release_temp(self.temp_cname) 2617 self.temp_cname = None 2618 2619 def result(self): 2620 try: 2621 return self.temp_cname 2622 except: 2623 assert False, "Remember to call allocate/release on TempNode" 2624 raise 2625 2626 # Do not participate in normal temp alloc/dealloc: 2627 def allocate_temp_result(self, code): 2628 pass 2629 2630 def release_temp_result(self, code): 2631 pass 2632 2633 class PyTempNode(TempNode): 2634 # TempNode holding a Python value. 2635 2636 def __init__(self, pos, env): 2637 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env) 2638 2639 class RawCNameExprNode(ExprNode): 2640 subexprs = [] 2641 2642 def __init__(self, pos, type=None, cname=None): 2643 ExprNode.__init__(self, pos, type=type) 2644 if cname is not None: 2645 self.cname = cname 2646 2647 def analyse_types(self, env): 2648 return self 2649 2650 def set_cname(self, cname): 2651 self.cname = cname 2652 2653 def result(self): 2654 return self.cname 2655 2656 def generate_result_code(self, code): 2657 pass 2658 2659 2660 #------------------------------------------------------------------- 2661 # 2662 # Parallel nodes (cython.parallel.thread(savailable|id)) 2663 # 2664 #------------------------------------------------------------------- 2665 2666 class ParallelThreadsAvailableNode(AtomicExprNode): 2667 """ 2668 Note: this is disabled and not a valid directive at this moment 2669 2670 Implements cython.parallel.threadsavailable(). If we are called from the 2671 sequential part of the application, we need to call omp_get_max_threads(), 2672 and in the parallel part we can just call omp_get_num_threads() 2673 """ 2674 2675 type = PyrexTypes.c_int_type 2676 2677 def analyse_types(self, env): 2678 self.is_temp = True 2679 # env.add_include_file("omp.h") 2680 return self 2681 2682 def generate_result_code(self, code): 2683 code.putln("#ifdef _OPENMP") 2684 code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" % 2685 self.temp_code) 2686 code.putln("else %s = omp_get_num_threads();" % self.temp_code) 2687 code.putln("#else") 2688 code.putln("%s = 1;" % self.temp_code) 2689 code.putln("#endif") 2690 2691 def result(self): 2692 return self.temp_code 2693 2694 2695 class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode): 2696 """ 2697 Implements cython.parallel.threadid() 2698 """ 2699 2700 type = PyrexTypes.c_int_type 2701 2702 def analyse_types(self, env): 2703 self.is_temp = True 2704 # env.add_include_file("omp.h") 2705 return self 2706 2707 def generate_result_code(self, code): 2708 code.putln("#ifdef _OPENMP") 2709 code.putln("%s = omp_get_thread_num();" % self.temp_code) 2710 code.putln("#else") 2711 code.putln("%s = 0;" % self.temp_code) 2712 code.putln("#endif") 2713 2714 def result(self): 2715 return self.temp_code 2716 2717 2718 #------------------------------------------------------------------- 2719 # 2720 # Trailer nodes 2721 # 2722 #------------------------------------------------------------------- 2723 2724 class IndexNode(ExprNode): 2725 # Sequence indexing. 2726 # 2727 # base ExprNode 2728 # index ExprNode 2729 # indices [ExprNode] 2730 # type_indices [PyrexType] 2731 # is_buffer_access boolean Whether this is a buffer access. 2732 # 2733 # indices is used on buffer access, index on non-buffer access. 2734 # The former contains a clean list of index parameters, the 2735 # latter whatever Python object is needed for index access. 2736 # 2737 # is_fused_index boolean Whether the index is used to specialize a 2738 # c(p)def function 2739 2740 subexprs = ['base', 'index', 'indices'] 2741 indices = None 2742 type_indices = None 2743 2744 is_subscript = True 2745 is_fused_index = False 2746 2747 # Whether we're assigning to a buffer (in that case it needs to be 2748 # writable) 2749 writable_needed = False 2750 2751 # Whether we are indexing or slicing a memoryviewslice 2752 memslice_index = False 2753 memslice_slice = False 2754 is_memslice_copy = False 2755 memslice_ellipsis_noop = False 2756 warned_untyped_idx = False 2757 # set by SingleAssignmentNode after analyse_types() 2758 is_memslice_scalar_assignment = False 2759 2760 def __init__(self, pos, index, **kw): 2761 ExprNode.__init__(self, pos, index=index, **kw) 2762 self._index = index 2763 2764 def calculate_constant_result(self): 2765 self.constant_result = \ 2766 self.base.constant_result[self.index.constant_result] 2767 2768 def compile_time_value(self, denv): 2769 base = self.base.compile_time_value(denv) 2770 index = self.index.compile_time_value(denv) 2771 try: 2772 return base[index] 2773 except Exception, e: 2774 self.compile_time_value_error(e) 2775 2776 def is_ephemeral(self): 2777 return self.base.is_ephemeral() 2778 2779 def is_simple(self): 2780 if self.is_buffer_access or self.memslice_index: 2781 return False 2782 elif self.memslice_slice: 2783 return True 2784 2785 base = self.base 2786 return (base.is_simple() and self.index.is_simple() 2787 and base.type and (base.type.is_ptr or base.type.is_array)) 2788 2789 def may_be_none(self): 2790 base_type = self.base.type 2791 if base_type: 2792 if base_type.is_string: 2793 return False 2794 if isinstance(self.index, SliceNode): 2795 # slicing! 2796 if base_type in (bytes_type, str_type, unicode_type, 2797 basestring_type, list_type, tuple_type): 2798 return False 2799 return ExprNode.may_be_none(self) 2800 2801 def analyse_target_declaration(self, env): 2802 pass 2803 2804 def analyse_as_type(self, env): 2805 base_type = self.base.analyse_as_type(env) 2806 if base_type and not base_type.is_pyobject: 2807 if base_type.is_cpp_class: 2808 if isinstance(self.index, TupleNode): 2809 template_values = self.index.args 2810 else: 2811 template_values = [self.index] 2812 import Nodes 2813 type_node = Nodes.TemplatedTypeNode( 2814 pos = self.pos, 2815 positional_args = template_values, 2816 keyword_args = None) 2817 return type_node.analyse(env, base_type = base_type) 2818 else: 2819 index = self.index.compile_time_value(env) 2820 if index is not None: 2821 return PyrexTypes.CArrayType(base_type, int(index)) 2822 error(self.pos, "Array size must be a compile time constant") 2823 return None 2824 2825 def type_dependencies(self, env): 2826 return self.base.type_dependencies(env) + self.index.type_dependencies(env) 2827 2828 def infer_type(self, env): 2829 base_type = self.base.infer_type(env) 2830 if isinstance(self.index, SliceNode): 2831 # slicing! 2832 if base_type.is_string: 2833 # sliced C strings must coerce to Python 2834 return bytes_type 2835 elif base_type.is_pyunicode_ptr: 2836 # sliced Py_UNICODE* strings must coerce to Python 2837 return unicode_type 2838 elif base_type in (unicode_type, bytes_type, str_type, 2839 bytearray_type, list_type, tuple_type): 2840 # slicing these returns the same type 2841 return base_type 2842 else: 2843 # TODO: Handle buffers (hopefully without too much redundancy). 2844 return py_object_type 2845 2846 index_type = self.index.infer_type(env) 2847 if index_type and index_type.is_int or isinstance(self.index, IntNode): 2848 # indexing! 2849 if base_type is unicode_type: 2850 # Py_UCS4 will automatically coerce to a unicode string 2851 # if required, so this is safe. We only infer Py_UCS4 2852 # when the index is a C integer type. Otherwise, we may 2853 # need to use normal Python item access, in which case 2854 # it's faster to return the one-char unicode string than 2855 # to receive it, throw it away, and potentially rebuild it 2856 # on a subsequent PyObject coercion. 2857 return PyrexTypes.c_py_ucs4_type 2858 elif base_type is str_type: 2859 # always returns str - Py2: bytes, Py3: unicode 2860 return base_type 2861 elif base_type is bytearray_type: 2862 return PyrexTypes.c_uchar_type 2863 elif isinstance(self.base, BytesNode): 2864 #if env.global_scope().context.language_level >= 3: 2865 # # inferring 'char' can be made to work in Python 3 mode 2866 # return PyrexTypes.c_char_type 2867 # Py2/3 return different types on indexing bytes objects 2868 return py_object_type 2869 elif base_type in (tuple_type, list_type): 2870 # if base is a literal, take a look at its values 2871 item_type = infer_sequence_item_type( 2872 env, self.base, self.index, seq_type=base_type) 2873 if item_type is not None: 2874 return item_type 2875 elif base_type.is_ptr or base_type.is_array: 2876 return base_type.base_type 2877 2878 if base_type.is_cpp_class: 2879 class FakeOperand: 2880 def __init__(self, **kwds): 2881 self.__dict__.update(kwds) 2882 operands = [ 2883 FakeOperand(pos=self.pos, type=base_type), 2884 FakeOperand(pos=self.pos, type=index_type), 2885 ] 2886 index_func = env.lookup_operator('[]', operands) 2887 if index_func is not None: 2888 return index_func.type.return_type 2889 2890 # may be slicing or indexing, we don't know 2891 if base_type in (unicode_type, str_type): 2892 # these types always returns their own type on Python indexing/slicing 2893 return base_type 2894 else: 2895 # TODO: Handle buffers (hopefully without too much redundancy). 2896 return py_object_type 2897 2898 def analyse_types(self, env): 2899 return self.analyse_base_and_index_types(env, getting=True) 2900 2901 def analyse_target_types(self, env): 2902 node = self.analyse_base_and_index_types(env, setting=True) 2903 if node.type.is_const: 2904 error(self.pos, "Assignment to const dereference") 2905 if not node.is_lvalue(): 2906 error(self.pos, "Assignment to non-lvalue of type '%s'" % node.type) 2907 return node 2908 2909 def analyse_base_and_index_types(self, env, getting=False, setting=False, 2910 analyse_base=True): 2911 # Note: This might be cleaned up by having IndexNode 2912 # parsed in a saner way and only construct the tuple if 2913 # needed. 2914 2915 # Note that this function must leave IndexNode in a cloneable state. 2916 # For buffers, self.index is packed out on the initial analysis, and 2917 # when cloning self.indices is copied. 2918 self.is_buffer_access = False 2919 2920 # a[...] = b 2921 self.is_memslice_copy = False 2922 # incomplete indexing, Ellipsis indexing or slicing 2923 self.memslice_slice = False 2924 # integer indexing 2925 self.memslice_index = False 2926 2927 if analyse_base: 2928 self.base = self.base.analyse_types(env) 2929 2930 if self.base.type.is_error: 2931 # Do not visit child tree if base is undeclared to avoid confusing 2932 # error messages 2933 self.type = PyrexTypes.error_type 2934 return self 2935 2936 is_slice = isinstance(self.index, SliceNode) 2937 2938 if not env.directives['wraparound']: 2939 if is_slice: 2940 check_negative_indices(self.index.start, self.index.stop) 2941 else: 2942 check_negative_indices(self.index) 2943 2944 # Potentially overflowing index value. 2945 if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value): 2946 self.index = self.index.coerce_to_pyobject(env) 2947 2948 is_memslice = self.base.type.is_memoryviewslice 2949 2950 # Handle the case where base is a literal char* (and we expect a string, not an int) 2951 if not is_memslice and (isinstance(self.base, BytesNode) or is_slice): 2952 if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array): 2953 self.base = self.base.coerce_to_pyobject(env) 2954 2955 skip_child_analysis = False 2956 buffer_access = False 2957 2958 if self.indices: 2959 indices = self.indices 2960 elif isinstance(self.index, TupleNode): 2961 indices = self.index.args 2962 else: 2963 indices = [self.index] 2964 2965 if (is_memslice and not self.indices and 2966 isinstance(self.index, EllipsisNode)): 2967 # Memoryviewslice copying 2968 self.is_memslice_copy = True 2969 2970 elif is_memslice: 2971 # memoryviewslice indexing or slicing 2972 import MemoryView 2973 2974 skip_child_analysis = True 2975 newaxes = [newaxis for newaxis in indices if newaxis.is_none] 2976 have_slices, indices = MemoryView.unellipsify(indices, 2977 newaxes, 2978 self.base.type.ndim) 2979 2980 self.memslice_index = (not newaxes and 2981 len(indices) == self.base.type.ndim) 2982 axes = [] 2983 2984 index_type = PyrexTypes.c_py_ssize_t_type 2985 new_indices = [] 2986 2987 if len(indices) - len(newaxes) > self.base.type.ndim: 2988 self.type = error_type 2989 error(indices[self.base.type.ndim].pos, 2990 "Too many indices specified for type %s" % 2991 self.base.type) 2992 return self 2993 2994 axis_idx = 0 2995 for i, index in enumerate(indices[:]): 2996 index = index.analyse_types(env) 2997 if not index.is_none: 2998 access, packing = self.base.type.axes[axis_idx] 2999 axis_idx += 1 3000 3001 if isinstance(index, SliceNode): 3002 self.memslice_slice = True 3003 if index.step.is_none: 3004 axes.append((access, packing)) 3005 else: 3006 axes.append((access, 'strided')) 3007 3008 # Coerce start, stop and step to temps of the right type 3009 for attr in ('start', 'stop', 'step'): 3010 value = getattr(index, attr) 3011 if not value.is_none: 3012 value = value.coerce_to(index_type, env) 3013 #value = value.coerce_to_temp(env) 3014 setattr(index, attr, value) 3015 new_indices.append(value) 3016 3017 elif index.is_none: 3018 self.memslice_slice = True 3019 new_indices.append(index) 3020 axes.append(('direct', 'strided')) 3021 3022 elif index.type.is_int or index.type.is_pyobject: 3023 if index.type.is_pyobject and not self.warned_untyped_idx: 3024 warning(index.pos, "Index should be typed for more " 3025 "efficient access", level=2) 3026 IndexNode.warned_untyped_idx = True 3027 3028 self.memslice_index = True 3029 index = index.coerce_to(index_type, env) 3030 indices[i] = index 3031 new_indices.append(index) 3032 3033 else: 3034 self.type = error_type 3035 error(index.pos, "Invalid index for memoryview specified") 3036 return self 3037 3038 self.memslice_index = self.memslice_index and not self.memslice_slice 3039 self.original_indices = indices 3040 # All indices with all start/stop/step for slices. 3041 # We need to keep this around 3042 self.indices = new_indices 3043 self.env = env 3044 3045 elif self.base.type.is_buffer: 3046 # Buffer indexing 3047 if len(indices) == self.base.type.ndim: 3048 buffer_access = True 3049 skip_child_analysis = True 3050 for x in indices: 3051 x = x.analyse_types(env) 3052 if not x.type.is_int: 3053 buffer_access = False 3054 3055 if buffer_access and not self.base.type.is_memoryviewslice: 3056 assert hasattr(self.base, "entry") # Must be a NameNode-like node 3057 3058 # On cloning, indices is cloned. Otherwise, unpack index into indices 3059 assert not (buffer_access and isinstance(self.index, CloneNode)) 3060 3061 self.nogil = env.nogil 3062 3063 if buffer_access or self.memslice_index: 3064 #if self.base.type.is_memoryviewslice and not self.base.is_name: 3065 # self.base = self.base.coerce_to_temp(env) 3066 self.base = self.base.coerce_to_simple(env) 3067 3068 self.indices = indices 3069 self.index = None 3070 self.type = self.base.type.dtype 3071 self.is_buffer_access = True 3072 self.buffer_type = self.base.type #self.base.entry.type 3073 3074 if getting and self.type.is_pyobject: 3075 self.is_temp = True 3076 3077 if setting and self.base.type.is_memoryviewslice: 3078 self.base.type.writable_needed = True 3079 elif setting: 3080 if not self.base.entry.type.writable: 3081 error(self.pos, "Writing to readonly buffer") 3082 else: 3083 self.writable_needed = True 3084 if self.base.type.is_buffer: 3085 self.base.entry.buffer_aux.writable_needed = True 3086 3087 elif self.is_memslice_copy: 3088 self.type = self.base.type 3089 if getting: 3090 self.memslice_ellipsis_noop = True 3091 else: 3092 self.memslice_broadcast = True 3093 3094 elif self.memslice_slice: 3095 self.index = None 3096 self.is_temp = True 3097 self.use_managed_ref = True 3098 3099 if not MemoryView.validate_axes(self.pos, axes): 3100 self.type = error_type 3101 return self 3102 3103 self.type = PyrexTypes.MemoryViewSliceType( 3104 self.base.type.dtype, axes) 3105 3106 if (self.base.type.is_memoryviewslice and not 3107 self.base.is_name and not 3108 self.base.result_in_temp()): 3109 self.base = self.base.coerce_to_temp(env) 3110 3111 if setting: 3112 self.memslice_broadcast = True 3113 3114 else: 3115 base_type = self.base.type 3116 3117 if not base_type.is_cfunction: 3118 if isinstance(self.index, TupleNode): 3119 self.index = self.index.analyse_types( 3120 env, skip_children=skip_child_analysis) 3121 elif not skip_child_analysis: 3122 self.index = self.index.analyse_types(env) 3123 self.original_index_type = self.index.type 3124 3125 if base_type.is_unicode_char: 3126 # we infer Py_UNICODE/Py_UCS4 for unicode strings in some 3127 # cases, but indexing must still work for them 3128 if setting: 3129 warning(self.pos, "cannot assign to Unicode string index", level=1) 3130 elif self.index.constant_result in (0, -1): 3131 # uchar[0] => uchar 3132 return self.base 3133 self.base = self.base.coerce_to_pyobject(env) 3134 base_type = self.base.type 3135 if base_type.is_pyobject: 3136 if self.index.type.is_int and base_type is not dict_type: 3137 if (getting 3138 and (base_type in (list_type, tuple_type, bytearray_type)) 3139 and (not self.index.type.signed 3140 or not env.directives['wraparound'] 3141 or (isinstance(self.index, IntNode) and 3142 self.index.has_constant_result() and self.index.constant_result >= 0)) 3143 and not env.directives['boundscheck']): 3144 self.is_temp = 0 3145 else: 3146 self.is_temp = 1 3147 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env) 3148 self.original_index_type.create_to_py_utility_code(env) 3149 else: 3150 self.index = self.index.coerce_to_pyobject(env) 3151 self.is_temp = 1 3152 if self.index.type.is_int and base_type is unicode_type: 3153 # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string 3154 # if required, so this is fast and safe 3155 self.type = PyrexTypes.c_py_ucs4_type 3156 elif self.index.type.is_int and base_type is bytearray_type: 3157 if setting: 3158 self.type = PyrexTypes.c_uchar_type 3159 else: 3160 # not using 'uchar' to enable fast and safe error reporting as '-1' 3161 self.type = PyrexTypes.c_int_type 3162 elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type): 3163 self.type = base_type 3164 else: 3165 item_type = None 3166 if base_type in (list_type, tuple_type) and self.index.type.is_int: 3167 item_type = infer_sequence_item_type( 3168 env, self.base, self.index, seq_type=base_type) 3169 if item_type is None: 3170 item_type = py_object_type 3171 self.type = item_type 3172 if base_type in (list_type, tuple_type, dict_type): 3173 # do the None check explicitly (not in a helper) to allow optimising it away 3174 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") 3175 else: 3176 if base_type.is_ptr or base_type.is_array: 3177 self.type = base_type.base_type 3178 if is_slice: 3179 self.type = base_type 3180 elif self.index.type.is_pyobject: 3181 self.index = self.index.coerce_to( 3182 PyrexTypes.c_py_ssize_t_type, env) 3183 elif not self.index.type.is_int: 3184 error(self.pos, 3185 "Invalid index type '%s'" % 3186 self.index.type) 3187 elif base_type.is_cpp_class: 3188 function = env.lookup_operator("[]", [self.base, self.index]) 3189 if function is None: 3190 error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type)) 3191 self.type = PyrexTypes.error_type 3192 self.result_code = "<error>" 3193 return self 3194 func_type = function.type 3195 if func_type.is_ptr: 3196 func_type = func_type.base_type 3197 self.index = self.index.coerce_to(func_type.args[0].type, env) 3198 self.type = func_type.return_type 3199 if setting and not func_type.return_type.is_reference: 3200 error(self.pos, "Can't set non-reference result '%s'" % self.type) 3201 elif base_type.is_cfunction: 3202 if base_type.is_fused: 3203 self.parse_indexed_fused_cdef(env) 3204 else: 3205 self.type_indices = self.parse_index_as_types(env) 3206 if base_type.templates is None: 3207 error(self.pos, "Can only parameterize template functions.") 3208 elif len(base_type.templates) != len(self.type_indices): 3209 error(self.pos, "Wrong number of template arguments: expected %s, got %s" % ( 3210 (len(base_type.templates), len(self.type_indices)))) 3211 self.type = base_type.specialize(dict(zip(base_type.templates, self.type_indices))) 3212 else: 3213 error(self.pos, 3214 "Attempting to index non-array type '%s'" % 3215 base_type) 3216 self.type = PyrexTypes.error_type 3217 3218 self.wrap_in_nonecheck_node(env, getting) 3219 return self 3220 3221 def wrap_in_nonecheck_node(self, env, getting): 3222 if not env.directives['nonecheck'] or not self.base.may_be_none(): 3223 return 3224 3225 if self.base.type.is_memoryviewslice: 3226 if self.is_memslice_copy and not getting: 3227 msg = "Cannot assign to None memoryview slice" 3228 elif self.memslice_slice: 3229 msg = "Cannot slice None memoryview slice" 3230 else: 3231 msg = "Cannot index None memoryview slice" 3232 else: 3233 msg = "'NoneType' object is not subscriptable" 3234 3235 self.base = self.base.as_none_safe_node(msg) 3236 3237 def parse_index_as_types(self, env, required=True): 3238 if isinstance(self.index, TupleNode): 3239 indices = self.index.args 3240 else: 3241 indices = [self.index] 3242 type_indices = [] 3243 for index in indices: 3244 type_indices.append(index.analyse_as_type(env)) 3245 if type_indices[-1] is None: 3246 if required: 3247 error(index.pos, "not parsable as a type") 3248 return None 3249 return type_indices 3250 3251 def parse_indexed_fused_cdef(self, env): 3252 """ 3253 Interpret fused_cdef_func[specific_type1, ...] 3254 3255 Note that if this method is called, we are an indexed cdef function 3256 with fused argument types, and this IndexNode will be replaced by the 3257 NameNode with specific entry just after analysis of expressions by 3258 AnalyseExpressionsTransform. 3259 """ 3260 self.type = PyrexTypes.error_type 3261 3262 self.is_fused_index = True 3263 3264 base_type = self.base.type 3265 specific_types = [] 3266 positions = [] 3267 3268 if self.index.is_name or self.index.is_attribute: 3269 positions.append(self.index.pos) 3270 elif isinstance(self.index, TupleNode): 3271 for arg in self.index.args: 3272 positions.append(arg.pos) 3273 specific_types = self.parse_index_as_types(env, required=False) 3274 3275 if specific_types is None: 3276 self.index = self.index.analyse_types(env) 3277 3278 if not self.base.entry.as_variable: 3279 error(self.pos, "Can only index fused functions with types") 3280 else: 3281 # A cpdef function indexed with Python objects 3282 self.base.entry = self.entry = self.base.entry.as_variable 3283 self.base.type = self.type = self.entry.type 3284 3285 self.base.is_temp = True 3286 self.is_temp = True 3287 3288 self.entry.used = True 3289 3290 self.is_fused_index = False 3291 return 3292 3293 for i, type in enumerate(specific_types): 3294 specific_types[i] = type.specialize_fused(env) 3295 3296 fused_types = base_type.get_fused_types() 3297 if len(specific_types) > len(fused_types): 3298 return error(self.pos, "Too many types specified") 3299 elif len(specific_types) < len(fused_types): 3300 t = fused_types[len(specific_types)] 3301 return error(self.pos, "Not enough types specified to specialize " 3302 "the function, %s is still fused" % t) 3303 3304 # See if our index types form valid specializations 3305 for pos, specific_type, fused_type in zip(positions, 3306 specific_types, 3307 fused_types): 3308 if not Utils.any([specific_type.same_as(t) 3309 for t in fused_type.types]): 3310 return error(pos, "Type not in fused type") 3311 3312 if specific_type is None or specific_type.is_error: 3313 return 3314 3315 fused_to_specific = dict(zip(fused_types, specific_types)) 3316 type = base_type.specialize(fused_to_specific) 3317 3318 if type.is_fused: 3319 # Only partially specific, this is invalid 3320 error(self.pos, 3321 "Index operation makes function only partially specific") 3322 else: 3323 # Fully specific, find the signature with the specialized entry 3324 for signature in self.base.type.get_all_specialized_function_types(): 3325 if type.same_as(signature): 3326 self.type = signature 3327 3328 if self.base.is_attribute: 3329 # Pretend to be a normal attribute, for cdef extension 3330 # methods 3331 self.entry = signature.entry 3332 self.is_attribute = True 3333 self.obj = self.base.obj 3334 3335 self.type.entry.used = True 3336 self.base.type = signature 3337 self.base.entry = signature.entry 3338 3339 break 3340 else: 3341 # This is a bug 3342 raise InternalError("Couldn't find the right signature") 3343 3344 gil_message = "Indexing Python object" 3345 3346 def nogil_check(self, env): 3347 if self.is_buffer_access or self.memslice_index or self.memslice_slice: 3348 if not self.memslice_slice and env.directives['boundscheck']: 3349 # error(self.pos, "Cannot check buffer index bounds without gil; " 3350 # "use boundscheck(False) directive") 3351 warning(self.pos, "Use boundscheck(False) for faster access", 3352 level=1) 3353 if self.type.is_pyobject: 3354 error(self.pos, "Cannot access buffer with object dtype without gil") 3355 return 3356 super(IndexNode, self).nogil_check(env) 3357 3358 3359 def check_const_addr(self): 3360 return self.base.check_const_addr() and self.index.check_const() 3361 3362 def is_lvalue(self): 3363 # NOTE: references currently have both is_reference and is_ptr 3364 # set. Since pointers and references have different lvalue 3365 # rules, we must be careful to separate the two. 3366 if self.type.is_reference: 3367 if self.type.ref_base_type.is_array: 3368 # fixed-sized arrays aren't l-values 3369 return False 3370 elif self.type.is_ptr: 3371 # non-const pointers can always be reassigned 3372 return True 3373 elif self.type.is_array: 3374 # fixed-sized arrays aren't l-values 3375 return False 3376 # Just about everything else returned by the index operator 3377 # can be an lvalue. 3378 return True 3379 3380 def calculate_result_code(self): 3381 if self.is_buffer_access: 3382 return "(*%s)" % self.buffer_ptr_code 3383 elif self.is_memslice_copy: 3384 return self.base.result() 3385 elif self.base.type in (list_type, tuple_type, bytearray_type): 3386 if self.base.type is list_type: 3387 index_code = "PyList_GET_ITEM(%s, %s)" 3388 elif self.base.type is tuple_type: 3389 index_code = "PyTuple_GET_ITEM(%s, %s)" 3390 elif self.base.type is bytearray_type: 3391 index_code = "((unsigned char)(PyByteArray_AS_STRING(%s)[%s]))" 3392 else: 3393 assert False, "unexpected base type in indexing: %s" % self.base.type 3394 elif self.base.type.is_cfunction: 3395 return "%s<%s>" % ( 3396 self.base.result(), 3397 ",".join([param.declaration_code("") for param in self.type_indices])) 3398 else: 3399 if (self.type.is_ptr or self.type.is_array) and self.type == self.base.type: 3400 error(self.pos, "Invalid use of pointer slice") 3401 return 3402 index_code = "(%s[%s])" 3403 return index_code % (self.base.result(), self.index.result()) 3404 3405 def extra_index_params(self, code): 3406 if self.index.type.is_int: 3407 is_list = self.base.type is list_type 3408 wraparound = ( 3409 bool(code.globalstate.directives['wraparound']) and 3410 self.original_index_type.signed and 3411 not (isinstance(self.index.constant_result, (int, long)) 3412 and self.index.constant_result >= 0)) 3413 boundscheck = bool(code.globalstate.directives['boundscheck']) 3414 return ", %s, %d, %s, %d, %d, %d" % ( 3415 self.original_index_type.declaration_code(""), 3416 self.original_index_type.signed and 1 or 0, 3417 self.original_index_type.to_py_function, 3418 is_list, wraparound, boundscheck) 3419 else: 3420 return "" 3421 3422 def generate_subexpr_evaluation_code(self, code): 3423 self.base.generate_evaluation_code(code) 3424 if self.type_indices is not None: 3425 pass 3426 elif self.indices is None: 3427 self.index.generate_evaluation_code(code) 3428 else: 3429 for i in self.indices: 3430 i.generate_evaluation_code(code) 3431 3432 def generate_subexpr_disposal_code(self, code): 3433 self.base.generate_disposal_code(code) 3434 if self.type_indices is not None: 3435 pass 3436 elif self.indices is None: 3437 self.index.generate_disposal_code(code) 3438 else: 3439 for i in self.indices: 3440 i.generate_disposal_code(code) 3441 3442 def free_subexpr_temps(self, code): 3443 self.base.free_temps(code) 3444 if self.indices is None: 3445 self.index.free_temps(code) 3446 else: 3447 for i in self.indices: 3448 i.free_temps(code) 3449 3450 def generate_result_code(self, code): 3451 if self.is_buffer_access or self.memslice_index: 3452 buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code) 3453 if self.type.is_pyobject: 3454 # is_temp is True, so must pull out value and incref it. 3455 # NOTE: object temporary results for nodes are declared 3456 # as PyObject *, so we need a cast 3457 code.putln("%s = (PyObject *) *%s;" % (self.temp_code, 3458 self.buffer_ptr_code)) 3459 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.temp_code) 3460 3461 elif self.memslice_slice: 3462 self.put_memoryviewslice_slice_code(code) 3463 3464 elif self.is_temp: 3465 if self.type.is_pyobject: 3466 error_value = 'NULL' 3467 if self.index.type.is_int: 3468 if self.base.type is list_type: 3469 function = "__Pyx_GetItemInt_List" 3470 elif self.base.type is tuple_type: 3471 function = "__Pyx_GetItemInt_Tuple" 3472 else: 3473 function = "__Pyx_GetItemInt" 3474 code.globalstate.use_utility_code( 3475 TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c")) 3476 else: 3477 if self.base.type is dict_type: 3478 function = "__Pyx_PyDict_GetItem" 3479 code.globalstate.use_utility_code( 3480 UtilityCode.load_cached("DictGetItem", "ObjectHandling.c")) 3481 else: 3482 function = "PyObject_GetItem" 3483 elif self.type.is_unicode_char and self.base.type is unicode_type: 3484 assert self.index.type.is_int 3485 function = "__Pyx_GetItemInt_Unicode" 3486 error_value = '(Py_UCS4)-1' 3487 code.globalstate.use_utility_code( 3488 UtilityCode.load_cached("GetItemIntUnicode", "StringTools.c")) 3489 elif self.base.type is bytearray_type: 3490 assert self.index.type.is_int 3491 assert self.type.is_int 3492 function = "__Pyx_GetItemInt_ByteArray" 3493 error_value = '-1' 3494 code.globalstate.use_utility_code( 3495 UtilityCode.load_cached("GetItemIntByteArray", "StringTools.c")) 3496 else: 3497 assert False, "unexpected type %s and base type %s for indexing" % ( 3498 self.type, self.base.type) 3499 3500 if self.index.type.is_int: 3501 index_code = self.index.result() 3502 else: 3503 index_code = self.index.py_result() 3504 3505 code.putln( 3506 "%s = %s(%s, %s%s); if (unlikely(%s == %s)) %s;" % ( 3507 self.result(), 3508 function, 3509 self.base.py_result(), 3510 index_code, 3511 self.extra_index_params(code), 3512 self.result(), 3513 error_value, 3514 code.error_goto(self.pos))) 3515 if self.type.is_pyobject: 3516 code.put_gotref(self.py_result()) 3517 3518 def generate_setitem_code(self, value_code, code): 3519 if self.index.type.is_int: 3520 if self.base.type is bytearray_type: 3521 code.globalstate.use_utility_code( 3522 UtilityCode.load_cached("SetItemIntByteArray", "StringTools.c")) 3523 function = "__Pyx_SetItemInt_ByteArray" 3524 else: 3525 code.globalstate.use_utility_code( 3526 UtilityCode.load_cached("SetItemInt", "ObjectHandling.c")) 3527 function = "__Pyx_SetItemInt" 3528 index_code = self.index.result() 3529 else: 3530 index_code = self.index.py_result() 3531 if self.base.type is dict_type: 3532 function = "PyDict_SetItem" 3533 # It would seem that we could specialized lists/tuples, but that 3534 # shouldn't happen here. 3535 # Both PyList_SetItem() and PyTuple_SetItem() take a Py_ssize_t as 3536 # index instead of an object, and bad conversion here would give 3537 # the wrong exception. Also, tuples are supposed to be immutable, 3538 # and raise a TypeError when trying to set their entries 3539 # (PyTuple_SetItem() is for creating new tuples from scratch). 3540 else: 3541 function = "PyObject_SetItem" 3542 code.putln( 3543 "if (unlikely(%s(%s, %s, %s%s) < 0)) %s" % ( 3544 function, 3545 self.base.py_result(), 3546 index_code, 3547 value_code, 3548 self.extra_index_params(code), 3549 code.error_goto(self.pos))) 3550 3551 def generate_buffer_setitem_code(self, rhs, code, op=""): 3552 # Used from generate_assignment_code and InPlaceAssignmentNode 3553 buffer_entry, ptrexpr = self.buffer_lookup_code(code) 3554 3555 if self.buffer_type.dtype.is_pyobject: 3556 # Must manage refcounts. Decref what is already there 3557 # and incref what we put in. 3558 ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type, 3559 manage_ref=False) 3560 rhs_code = rhs.result() 3561 code.putln("%s = %s;" % (ptr, ptrexpr)) 3562 code.put_gotref("*%s" % ptr) 3563 code.putln("__Pyx_INCREF(%s); __Pyx_DECREF(*%s);" % ( 3564 rhs_code, ptr)) 3565 code.putln("*%s %s= %s;" % (ptr, op, rhs_code)) 3566 code.put_giveref("*%s" % ptr) 3567 code.funcstate.release_temp(ptr) 3568 else: 3569 # Simple case 3570 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result())) 3571 3572 def generate_assignment_code(self, rhs, code): 3573 generate_evaluation_code = (self.is_memslice_scalar_assignment or 3574 self.memslice_slice) 3575 if generate_evaluation_code: 3576 self.generate_evaluation_code(code) 3577 else: 3578 self.generate_subexpr_evaluation_code(code) 3579 3580 if self.is_buffer_access or self.memslice_index: 3581 self.generate_buffer_setitem_code(rhs, code) 3582 elif self.is_memslice_scalar_assignment: 3583 self.generate_memoryviewslice_assign_scalar_code(rhs, code) 3584 elif self.memslice_slice or self.is_memslice_copy: 3585 self.generate_memoryviewslice_setslice_code(rhs, code) 3586 elif self.type.is_pyobject: 3587 self.generate_setitem_code(rhs.py_result(), code) 3588 elif self.base.type is bytearray_type: 3589 value_code = self._check_byte_value(code, rhs) 3590 self.generate_setitem_code(value_code, code) 3591 else: 3592 code.putln( 3593 "%s = %s;" % ( 3594 self.result(), rhs.result())) 3595 3596 if generate_evaluation_code: 3597 self.generate_disposal_code(code) 3598 else: 3599 self.generate_subexpr_disposal_code(code) 3600 self.free_subexpr_temps(code) 3601 3602 rhs.generate_disposal_code(code) 3603 rhs.free_temps(code) 3604 3605 def _check_byte_value(self, code, rhs): 3606 # TODO: should we do this generally on downcasts, or just here? 3607 assert rhs.type.is_int, repr(rhs.type) 3608 value_code = rhs.result() 3609 if rhs.has_constant_result(): 3610 if 0 <= rhs.constant_result < 256: 3611 return value_code 3612 needs_cast = True # make at least the C compiler happy 3613 warning(rhs.pos, 3614 "value outside of range(0, 256)" 3615 " when assigning to byte: %s" % rhs.constant_result, 3616 level=1) 3617 else: 3618 needs_cast = rhs.type != PyrexTypes.c_uchar_type 3619 3620 if not self.nogil: 3621 conditions = [] 3622 if rhs.is_literal or rhs.type.signed: 3623 conditions.append('%s < 0' % value_code) 3624 if (rhs.is_literal or not 3625 (rhs.is_temp and rhs.type in ( 3626 PyrexTypes.c_uchar_type, PyrexTypes.c_char_type, 3627 PyrexTypes.c_schar_type))): 3628 conditions.append('%s > 255' % value_code) 3629 if conditions: 3630 code.putln("if (unlikely(%s)) {" % ' || '.join(conditions)) 3631 code.putln( 3632 'PyErr_SetString(PyExc_ValueError,' 3633 ' "byte must be in range(0, 256)"); %s' % 3634 code.error_goto(self.pos)) 3635 code.putln("}") 3636 3637 if needs_cast: 3638 value_code = '((unsigned char)%s)' % value_code 3639 return value_code 3640 3641 def generate_deletion_code(self, code, ignore_nonexisting=False): 3642 self.generate_subexpr_evaluation_code(code) 3643 #if self.type.is_pyobject: 3644 if self.index.type.is_int: 3645 function = "__Pyx_DelItemInt" 3646 index_code = self.index.result() 3647 code.globalstate.use_utility_code( 3648 UtilityCode.load_cached("DelItemInt", "ObjectHandling.c")) 3649 else: 3650 index_code = self.index.py_result() 3651 if self.base.type is dict_type: 3652 function = "PyDict_DelItem" 3653 else: 3654 function = "PyObject_DelItem" 3655 code.putln( 3656 "if (%s(%s, %s%s) < 0) %s" % ( 3657 function, 3658 self.base.py_result(), 3659 index_code, 3660 self.extra_index_params(code), 3661 code.error_goto(self.pos))) 3662 self.generate_subexpr_disposal_code(code) 3663 self.free_subexpr_temps(code) 3664 3665 def buffer_entry(self): 3666 import Buffer, MemoryView 3667 3668 base = self.base 3669 if self.base.is_nonecheck: 3670 base = base.arg 3671 3672 if base.is_name: 3673 entry = base.entry 3674 else: 3675 # SimpleCallNode is_simple is not consistent with coerce_to_simple 3676 assert base.is_simple() or base.is_temp 3677 cname = base.result() 3678 entry = Symtab.Entry(cname, cname, self.base.type, self.base.pos) 3679 3680 if entry.type.is_buffer: 3681 buffer_entry = Buffer.BufferEntry(entry) 3682 else: 3683 buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry) 3684 3685 return buffer_entry 3686 3687 def buffer_lookup_code(self, code): 3688 "ndarray[1, 2, 3] and memslice[1, 2, 3]" 3689 # Assign indices to temps 3690 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) 3691 for i in self.indices] 3692 3693 for temp, index in zip(index_temps, self.indices): 3694 code.putln("%s = %s;" % (temp, index.result())) 3695 3696 # Generate buffer access code using these temps 3697 import Buffer 3698 buffer_entry = self.buffer_entry() 3699 if buffer_entry.type.is_buffer: 3700 negative_indices = buffer_entry.type.negative_indices 3701 else: 3702 negative_indices = Buffer.buffer_defaults['negative_indices'] 3703 3704 return buffer_entry, Buffer.put_buffer_lookup_code( 3705 entry=buffer_entry, 3706 index_signeds=[i.type.signed for i in self.indices], 3707 index_cnames=index_temps, 3708 directives=code.globalstate.directives, 3709 pos=self.pos, code=code, 3710 negative_indices=negative_indices, 3711 in_nogil_context=self.in_nogil_context) 3712 3713 def put_memoryviewslice_slice_code(self, code): 3714 "memslice[:]" 3715 buffer_entry = self.buffer_entry() 3716 have_gil = not self.in_nogil_context 3717 3718 if sys.version_info < (3,): 3719 def next_(it): 3720 return it.next() 3721 else: 3722 next_ = next 3723 3724 have_slices = False 3725 it = iter(self.indices) 3726 for index in self.original_indices: 3727 is_slice = isinstance(index, SliceNode) 3728 have_slices = have_slices or is_slice 3729 if is_slice: 3730 if not index.start.is_none: 3731 index.start = next_(it) 3732 if not index.stop.is_none: 3733 index.stop = next_(it) 3734 if not index.step.is_none: 3735 index.step = next_(it) 3736 else: 3737 next_(it) 3738 3739 assert not list(it) 3740 3741 buffer_entry.generate_buffer_slice_code(code, self.original_indices, 3742 self.result(), 3743 have_gil=have_gil, 3744 have_slices=have_slices, 3745 directives=code.globalstate.directives) 3746 3747 def generate_memoryviewslice_setslice_code(self, rhs, code): 3748 "memslice1[...] = memslice2 or memslice1[:] = memslice2" 3749 import MemoryView 3750 MemoryView.copy_broadcast_memview_src_to_dst(rhs, self, code) 3751 3752 def generate_memoryviewslice_assign_scalar_code(self, rhs, code): 3753 "memslice1[...] = 0.0 or memslice1[:] = 0.0" 3754 import MemoryView 3755 MemoryView.assign_scalar(self, rhs, code) 3756 3757 3758 class SliceIndexNode(ExprNode): 3759 # 2-element slice indexing 3760 # 3761 # base ExprNode 3762 # start ExprNode or None 3763 # stop ExprNode or None 3764 # slice ExprNode or None constant slice object 3765 3766 subexprs = ['base', 'start', 'stop', 'slice'] 3767 3768 slice = None 3769 3770 def infer_type(self, env): 3771 base_type = self.base.infer_type(env) 3772 if base_type.is_string or base_type.is_cpp_class: 3773 return bytes_type 3774 elif base_type.is_pyunicode_ptr: 3775 return unicode_type 3776 elif base_type in (bytes_type, str_type, unicode_type, 3777 basestring_type, list_type, tuple_type): 3778 return base_type 3779 elif base_type.is_ptr or base_type.is_array: 3780 return PyrexTypes.c_array_type(base_type.base_type, None) 3781 return py_object_type 3782 3783 def may_be_none(self): 3784 base_type = self.base.type 3785 if base_type: 3786 if base_type.is_string: 3787 return False 3788 if base_type in (bytes_type, str_type, unicode_type, 3789 basestring_type, list_type, tuple_type): 3790 return False 3791 return ExprNode.may_be_none(self) 3792 3793 def calculate_constant_result(self): 3794 if self.start is None: 3795 start = None 3796 else: 3797 start = self.start.constant_result 3798 if self.stop is None: 3799 stop = None 3800 else: 3801 stop = self.stop.constant_result 3802 self.constant_result = self.base.constant_result[start:stop] 3803 3804 def compile_time_value(self, denv): 3805 base = self.base.compile_time_value(denv) 3806 if self.start is None: 3807 start = 0 3808 else: 3809 start = self.start.compile_time_value(denv) 3810 if self.stop is None: 3811 stop = None 3812 else: 3813 stop = self.stop.compile_time_value(denv) 3814 try: 3815 return base[start:stop] 3816 except Exception, e: 3817 self.compile_time_value_error(e) 3818 3819 def analyse_target_declaration(self, env): 3820 pass 3821 3822 def analyse_target_types(self, env): 3823 node = self.analyse_types(env, getting=False) 3824 # when assigning, we must accept any Python type 3825 if node.type.is_pyobject: 3826 node.type = py_object_type 3827 return node 3828 3829 def analyse_types(self, env, getting=True): 3830 self.base = self.base.analyse_types(env) 3831 3832 if self.base.type.is_memoryviewslice: 3833 none_node = NoneNode(self.pos) 3834 index = SliceNode(self.pos, 3835 start=self.start or none_node, 3836 stop=self.stop or none_node, 3837 step=none_node) 3838 index_node = IndexNode(self.pos, index, base=self.base) 3839 return index_node.analyse_base_and_index_types( 3840 env, getting=getting, setting=not getting, 3841 analyse_base=False) 3842 3843 if self.start: 3844 self.start = self.start.analyse_types(env) 3845 if self.stop: 3846 self.stop = self.stop.analyse_types(env) 3847 3848 if not env.directives['wraparound']: 3849 check_negative_indices(self.start, self.stop) 3850 3851 base_type = self.base.type 3852 if base_type.is_string or base_type.is_cpp_string: 3853 self.type = default_str_type(env) 3854 elif base_type.is_pyunicode_ptr: 3855 self.type = unicode_type 3856 elif base_type.is_ptr: 3857 self.type = base_type 3858 elif base_type.is_array: 3859 # we need a ptr type here instead of an array type, as 3860 # array types can result in invalid type casts in the C 3861 # code 3862 self.type = PyrexTypes.CPtrType(base_type.base_type) 3863 else: 3864 self.base = self.base.coerce_to_pyobject(env) 3865 self.type = py_object_type 3866 if base_type.is_builtin_type: 3867 # slicing builtin types returns something of the same type 3868 self.type = base_type 3869 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") 3870 3871 if self.type is py_object_type: 3872 if (not self.start or self.start.is_literal) and \ 3873 (not self.stop or self.stop.is_literal): 3874 # cache the constant slice object, in case we need it 3875 none_node = NoneNode(self.pos) 3876 self.slice = SliceNode( 3877 self.pos, 3878 start=copy.deepcopy(self.start or none_node), 3879 stop=copy.deepcopy(self.stop or none_node), 3880 step=none_node 3881 ).analyse_types(env) 3882 else: 3883 c_int = PyrexTypes.c_py_ssize_t_type 3884 if self.start: 3885 self.start = self.start.coerce_to(c_int, env) 3886 if self.stop: 3887 self.stop = self.stop.coerce_to(c_int, env) 3888 self.is_temp = 1 3889 return self 3890 3891 nogil_check = Node.gil_error 3892 gil_message = "Slicing Python object" 3893 3894 get_slice_utility_code = TempitaUtilityCode.load( 3895 "SliceObject", "ObjectHandling.c", context={'access': 'Get'}) 3896 3897 set_slice_utility_code = TempitaUtilityCode.load( 3898 "SliceObject", "ObjectHandling.c", context={'access': 'Set'}) 3899 3900 def coerce_to(self, dst_type, env): 3901 if ((self.base.type.is_string or self.base.type.is_cpp_string) 3902 and dst_type in (bytes_type, bytearray_type, str_type, unicode_type)): 3903 if (dst_type not in (bytes_type, bytearray_type) 3904 and not env.directives['c_string_encoding']): 3905 error(self.pos, 3906 "default encoding required for conversion from '%s' to '%s'" % 3907 (self.base.type, dst_type)) 3908 self.type = dst_type 3909 return super(SliceIndexNode, self).coerce_to(dst_type, env) 3910 3911 def generate_result_code(self, code): 3912 if not self.type.is_pyobject: 3913 error(self.pos, 3914 "Slicing is not currently supported for '%s'." % self.type) 3915 return 3916 3917 base_result = self.base.result() 3918 result = self.result() 3919 start_code = self.start_code() 3920 stop_code = self.stop_code() 3921 if self.base.type.is_string: 3922 base_result = self.base.result() 3923 if self.base.type != PyrexTypes.c_char_ptr_type: 3924 base_result = '((const char*)%s)' % base_result 3925 if self.type is bytearray_type: 3926 type_name = 'ByteArray' 3927 else: 3928 type_name = self.type.name.title() 3929 if self.stop is None: 3930 code.putln( 3931 "%s = __Pyx_Py%s_FromString(%s + %s); %s" % ( 3932 result, 3933 type_name, 3934 base_result, 3935 start_code, 3936 code.error_goto_if_null(result, self.pos))) 3937 else: 3938 code.putln( 3939 "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % ( 3940 result, 3941 type_name, 3942 base_result, 3943 start_code, 3944 stop_code, 3945 start_code, 3946 code.error_goto_if_null(result, self.pos))) 3947 elif self.base.type.is_pyunicode_ptr: 3948 base_result = self.base.result() 3949 if self.base.type != PyrexTypes.c_py_unicode_ptr_type: 3950 base_result = '((const Py_UNICODE*)%s)' % base_result 3951 if self.stop is None: 3952 code.putln( 3953 "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % ( 3954 result, 3955 base_result, 3956 start_code, 3957 code.error_goto_if_null(result, self.pos))) 3958 else: 3959 code.putln( 3960 "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % ( 3961 result, 3962 base_result, 3963 start_code, 3964 stop_code, 3965 start_code, 3966 code.error_goto_if_null(result, self.pos))) 3967 3968 elif self.base.type is unicode_type: 3969 code.globalstate.use_utility_code( 3970 UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")) 3971 code.putln( 3972 "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % ( 3973 result, 3974 base_result, 3975 start_code, 3976 stop_code, 3977 code.error_goto_if_null(result, self.pos))) 3978 elif self.type is py_object_type: 3979 code.globalstate.use_utility_code(self.get_slice_utility_code) 3980 (has_c_start, has_c_stop, c_start, c_stop, 3981 py_start, py_stop, py_slice) = self.get_slice_config() 3982 code.putln( 3983 "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % ( 3984 result, 3985 self.base.py_result(), 3986 c_start, c_stop, 3987 py_start, py_stop, py_slice, 3988 has_c_start, has_c_stop, 3989 bool(code.globalstate.directives['wraparound']), 3990 code.error_goto_if_null(result, self.pos))) 3991 else: 3992 if self.base.type is list_type: 3993 code.globalstate.use_utility_code( 3994 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) 3995 cfunc = '__Pyx_PyList_GetSlice' 3996 elif self.base.type is tuple_type: 3997 code.globalstate.use_utility_code( 3998 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) 3999 cfunc = '__Pyx_PyTuple_GetSlice' 4000 else: 4001 cfunc = '__Pyx_PySequence_GetSlice' 4002 code.putln( 4003 "%s = %s(%s, %s, %s); %s" % ( 4004 result, 4005 cfunc, 4006 self.base.py_result(), 4007 start_code, 4008 stop_code, 4009 code.error_goto_if_null(result, self.pos))) 4010 code.put_gotref(self.py_result()) 4011 4012 def generate_assignment_code(self, rhs, code): 4013 self.generate_subexpr_evaluation_code(code) 4014 if self.type.is_pyobject: 4015 code.globalstate.use_utility_code(self.set_slice_utility_code) 4016 (has_c_start, has_c_stop, c_start, c_stop, 4017 py_start, py_stop, py_slice) = self.get_slice_config() 4018 code.put_error_if_neg(self.pos, 4019 "__Pyx_PyObject_SetSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( 4020 self.base.py_result(), 4021 rhs.py_result(), 4022 c_start, c_stop, 4023 py_start, py_stop, py_slice, 4024 has_c_start, has_c_stop, 4025 bool(code.globalstate.directives['wraparound']))) 4026 else: 4027 start_offset = '' 4028 if self.start: 4029 start_offset = self.start_code() 4030 if start_offset == '0': 4031 start_offset = '' 4032 else: 4033 start_offset += '+' 4034 if rhs.type.is_array: 4035 array_length = rhs.type.size 4036 self.generate_slice_guard_code(code, array_length) 4037 else: 4038 error(self.pos, 4039 "Slice assignments from pointers are not yet supported.") 4040 # FIXME: fix the array size according to start/stop 4041 array_length = self.base.type.size 4042 for i in range(array_length): 4043 code.putln("%s[%s%s] = %s[%d];" % ( 4044 self.base.result(), start_offset, i, 4045 rhs.result(), i)) 4046 self.generate_subexpr_disposal_code(code) 4047 self.free_subexpr_temps(code) 4048 rhs.generate_disposal_code(code) 4049 rhs.free_temps(code) 4050 4051 def generate_deletion_code(self, code, ignore_nonexisting=False): 4052 if not self.base.type.is_pyobject: 4053 error(self.pos, 4054 "Deleting slices is only supported for Python types, not '%s'." % self.type) 4055 return 4056 self.generate_subexpr_evaluation_code(code) 4057 code.globalstate.use_utility_code(self.set_slice_utility_code) 4058 (has_c_start, has_c_stop, c_start, c_stop, 4059 py_start, py_stop, py_slice) = self.get_slice_config() 4060 code.put_error_if_neg(self.pos, 4061 "__Pyx_PyObject_DelSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( 4062 self.base.py_result(), 4063 c_start, c_stop, 4064 py_start, py_stop, py_slice, 4065 has_c_start, has_c_stop, 4066 bool(code.globalstate.directives['wraparound']))) 4067 self.generate_subexpr_disposal_code(code) 4068 self.free_subexpr_temps(code) 4069 4070 def get_slice_config(self): 4071 has_c_start, c_start, py_start = False, '0', 'NULL' 4072 if self.start: 4073 has_c_start = not self.start.type.is_pyobject 4074 if has_c_start: 4075 c_start = self.start.result() 4076 else: 4077 py_start = '&%s' % self.start.py_result() 4078 has_c_stop, c_stop, py_stop = False, '0', 'NULL' 4079 if self.stop: 4080 has_c_stop = not self.stop.type.is_pyobject 4081 if has_c_stop: 4082 c_stop = self.stop.result() 4083 else: 4084 py_stop = '&%s' % self.stop.py_result() 4085 py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL' 4086 return (has_c_start, has_c_stop, c_start, c_stop, 4087 py_start, py_stop, py_slice) 4088 4089 def generate_slice_guard_code(self, code, target_size): 4090 if not self.base.type.is_array: 4091 return 4092 slice_size = self.base.type.size 4093 start = stop = None 4094 if self.stop: 4095 stop = self.stop.result() 4096 try: 4097 stop = int(stop) 4098 if stop < 0: 4099 slice_size = self.base.type.size + stop 4100 else: 4101 slice_size = stop 4102 stop = None 4103 except ValueError: 4104 pass 4105 if self.start: 4106 start = self.start.result() 4107 try: 4108 start = int(start) 4109 if start < 0: 4110 start = self.base.type.size + start 4111 slice_size -= start 4112 start = None 4113 except ValueError: 4114 pass 4115 check = None 4116 if slice_size < 0: 4117 if target_size > 0: 4118 error(self.pos, "Assignment to empty slice.") 4119 elif start is None and stop is None: 4120 # we know the exact slice length 4121 if target_size != slice_size: 4122 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % ( 4123 slice_size, target_size)) 4124 elif start is not None: 4125 if stop is None: 4126 stop = slice_size 4127 check = "(%s)-(%s)" % (stop, start) 4128 else: # stop is not None: 4129 check = stop 4130 if check: 4131 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size)) 4132 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_T "d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % ( 4133 target_size, check)) 4134 code.putln(code.error_goto(self.pos)) 4135 code.putln("}") 4136 4137 def start_code(self): 4138 if self.start: 4139 return self.start.result() 4140 else: 4141 return "0" 4142 4143 def stop_code(self): 4144 if self.stop: 4145 return self.stop.result() 4146 elif self.base.type.is_array: 4147 return self.base.type.size 4148 else: 4149 return "PY_SSIZE_T_MAX" 4150 4151 def calculate_result_code(self): 4152 # self.result() is not used, but this method must exist 4153 return "<unused>" 4154 4155 4156 class SliceNode(ExprNode): 4157 # start:stop:step in subscript list 4158 # 4159 # start ExprNode 4160 # stop ExprNode 4161 # step ExprNode 4162 4163 subexprs = ['start', 'stop', 'step'] 4164 4165 type = slice_type 4166 is_temp = 1 4167 4168 def calculate_constant_result(self): 4169 self.constant_result = slice( 4170 self.start.constant_result, 4171 self.stop.constant_result, 4172 self.step.constant_result) 4173 4174 def compile_time_value(self, denv): 4175 start = self.start.compile_time_value(denv) 4176 stop = self.stop.compile_time_value(denv) 4177 step = self.step.compile_time_value(denv) 4178 try: 4179 return slice(start, stop, step) 4180 except Exception, e: 4181 self.compile_time_value_error(e) 4182 4183 def may_be_none(self): 4184 return False 4185 4186 def analyse_types(self, env): 4187 start = self.start.analyse_types(env) 4188 stop = self.stop.analyse_types(env) 4189 step = self.step.analyse_types(env) 4190 self.start = start.coerce_to_pyobject(env) 4191 self.stop = stop.coerce_to_pyobject(env) 4192 self.step = step.coerce_to_pyobject(env) 4193 if self.start.is_literal and self.stop.is_literal and self.step.is_literal: 4194 self.is_literal = True 4195 self.is_temp = False 4196 return self 4197 4198 gil_message = "Constructing Python slice object" 4199 4200 def calculate_result_code(self): 4201 return self.result_code 4202 4203 def generate_result_code(self, code): 4204 if self.is_literal: 4205 self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2) 4206 code = code.get_cached_constants_writer() 4207 code.mark_pos(self.pos) 4208 4209 code.putln( 4210 "%s = PySlice_New(%s, %s, %s); %s" % ( 4211 self.result(), 4212 self.start.py_result(), 4213 self.stop.py_result(), 4214 self.step.py_result(), 4215 code.error_goto_if_null(self.result(), self.pos))) 4216 code.put_gotref(self.py_result()) 4217 if self.is_literal: 4218 code.put_giveref(self.py_result()) 4219 4220 def __deepcopy__(self, memo): 4221 """ 4222 There is a copy bug in python 2.4 for slice objects. 4223 """ 4224 return SliceNode( 4225 self.pos, 4226 start=copy.deepcopy(self.start, memo), 4227 stop=copy.deepcopy(self.stop, memo), 4228 step=copy.deepcopy(self.step, memo), 4229 is_temp=self.is_temp, 4230 is_literal=self.is_literal, 4231 constant_result=self.constant_result) 4232 4233 4234 class CallNode(ExprNode): 4235 4236 # allow overriding the default 'may_be_none' behaviour 4237 may_return_none = None 4238 4239 def infer_type(self, env): 4240 function = self.function 4241 func_type = function.infer_type(env) 4242 if isinstance(function, NewExprNode): 4243 # note: needs call to infer_type() above 4244 return PyrexTypes.CPtrType(function.class_type) 4245 if func_type is py_object_type: 4246 # function might have lied for safety => try to find better type 4247 entry = getattr(function, 'entry', None) 4248 if entry is not None: 4249 func_type = entry.type or func_type 4250 if func_type.is_ptr: 4251 func_type = func_type.base_type 4252 if func_type.is_cfunction: 4253 return func_type.return_type 4254 elif func_type is type_type: 4255 if function.is_name and function.entry and function.entry.type: 4256 result_type = function.entry.type 4257 if result_type.is_extension_type: 4258 return result_type 4259 elif result_type.is_builtin_type: 4260 if function.entry.name == 'float': 4261 return PyrexTypes.c_double_type 4262 elif function.entry.name in Builtin.types_that_construct_their_instance: 4263 return result_type 4264 return py_object_type 4265 4266 def type_dependencies(self, env): 4267 # TODO: Update when Danilo's C++ code merged in to handle the 4268 # the case of function overloading. 4269 return self.function.type_dependencies(env) 4270 4271 def is_simple(self): 4272 # C function calls could be considered simple, but they may 4273 # have side-effects that may hit when multiple operations must 4274 # be effected in order, e.g. when constructing the argument 4275 # sequence for a function call or comparing values. 4276 return False 4277 4278 def may_be_none(self): 4279 if self.may_return_none is not None: 4280 return self.may_return_none 4281 func_type = self.function.type 4282 if func_type is type_type and self.function.is_name: 4283 entry = self.function.entry 4284 if entry.type.is_extension_type: 4285 return False 4286 if (entry.type.is_builtin_type and 4287 entry.name in Builtin.types_that_construct_their_instance): 4288 return False 4289 return ExprNode.may_be_none(self) 4290 4291 def analyse_as_type_constructor(self, env): 4292 type = self.function.analyse_as_type(env) 4293 if type and type.is_struct_or_union: 4294 args, kwds = self.explicit_args_kwds() 4295 items = [] 4296 for arg, member in zip(args, type.scope.var_entries): 4297 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg)) 4298 if kwds: 4299 items += kwds.key_value_pairs 4300 self.key_value_pairs = items 4301 self.__class__ = DictNode 4302 self.analyse_types(env) # FIXME 4303 self.coerce_to(type, env) 4304 return True 4305 elif type and type.is_cpp_class: 4306 self.args = [ arg.analyse_types(env) for arg in self.args ] 4307 constructor = type.scope.lookup("<init>") 4308 self.function = RawCNameExprNode(self.function.pos, constructor.type) 4309 self.function.entry = constructor 4310 self.function.set_cname(type.declaration_code("")) 4311 self.analyse_c_function_call(env) 4312 self.type = type 4313 return True 4314 4315 def is_lvalue(self): 4316 return self.type.is_reference 4317 4318 def nogil_check(self, env): 4319 func_type = self.function_type() 4320 if func_type.is_pyobject: 4321 self.gil_error() 4322 elif not getattr(func_type, 'nogil', False): 4323 self.gil_error() 4324 4325 gil_message = "Calling gil-requiring function" 4326 4327 4328 class SimpleCallNode(CallNode): 4329 # Function call without keyword, * or ** args. 4330 # 4331 # function ExprNode 4332 # args [ExprNode] 4333 # arg_tuple ExprNode or None used internally 4334 # self ExprNode or None used internally 4335 # coerced_self ExprNode or None used internally 4336 # wrapper_call bool used internally 4337 # has_optional_args bool used internally 4338 # nogil bool used internally 4339 4340 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] 4341 4342 self = None 4343 coerced_self = None 4344 arg_tuple = None 4345 wrapper_call = False 4346 has_optional_args = False 4347 nogil = False 4348 analysed = False 4349 4350 def compile_time_value(self, denv): 4351 function = self.function.compile_time_value(denv) 4352 args = [arg.compile_time_value(denv) for arg in self.args] 4353 try: 4354 return function(*args) 4355 except Exception, e: 4356 self.compile_time_value_error(e) 4357 4358 def analyse_as_type(self, env): 4359 attr = self.function.as_cython_attribute() 4360 if attr == 'pointer': 4361 if len(self.args) != 1: 4362 error(self.args.pos, "only one type allowed.") 4363 else: 4364 type = self.args[0].analyse_as_type(env) 4365 if not type: 4366 error(self.args[0].pos, "Unknown type") 4367 else: 4368 return PyrexTypes.CPtrType(type) 4369 4370 def explicit_args_kwds(self): 4371 return self.args, None 4372 4373 def analyse_types(self, env): 4374 if self.analyse_as_type_constructor(env): 4375 return self 4376 if self.analysed: 4377 return self 4378 self.analysed = True 4379 self.function.is_called = 1 4380 self.function = self.function.analyse_types(env) 4381 function = self.function 4382 4383 if function.is_attribute and function.entry and function.entry.is_cmethod: 4384 # Take ownership of the object from which the attribute 4385 # was obtained, because we need to pass it as 'self'. 4386 self.self = function.obj 4387 function.obj = CloneNode(self.self) 4388 4389 func_type = self.function_type() 4390 if func_type.is_pyobject: 4391 self.arg_tuple = TupleNode(self.pos, args = self.args) 4392 self.arg_tuple = self.arg_tuple.analyse_types(env) 4393 self.args = None 4394 if func_type is Builtin.type_type and function.is_name and \ 4395 function.entry and \ 4396 function.entry.is_builtin and \ 4397 function.entry.name in Builtin.types_that_construct_their_instance: 4398 # calling a builtin type that returns a specific object type 4399 if function.entry.name == 'float': 4400 # the following will come true later on in a transform 4401 self.type = PyrexTypes.c_double_type 4402 self.result_ctype = PyrexTypes.c_double_type 4403 else: 4404 self.type = Builtin.builtin_types[function.entry.name] 4405 self.result_ctype = py_object_type 4406 self.may_return_none = False 4407 elif function.is_name and function.type_entry: 4408 # We are calling an extension type constructor. As 4409 # long as we do not support __new__(), the result type 4410 # is clear 4411 self.type = function.type_entry.type 4412 self.result_ctype = py_object_type 4413 self.may_return_none = False 4414 else: 4415 self.type = py_object_type 4416 self.is_temp = 1 4417 else: 4418 self.args = [ arg.analyse_types(env) for arg in self.args ] 4419 self.analyse_c_function_call(env) 4420 return self 4421 4422 def function_type(self): 4423 # Return the type of the function being called, coercing a function 4424 # pointer to a function if necessary. If the function has fused 4425 # arguments, return the specific type. 4426 func_type = self.function.type 4427 4428 if func_type.is_ptr: 4429 func_type = func_type.base_type 4430 4431 return func_type 4432 4433 def analyse_c_function_call(self, env): 4434 if self.function.type is error_type: 4435 self.type = error_type 4436 return 4437 4438 if self.self: 4439 args = [self.self] + self.args 4440 else: 4441 args = self.args 4442 4443 if self.function.type.is_cpp_class: 4444 overloaded_entry = self.function.type.scope.lookup("operator()") 4445 if overloaded_entry is None: 4446 self.type = PyrexTypes.error_type 4447 self.result_code = "<error>" 4448 return 4449 elif hasattr(self.function, 'entry'): 4450 overloaded_entry = self.function.entry 4451 elif (isinstance(self.function, IndexNode) and 4452 self.function.is_fused_index): 4453 overloaded_entry = self.function.type.entry 4454 else: 4455 overloaded_entry = None 4456 4457 if overloaded_entry: 4458 if self.function.type.is_fused: 4459 functypes = self.function.type.get_all_specialized_function_types() 4460 alternatives = [f.entry for f in functypes] 4461 else: 4462 alternatives = overloaded_entry.all_alternatives() 4463 4464 entry = PyrexTypes.best_match(args, alternatives, self.pos, env) 4465 4466 if not entry: 4467 self.type = PyrexTypes.error_type 4468 self.result_code = "<error>" 4469 return 4470 4471 entry.used = True 4472 self.function.entry = entry 4473 self.function.type = entry.type 4474 func_type = self.function_type() 4475 else: 4476 entry = None 4477 func_type = self.function_type() 4478 if not func_type.is_cfunction: 4479 error(self.pos, "Calling non-function type '%s'" % func_type) 4480 self.type = PyrexTypes.error_type 4481 self.result_code = "<error>" 4482 return 4483 4484 # Check no. of args 4485 max_nargs = len(func_type.args) 4486 expected_nargs = max_nargs - func_type.optional_arg_count 4487 actual_nargs = len(args) 4488 if func_type.optional_arg_count and expected_nargs != actual_nargs: 4489 self.has_optional_args = 1 4490 self.is_temp = 1 4491 4492 # check 'self' argument 4493 if entry and entry.is_cmethod and func_type.args: 4494 formal_arg = func_type.args[0] 4495 arg = args[0] 4496 if formal_arg.not_none: 4497 if self.self: 4498 self.self = self.self.as_none_safe_node( 4499 "'NoneType' object has no attribute '%s'", 4500 error='PyExc_AttributeError', 4501 format_args=[entry.name]) 4502 else: 4503 # unbound method 4504 arg = arg.as_none_safe_node( 4505 "descriptor '%s' requires a '%s' object but received a 'NoneType'", 4506 format_args=[entry.name, formal_arg.type.name]) 4507 if self.self: 4508 if formal_arg.accept_builtin_subtypes: 4509 arg = CMethodSelfCloneNode(self.self) 4510 else: 4511 arg = CloneNode(self.self) 4512 arg = self.coerced_self = arg.coerce_to(formal_arg.type, env) 4513 elif formal_arg.type.is_builtin_type: 4514 # special case: unbound methods of builtins accept subtypes 4515 arg = arg.coerce_to(formal_arg.type, env) 4516 if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode): 4517 arg.exact_builtin_type = False 4518 args[0] = arg 4519 4520 # Coerce arguments 4521 some_args_in_temps = False 4522 for i in xrange(min(max_nargs, actual_nargs)): 4523 formal_arg = func_type.args[i] 4524 formal_type = formal_arg.type 4525 arg = args[i].coerce_to(formal_type, env) 4526 if formal_arg.not_none: 4527 # C methods must do the None checks at *call* time 4528 arg = arg.as_none_safe_node( 4529 "cannot pass None into a C function argument that is declared 'not None'") 4530 if arg.is_temp: 4531 if i > 0: 4532 # first argument in temp doesn't impact subsequent arguments 4533 some_args_in_temps = True 4534 elif arg.type.is_pyobject and not env.nogil: 4535 if i == 0 and self.self is not None: 4536 # a method's cloned "self" argument is ok 4537 pass 4538 elif arg.nonlocally_immutable(): 4539 # plain local variables are ok 4540 pass 4541 else: 4542 # we do not safely own the argument's reference, 4543 # but we must make sure it cannot be collected 4544 # before we return from the function, so we create 4545 # an owned temp reference to it 4546 if i > 0: # first argument doesn't matter 4547 some_args_in_temps = True 4548 arg = arg.coerce_to_temp(env) 4549 args[i] = arg 4550 4551 # handle additional varargs parameters 4552 for i in xrange(max_nargs, actual_nargs): 4553 arg = args[i] 4554 if arg.type.is_pyobject: 4555 arg_ctype = arg.type.default_coerced_ctype() 4556 if arg_ctype is None: 4557 error(self.args[i].pos, 4558 "Python object cannot be passed as a varargs parameter") 4559 else: 4560 args[i] = arg = arg.coerce_to(arg_ctype, env) 4561 if arg.is_temp and i > 0: 4562 some_args_in_temps = True 4563 4564 if some_args_in_temps: 4565 # if some args are temps and others are not, they may get 4566 # constructed in the wrong order (temps first) => make 4567 # sure they are either all temps or all not temps (except 4568 # for the last argument, which is evaluated last in any 4569 # case) 4570 for i in xrange(actual_nargs-1): 4571 if i == 0 and self.self is not None: 4572 continue # self is ok 4573 arg = args[i] 4574 if arg.nonlocally_immutable(): 4575 # locals, C functions, unassignable types are safe. 4576 pass 4577 elif arg.type.is_cpp_class: 4578 # Assignment has side effects, avoid. 4579 pass 4580 elif env.nogil and arg.type.is_pyobject: 4581 # can't copy a Python reference into a temp in nogil 4582 # env (this is safe: a construction would fail in 4583 # nogil anyway) 4584 pass 4585 else: 4586 #self.args[i] = arg.coerce_to_temp(env) 4587 # instead: issue a warning 4588 if i > 0 or i == 1 and self.self is not None: # skip first arg 4589 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) 4590 break 4591 4592 self.args[:] = args 4593 4594 # Calc result type and code fragment 4595 if isinstance(self.function, NewExprNode): 4596 self.type = PyrexTypes.CPtrType(self.function.class_type) 4597 else: 4598 self.type = func_type.return_type 4599 4600 if self.function.is_name or self.function.is_attribute: 4601 if self.function.entry and self.function.entry.utility_code: 4602 self.is_temp = 1 # currently doesn't work for self.calculate_result_code() 4603 4604 if self.type.is_pyobject: 4605 self.result_ctype = py_object_type 4606 self.is_temp = 1 4607 elif func_type.exception_value is not None \ 4608 or func_type.exception_check: 4609 self.is_temp = 1 4610 elif self.type.is_memoryviewslice: 4611 self.is_temp = 1 4612 # func_type.exception_check = True 4613 4614 # Called in 'nogil' context? 4615 self.nogil = env.nogil 4616 if (self.nogil and 4617 func_type.exception_check and 4618 func_type.exception_check != '+'): 4619 env.use_utility_code(pyerr_occurred_withgil_utility_code) 4620 # C++ exception handler 4621 if func_type.exception_check == '+': 4622 if func_type.exception_value is None: 4623 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 4624 4625 def calculate_result_code(self): 4626 return self.c_call_code() 4627 4628 def c_call_code(self): 4629 func_type = self.function_type() 4630 if self.type is PyrexTypes.error_type or not func_type.is_cfunction: 4631 return "<error>" 4632 formal_args = func_type.args 4633 arg_list_code = [] 4634 args = list(zip(formal_args, self.args)) 4635 max_nargs = len(func_type.args) 4636 expected_nargs = max_nargs - func_type.optional_arg_count 4637 actual_nargs = len(self.args) 4638 for formal_arg, actual_arg in args[:expected_nargs]: 4639 arg_code = actual_arg.result_as(formal_arg.type) 4640 arg_list_code.append(arg_code) 4641 4642 if func_type.is_overridable: 4643 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod))) 4644 4645 if func_type.optional_arg_count: 4646 if expected_nargs == actual_nargs: 4647 optional_args = 'NULL' 4648 else: 4649 optional_args = "&%s" % self.opt_arg_struct 4650 arg_list_code.append(optional_args) 4651 4652 for actual_arg in self.args[len(formal_args):]: 4653 arg_list_code.append(actual_arg.result()) 4654 4655 result = "%s(%s)" % (self.function.result(), ', '.join(arg_list_code)) 4656 return result 4657 4658 def generate_result_code(self, code): 4659 func_type = self.function_type() 4660 if self.function.is_name or self.function.is_attribute: 4661 if self.function.entry and self.function.entry.utility_code: 4662 code.globalstate.use_utility_code(self.function.entry.utility_code) 4663 if func_type.is_pyobject: 4664 arg_code = self.arg_tuple.py_result() 4665 code.globalstate.use_utility_code(UtilityCode.load_cached( 4666 "PyObjectCall", "ObjectHandling.c")) 4667 code.putln( 4668 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % ( 4669 self.result(), 4670 self.function.py_result(), 4671 arg_code, 4672 code.error_goto_if_null(self.result(), self.pos))) 4673 code.put_gotref(self.py_result()) 4674 elif func_type.is_cfunction: 4675 if self.has_optional_args: 4676 actual_nargs = len(self.args) 4677 expected_nargs = len(func_type.args) - func_type.optional_arg_count 4678 self.opt_arg_struct = code.funcstate.allocate_temp( 4679 func_type.op_arg_struct.base_type, manage_ref=True) 4680 code.putln("%s.%s = %s;" % ( 4681 self.opt_arg_struct, 4682 Naming.pyrex_prefix + "n", 4683 len(self.args) - expected_nargs)) 4684 args = list(zip(func_type.args, self.args)) 4685 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]: 4686 code.putln("%s.%s = %s;" % ( 4687 self.opt_arg_struct, 4688 func_type.opt_arg_cname(formal_arg.name), 4689 actual_arg.result_as(formal_arg.type))) 4690 exc_checks = [] 4691 if self.type.is_pyobject and self.is_temp: 4692 exc_checks.append("!%s" % self.result()) 4693 elif self.type.is_memoryviewslice: 4694 assert self.is_temp 4695 exc_checks.append(self.type.error_condition(self.result())) 4696 else: 4697 exc_val = func_type.exception_value 4698 exc_check = func_type.exception_check 4699 if exc_val is not None: 4700 exc_checks.append("%s == %s" % (self.result(), exc_val)) 4701 if exc_check: 4702 if self.nogil: 4703 exc_checks.append("__Pyx_ErrOccurredWithGIL()") 4704 else: 4705 exc_checks.append("PyErr_Occurred()") 4706 if self.is_temp or exc_checks: 4707 rhs = self.c_call_code() 4708 if self.result(): 4709 lhs = "%s = " % self.result() 4710 if self.is_temp and self.type.is_pyobject: 4711 #return_type = self.type # func_type.return_type 4712 #print "SimpleCallNode.generate_result_code: casting", rhs, \ 4713 # "from", return_type, "to pyobject" ### 4714 rhs = typecast(py_object_type, self.type, rhs) 4715 else: 4716 lhs = "" 4717 if func_type.exception_check == '+': 4718 if func_type.exception_value is None: 4719 raise_py_exception = "__Pyx_CppExn2PyErr();" 4720 elif func_type.exception_value.type.is_pyobject: 4721 raise_py_exception = 'try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % ( 4722 func_type.exception_value.entry.cname, 4723 func_type.exception_value.entry.cname) 4724 else: 4725 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.");' % func_type.exception_value.entry.cname 4726 code.putln("try {") 4727 code.putln("%s%s;" % (lhs, rhs)) 4728 code.putln("} catch(...) {") 4729 if self.nogil: 4730 code.put_ensure_gil(declare_gilstate=True) 4731 code.putln(raise_py_exception) 4732 if self.nogil: 4733 code.put_release_ensured_gil() 4734 code.putln(code.error_goto(self.pos)) 4735 code.putln("}") 4736 else: 4737 if exc_checks: 4738 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos) 4739 else: 4740 goto_error = "" 4741 code.putln("%s%s; %s" % (lhs, rhs, goto_error)) 4742 if self.type.is_pyobject and self.result(): 4743 code.put_gotref(self.py_result()) 4744 if self.has_optional_args: 4745 code.funcstate.release_temp(self.opt_arg_struct) 4746 4747 4748 class InlinedDefNodeCallNode(CallNode): 4749 # Inline call to defnode 4750 # 4751 # function PyCFunctionNode 4752 # function_name NameNode 4753 # args [ExprNode] 4754 4755 subexprs = ['args', 'function_name'] 4756 is_temp = 1 4757 type = py_object_type 4758 function = None 4759 function_name = None 4760 4761 def can_be_inlined(self): 4762 func_type= self.function.def_node 4763 if func_type.star_arg or func_type.starstar_arg: 4764 return False 4765 if len(func_type.args) != len(self.args): 4766 return False 4767 return True 4768 4769 def analyse_types(self, env): 4770 self.function_name = self.function_name.analyse_types(env) 4771 4772 self.args = [ arg.analyse_types(env) for arg in self.args ] 4773 func_type = self.function.def_node 4774 actual_nargs = len(self.args) 4775 4776 # Coerce arguments 4777 some_args_in_temps = False 4778 for i in xrange(actual_nargs): 4779 formal_type = func_type.args[i].type 4780 arg = self.args[i].coerce_to(formal_type, env) 4781 if arg.is_temp: 4782 if i > 0: 4783 # first argument in temp doesn't impact subsequent arguments 4784 some_args_in_temps = True 4785 elif arg.type.is_pyobject and not env.nogil: 4786 if arg.nonlocally_immutable(): 4787 # plain local variables are ok 4788 pass 4789 else: 4790 # we do not safely own the argument's reference, 4791 # but we must make sure it cannot be collected 4792 # before we return from the function, so we create 4793 # an owned temp reference to it 4794 if i > 0: # first argument doesn't matter 4795 some_args_in_temps = True 4796 arg = arg.coerce_to_temp(env) 4797 self.args[i] = arg 4798 4799 if some_args_in_temps: 4800 # if some args are temps and others are not, they may get 4801 # constructed in the wrong order (temps first) => make 4802 # sure they are either all temps or all not temps (except 4803 # for the last argument, which is evaluated last in any 4804 # case) 4805 for i in xrange(actual_nargs-1): 4806 arg = self.args[i] 4807 if arg.nonlocally_immutable(): 4808 # locals, C functions, unassignable types are safe. 4809 pass 4810 elif arg.type.is_cpp_class: 4811 # Assignment has side effects, avoid. 4812 pass 4813 elif env.nogil and arg.type.is_pyobject: 4814 # can't copy a Python reference into a temp in nogil 4815 # env (this is safe: a construction would fail in 4816 # nogil anyway) 4817 pass 4818 else: 4819 #self.args[i] = arg.coerce_to_temp(env) 4820 # instead: issue a warning 4821 if i > 0: 4822 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) 4823 break 4824 return self 4825 4826 def generate_result_code(self, code): 4827 arg_code = [self.function_name.py_result()] 4828 func_type = self.function.def_node 4829 for arg, proto_arg in zip(self.args, func_type.args): 4830 if arg.type.is_pyobject: 4831 arg_code.append(arg.result_as(proto_arg.type)) 4832 else: 4833 arg_code.append(arg.result()) 4834 arg_code = ', '.join(arg_code) 4835 code.putln( 4836 "%s = %s(%s); %s" % ( 4837 self.result(), 4838 self.function.def_node.entry.pyfunc_cname, 4839 arg_code, 4840 code.error_goto_if_null(self.result(), self.pos))) 4841 code.put_gotref(self.py_result()) 4842 4843 4844 class PythonCapiFunctionNode(ExprNode): 4845 subexprs = [] 4846 4847 def __init__(self, pos, py_name, cname, func_type, utility_code = None): 4848 ExprNode.__init__(self, pos, name=py_name, cname=cname, 4849 type=func_type, utility_code=utility_code) 4850 4851 def analyse_types(self, env): 4852 return self 4853 4854 def generate_result_code(self, code): 4855 if self.utility_code: 4856 code.globalstate.use_utility_code(self.utility_code) 4857 4858 def calculate_result_code(self): 4859 return self.cname 4860 4861 4862 class PythonCapiCallNode(SimpleCallNode): 4863 # Python C-API Function call (only created in transforms) 4864 4865 # By default, we assume that the call never returns None, as this 4866 # is true for most C-API functions in CPython. If this does not 4867 # apply to a call, set the following to True (or None to inherit 4868 # the default behaviour). 4869 may_return_none = False 4870 4871 def __init__(self, pos, function_name, func_type, 4872 utility_code = None, py_name=None, **kwargs): 4873 self.type = func_type.return_type 4874 self.result_ctype = self.type 4875 self.function = PythonCapiFunctionNode( 4876 pos, py_name, function_name, func_type, 4877 utility_code = utility_code) 4878 # call this last so that we can override the constructed 4879 # attributes above with explicit keyword arguments if required 4880 SimpleCallNode.__init__(self, pos, **kwargs) 4881 4882 4883 class GeneralCallNode(CallNode): 4884 # General Python function call, including keyword, 4885 # * and ** arguments. 4886 # 4887 # function ExprNode 4888 # positional_args ExprNode Tuple of positional arguments 4889 # keyword_args ExprNode or None Dict of keyword arguments 4890 4891 type = py_object_type 4892 4893 subexprs = ['function', 'positional_args', 'keyword_args'] 4894 4895 nogil_check = Node.gil_error 4896 4897 def compile_time_value(self, denv): 4898 function = self.function.compile_time_value(denv) 4899 positional_args = self.positional_args.compile_time_value(denv) 4900 keyword_args = self.keyword_args.compile_time_value(denv) 4901 try: 4902 return function(*positional_args, **keyword_args) 4903 except Exception, e: 4904 self.compile_time_value_error(e) 4905 4906 def explicit_args_kwds(self): 4907 if (self.keyword_args and not isinstance(self.keyword_args, DictNode) or 4908 not isinstance(self.positional_args, TupleNode)): 4909 raise CompileError(self.pos, 4910 'Compile-time keyword arguments must be explicit.') 4911 return self.positional_args.args, self.keyword_args 4912 4913 def analyse_types(self, env): 4914 if self.analyse_as_type_constructor(env): 4915 return self 4916 self.function = self.function.analyse_types(env) 4917 if not self.function.type.is_pyobject: 4918 if self.function.type.is_error: 4919 self.type = error_type 4920 return self 4921 if hasattr(self.function, 'entry'): 4922 node = self.map_to_simple_call_node() 4923 if node is not None and node is not self: 4924 return node.analyse_types(env) 4925 elif self.function.entry.as_variable: 4926 self.function = self.function.coerce_to_pyobject(env) 4927 elif node is self: 4928 error(self.pos, 4929 "Non-trivial keyword arguments and starred " 4930 "arguments not allowed in cdef functions.") 4931 else: 4932 # error was already reported 4933 pass 4934 else: 4935 self.function = self.function.coerce_to_pyobject(env) 4936 if self.keyword_args: 4937 self.keyword_args = self.keyword_args.analyse_types(env) 4938 self.positional_args = self.positional_args.analyse_types(env) 4939 self.positional_args = \ 4940 self.positional_args.coerce_to_pyobject(env) 4941 function = self.function 4942 if function.is_name and function.type_entry: 4943 # We are calling an extension type constructor. As long 4944 # as we do not support __new__(), the result type is clear 4945 self.type = function.type_entry.type 4946 self.result_ctype = py_object_type 4947 self.may_return_none = False 4948 else: 4949 self.type = py_object_type 4950 self.is_temp = 1 4951 return self 4952 4953 def map_to_simple_call_node(self): 4954 """ 4955 Tries to map keyword arguments to declared positional arguments. 4956 Returns self to try a Python call, None to report an error 4957 or a SimpleCallNode if the mapping succeeds. 4958 """ 4959 if not isinstance(self.positional_args, TupleNode): 4960 # has starred argument 4961 return self 4962 if not isinstance(self.keyword_args, DictNode): 4963 # keywords come from arbitrary expression => nothing to do here 4964 return self 4965 function = self.function 4966 entry = getattr(function, 'entry', None) 4967 if not entry: 4968 return self 4969 function_type = entry.type 4970 if function_type.is_ptr: 4971 function_type = function_type.base_type 4972 if not function_type.is_cfunction: 4973 return self 4974 4975 pos_args = self.positional_args.args 4976 kwargs = self.keyword_args 4977 declared_args = function_type.args 4978 if entry.is_cmethod: 4979 declared_args = declared_args[1:] # skip 'self' 4980 4981 if len(pos_args) > len(declared_args): 4982 error(self.pos, "function call got too many positional arguments, " 4983 "expected %d, got %s" % (len(declared_args), 4984 len(pos_args))) 4985 return None 4986 4987 matched_args = set([ arg.name for arg in declared_args[:len(pos_args)] 4988 if arg.name ]) 4989 unmatched_args = declared_args[len(pos_args):] 4990 matched_kwargs_count = 0 4991 args = list(pos_args) 4992 4993 # check for duplicate keywords 4994 seen = set(matched_args) 4995 has_errors = False 4996 for arg in kwargs.key_value_pairs: 4997 name = arg.key.value 4998 if name in seen: 4999 error(arg.pos, "argument '%s' passed twice" % name) 5000 has_errors = True 5001 # continue to report more errors if there are any 5002 seen.add(name) 5003 5004 # match keywords that are passed in order 5005 for decl_arg, arg in zip(unmatched_args, kwargs.key_value_pairs): 5006 name = arg.key.value 5007 if decl_arg.name == name: 5008 matched_args.add(name) 5009 matched_kwargs_count += 1 5010 args.append(arg.value) 5011 else: 5012 break 5013 5014 # match keyword arguments that are passed out-of-order, but keep 5015 # the evaluation of non-simple arguments in order by moving them 5016 # into temps 5017 from Cython.Compiler.UtilNodes import EvalWithTempExprNode, LetRefNode 5018 temps = [] 5019 if len(kwargs.key_value_pairs) > matched_kwargs_count: 5020 unmatched_args = declared_args[len(args):] 5021 keywords = dict([ (arg.key.value, (i+len(pos_args), arg)) 5022 for i, arg in enumerate(kwargs.key_value_pairs) ]) 5023 first_missing_keyword = None 5024 for decl_arg in unmatched_args: 5025 name = decl_arg.name 5026 if name not in keywords: 5027 # missing keyword argument => either done or error 5028 if not first_missing_keyword: 5029 first_missing_keyword = name 5030 continue 5031 elif first_missing_keyword: 5032 if entry.as_variable: 5033 # we might be able to convert the function to a Python 5034 # object, which then allows full calling semantics 5035 # with default values in gaps - currently, we only 5036 # support optional arguments at the end 5037 return self 5038 # wasn't the last keyword => gaps are not supported 5039 error(self.pos, "C function call is missing " 5040 "argument '%s'" % first_missing_keyword) 5041 return None 5042 pos, arg = keywords[name] 5043 matched_args.add(name) 5044 matched_kwargs_count += 1 5045 if arg.value.is_simple(): 5046 args.append(arg.value) 5047 else: 5048 temp = LetRefNode(arg.value) 5049 assert temp.is_simple() 5050 args.append(temp) 5051 temps.append((pos, temp)) 5052 5053 if temps: 5054 # may have to move preceding non-simple args into temps 5055 final_args = [] 5056 new_temps = [] 5057 first_temp_arg = temps[0][-1] 5058 for arg_value in args: 5059 if arg_value is first_temp_arg: 5060 break # done 5061 if arg_value.is_simple(): 5062 final_args.append(arg_value) 5063 else: 5064 temp = LetRefNode(arg_value) 5065 new_temps.append(temp) 5066 final_args.append(temp) 5067 if new_temps: 5068 args = final_args 5069 temps = new_temps + [ arg for i,arg in sorted(temps) ] 5070 5071 # check for unexpected keywords 5072 for arg in kwargs.key_value_pairs: 5073 name = arg.key.value 5074 if name not in matched_args: 5075 has_errors = True 5076 error(arg.pos, 5077 "C function got unexpected keyword argument '%s'" % 5078 name) 5079 5080 if has_errors: 5081 # error was reported already 5082 return None 5083 5084 # all keywords mapped to positional arguments 5085 # if we are missing arguments, SimpleCallNode will figure it out 5086 node = SimpleCallNode(self.pos, function=function, args=args) 5087 for temp in temps[::-1]: 5088 node = EvalWithTempExprNode(temp, node) 5089 return node 5090 5091 def generate_result_code(self, code): 5092 if self.type.is_error: return 5093 if self.keyword_args: 5094 kwargs = self.keyword_args.py_result() 5095 else: 5096 kwargs = 'NULL' 5097 code.globalstate.use_utility_code(UtilityCode.load_cached( 5098 "PyObjectCall", "ObjectHandling.c")) 5099 code.putln( 5100 "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % ( 5101 self.result(), 5102 self.function.py_result(), 5103 self.positional_args.py_result(), 5104 kwargs, 5105 code.error_goto_if_null(self.result(), self.pos))) 5106 code.put_gotref(self.py_result()) 5107 5108 5109 class AsTupleNode(ExprNode): 5110 # Convert argument to tuple. Used for normalising 5111 # the * argument of a function call. 5112 # 5113 # arg ExprNode 5114 5115 subexprs = ['arg'] 5116 5117 def calculate_constant_result(self): 5118 self.constant_result = tuple(self.arg.constant_result) 5119 5120 def compile_time_value(self, denv): 5121 arg = self.arg.compile_time_value(denv) 5122 try: 5123 return tuple(arg) 5124 except Exception, e: 5125 self.compile_time_value_error(e) 5126 5127 def analyse_types(self, env): 5128 self.arg = self.arg.analyse_types(env) 5129 self.arg = self.arg.coerce_to_pyobject(env) 5130 self.type = tuple_type 5131 self.is_temp = 1 5132 return self 5133 5134 def may_be_none(self): 5135 return False 5136 5137 nogil_check = Node.gil_error 5138 gil_message = "Constructing Python tuple" 5139 5140 def generate_result_code(self, code): 5141 code.putln( 5142 "%s = PySequence_Tuple(%s); %s" % ( 5143 self.result(), 5144 self.arg.py_result(), 5145 code.error_goto_if_null(self.result(), self.pos))) 5146 code.put_gotref(self.py_result()) 5147 5148 5149 class AttributeNode(ExprNode): 5150 # obj.attribute 5151 # 5152 # obj ExprNode 5153 # attribute string 5154 # needs_none_check boolean Used if obj is an extension type. 5155 # If set to True, it is known that the type is not None. 5156 # 5157 # Used internally: 5158 # 5159 # is_py_attr boolean Is a Python getattr operation 5160 # member string C name of struct member 5161 # is_called boolean Function call is being done on result 5162 # entry Entry Symbol table entry of attribute 5163 5164 is_attribute = 1 5165 subexprs = ['obj'] 5166 5167 type = PyrexTypes.error_type 5168 entry = None 5169 is_called = 0 5170 needs_none_check = True 5171 is_memslice_transpose = False 5172 is_special_lookup = False 5173 5174 def as_cython_attribute(self): 5175 if (isinstance(self.obj, NameNode) and 5176 self.obj.is_cython_module and not 5177 self.attribute == u"parallel"): 5178 return self.attribute 5179 5180 cy = self.obj.as_cython_attribute() 5181 if cy: 5182 return "%s.%s" % (cy, self.attribute) 5183 return None 5184 5185 def coerce_to(self, dst_type, env): 5186 # If coercing to a generic pyobject and this is a cpdef function 5187 # we can create the corresponding attribute 5188 if dst_type is py_object_type: 5189 entry = self.entry 5190 if entry and entry.is_cfunction and entry.as_variable: 5191 # must be a cpdef function 5192 self.is_temp = 1 5193 self.entry = entry.as_variable 5194 self.analyse_as_python_attribute(env) 5195 return self 5196 return ExprNode.coerce_to(self, dst_type, env) 5197 5198 def calculate_constant_result(self): 5199 attr = self.attribute 5200 if attr.startswith("__") and attr.endswith("__"): 5201 return 5202 self.constant_result = getattr(self.obj.constant_result, attr) 5203 5204 def compile_time_value(self, denv): 5205 attr = self.attribute 5206 if attr.startswith("__") and attr.endswith("__"): 5207 error(self.pos, 5208 "Invalid attribute name '%s' in compile-time expression" % attr) 5209 return None 5210 obj = self.obj.compile_time_value(denv) 5211 try: 5212 return getattr(obj, attr) 5213 except Exception, e: 5214 self.compile_time_value_error(e) 5215 5216 def type_dependencies(self, env): 5217 return self.obj.type_dependencies(env) 5218 5219 def infer_type(self, env): 5220 # FIXME: this is way too redundant with analyse_types() 5221 node = self.analyse_as_cimported_attribute_node(env, target=False) 5222 if node is not None: 5223 return node.entry.type 5224 node = self.analyse_as_unbound_cmethod_node(env) 5225 if node is not None: 5226 return node.entry.type 5227 obj_type = self.obj.infer_type(env) 5228 self.analyse_attribute(env, obj_type=obj_type) 5229 if obj_type.is_builtin_type and self.type.is_cfunction: 5230 # special case: C-API replacements for C methods of 5231 # builtin types cannot be inferred as C functions as 5232 # that would prevent their use as bound methods 5233 return py_object_type 5234 return self.type 5235 5236 def analyse_target_declaration(self, env): 5237 pass 5238 5239 def analyse_target_types(self, env): 5240 node = self.analyse_types(env, target = 1) 5241 if node.type.is_const: 5242 error(self.pos, "Assignment to const attribute '%s'" % self.attribute) 5243 if not node.is_lvalue(): 5244 error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type) 5245 return node 5246 5247 def analyse_types(self, env, target = 0): 5248 self.initialized_check = env.directives['initializedcheck'] 5249 node = self.analyse_as_cimported_attribute_node(env, target) 5250 if node is None and not target: 5251 node = self.analyse_as_unbound_cmethod_node(env) 5252 if node is None: 5253 node = self.analyse_as_ordinary_attribute_node(env, target) 5254 assert node is not None 5255 if node.entry: 5256 node.entry.used = True 5257 if node.is_attribute: 5258 node.wrap_obj_in_nonecheck(env) 5259 return node 5260 5261 def analyse_as_cimported_attribute_node(self, env, target): 5262 # Try to interpret this as a reference to an imported 5263 # C const, type, var or function. If successful, mutates 5264 # this node into a NameNode and returns 1, otherwise 5265 # returns 0. 5266 module_scope = self.obj.analyse_as_module(env) 5267 if module_scope: 5268 entry = module_scope.lookup_here(self.attribute) 5269 if entry and ( 5270 entry.is_cglobal or entry.is_cfunction 5271 or entry.is_type or entry.is_const): 5272 return self.as_name_node(env, entry, target) 5273 return None 5274 5275 def analyse_as_unbound_cmethod_node(self, env): 5276 # Try to interpret this as a reference to an unbound 5277 # C method of an extension type or builtin type. If successful, 5278 # creates a corresponding NameNode and returns it, otherwise 5279 # returns None. 5280 type = self.obj.analyse_as_extension_type(env) 5281 if type: 5282 entry = type.scope.lookup_here(self.attribute) 5283 if entry and entry.is_cmethod: 5284 if type.is_builtin_type: 5285 if not self.is_called: 5286 # must handle this as Python object 5287 return None 5288 ubcm_entry = entry 5289 else: 5290 # Create a temporary entry describing the C method 5291 # as an ordinary function. 5292 ubcm_entry = Symtab.Entry(entry.name, 5293 "%s->%s" % (type.vtabptr_cname, entry.cname), 5294 entry.type) 5295 ubcm_entry.is_cfunction = 1 5296 ubcm_entry.func_cname = entry.func_cname 5297 ubcm_entry.is_unbound_cmethod = 1 5298 return self.as_name_node(env, ubcm_entry, target=False) 5299 return None 5300 5301 def analyse_as_type(self, env): 5302 module_scope = self.obj.analyse_as_module(env) 5303 if module_scope: 5304 return module_scope.lookup_type(self.attribute) 5305 if not self.obj.is_string_literal: 5306 base_type = self.obj.analyse_as_type(env) 5307 if base_type and hasattr(base_type, 'scope') and base_type.scope is not None: 5308 return base_type.scope.lookup_type(self.attribute) 5309 return None 5310 5311 def analyse_as_extension_type(self, env): 5312 # Try to interpret this as a reference to an extension type 5313 # in a cimported module. Returns the extension type, or None. 5314 module_scope = self.obj.analyse_as_module(env) 5315 if module_scope: 5316 entry = module_scope.lookup_here(self.attribute) 5317 if entry and entry.is_type: 5318 if entry.type.is_extension_type or entry.type.is_builtin_type: 5319 return entry.type 5320 return None 5321 5322 def analyse_as_module(self, env): 5323 # Try to interpret this as a reference to a cimported module 5324 # in another cimported module. Returns the module scope, or None. 5325 module_scope = self.obj.analyse_as_module(env) 5326 if module_scope: 5327 entry = module_scope.lookup_here(self.attribute) 5328 if entry and entry.as_module: 5329 return entry.as_module 5330 return None 5331 5332 def as_name_node(self, env, entry, target): 5333 # Create a corresponding NameNode from this node and complete the 5334 # analyse_types phase. 5335 node = NameNode.from_node(self, name=self.attribute, entry=entry) 5336 if target: 5337 node = node.analyse_target_types(env) 5338 else: 5339 node = node.analyse_rvalue_entry(env) 5340 node.entry.used = 1 5341 return node 5342 5343 def analyse_as_ordinary_attribute_node(self, env, target): 5344 self.obj = self.obj.analyse_types(env) 5345 self.analyse_attribute(env) 5346 if self.entry and self.entry.is_cmethod and not self.is_called: 5347 # error(self.pos, "C method can only be called") 5348 pass 5349 ## Reference to C array turns into pointer to first element. 5350 #while self.type.is_array: 5351 # self.type = self.type.element_ptr_type() 5352 if self.is_py_attr: 5353 if not target: 5354 self.is_temp = 1 5355 self.result_ctype = py_object_type 5356 elif target and self.obj.type.is_builtin_type: 5357 error(self.pos, "Assignment to an immutable object field") 5358 #elif self.type.is_memoryviewslice and not target: 5359 # self.is_temp = True 5360 return self 5361 5362 def analyse_attribute(self, env, obj_type = None): 5363 # Look up attribute and set self.type and self.member. 5364 immutable_obj = obj_type is not None # used during type inference 5365 self.is_py_attr = 0 5366 self.member = self.attribute 5367 if obj_type is None: 5368 if self.obj.type.is_string or self.obj.type.is_pyunicode_ptr: 5369 self.obj = self.obj.coerce_to_pyobject(env) 5370 obj_type = self.obj.type 5371 else: 5372 if obj_type.is_string or obj_type.is_pyunicode_ptr: 5373 obj_type = py_object_type 5374 if obj_type.is_ptr or obj_type.is_array: 5375 obj_type = obj_type.base_type 5376 self.op = "->" 5377 elif obj_type.is_extension_type or obj_type.is_builtin_type: 5378 self.op = "->" 5379 else: 5380 self.op = "." 5381 if obj_type.has_attributes: 5382 if obj_type.attributes_known(): 5383 if (obj_type.is_memoryviewslice and not 5384 obj_type.scope.lookup_here(self.attribute)): 5385 if self.attribute == 'T': 5386 self.is_memslice_transpose = True 5387 self.is_temp = True 5388 self.use_managed_ref = True 5389 self.type = self.obj.type 5390 return 5391 else: 5392 obj_type.declare_attribute(self.attribute, env, self.pos) 5393 entry = obj_type.scope.lookup_here(self.attribute) 5394 if entry and entry.is_member: 5395 entry = None 5396 else: 5397 error(self.pos, 5398 "Cannot select attribute of incomplete type '%s'" 5399 % obj_type) 5400 self.type = PyrexTypes.error_type 5401 return 5402 self.entry = entry 5403 if entry: 5404 if obj_type.is_extension_type and entry.name == "__weakref__": 5405 error(self.pos, "Illegal use of special attribute __weakref__") 5406 5407 # def methods need the normal attribute lookup 5408 # because they do not have struct entries 5409 # fused function go through assignment synthesis 5410 # (foo = pycfunction(foo_func_obj)) and need to go through 5411 # regular Python lookup as well 5412 if (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod: 5413 self.type = entry.type 5414 self.member = entry.cname 5415 return 5416 else: 5417 # If it's not a variable or C method, it must be a Python 5418 # method of an extension type, so we treat it like a Python 5419 # attribute. 5420 pass 5421 # If we get here, the base object is not a struct/union/extension 5422 # type, or it is an extension type and the attribute is either not 5423 # declared or is declared as a Python method. Treat it as a Python 5424 # attribute reference. 5425 self.analyse_as_python_attribute(env, obj_type, immutable_obj) 5426 5427 def analyse_as_python_attribute(self, env, obj_type=None, immutable_obj=False): 5428 if obj_type is None: 5429 obj_type = self.obj.type 5430 # mangle private '__*' Python attributes used inside of a class 5431 self.attribute = env.mangle_class_private_name(self.attribute) 5432 self.member = self.attribute 5433 self.type = py_object_type 5434 self.is_py_attr = 1 5435 if not obj_type.is_pyobject and not obj_type.is_error: 5436 if obj_type.can_coerce_to_pyobject(env): 5437 if not immutable_obj: 5438 self.obj = self.obj.coerce_to_pyobject(env) 5439 elif (obj_type.is_cfunction and (self.obj.is_name or self.obj.is_attribute) 5440 and self.obj.entry.as_variable 5441 and self.obj.entry.as_variable.type.is_pyobject): 5442 # might be an optimised builtin function => unpack it 5443 if not immutable_obj: 5444 self.obj = self.obj.coerce_to_pyobject(env) 5445 else: 5446 error(self.pos, 5447 "Object of type '%s' has no attribute '%s'" % 5448 (obj_type, self.attribute)) 5449 5450 def wrap_obj_in_nonecheck(self, env): 5451 if not env.directives['nonecheck']: 5452 return 5453 5454 msg = None 5455 format_args = () 5456 if (self.obj.type.is_extension_type and self.needs_none_check and not 5457 self.is_py_attr): 5458 msg = "'NoneType' object has no attribute '%s'" 5459 format_args = (self.attribute,) 5460 elif self.obj.type.is_memoryviewslice: 5461 if self.is_memslice_transpose: 5462 msg = "Cannot transpose None memoryview slice" 5463 else: 5464 entry = self.obj.type.scope.lookup_here(self.attribute) 5465 if entry: 5466 # copy/is_c_contig/shape/strides etc 5467 msg = "Cannot access '%s' attribute of None memoryview slice" 5468 format_args = (entry.name,) 5469 5470 if msg: 5471 self.obj = self.obj.as_none_safe_node(msg, 'PyExc_AttributeError', 5472 format_args=format_args) 5473 5474 5475 def nogil_check(self, env): 5476 if self.is_py_attr: 5477 self.gil_error() 5478 elif self.type.is_memoryviewslice: 5479 import MemoryView 5480 MemoryView.err_if_nogil_initialized_check(self.pos, env, 'attribute') 5481 5482 gil_message = "Accessing Python attribute" 5483 5484 def is_simple(self): 5485 if self.obj: 5486 return self.result_in_temp() or self.obj.is_simple() 5487 else: 5488 return NameNode.is_simple(self) 5489 5490 def is_lvalue(self): 5491 if self.obj: 5492 return not self.type.is_array 5493 else: 5494 return NameNode.is_lvalue(self) 5495 5496 def is_ephemeral(self): 5497 if self.obj: 5498 return self.obj.is_ephemeral() 5499 else: 5500 return NameNode.is_ephemeral(self) 5501 5502 def calculate_result_code(self): 5503 #print "AttributeNode.calculate_result_code:", self.member ### 5504 #print "...obj node =", self.obj, "code", self.obj.result() ### 5505 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ### 5506 obj = self.obj 5507 obj_code = obj.result_as(obj.type) 5508 #print "...obj_code =", obj_code ### 5509 if self.entry and self.entry.is_cmethod: 5510 if obj.type.is_extension_type and not self.entry.is_builtin_cmethod: 5511 if self.entry.final_func_cname: 5512 return self.entry.final_func_cname 5513 5514 if self.type.from_fused: 5515 # If the attribute was specialized through indexing, make 5516 # sure to get the right fused name, as our entry was 5517 # replaced by our parent index node 5518 # (AnalyseExpressionsTransform) 5519 self.member = self.entry.cname 5520 5521 return "((struct %s *)%s%s%s)->%s" % ( 5522 obj.type.vtabstruct_cname, obj_code, self.op, 5523 obj.type.vtabslot_cname, self.member) 5524 elif self.result_is_used: 5525 return self.member 5526 # Generating no code at all for unused access to optimised builtin 5527 # methods fixes the problem that some optimisations only exist as 5528 # macros, i.e. there is no function pointer to them, so we would 5529 # generate invalid C code here. 5530 return 5531 elif obj.type.is_complex: 5532 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code) 5533 else: 5534 if obj.type.is_builtin_type and self.entry and self.entry.is_variable: 5535 # accessing a field of a builtin type, need to cast better than result_as() does 5536 obj_code = obj.type.cast_code(obj.result(), to_object_struct = True) 5537 return "%s%s%s" % (obj_code, self.op, self.member) 5538 5539 def generate_result_code(self, code): 5540 if self.is_py_attr: 5541 if self.is_special_lookup: 5542 code.globalstate.use_utility_code( 5543 UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c")) 5544 lookup_func_name = '__Pyx_PyObject_LookupSpecial' 5545 else: 5546 code.globalstate.use_utility_code( 5547 UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c")) 5548 lookup_func_name = '__Pyx_PyObject_GetAttrStr' 5549 code.putln( 5550 '%s = %s(%s, %s); %s' % ( 5551 self.result(), 5552 lookup_func_name, 5553 self.obj.py_result(), 5554 code.intern_identifier(self.attribute), 5555 code.error_goto_if_null(self.result(), self.pos))) 5556 code.put_gotref(self.py_result()) 5557 elif self.type.is_memoryviewslice: 5558 if self.is_memslice_transpose: 5559 # transpose the slice 5560 for access, packing in self.type.axes: 5561 if access == 'ptr': 5562 error(self.pos, "Transposing not supported for slices " 5563 "with indirect dimensions") 5564 return 5565 5566 code.putln("%s = %s;" % (self.result(), self.obj.result())) 5567 if self.obj.is_name or (self.obj.is_attribute and 5568 self.obj.is_memslice_transpose): 5569 code.put_incref_memoryviewslice(self.result(), have_gil=True) 5570 5571 T = "__pyx_memslice_transpose(&%s) == 0" 5572 code.putln(code.error_goto_if(T % self.result(), self.pos)) 5573 elif self.initialized_check: 5574 code.putln( 5575 'if (unlikely(!%s.memview)) {' 5576 'PyErr_SetString(PyExc_AttributeError,' 5577 '"Memoryview is not initialized");' 5578 '%s' 5579 '}' % (self.result(), code.error_goto(self.pos))) 5580 else: 5581 # result_code contains what is needed, but we may need to insert 5582 # a check and raise an exception 5583 if self.obj.type.is_extension_type: 5584 pass 5585 elif self.entry and self.entry.is_cmethod and self.entry.utility_code: 5586 # C method implemented as function call with utility code 5587 code.globalstate.use_utility_code(self.entry.utility_code) 5588 5589 def generate_disposal_code(self, code): 5590 if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_transpose: 5591 # mirror condition for putting the memview incref here: 5592 if self.obj.is_name or (self.obj.is_attribute and 5593 self.obj.is_memslice_transpose): 5594 code.put_xdecref_memoryviewslice( 5595 self.result(), have_gil=True) 5596 else: 5597 ExprNode.generate_disposal_code(self, code) 5598 5599 def generate_assignment_code(self, rhs, code): 5600 self.obj.generate_evaluation_code(code) 5601 if self.is_py_attr: 5602 code.globalstate.use_utility_code( 5603 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 5604 code.put_error_if_neg(self.pos, 5605 '__Pyx_PyObject_SetAttrStr(%s, %s, %s)' % ( 5606 self.obj.py_result(), 5607 code.intern_identifier(self.attribute), 5608 rhs.py_result())) 5609 rhs.generate_disposal_code(code) 5610 rhs.free_temps(code) 5611 elif self.obj.type.is_complex: 5612 code.putln("__Pyx_SET_C%s(%s, %s);" % ( 5613 self.member.upper(), 5614 self.obj.result_as(self.obj.type), 5615 rhs.result_as(self.ctype()))) 5616 else: 5617 select_code = self.result() 5618 if self.type.is_pyobject and self.use_managed_ref: 5619 rhs.make_owned_reference(code) 5620 code.put_giveref(rhs.py_result()) 5621 code.put_gotref(select_code) 5622 code.put_decref(select_code, self.ctype()) 5623 elif self.type.is_memoryviewslice: 5624 import MemoryView 5625 MemoryView.put_assign_to_memviewslice( 5626 select_code, rhs, rhs.result(), self.type, code) 5627 5628 if not self.type.is_memoryviewslice: 5629 code.putln( 5630 "%s = %s;" % ( 5631 select_code, 5632 rhs.result_as(self.ctype()))) 5633 #rhs.result())) 5634 rhs.generate_post_assignment_code(code) 5635 rhs.free_temps(code) 5636 self.obj.generate_disposal_code(code) 5637 self.obj.free_temps(code) 5638 5639 def generate_deletion_code(self, code, ignore_nonexisting=False): 5640 self.obj.generate_evaluation_code(code) 5641 if self.is_py_attr or (self.entry.scope.is_property_scope 5642 and u'__del__' in self.entry.scope.entries): 5643 code.globalstate.use_utility_code( 5644 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 5645 code.put_error_if_neg(self.pos, 5646 '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( 5647 self.obj.py_result(), 5648 code.intern_identifier(self.attribute))) 5649 else: 5650 error(self.pos, "Cannot delete C attribute of extension type") 5651 self.obj.generate_disposal_code(code) 5652 self.obj.free_temps(code) 5653 5654 def annotate(self, code): 5655 if self.is_py_attr: 5656 style, text = 'py_attr', 'python attribute (%s)' 5657 else: 5658 style, text = 'c_attr', 'c attribute (%s)' 5659 code.annotate(self.pos, AnnotationItem(style, text % self.type, size=len(self.attribute))) 5660 5661 5662 #------------------------------------------------------------------- 5663 # 5664 # Constructor nodes 5665 # 5666 #------------------------------------------------------------------- 5667 5668 class StarredTargetNode(ExprNode): 5669 # A starred expression like "*a" 5670 # 5671 # This is only allowed in sequence assignment targets such as 5672 # 5673 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4] 5674 # 5675 # and will be removed during type analysis (or generate an error 5676 # if it's found at unexpected places). 5677 # 5678 # target ExprNode 5679 5680 subexprs = ['target'] 5681 is_starred = 1 5682 type = py_object_type 5683 is_temp = 1 5684 5685 def __init__(self, pos, target): 5686 ExprNode.__init__(self, pos) 5687 self.target = target 5688 5689 def analyse_declarations(self, env): 5690 error(self.pos, "can use starred expression only as assignment target") 5691 self.target.analyse_declarations(env) 5692 5693 def analyse_types(self, env): 5694 error(self.pos, "can use starred expression only as assignment target") 5695 self.target = self.target.analyse_types(env) 5696 self.type = self.target.type 5697 return self 5698 5699 def analyse_target_declaration(self, env): 5700 self.target.analyse_target_declaration(env) 5701 5702 def analyse_target_types(self, env): 5703 self.target = self.target.analyse_target_types(env) 5704 self.type = self.target.type 5705 return self 5706 5707 def calculate_result_code(self): 5708 return "" 5709 5710 def generate_result_code(self, code): 5711 pass 5712 5713 5714 class SequenceNode(ExprNode): 5715 # Base class for list and tuple constructor nodes. 5716 # Contains common code for performing sequence unpacking. 5717 # 5718 # args [ExprNode] 5719 # unpacked_items [ExprNode] or None 5720 # coerced_unpacked_items [ExprNode] or None 5721 # mult_factor ExprNode the integer number of content repetitions ([1,2]*3) 5722 5723 subexprs = ['args', 'mult_factor'] 5724 5725 is_sequence_constructor = 1 5726 unpacked_items = None 5727 mult_factor = None 5728 slow = False # trade speed for code size (e.g. use PyTuple_Pack()) 5729 5730 def compile_time_value_list(self, denv): 5731 return [arg.compile_time_value(denv) for arg in self.args] 5732 5733 def replace_starred_target_node(self): 5734 # replace a starred node in the targets by the contained expression 5735 self.starred_assignment = False 5736 args = [] 5737 for arg in self.args: 5738 if arg.is_starred: 5739 if self.starred_assignment: 5740 error(arg.pos, "more than 1 starred expression in assignment") 5741 self.starred_assignment = True 5742 arg = arg.target 5743 arg.is_starred = True 5744 args.append(arg) 5745 self.args = args 5746 5747 def analyse_target_declaration(self, env): 5748 self.replace_starred_target_node() 5749 for arg in self.args: 5750 arg.analyse_target_declaration(env) 5751 5752 def analyse_types(self, env, skip_children=False): 5753 for i in range(len(self.args)): 5754 arg = self.args[i] 5755 if not skip_children: arg = arg.analyse_types(env) 5756 self.args[i] = arg.coerce_to_pyobject(env) 5757 if self.mult_factor: 5758 self.mult_factor = self.mult_factor.analyse_types(env) 5759 if not self.mult_factor.type.is_int: 5760 self.mult_factor = self.mult_factor.coerce_to_pyobject(env) 5761 self.is_temp = 1 5762 # not setting self.type here, subtypes do this 5763 return self 5764 5765 def may_be_none(self): 5766 return False 5767 5768 def analyse_target_types(self, env): 5769 if self.mult_factor: 5770 error(self.pos, "can't assign to multiplied sequence") 5771 self.unpacked_items = [] 5772 self.coerced_unpacked_items = [] 5773 self.any_coerced_items = False 5774 for i, arg in enumerate(self.args): 5775 arg = self.args[i] = arg.analyse_target_types(env) 5776 if arg.is_starred: 5777 if not arg.type.assignable_from(Builtin.list_type): 5778 error(arg.pos, 5779 "starred target must have Python object (list) type") 5780 if arg.type is py_object_type: 5781 arg.type = Builtin.list_type 5782 unpacked_item = PyTempNode(self.pos, env) 5783 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) 5784 if unpacked_item is not coerced_unpacked_item: 5785 self.any_coerced_items = True 5786 self.unpacked_items.append(unpacked_item) 5787 self.coerced_unpacked_items.append(coerced_unpacked_item) 5788 self.type = py_object_type 5789 return self 5790 5791 def generate_result_code(self, code): 5792 self.generate_operation_code(code) 5793 5794 def generate_sequence_packing_code(self, code, target=None, plain=False): 5795 if target is None: 5796 target = self.result() 5797 size_factor = c_mult = '' 5798 mult_factor = None 5799 5800 if self.mult_factor and not plain: 5801 mult_factor = self.mult_factor 5802 if mult_factor.type.is_int: 5803 c_mult = mult_factor.result() 5804 if isinstance(mult_factor.constant_result, (int,long)) \ 5805 and mult_factor.constant_result > 0: 5806 size_factor = ' * %s' % mult_factor.constant_result 5807 else: 5808 size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult) 5809 5810 if self.type is Builtin.tuple_type and (self.is_literal or self.slow) and not c_mult: 5811 # use PyTuple_Pack() to avoid generating huge amounts of one-time code 5812 code.putln('%s = PyTuple_Pack(%d, %s); %s' % ( 5813 target, 5814 len(self.args), 5815 ', '.join([ arg.py_result() for arg in self.args ]), 5816 code.error_goto_if_null(target, self.pos))) 5817 code.put_gotref(target) 5818 else: 5819 # build the tuple/list step by step, potentially multiplying it as we go 5820 if self.type is Builtin.list_type: 5821 create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM' 5822 elif self.type is Builtin.tuple_type: 5823 create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM' 5824 else: 5825 raise InternalError("sequence packing for unexpected type %s" % self.type) 5826 arg_count = len(self.args) 5827 code.putln("%s = %s(%s%s); %s" % ( 5828 target, create_func, arg_count, size_factor, 5829 code.error_goto_if_null(target, self.pos))) 5830 code.put_gotref(target) 5831 5832 if c_mult: 5833 # FIXME: can't use a temp variable here as the code may 5834 # end up in the constant building function. Temps 5835 # currently don't work there. 5836 5837 #counter = code.funcstate.allocate_temp(mult_factor.type, manage_ref=False) 5838 counter = Naming.quick_temp_cname 5839 code.putln('{ Py_ssize_t %s;' % counter) 5840 if arg_count == 1: 5841 offset = counter 5842 else: 5843 offset = '%s * %s' % (counter, arg_count) 5844 code.putln('for (%s=0; %s < %s; %s++) {' % ( 5845 counter, counter, c_mult, counter 5846 )) 5847 else: 5848 offset = '' 5849 5850 for i in xrange(arg_count): 5851 arg = self.args[i] 5852 if c_mult or not arg.result_in_temp(): 5853 code.put_incref(arg.result(), arg.ctype()) 5854 code.putln("%s(%s, %s, %s);" % ( 5855 set_item_func, 5856 target, 5857 (offset and i) and ('%s + %s' % (offset, i)) or (offset or i), 5858 arg.py_result())) 5859 code.put_giveref(arg.py_result()) 5860 5861 if c_mult: 5862 code.putln('}') 5863 #code.funcstate.release_temp(counter) 5864 code.putln('}') 5865 5866 if mult_factor is not None and mult_factor.type.is_pyobject: 5867 code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' % ( 5868 Naming.quick_temp_cname, target, mult_factor.py_result(), 5869 code.error_goto_if_null(Naming.quick_temp_cname, self.pos) 5870 )) 5871 code.put_gotref(Naming.quick_temp_cname) 5872 code.put_decref(target, py_object_type) 5873 code.putln('%s = %s;' % (target, Naming.quick_temp_cname)) 5874 code.putln('}') 5875 5876 def generate_subexpr_disposal_code(self, code): 5877 if self.mult_factor and self.mult_factor.type.is_int: 5878 super(SequenceNode, self).generate_subexpr_disposal_code(code) 5879 elif self.type is Builtin.tuple_type and (self.is_literal or self.slow): 5880 super(SequenceNode, self).generate_subexpr_disposal_code(code) 5881 else: 5882 # We call generate_post_assignment_code here instead 5883 # of generate_disposal_code, because values were stored 5884 # in the tuple using a reference-stealing operation. 5885 for arg in self.args: 5886 arg.generate_post_assignment_code(code) 5887 # Should NOT call free_temps -- this is invoked by the default 5888 # generate_evaluation_code which will do that. 5889 if self.mult_factor: 5890 self.mult_factor.generate_disposal_code(code) 5891 5892 def generate_assignment_code(self, rhs, code): 5893 if self.starred_assignment: 5894 self.generate_starred_assignment_code(rhs, code) 5895 else: 5896 self.generate_parallel_assignment_code(rhs, code) 5897 5898 for item in self.unpacked_items: 5899 item.release(code) 5900 rhs.free_temps(code) 5901 5902 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( 5903 PyrexTypes.py_object_type, [ 5904 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), 5905 ])) 5906 5907 def generate_parallel_assignment_code(self, rhs, code): 5908 # Need to work around the fact that generate_evaluation_code 5909 # allocates the temps in a rather hacky way -- the assignment 5910 # is evaluated twice, within each if-block. 5911 for item in self.unpacked_items: 5912 item.allocate(code) 5913 special_unpack = (rhs.type is py_object_type 5914 or rhs.type in (tuple_type, list_type) 5915 or not rhs.type.is_builtin_type) 5916 long_enough_for_a_loop = len(self.unpacked_items) > 3 5917 5918 if special_unpack: 5919 self.generate_special_parallel_unpacking_code( 5920 code, rhs, use_loop=long_enough_for_a_loop) 5921 else: 5922 code.putln("{") 5923 self.generate_generic_parallel_unpacking_code( 5924 code, rhs, self.unpacked_items, use_loop=long_enough_for_a_loop) 5925 code.putln("}") 5926 5927 for value_node in self.coerced_unpacked_items: 5928 value_node.generate_evaluation_code(code) 5929 for i in range(len(self.args)): 5930 self.args[i].generate_assignment_code( 5931 self.coerced_unpacked_items[i], code) 5932 5933 def generate_special_parallel_unpacking_code(self, code, rhs, use_loop): 5934 sequence_type_test = '1' 5935 none_check = "likely(%s != Py_None)" % rhs.py_result() 5936 if rhs.type is list_type: 5937 sequence_types = ['List'] 5938 if rhs.may_be_none(): 5939 sequence_type_test = none_check 5940 elif rhs.type is tuple_type: 5941 sequence_types = ['Tuple'] 5942 if rhs.may_be_none(): 5943 sequence_type_test = none_check 5944 else: 5945 sequence_types = ['Tuple', 'List'] 5946 tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result() 5947 list_check = 'PyList_CheckExact(%s)' % rhs.py_result() 5948 sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check) 5949 5950 code.putln("if (%s) {" % sequence_type_test) 5951 code.putln("PyObject* sequence = %s;" % rhs.py_result()) 5952 5953 # list/tuple => check size 5954 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") 5955 code.putln("Py_ssize_t size = Py_SIZE(sequence);") 5956 code.putln("#else") 5957 code.putln("Py_ssize_t size = PySequence_Size(sequence);") # < 0 => exception 5958 code.putln("#endif") 5959 code.putln("if (unlikely(size != %d)) {" % len(self.args)) 5960 code.globalstate.use_utility_code(raise_too_many_values_to_unpack) 5961 code.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % ( 5962 len(self.args), len(self.args))) 5963 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 5964 code.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);") 5965 code.putln(code.error_goto(self.pos)) 5966 code.putln("}") 5967 5968 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") 5969 # unpack items from list/tuple in unrolled loop (can't fail) 5970 if len(sequence_types) == 2: 5971 code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0]) 5972 for i, item in enumerate(self.unpacked_items): 5973 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( 5974 item.result(), sequence_types[0], i)) 5975 if len(sequence_types) == 2: 5976 code.putln("} else {") 5977 for i, item in enumerate(self.unpacked_items): 5978 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( 5979 item.result(), sequence_types[1], i)) 5980 code.putln("}") 5981 for item in self.unpacked_items: 5982 code.put_incref(item.result(), item.ctype()) 5983 5984 code.putln("#else") 5985 # in non-CPython, use the PySequence protocol (which can fail) 5986 if not use_loop: 5987 for i, item in enumerate(self.unpacked_items): 5988 code.putln("%s = PySequence_ITEM(sequence, %d); %s" % ( 5989 item.result(), i, 5990 code.error_goto_if_null(item.result(), self.pos))) 5991 code.put_gotref(item.result()) 5992 else: 5993 code.putln("{") 5994 code.putln("Py_ssize_t i;") 5995 code.putln("PyObject** temps[%s] = {%s};" % ( 5996 len(self.unpacked_items), 5997 ','.join(['&%s' % item.result() for item in self.unpacked_items]))) 5998 code.putln("for (i=0; i < %s; i++) {" % len(self.unpacked_items)) 5999 code.putln("PyObject* item = PySequence_ITEM(sequence, i); %s" % ( 6000 code.error_goto_if_null('item', self.pos))) 6001 code.put_gotref('item') 6002 code.putln("*(temps[i]) = item;") 6003 code.putln("}") 6004 code.putln("}") 6005 6006 code.putln("#endif") 6007 rhs.generate_disposal_code(code) 6008 6009 if sequence_type_test == '1': 6010 code.putln("}") # all done 6011 elif sequence_type_test == none_check: 6012 # either tuple/list or None => save some code by generating the error directly 6013 code.putln("} else {") 6014 code.globalstate.use_utility_code( 6015 UtilityCode.load_cached("RaiseNoneIterError", "ObjectHandling.c")) 6016 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code.error_goto(self.pos)) 6017 code.putln("}") # all done 6018 else: 6019 code.putln("} else {") # needs iteration fallback code 6020 self.generate_generic_parallel_unpacking_code( 6021 code, rhs, self.unpacked_items, use_loop=use_loop) 6022 code.putln("}") 6023 6024 def generate_generic_parallel_unpacking_code(self, code, rhs, unpacked_items, use_loop, terminate=True): 6025 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 6026 code.globalstate.use_utility_code(UtilityCode.load_cached("IterFinish", "ObjectHandling.c")) 6027 code.putln("Py_ssize_t index = -1;") # must be at the start of a C block! 6028 6029 if use_loop: 6030 code.putln("PyObject** temps[%s] = {%s};" % ( 6031 len(self.unpacked_items), 6032 ','.join(['&%s' % item.result() for item in unpacked_items]))) 6033 6034 iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 6035 code.putln( 6036 "%s = PyObject_GetIter(%s); %s" % ( 6037 iterator_temp, 6038 rhs.py_result(), 6039 code.error_goto_if_null(iterator_temp, self.pos))) 6040 code.put_gotref(iterator_temp) 6041 rhs.generate_disposal_code(code) 6042 6043 iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) 6044 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % ( 6045 iternext_func, iterator_temp)) 6046 6047 unpacking_error_label = code.new_label('unpacking_failed') 6048 unpack_code = "%s(%s)" % (iternext_func, iterator_temp) 6049 if use_loop: 6050 code.putln("for (index=0; index < %s; index++) {" % len(unpacked_items)) 6051 code.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code) 6052 code.put_goto(unpacking_error_label) 6053 code.put_gotref("item") 6054 code.putln("*(temps[index]) = item;") 6055 code.putln("}") 6056 else: 6057 for i, item in enumerate(unpacked_items): 6058 code.put( 6059 "index = %d; %s = %s; if (unlikely(!%s)) " % ( 6060 i, 6061 item.result(), 6062 unpack_code, 6063 item.result())) 6064 code.put_goto(unpacking_error_label) 6065 code.put_gotref(item.py_result()) 6066 6067 if terminate: 6068 code.globalstate.use_utility_code( 6069 UtilityCode.load_cached("UnpackItemEndCheck", "ObjectHandling.c")) 6070 code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s, %d)" % ( 6071 unpack_code, 6072 len(unpacked_items))) 6073 code.putln("%s = NULL;" % iternext_func) 6074 code.put_decref_clear(iterator_temp, py_object_type) 6075 6076 unpacking_done_label = code.new_label('unpacking_done') 6077 code.put_goto(unpacking_done_label) 6078 6079 code.put_label(unpacking_error_label) 6080 code.put_decref_clear(iterator_temp, py_object_type) 6081 code.putln("%s = NULL;" % iternext_func) 6082 code.putln("if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);") 6083 code.putln(code.error_goto(self.pos)) 6084 code.put_label(unpacking_done_label) 6085 6086 code.funcstate.release_temp(iternext_func) 6087 if terminate: 6088 code.funcstate.release_temp(iterator_temp) 6089 iterator_temp = None 6090 6091 return iterator_temp 6092 6093 def generate_starred_assignment_code(self, rhs, code): 6094 for i, arg in enumerate(self.args): 6095 if arg.is_starred: 6096 starred_target = self.unpacked_items[i] 6097 unpacked_fixed_items_left = self.unpacked_items[:i] 6098 unpacked_fixed_items_right = self.unpacked_items[i+1:] 6099 break 6100 else: 6101 assert False 6102 6103 iterator_temp = None 6104 if unpacked_fixed_items_left: 6105 for item in unpacked_fixed_items_left: 6106 item.allocate(code) 6107 code.putln('{') 6108 iterator_temp = self.generate_generic_parallel_unpacking_code( 6109 code, rhs, unpacked_fixed_items_left, 6110 use_loop=True, terminate=False) 6111 for i, item in enumerate(unpacked_fixed_items_left): 6112 value_node = self.coerced_unpacked_items[i] 6113 value_node.generate_evaluation_code(code) 6114 code.putln('}') 6115 6116 starred_target.allocate(code) 6117 target_list = starred_target.result() 6118 code.putln("%s = PySequence_List(%s); %s" % ( 6119 target_list, 6120 iterator_temp or rhs.py_result(), 6121 code.error_goto_if_null(target_list, self.pos))) 6122 code.put_gotref(target_list) 6123 6124 if iterator_temp: 6125 code.put_decref_clear(iterator_temp, py_object_type) 6126 code.funcstate.release_temp(iterator_temp) 6127 else: 6128 rhs.generate_disposal_code(code) 6129 6130 if unpacked_fixed_items_right: 6131 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 6132 length_temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) 6133 code.putln('%s = PyList_GET_SIZE(%s);' % (length_temp, target_list)) 6134 code.putln("if (unlikely(%s < %d)) {" % (length_temp, len(unpacked_fixed_items_right))) 6135 code.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % ( 6136 len(unpacked_fixed_items_left), length_temp, 6137 code.error_goto(self.pos))) 6138 code.putln('}') 6139 6140 for item in unpacked_fixed_items_right[::-1]: 6141 item.allocate(code) 6142 for i, (item, coerced_arg) in enumerate(zip(unpacked_fixed_items_right[::-1], 6143 self.coerced_unpacked_items[::-1])): 6144 code.putln('#if CYTHON_COMPILING_IN_CPYTHON') 6145 code.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % ( 6146 item.py_result(), target_list, length_temp, i+1)) 6147 # resize the list the hard way 6148 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list) 6149 code.putln('#else') 6150 code.putln("%s = PySequence_ITEM(%s, %s-%d); " % ( 6151 item.py_result(), target_list, length_temp, i+1)) 6152 code.putln('#endif') 6153 code.put_gotref(item.py_result()) 6154 coerced_arg.generate_evaluation_code(code) 6155 6156 code.putln('#if !CYTHON_COMPILING_IN_CPYTHON') 6157 sublist_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 6158 code.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % ( 6159 sublist_temp, target_list, length_temp, len(unpacked_fixed_items_right), 6160 code.error_goto_if_null(sublist_temp, self.pos))) 6161 code.put_gotref(sublist_temp) 6162 code.funcstate.release_temp(length_temp) 6163 code.put_decref(target_list, py_object_type) 6164 code.putln('%s = %s; %s = NULL;' % (target_list, sublist_temp, sublist_temp)) 6165 code.putln('#else') 6166 code.putln('%s = %s;' % (sublist_temp, sublist_temp)) # avoid warning about unused variable 6167 code.funcstate.release_temp(sublist_temp) 6168 code.putln('#endif') 6169 6170 for i, arg in enumerate(self.args): 6171 arg.generate_assignment_code(self.coerced_unpacked_items[i], code) 6172 6173 def annotate(self, code): 6174 for arg in self.args: 6175 arg.annotate(code) 6176 if self.unpacked_items: 6177 for arg in self.unpacked_items: 6178 arg.annotate(code) 6179 for arg in self.coerced_unpacked_items: 6180 arg.annotate(code) 6181 6182 6183 class TupleNode(SequenceNode): 6184 # Tuple constructor. 6185 6186 type = tuple_type 6187 is_partly_literal = False 6188 6189 gil_message = "Constructing Python tuple" 6190 6191 def analyse_types(self, env, skip_children=False): 6192 if len(self.args) == 0: 6193 node = self 6194 node.is_temp = False 6195 node.is_literal = True 6196 else: 6197 node = SequenceNode.analyse_types(self, env, skip_children) 6198 for child in node.args: 6199 if not child.is_literal: 6200 break 6201 else: 6202 if not node.mult_factor or node.mult_factor.is_literal and \ 6203 isinstance(node.mult_factor.constant_result, (int, long)): 6204 node.is_temp = False 6205 node.is_literal = True 6206 else: 6207 if not node.mult_factor.type.is_pyobject: 6208 node.mult_factor = node.mult_factor.coerce_to_pyobject(env) 6209 node.is_temp = True 6210 node.is_partly_literal = True 6211 return node 6212 6213 def is_simple(self): 6214 # either temp or constant => always simple 6215 return True 6216 6217 def nonlocally_immutable(self): 6218 # either temp or constant => always safe 6219 return True 6220 6221 def calculate_result_code(self): 6222 if len(self.args) > 0: 6223 return self.result_code 6224 else: 6225 return Naming.empty_tuple 6226 6227 def calculate_constant_result(self): 6228 self.constant_result = tuple([ 6229 arg.constant_result for arg in self.args]) 6230 6231 def compile_time_value(self, denv): 6232 values = self.compile_time_value_list(denv) 6233 try: 6234 return tuple(values) 6235 except Exception, e: 6236 self.compile_time_value_error(e) 6237 6238 def generate_operation_code(self, code): 6239 if len(self.args) == 0: 6240 # result_code is Naming.empty_tuple 6241 return 6242 if self.is_partly_literal: 6243 # underlying tuple is const, but factor is not 6244 tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2) 6245 const_code = code.get_cached_constants_writer() 6246 const_code.mark_pos(self.pos) 6247 self.generate_sequence_packing_code(const_code, tuple_target, plain=True) 6248 const_code.put_giveref(tuple_target) 6249 code.putln('%s = PyNumber_Multiply(%s, %s); %s' % ( 6250 self.result(), tuple_target, self.mult_factor.py_result(), 6251 code.error_goto_if_null(self.result(), self.pos) 6252 )) 6253 code.put_gotref(self.py_result()) 6254 elif self.is_literal: 6255 # non-empty cached tuple => result is global constant, 6256 # creation code goes into separate code writer 6257 self.result_code = code.get_py_const(py_object_type, 'tuple', cleanup_level=2) 6258 code = code.get_cached_constants_writer() 6259 code.mark_pos(self.pos) 6260 self.generate_sequence_packing_code(code) 6261 code.put_giveref(self.py_result()) 6262 else: 6263 self.generate_sequence_packing_code(code) 6264 6265 6266 class ListNode(SequenceNode): 6267 # List constructor. 6268 6269 # obj_conversion_errors [PyrexError] used internally 6270 # orignial_args [ExprNode] used internally 6271 6272 obj_conversion_errors = [] 6273 type = list_type 6274 in_module_scope = False 6275 6276 gil_message = "Constructing Python list" 6277 6278 def type_dependencies(self, env): 6279 return () 6280 6281 def infer_type(self, env): 6282 # TOOD: Infer non-object list arrays. 6283 return list_type 6284 6285 def analyse_expressions(self, env): 6286 node = SequenceNode.analyse_expressions(self, env) 6287 return node.coerce_to_pyobject(env) 6288 6289 def analyse_types(self, env): 6290 hold_errors() 6291 self.original_args = list(self.args) 6292 node = SequenceNode.analyse_types(self, env) 6293 node.obj_conversion_errors = held_errors() 6294 release_errors(ignore=True) 6295 if env.is_module_scope: 6296 self.in_module_scope = True 6297 return node 6298 6299 def coerce_to(self, dst_type, env): 6300 if dst_type.is_pyobject: 6301 for err in self.obj_conversion_errors: 6302 report_error(err) 6303 self.obj_conversion_errors = [] 6304 if not self.type.subtype_of(dst_type): 6305 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) 6306 elif self.mult_factor: 6307 error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type) 6308 elif dst_type.is_ptr and dst_type.base_type is not PyrexTypes.c_void_type: 6309 base_type = dst_type.base_type 6310 self.type = PyrexTypes.CArrayType(base_type, len(self.args)) 6311 for i in range(len(self.original_args)): 6312 arg = self.args[i] 6313 if isinstance(arg, CoerceToPyTypeNode): 6314 arg = arg.arg 6315 self.args[i] = arg.coerce_to(base_type, env) 6316 elif dst_type.is_struct: 6317 if len(self.args) > len(dst_type.scope.var_entries): 6318 error(self.pos, "Too may members for '%s'" % dst_type) 6319 else: 6320 if len(self.args) < len(dst_type.scope.var_entries): 6321 warning(self.pos, "Too few members for '%s'" % dst_type, 1) 6322 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)): 6323 if isinstance(arg, CoerceToPyTypeNode): 6324 arg = arg.arg 6325 self.args[i] = arg.coerce_to(member.type, env) 6326 self.type = dst_type 6327 else: 6328 self.type = error_type 6329 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) 6330 return self 6331 6332 def as_tuple(self): 6333 t = TupleNode(self.pos, args=self.args, mult_factor=self.mult_factor) 6334 if isinstance(self.constant_result, list): 6335 t.constant_result = tuple(self.constant_result) 6336 return t 6337 6338 def allocate_temp_result(self, code): 6339 if self.type.is_array and self.in_module_scope: 6340 self.temp_code = code.funcstate.allocate_temp( 6341 self.type, manage_ref=False, static=True) 6342 else: 6343 SequenceNode.allocate_temp_result(self, code) 6344 6345 def release_temp_result(self, env): 6346 if self.type.is_array: 6347 # To be valid C++, we must allocate the memory on the stack 6348 # manually and be sure not to reuse it for something else. 6349 pass 6350 else: 6351 SequenceNode.release_temp_result(self, env) 6352 6353 def calculate_constant_result(self): 6354 if self.mult_factor: 6355 raise ValueError() # may exceed the compile time memory 6356 self.constant_result = [ 6357 arg.constant_result for arg in self.args] 6358 6359 def compile_time_value(self, denv): 6360 l = self.compile_time_value_list(denv) 6361 if self.mult_factor: 6362 l *= self.mult_factor.compile_time_value(denv) 6363 return l 6364 6365 def generate_operation_code(self, code): 6366 if self.type.is_pyobject: 6367 for err in self.obj_conversion_errors: 6368 report_error(err) 6369 self.generate_sequence_packing_code(code) 6370 elif self.type.is_array: 6371 for i, arg in enumerate(self.args): 6372 code.putln("%s[%s] = %s;" % ( 6373 self.result(), 6374 i, 6375 arg.result())) 6376 elif self.type.is_struct: 6377 for arg, member in zip(self.args, self.type.scope.var_entries): 6378 code.putln("%s.%s = %s;" % ( 6379 self.result(), 6380 member.cname, 6381 arg.result())) 6382 else: 6383 raise InternalError("List type never specified") 6384 6385 6386 class ScopedExprNode(ExprNode): 6387 # Abstract base class for ExprNodes that have their own local 6388 # scope, such as generator expressions. 6389 # 6390 # expr_scope Scope the inner scope of the expression 6391 6392 subexprs = [] 6393 expr_scope = None 6394 6395 # does this node really have a local scope, e.g. does it leak loop 6396 # variables or not? non-leaking Py3 behaviour is default, except 6397 # for list comprehensions where the behaviour differs in Py2 and 6398 # Py3 (set in Parsing.py based on parser context) 6399 has_local_scope = True 6400 6401 def init_scope(self, outer_scope, expr_scope=None): 6402 if expr_scope is not None: 6403 self.expr_scope = expr_scope 6404 elif self.has_local_scope: 6405 self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope) 6406 else: 6407 self.expr_scope = None 6408 6409 def analyse_declarations(self, env): 6410 self.init_scope(env) 6411 6412 def analyse_scoped_declarations(self, env): 6413 # this is called with the expr_scope as env 6414 pass 6415 6416 def analyse_types(self, env): 6417 # no recursion here, the children will be analysed separately below 6418 return self 6419 6420 def analyse_scoped_expressions(self, env): 6421 # this is called with the expr_scope as env 6422 return self 6423 6424 def generate_evaluation_code(self, code): 6425 # set up local variables and free their references on exit 6426 generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code 6427 if not self.has_local_scope or not self.expr_scope.var_entries: 6428 # no local variables => delegate, done 6429 generate_inner_evaluation_code(code) 6430 return 6431 6432 code.putln('{ /* enter inner scope */') 6433 py_entries = [] 6434 for entry in self.expr_scope.var_entries: 6435 if not entry.in_closure: 6436 code.put_var_declaration(entry) 6437 if entry.type.is_pyobject and entry.used: 6438 py_entries.append(entry) 6439 if not py_entries: 6440 # no local Python references => no cleanup required 6441 generate_inner_evaluation_code(code) 6442 code.putln('} /* exit inner scope */') 6443 return 6444 6445 # must free all local Python references at each exit point 6446 old_loop_labels = tuple(code.new_loop_labels()) 6447 old_error_label = code.new_error_label() 6448 6449 generate_inner_evaluation_code(code) 6450 6451 # normal (non-error) exit 6452 for entry in py_entries: 6453 code.put_var_decref(entry) 6454 6455 # error/loop body exit points 6456 exit_scope = code.new_label('exit_scope') 6457 code.put_goto(exit_scope) 6458 for label, old_label in ([(code.error_label, old_error_label)] + 6459 list(zip(code.get_loop_labels(), old_loop_labels))): 6460 if code.label_used(label): 6461 code.put_label(label) 6462 for entry in py_entries: 6463 code.put_var_decref(entry) 6464 code.put_goto(old_label) 6465 code.put_label(exit_scope) 6466 code.putln('} /* exit inner scope */') 6467 6468 code.set_loop_labels(old_loop_labels) 6469 code.error_label = old_error_label 6470 6471 6472 class ComprehensionNode(ScopedExprNode): 6473 # A list/set/dict comprehension 6474 6475 child_attrs = ["loop"] 6476 6477 is_temp = True 6478 6479 def infer_type(self, env): 6480 return self.type 6481 6482 def analyse_declarations(self, env): 6483 self.append.target = self # this is used in the PyList_Append of the inner loop 6484 self.init_scope(env) 6485 6486 def analyse_scoped_declarations(self, env): 6487 self.loop.analyse_declarations(env) 6488 6489 def analyse_types(self, env): 6490 if not self.has_local_scope: 6491 self.loop = self.loop.analyse_expressions(env) 6492 return self 6493 6494 def analyse_scoped_expressions(self, env): 6495 if self.has_local_scope: 6496 self.loop = self.loop.analyse_expressions(env) 6497 return self 6498 6499 def may_be_none(self): 6500 return False 6501 6502 def generate_result_code(self, code): 6503 self.generate_operation_code(code) 6504 6505 def generate_operation_code(self, code): 6506 if self.type is Builtin.list_type: 6507 create_code = 'PyList_New(0)' 6508 elif self.type is Builtin.set_type: 6509 create_code = 'PySet_New(NULL)' 6510 elif self.type is Builtin.dict_type: 6511 create_code = 'PyDict_New()' 6512 else: 6513 raise InternalError("illegal type for comprehension: %s" % self.type) 6514 code.putln('%s = %s; %s' % ( 6515 self.result(), create_code, 6516 code.error_goto_if_null(self.result(), self.pos))) 6517 6518 code.put_gotref(self.result()) 6519 self.loop.generate_execution_code(code) 6520 6521 def annotate(self, code): 6522 self.loop.annotate(code) 6523 6524 6525 class ComprehensionAppendNode(Node): 6526 # Need to be careful to avoid infinite recursion: 6527 # target must not be in child_attrs/subexprs 6528 6529 child_attrs = ['expr'] 6530 target = None 6531 6532 type = PyrexTypes.c_int_type 6533 6534 def analyse_expressions(self, env): 6535 self.expr = self.expr.analyse_expressions(env) 6536 if not self.expr.type.is_pyobject: 6537 self.expr = self.expr.coerce_to_pyobject(env) 6538 return self 6539 6540 def generate_execution_code(self, code): 6541 if self.target.type is list_type: 6542 code.globalstate.use_utility_code( 6543 UtilityCode.load_cached("ListCompAppend", "Optimize.c")) 6544 function = "__Pyx_ListComp_Append" 6545 elif self.target.type is set_type: 6546 function = "PySet_Add" 6547 else: 6548 raise InternalError( 6549 "Invalid type for comprehension node: %s" % self.target.type) 6550 6551 self.expr.generate_evaluation_code(code) 6552 code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % ( 6553 function, 6554 self.target.result(), 6555 self.expr.result() 6556 ), self.pos)) 6557 self.expr.generate_disposal_code(code) 6558 self.expr.free_temps(code) 6559 6560 def generate_function_definitions(self, env, code): 6561 self.expr.generate_function_definitions(env, code) 6562 6563 def annotate(self, code): 6564 self.expr.annotate(code) 6565 6566 class DictComprehensionAppendNode(ComprehensionAppendNode): 6567 child_attrs = ['key_expr', 'value_expr'] 6568 6569 def analyse_expressions(self, env): 6570 self.key_expr = self.key_expr.analyse_expressions(env) 6571 if not self.key_expr.type.is_pyobject: 6572 self.key_expr = self.key_expr.coerce_to_pyobject(env) 6573 self.value_expr = self.value_expr.analyse_expressions(env) 6574 if not self.value_expr.type.is_pyobject: 6575 self.value_expr = self.value_expr.coerce_to_pyobject(env) 6576 return self 6577 6578 def generate_execution_code(self, code): 6579 self.key_expr.generate_evaluation_code(code) 6580 self.value_expr.generate_evaluation_code(code) 6581 code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % ( 6582 self.target.result(), 6583 self.key_expr.result(), 6584 self.value_expr.result() 6585 ), self.pos)) 6586 self.key_expr.generate_disposal_code(code) 6587 self.key_expr.free_temps(code) 6588 self.value_expr.generate_disposal_code(code) 6589 self.value_expr.free_temps(code) 6590 6591 def generate_function_definitions(self, env, code): 6592 self.key_expr.generate_function_definitions(env, code) 6593 self.value_expr.generate_function_definitions(env, code) 6594 6595 def annotate(self, code): 6596 self.key_expr.annotate(code) 6597 self.value_expr.annotate(code) 6598 6599 6600 class InlinedGeneratorExpressionNode(ScopedExprNode): 6601 # An inlined generator expression for which the result is 6602 # calculated inside of the loop. This will only be created by 6603 # transforms when replacing builtin calls on generator 6604 # expressions. 6605 # 6606 # loop ForStatNode the for-loop, not containing any YieldExprNodes 6607 # result_node ResultRefNode the reference to the result value temp 6608 # orig_func String the name of the builtin function this node replaces 6609 6610 child_attrs = ["loop"] 6611 loop_analysed = False 6612 type = py_object_type 6613 6614 def analyse_scoped_declarations(self, env): 6615 self.loop.analyse_declarations(env) 6616 6617 def may_be_none(self): 6618 return False 6619 6620 def annotate(self, code): 6621 self.loop.annotate(code) 6622 6623 def infer_type(self, env): 6624 return self.result_node.infer_type(env) 6625 6626 def analyse_types(self, env): 6627 if not self.has_local_scope: 6628 self.loop_analysed = True 6629 self.loop = self.loop.analyse_expressions(env) 6630 self.type = self.result_node.type 6631 self.is_temp = True 6632 return self 6633 6634 def analyse_scoped_expressions(self, env): 6635 self.loop_analysed = True 6636 if self.has_local_scope: 6637 self.loop = self.loop.analyse_expressions(env) 6638 return self 6639 6640 def coerce_to(self, dst_type, env): 6641 if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed: 6642 # We can optimise by dropping the aggregation variable and 6643 # the add operations into C. This can only be done safely 6644 # before analysing the loop body, after that, the result 6645 # reference type will have infected expressions and 6646 # assignments. 6647 self.result_node.type = self.type = dst_type 6648 return self 6649 return super(InlinedGeneratorExpressionNode, self).coerce_to(dst_type, env) 6650 6651 def generate_result_code(self, code): 6652 self.result_node.result_code = self.result() 6653 self.loop.generate_execution_code(code) 6654 6655 6656 class SetNode(ExprNode): 6657 # Set constructor. 6658 6659 type = set_type 6660 6661 subexprs = ['args'] 6662 6663 gil_message = "Constructing Python set" 6664 6665 def analyse_types(self, env): 6666 for i in range(len(self.args)): 6667 arg = self.args[i] 6668 arg = arg.analyse_types(env) 6669 self.args[i] = arg.coerce_to_pyobject(env) 6670 self.type = set_type 6671 self.is_temp = 1 6672 return self 6673 6674 def may_be_none(self): 6675 return False 6676 6677 def calculate_constant_result(self): 6678 self.constant_result = set([ 6679 arg.constant_result for arg in self.args]) 6680 6681 def compile_time_value(self, denv): 6682 values = [arg.compile_time_value(denv) for arg in self.args] 6683 try: 6684 return set(values) 6685 except Exception, e: 6686 self.compile_time_value_error(e) 6687 6688 def generate_evaluation_code(self, code): 6689 code.globalstate.use_utility_code(Builtin.py_set_utility_code) 6690 self.allocate_temp_result(code) 6691 code.putln( 6692 "%s = PySet_New(0); %s" % ( 6693 self.result(), 6694 code.error_goto_if_null(self.result(), self.pos))) 6695 code.put_gotref(self.py_result()) 6696 for arg in self.args: 6697 arg.generate_evaluation_code(code) 6698 code.put_error_if_neg( 6699 self.pos, 6700 "PySet_Add(%s, %s)" % (self.result(), arg.py_result())) 6701 arg.generate_disposal_code(code) 6702 arg.free_temps(code) 6703 6704 6705 class DictNode(ExprNode): 6706 # Dictionary constructor. 6707 # 6708 # key_value_pairs [DictItemNode] 6709 # exclude_null_values [boolean] Do not add NULL values to dict 6710 # 6711 # obj_conversion_errors [PyrexError] used internally 6712 6713 subexprs = ['key_value_pairs'] 6714 is_temp = 1 6715 exclude_null_values = False 6716 type = dict_type 6717 6718 obj_conversion_errors = [] 6719 6720 @classmethod 6721 def from_pairs(cls, pos, pairs): 6722 return cls(pos, key_value_pairs=[ 6723 DictItemNode(pos, key=k, value=v) for k, v in pairs]) 6724 6725 def calculate_constant_result(self): 6726 self.constant_result = dict([ 6727 item.constant_result for item in self.key_value_pairs]) 6728 6729 def compile_time_value(self, denv): 6730 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv)) 6731 for item in self.key_value_pairs] 6732 try: 6733 return dict(pairs) 6734 except Exception, e: 6735 self.compile_time_value_error(e) 6736 6737 def type_dependencies(self, env): 6738 return () 6739 6740 def infer_type(self, env): 6741 # TOOD: Infer struct constructors. 6742 return dict_type 6743 6744 def analyse_types(self, env): 6745 hold_errors() 6746 self.key_value_pairs = [ item.analyse_types(env) 6747 for item in self.key_value_pairs ] 6748 self.obj_conversion_errors = held_errors() 6749 release_errors(ignore=True) 6750 return self 6751 6752 def may_be_none(self): 6753 return False 6754 6755 def coerce_to(self, dst_type, env): 6756 if dst_type.is_pyobject: 6757 self.release_errors() 6758 if not self.type.subtype_of(dst_type): 6759 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 6760 elif dst_type.is_struct_or_union: 6761 self.type = dst_type 6762 if not dst_type.is_struct and len(self.key_value_pairs) != 1: 6763 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type) 6764 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries): 6765 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1) 6766 for item in self.key_value_pairs: 6767 if isinstance(item.key, CoerceToPyTypeNode): 6768 item.key = item.key.arg 6769 if not item.key.is_string_literal: 6770 error(item.key.pos, "Invalid struct field identifier") 6771 item.key = StringNode(item.key.pos, value="<error>") 6772 else: 6773 key = str(item.key.value) # converts string literals to unicode in Py3 6774 member = dst_type.scope.lookup_here(key) 6775 if not member: 6776 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key)) 6777 else: 6778 value = item.value 6779 if isinstance(value, CoerceToPyTypeNode): 6780 value = value.arg 6781 item.value = value.coerce_to(member.type, env) 6782 else: 6783 self.type = error_type 6784 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 6785 return self 6786 6787 def release_errors(self): 6788 for err in self.obj_conversion_errors: 6789 report_error(err) 6790 self.obj_conversion_errors = [] 6791 6792 gil_message = "Constructing Python dict" 6793 6794 def generate_evaluation_code(self, code): 6795 # Custom method used here because key-value 6796 # pairs are evaluated and used one at a time. 6797 code.mark_pos(self.pos) 6798 self.allocate_temp_result(code) 6799 if self.type.is_pyobject: 6800 self.release_errors() 6801 code.putln( 6802 "%s = PyDict_New(); %s" % ( 6803 self.result(), 6804 code.error_goto_if_null(self.result(), self.pos))) 6805 code.put_gotref(self.py_result()) 6806 for item in self.key_value_pairs: 6807 item.generate_evaluation_code(code) 6808 if self.type.is_pyobject: 6809 if self.exclude_null_values: 6810 code.putln('if (%s) {' % item.value.py_result()) 6811 code.put_error_if_neg(self.pos, 6812 "PyDict_SetItem(%s, %s, %s)" % ( 6813 self.result(), 6814 item.key.py_result(), 6815 item.value.py_result())) 6816 if self.exclude_null_values: 6817 code.putln('}') 6818 else: 6819 code.putln("%s.%s = %s;" % ( 6820 self.result(), 6821 item.key.value, 6822 item.value.result())) 6823 item.generate_disposal_code(code) 6824 item.free_temps(code) 6825 6826 def annotate(self, code): 6827 for item in self.key_value_pairs: 6828 item.annotate(code) 6829 6830 class DictItemNode(ExprNode): 6831 # Represents a single item in a DictNode 6832 # 6833 # key ExprNode 6834 # value ExprNode 6835 subexprs = ['key', 'value'] 6836 6837 nogil_check = None # Parent DictNode takes care of it 6838 6839 def calculate_constant_result(self): 6840 self.constant_result = ( 6841 self.key.constant_result, self.value.constant_result) 6842 6843 def analyse_types(self, env): 6844 self.key = self.key.analyse_types(env) 6845 self.value = self.value.analyse_types(env) 6846 self.key = self.key.coerce_to_pyobject(env) 6847 self.value = self.value.coerce_to_pyobject(env) 6848 return self 6849 6850 def generate_evaluation_code(self, code): 6851 self.key.generate_evaluation_code(code) 6852 self.value.generate_evaluation_code(code) 6853 6854 def generate_disposal_code(self, code): 6855 self.key.generate_disposal_code(code) 6856 self.value.generate_disposal_code(code) 6857 6858 def free_temps(self, code): 6859 self.key.free_temps(code) 6860 self.value.free_temps(code) 6861 6862 def __iter__(self): 6863 return iter([self.key, self.value]) 6864 6865 6866 class SortedDictKeysNode(ExprNode): 6867 # build sorted list of dict keys, e.g. for dir() 6868 subexprs = ['arg'] 6869 6870 is_temp = True 6871 6872 def __init__(self, arg): 6873 ExprNode.__init__(self, arg.pos, arg=arg) 6874 self.type = Builtin.list_type 6875 6876 def analyse_types(self, env): 6877 arg = self.arg.analyse_types(env) 6878 if arg.type is Builtin.dict_type: 6879 arg = arg.as_none_safe_node( 6880 "'NoneType' object is not iterable") 6881 self.arg = arg 6882 return self 6883 6884 def may_be_none(self): 6885 return False 6886 6887 def generate_result_code(self, code): 6888 dict_result = self.arg.py_result() 6889 if self.arg.type is Builtin.dict_type: 6890 function = 'PyDict_Keys' 6891 else: 6892 function = 'PyMapping_Keys' 6893 code.putln('%s = %s(%s); %s' % ( 6894 self.result(), function, dict_result, 6895 code.error_goto_if_null(self.result(), self.pos))) 6896 code.put_gotref(self.py_result()) 6897 code.put_error_if_neg( 6898 self.pos, 'PyList_Sort(%s)' % self.py_result()) 6899 6900 6901 class ModuleNameMixin(object): 6902 def get_py_mod_name(self, code): 6903 return code.get_py_string_const( 6904 self.module_name, identifier=True) 6905 6906 def get_py_qualified_name(self, code): 6907 return code.get_py_string_const( 6908 self.qualname, identifier=True) 6909 6910 6911 class ClassNode(ExprNode, ModuleNameMixin): 6912 # Helper class used in the implementation of Python 6913 # class definitions. Constructs a class object given 6914 # a name, tuple of bases and class dictionary. 6915 # 6916 # name EncodedString Name of the class 6917 # bases ExprNode Base class tuple 6918 # dict ExprNode Class dict (not owned by this node) 6919 # doc ExprNode or None Doc string 6920 # module_name EncodedString Name of defining module 6921 6922 subexprs = ['bases', 'doc'] 6923 6924 def analyse_types(self, env): 6925 self.bases = self.bases.analyse_types(env) 6926 if self.doc: 6927 self.doc = self.doc.analyse_types(env) 6928 self.doc = self.doc.coerce_to_pyobject(env) 6929 self.type = py_object_type 6930 self.is_temp = 1 6931 env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandling.c")) 6932 return self 6933 6934 def may_be_none(self): 6935 return True 6936 6937 gil_message = "Constructing Python class" 6938 6939 def generate_result_code(self, code): 6940 cname = code.intern_identifier(self.name) 6941 6942 if self.doc: 6943 code.put_error_if_neg(self.pos, 6944 'PyDict_SetItem(%s, %s, %s)' % ( 6945 self.dict.py_result(), 6946 code.intern_identifier( 6947 StringEncoding.EncodedString("__doc__")), 6948 self.doc.py_result())) 6949 py_mod_name = self.get_py_mod_name(code) 6950 qualname = self.get_py_qualified_name(code) 6951 code.putln( 6952 '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % ( 6953 self.result(), 6954 self.bases.py_result(), 6955 self.dict.py_result(), 6956 cname, 6957 qualname, 6958 py_mod_name, 6959 code.error_goto_if_null(self.result(), self.pos))) 6960 code.put_gotref(self.py_result()) 6961 6962 6963 class Py3ClassNode(ExprNode): 6964 # Helper class used in the implementation of Python3+ 6965 # class definitions. Constructs a class object given 6966 # a name, tuple of bases and class dictionary. 6967 # 6968 # name EncodedString Name of the class 6969 # dict ExprNode Class dict (not owned by this node) 6970 # module_name EncodedString Name of defining module 6971 # calculate_metaclass bool should call CalculateMetaclass() 6972 # allow_py2_metaclass bool should look for Py2 metaclass 6973 6974 subexprs = [] 6975 6976 def analyse_types(self, env): 6977 self.type = py_object_type 6978 self.is_temp = 1 6979 return self 6980 6981 def may_be_none(self): 6982 return True 6983 6984 gil_message = "Constructing Python class" 6985 6986 def generate_result_code(self, code): 6987 code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreate", "ObjectHandling.c")) 6988 cname = code.intern_identifier(self.name) 6989 if self.mkw: 6990 mkw = self.mkw.py_result() 6991 else: 6992 mkw = 'NULL' 6993 if self.metaclass: 6994 metaclass = self.metaclass.result() 6995 else: 6996 metaclass = "((PyObject*)&__Pyx_DefaultClassType)" 6997 code.putln( 6998 '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % ( 6999 self.result(), 7000 metaclass, 7001 cname, 7002 self.bases.py_result(), 7003 self.dict.py_result(), 7004 mkw, 7005 self.calculate_metaclass, 7006 self.allow_py2_metaclass, 7007 code.error_goto_if_null(self.result(), self.pos))) 7008 code.put_gotref(self.py_result()) 7009 7010 class KeywordArgsNode(ExprNode): 7011 # Helper class for keyword arguments. 7012 # 7013 # starstar_arg DictNode 7014 # keyword_args [DictItemNode] 7015 7016 subexprs = ['starstar_arg', 'keyword_args'] 7017 is_temp = 1 7018 type = dict_type 7019 7020 def calculate_constant_result(self): 7021 result = dict(self.starstar_arg.constant_result) 7022 for item in self.keyword_args: 7023 key, value = item.constant_result 7024 if key in result: 7025 raise ValueError("duplicate keyword argument found: %s" % key) 7026 result[key] = value 7027 self.constant_result = result 7028 7029 def compile_time_value(self, denv): 7030 result = self.starstar_arg.compile_time_value(denv) 7031 pairs = [ (item.key.compile_time_value(denv), item.value.compile_time_value(denv)) 7032 for item in self.keyword_args ] 7033 try: 7034 result = dict(result) 7035 for key, value in pairs: 7036 if key in result: 7037 raise ValueError("duplicate keyword argument found: %s" % key) 7038 result[key] = value 7039 except Exception, e: 7040 self.compile_time_value_error(e) 7041 return result 7042 7043 def type_dependencies(self, env): 7044 return () 7045 7046 def infer_type(self, env): 7047 return dict_type 7048 7049 def analyse_types(self, env): 7050 arg = self.starstar_arg.analyse_types(env) 7051 arg = arg.coerce_to_pyobject(env) 7052 self.starstar_arg = arg.as_none_safe_node( 7053 # FIXME: CPython's error message starts with the runtime function name 7054 'argument after ** must be a mapping, not NoneType') 7055 self.keyword_args = [ item.analyse_types(env) 7056 for item in self.keyword_args ] 7057 return self 7058 7059 def may_be_none(self): 7060 return False 7061 7062 gil_message = "Constructing Python dict" 7063 7064 def generate_evaluation_code(self, code): 7065 code.mark_pos(self.pos) 7066 self.allocate_temp_result(code) 7067 self.starstar_arg.generate_evaluation_code(code) 7068 if self.starstar_arg.type is not Builtin.dict_type: 7069 # CPython supports calling functions with non-dicts, so do we 7070 code.putln('if (likely(PyDict_Check(%s))) {' % 7071 self.starstar_arg.py_result()) 7072 if self.keyword_args: 7073 code.putln( 7074 "%s = PyDict_Copy(%s); %s" % ( 7075 self.result(), 7076 self.starstar_arg.py_result(), 7077 code.error_goto_if_null(self.result(), self.pos))) 7078 code.put_gotref(self.py_result()) 7079 else: 7080 code.putln("%s = %s;" % ( 7081 self.result(), 7082 self.starstar_arg.py_result())) 7083 code.put_incref(self.result(), py_object_type) 7084 if self.starstar_arg.type is not Builtin.dict_type: 7085 code.putln('} else {') 7086 code.putln( 7087 "%s = PyObject_CallFunctionObjArgs(" 7088 "(PyObject*)&PyDict_Type, %s, NULL); %s" % ( 7089 self.result(), 7090 self.starstar_arg.py_result(), 7091 code.error_goto_if_null(self.result(), self.pos))) 7092 code.put_gotref(self.py_result()) 7093 code.putln('}') 7094 self.starstar_arg.generate_disposal_code(code) 7095 self.starstar_arg.free_temps(code) 7096 7097 if not self.keyword_args: 7098 return 7099 7100 code.globalstate.use_utility_code( 7101 UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c")) 7102 for item in self.keyword_args: 7103 item.generate_evaluation_code(code) 7104 code.putln("if (unlikely(PyDict_GetItem(%s, %s))) {" % ( 7105 self.result(), 7106 item.key.py_result())) 7107 # FIXME: find out function name at runtime! 7108 code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( 7109 item.key.py_result(), 7110 code.error_goto(self.pos))) 7111 code.putln("}") 7112 code.put_error_if_neg(self.pos, 7113 "PyDict_SetItem(%s, %s, %s)" % ( 7114 self.result(), 7115 item.key.py_result(), 7116 item.value.py_result())) 7117 item.generate_disposal_code(code) 7118 item.free_temps(code) 7119 7120 def annotate(self, code): 7121 self.starstar_arg.annotate(code) 7122 for item in self.keyword_args: 7123 item.annotate(code) 7124 7125 class PyClassMetaclassNode(ExprNode): 7126 # Helper class holds Python3 metaclass object 7127 # 7128 # bases ExprNode Base class tuple (not owned by this node) 7129 # mkw ExprNode Class keyword arguments (not owned by this node) 7130 7131 subexprs = [] 7132 7133 def analyse_types(self, env): 7134 self.type = py_object_type 7135 self.is_temp = True 7136 return self 7137 7138 def may_be_none(self): 7139 return True 7140 7141 def generate_result_code(self, code): 7142 if self.mkw: 7143 code.globalstate.use_utility_code( 7144 UtilityCode.load_cached("Py3MetaclassGet", "ObjectHandling.c")) 7145 call = "__Pyx_Py3MetaclassGet(%s, %s)" % ( 7146 self.bases.result(), 7147 self.mkw.result()) 7148 else: 7149 code.globalstate.use_utility_code( 7150 UtilityCode.load_cached("CalculateMetaclass", "ObjectHandling.c")) 7151 call = "__Pyx_CalculateMetaclass(NULL, %s)" % ( 7152 self.bases.result()) 7153 code.putln( 7154 "%s = %s; %s" % ( 7155 self.result(), call, 7156 code.error_goto_if_null(self.result(), self.pos))) 7157 code.put_gotref(self.py_result()) 7158 7159 class PyClassNamespaceNode(ExprNode, ModuleNameMixin): 7160 # Helper class holds Python3 namespace object 7161 # 7162 # All this are not owned by this node 7163 # metaclass ExprNode Metaclass object 7164 # bases ExprNode Base class tuple 7165 # mkw ExprNode Class keyword arguments 7166 # doc ExprNode or None Doc string (owned) 7167 7168 subexprs = ['doc'] 7169 7170 def analyse_types(self, env): 7171 if self.doc: 7172 self.doc = self.doc.analyse_types(env) 7173 self.doc = self.doc.coerce_to_pyobject(env) 7174 self.type = py_object_type 7175 self.is_temp = 1 7176 return self 7177 7178 def may_be_none(self): 7179 return True 7180 7181 def generate_result_code(self, code): 7182 cname = code.intern_identifier(self.name) 7183 py_mod_name = self.get_py_mod_name(code) 7184 qualname = self.get_py_qualified_name(code) 7185 if self.doc: 7186 doc_code = self.doc.result() 7187 else: 7188 doc_code = '(PyObject *) NULL' 7189 if self.mkw: 7190 mkw = self.mkw.py_result() 7191 else: 7192 mkw = '(PyObject *) NULL' 7193 if self.metaclass: 7194 metaclass = self.metaclass.result() 7195 else: 7196 metaclass = "(PyObject *) NULL" 7197 code.putln( 7198 "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % ( 7199 self.result(), 7200 metaclass, 7201 self.bases.result(), 7202 cname, 7203 qualname, 7204 mkw, 7205 py_mod_name, 7206 doc_code, 7207 code.error_goto_if_null(self.result(), self.pos))) 7208 code.put_gotref(self.py_result()) 7209 7210 7211 class ClassCellInjectorNode(ExprNode): 7212 # Initialize CyFunction.func_classobj 7213 is_temp = True 7214 type = py_object_type 7215 subexprs = [] 7216 is_active = False 7217 7218 def analyse_expressions(self, env): 7219 if self.is_active: 7220 env.use_utility_code( 7221 UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c")) 7222 return self 7223 7224 def generate_evaluation_code(self, code): 7225 if self.is_active: 7226 self.allocate_temp_result(code) 7227 code.putln( 7228 '%s = PyList_New(0); %s' % ( 7229 self.result(), 7230 code.error_goto_if_null(self.result(), self.pos))) 7231 code.put_gotref(self.result()) 7232 7233 def generate_injection_code(self, code, classobj_cname): 7234 if self.is_active: 7235 code.putln('__Pyx_CyFunction_InitClassCell(%s, %s);' % ( 7236 self.result(), classobj_cname)) 7237 7238 7239 class ClassCellNode(ExprNode): 7240 # Class Cell for noargs super() 7241 subexprs = [] 7242 is_temp = True 7243 is_generator = False 7244 type = py_object_type 7245 7246 def analyse_types(self, env): 7247 return self 7248 7249 def generate_result_code(self, code): 7250 if not self.is_generator: 7251 code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % ( 7252 self.result(), 7253 Naming.self_cname)) 7254 else: 7255 code.putln('%s = %s->classobj;' % ( 7256 self.result(), Naming.generator_cname)) 7257 code.putln( 7258 'if (!%s) { PyErr_SetString(PyExc_SystemError, ' 7259 '"super(): empty __class__ cell"); %s }' % ( 7260 self.result(), 7261 code.error_goto(self.pos))) 7262 code.put_incref(self.result(), py_object_type) 7263 7264 7265 class BoundMethodNode(ExprNode): 7266 # Helper class used in the implementation of Python 7267 # class definitions. Constructs an bound method 7268 # object from a class and a function. 7269 # 7270 # function ExprNode Function object 7271 # self_object ExprNode self object 7272 7273 subexprs = ['function'] 7274 7275 def analyse_types(self, env): 7276 self.function = self.function.analyse_types(env) 7277 self.type = py_object_type 7278 self.is_temp = 1 7279 return self 7280 7281 gil_message = "Constructing a bound method" 7282 7283 def generate_result_code(self, code): 7284 code.putln( 7285 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % ( 7286 self.result(), 7287 self.function.py_result(), 7288 self.self_object.py_result(), 7289 self.self_object.py_result(), 7290 code.error_goto_if_null(self.result(), self.pos))) 7291 code.put_gotref(self.py_result()) 7292 7293 class UnboundMethodNode(ExprNode): 7294 # Helper class used in the implementation of Python 7295 # class definitions. Constructs an unbound method 7296 # object from a class and a function. 7297 # 7298 # function ExprNode Function object 7299 7300 type = py_object_type 7301 is_temp = 1 7302 7303 subexprs = ['function'] 7304 7305 def analyse_types(self, env): 7306 self.function = self.function.analyse_types(env) 7307 return self 7308 7309 def may_be_none(self): 7310 return False 7311 7312 gil_message = "Constructing an unbound method" 7313 7314 def generate_result_code(self, code): 7315 class_cname = code.pyclass_stack[-1].classobj.result() 7316 code.putln( 7317 "%s = PyMethod_New(%s, 0, %s); %s" % ( 7318 self.result(), 7319 self.function.py_result(), 7320 class_cname, 7321 code.error_goto_if_null(self.result(), self.pos))) 7322 code.put_gotref(self.py_result()) 7323 7324 7325 class PyCFunctionNode(ExprNode, ModuleNameMixin): 7326 # Helper class used in the implementation of Python 7327 # functions. Constructs a PyCFunction object 7328 # from a PyMethodDef struct. 7329 # 7330 # pymethdef_cname string PyMethodDef structure 7331 # self_object ExprNode or None 7332 # binding bool 7333 # def_node DefNode the Python function node 7334 # module_name EncodedString Name of defining module 7335 # code_object CodeObjectNode the PyCodeObject creator node 7336 7337 subexprs = ['code_object', 'defaults_tuple', 'defaults_kwdict', 7338 'annotations_dict'] 7339 7340 self_object = None 7341 code_object = None 7342 binding = False 7343 def_node = None 7344 defaults = None 7345 defaults_struct = None 7346 defaults_pyobjects = 0 7347 defaults_tuple = None 7348 defaults_kwdict = None 7349 annotations_dict = None 7350 7351 type = py_object_type 7352 is_temp = 1 7353 7354 specialized_cpdefs = None 7355 is_specialization = False 7356 7357 @classmethod 7358 def from_defnode(cls, node, binding): 7359 return cls(node.pos, 7360 def_node=node, 7361 pymethdef_cname=node.entry.pymethdef_cname, 7362 binding=binding or node.specialized_cpdefs, 7363 specialized_cpdefs=node.specialized_cpdefs, 7364 code_object=CodeObjectNode(node)) 7365 7366 def analyse_types(self, env): 7367 if self.binding: 7368 self.analyse_default_args(env) 7369 return self 7370 7371 def analyse_default_args(self, env): 7372 """ 7373 Handle non-literal function's default arguments. 7374 """ 7375 nonliteral_objects = [] 7376 nonliteral_other = [] 7377 default_args = [] 7378 default_kwargs = [] 7379 annotations = [] 7380 for arg in self.def_node.args: 7381 if arg.default: 7382 if not arg.default.is_literal: 7383 arg.is_dynamic = True 7384 if arg.type.is_pyobject: 7385 nonliteral_objects.append(arg) 7386 else: 7387 nonliteral_other.append(arg) 7388 else: 7389 arg.default = DefaultLiteralArgNode(arg.pos, arg.default) 7390 if arg.kw_only: 7391 default_kwargs.append(arg) 7392 else: 7393 default_args.append(arg) 7394 if arg.annotation: 7395 arg.annotation = arg.annotation.analyse_types(env) 7396 if not arg.annotation.type.is_pyobject: 7397 arg.annotation = arg.annotation.coerce_to_pyobject(env) 7398 annotations.append((arg.pos, arg.name, arg.annotation)) 7399 if self.def_node.return_type_annotation: 7400 annotations.append((self.def_node.return_type_annotation.pos, 7401 StringEncoding.EncodedString("return"), 7402 self.def_node.return_type_annotation)) 7403 7404 if nonliteral_objects or nonliteral_other: 7405 module_scope = env.global_scope() 7406 cname = module_scope.next_id(Naming.defaults_struct_prefix) 7407 scope = Symtab.StructOrUnionScope(cname) 7408 self.defaults = [] 7409 for arg in nonliteral_objects: 7410 entry = scope.declare_var(arg.name, arg.type, None, 7411 Naming.arg_prefix + arg.name, 7412 allow_pyobject=True) 7413 self.defaults.append((arg, entry)) 7414 for arg in nonliteral_other: 7415 entry = scope.declare_var(arg.name, arg.type, None, 7416 Naming.arg_prefix + arg.name, 7417 allow_pyobject=False) 7418 self.defaults.append((arg, entry)) 7419 entry = module_scope.declare_struct_or_union( 7420 None, 'struct', scope, 1, None, cname=cname) 7421 self.defaults_struct = scope 7422 self.defaults_pyobjects = len(nonliteral_objects) 7423 for arg, entry in self.defaults: 7424 arg.default_value = '%s->%s' % ( 7425 Naming.dynamic_args_cname, entry.cname) 7426 self.def_node.defaults_struct = self.defaults_struct.name 7427 7428 if default_args or default_kwargs: 7429 if self.defaults_struct is None: 7430 if default_args: 7431 defaults_tuple = TupleNode(self.pos, args=[ 7432 arg.default for arg in default_args]) 7433 self.defaults_tuple = defaults_tuple.analyse_types(env) 7434 if default_kwargs: 7435 defaults_kwdict = DictNode(self.pos, key_value_pairs=[ 7436 DictItemNode( 7437 arg.pos, 7438 key=IdentifierStringNode(arg.pos, value=arg.name), 7439 value=arg.default) 7440 for arg in default_kwargs]) 7441 self.defaults_kwdict = defaults_kwdict.analyse_types(env) 7442 else: 7443 if default_args: 7444 defaults_tuple = DefaultsTupleNode( 7445 self.pos, default_args, self.defaults_struct) 7446 else: 7447 defaults_tuple = NoneNode(self.pos) 7448 if default_kwargs: 7449 defaults_kwdict = DefaultsKwDictNode( 7450 self.pos, default_kwargs, self.defaults_struct) 7451 else: 7452 defaults_kwdict = NoneNode(self.pos) 7453 7454 defaults_getter = Nodes.DefNode( 7455 self.pos, args=[], star_arg=None, starstar_arg=None, 7456 body=Nodes.ReturnStatNode( 7457 self.pos, return_type=py_object_type, 7458 value=TupleNode( 7459 self.pos, args=[defaults_tuple, defaults_kwdict])), 7460 decorators=None, 7461 name=StringEncoding.EncodedString("__defaults__")) 7462 defaults_getter.analyse_declarations(env) 7463 defaults_getter = defaults_getter.analyse_expressions(env) 7464 defaults_getter.body = defaults_getter.body.analyse_expressions( 7465 defaults_getter.local_scope) 7466 defaults_getter.py_wrapper_required = False 7467 defaults_getter.pymethdef_required = False 7468 self.def_node.defaults_getter = defaults_getter 7469 if annotations: 7470 annotations_dict = DictNode(self.pos, key_value_pairs=[ 7471 DictItemNode( 7472 pos, key=IdentifierStringNode(pos, value=name), 7473 value=value) 7474 for pos, name, value in annotations]) 7475 self.annotations_dict = annotations_dict.analyse_types(env) 7476 7477 def may_be_none(self): 7478 return False 7479 7480 gil_message = "Constructing Python function" 7481 7482 def self_result_code(self): 7483 if self.self_object is None: 7484 self_result = "NULL" 7485 else: 7486 self_result = self.self_object.py_result() 7487 return self_result 7488 7489 def generate_result_code(self, code): 7490 if self.binding: 7491 self.generate_cyfunction_code(code) 7492 else: 7493 self.generate_pycfunction_code(code) 7494 7495 def generate_pycfunction_code(self, code): 7496 py_mod_name = self.get_py_mod_name(code) 7497 code.putln( 7498 '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % ( 7499 self.result(), 7500 self.pymethdef_cname, 7501 self.self_result_code(), 7502 py_mod_name, 7503 code.error_goto_if_null(self.result(), self.pos))) 7504 7505 code.put_gotref(self.py_result()) 7506 7507 def generate_cyfunction_code(self, code): 7508 if self.specialized_cpdefs: 7509 def_node = self.specialized_cpdefs[0] 7510 else: 7511 def_node = self.def_node 7512 7513 if self.specialized_cpdefs or self.is_specialization: 7514 code.globalstate.use_utility_code( 7515 UtilityCode.load_cached("FusedFunction", "CythonFunction.c")) 7516 constructor = "__pyx_FusedFunction_NewEx" 7517 else: 7518 code.globalstate.use_utility_code( 7519 UtilityCode.load_cached("CythonFunction", "CythonFunction.c")) 7520 constructor = "__Pyx_CyFunction_NewEx" 7521 7522 if self.code_object: 7523 code_object_result = self.code_object.py_result() 7524 else: 7525 code_object_result = 'NULL' 7526 7527 flags = [] 7528 if def_node.is_staticmethod: 7529 flags.append('__Pyx_CYFUNCTION_STATICMETHOD') 7530 elif def_node.is_classmethod: 7531 flags.append('__Pyx_CYFUNCTION_CLASSMETHOD') 7532 7533 if def_node.local_scope.parent_scope.is_c_class_scope: 7534 flags.append('__Pyx_CYFUNCTION_CCLASS') 7535 7536 if flags: 7537 flags = ' | '.join(flags) 7538 else: 7539 flags = '0' 7540 7541 code.putln( 7542 '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % ( 7543 self.result(), 7544 constructor, 7545 self.pymethdef_cname, 7546 flags, 7547 self.get_py_qualified_name(code), 7548 self.self_result_code(), 7549 self.get_py_mod_name(code), 7550 "PyModule_GetDict(%s)" % Naming.module_cname, 7551 code_object_result, 7552 code.error_goto_if_null(self.result(), self.pos))) 7553 7554 code.put_gotref(self.py_result()) 7555 7556 if def_node.requires_classobj: 7557 assert code.pyclass_stack, "pyclass_stack is empty" 7558 class_node = code.pyclass_stack[-1] 7559 code.put_incref(self.py_result(), py_object_type) 7560 code.putln( 7561 'PyList_Append(%s, %s);' % ( 7562 class_node.class_cell.result(), 7563 self.result())) 7564 code.put_giveref(self.py_result()) 7565 7566 if self.defaults: 7567 code.putln( 7568 'if (!__Pyx_CyFunction_InitDefaults(%s, sizeof(%s), %d)) %s' % ( 7569 self.result(), self.defaults_struct.name, 7570 self.defaults_pyobjects, code.error_goto(self.pos))) 7571 defaults = '__Pyx_CyFunction_Defaults(%s, %s)' % ( 7572 self.defaults_struct.name, self.result()) 7573 for arg, entry in self.defaults: 7574 arg.generate_assignment_code(code, target='%s->%s' % ( 7575 defaults, entry.cname)) 7576 7577 if self.defaults_tuple: 7578 code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % ( 7579 self.result(), self.defaults_tuple.py_result())) 7580 if self.defaults_kwdict: 7581 code.putln('__Pyx_CyFunction_SetDefaultsKwDict(%s, %s);' % ( 7582 self.result(), self.defaults_kwdict.py_result())) 7583 if def_node.defaults_getter: 7584 code.putln('__Pyx_CyFunction_SetDefaultsGetter(%s, %s);' % ( 7585 self.result(), def_node.defaults_getter.entry.pyfunc_cname)) 7586 if self.annotations_dict: 7587 code.putln('__Pyx_CyFunction_SetAnnotationsDict(%s, %s);' % ( 7588 self.result(), self.annotations_dict.py_result())) 7589 7590 7591 class InnerFunctionNode(PyCFunctionNode): 7592 # Special PyCFunctionNode that depends on a closure class 7593 # 7594 7595 binding = True 7596 needs_self_code = True 7597 7598 def self_result_code(self): 7599 if self.needs_self_code: 7600 return "((PyObject*)%s)" % Naming.cur_scope_cname 7601 return "NULL" 7602 7603 7604 class CodeObjectNode(ExprNode): 7605 # Create a PyCodeObject for a CyFunction instance. 7606 # 7607 # def_node DefNode the Python function node 7608 # varnames TupleNode a tuple with all local variable names 7609 7610 subexprs = ['varnames'] 7611 is_temp = False 7612 7613 def __init__(self, def_node): 7614 ExprNode.__init__(self, def_node.pos, def_node=def_node) 7615 args = list(def_node.args) 7616 # if we have args/kwargs, then the first two in var_entries are those 7617 local_vars = [arg for arg in def_node.local_scope.var_entries if arg.name] 7618 self.varnames = TupleNode( 7619 def_node.pos, 7620 args=[IdentifierStringNode(arg.pos, value=arg.name) 7621 for arg in args + local_vars], 7622 is_temp=0, 7623 is_literal=1) 7624 7625 def may_be_none(self): 7626 return False 7627 7628 def calculate_result_code(self): 7629 return self.result_code 7630 7631 def generate_result_code(self, code): 7632 self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) 7633 7634 code = code.get_cached_constants_writer() 7635 code.mark_pos(self.pos) 7636 func = self.def_node 7637 func_name = code.get_py_string_const( 7638 func.name, identifier=True, is_str=False, unicode_value=func.name) 7639 # FIXME: better way to get the module file path at module init time? Encoding to use? 7640 file_path = StringEncoding.BytesLiteral(func.pos[0].get_filenametable_entry().encode('utf8')) 7641 file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True) 7642 7643 flags = [] 7644 if self.def_node.star_arg: 7645 flags.append('CO_VARARGS') 7646 if self.def_node.starstar_arg: 7647 flags.append('CO_VARKEYWORDS') 7648 7649 code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % ( 7650 self.result_code, 7651 len(func.args) - func.num_kwonly_args, # argcount 7652 func.num_kwonly_args, # kwonlyargcount (Py3 only) 7653 len(self.varnames.args), # nlocals 7654 '|'.join(flags) or '0', # flags 7655 Naming.empty_bytes, # code 7656 Naming.empty_tuple, # consts 7657 Naming.empty_tuple, # names (FIXME) 7658 self.varnames.result(), # varnames 7659 Naming.empty_tuple, # freevars (FIXME) 7660 Naming.empty_tuple, # cellvars (FIXME) 7661 file_path_const, # filename 7662 func_name, # name 7663 self.pos[1], # firstlineno 7664 Naming.empty_bytes, # lnotab 7665 code.error_goto_if_null(self.result_code, self.pos), 7666 )) 7667 7668 7669 class DefaultLiteralArgNode(ExprNode): 7670 # CyFunction's literal argument default value 7671 # 7672 # Evaluate literal only once. 7673 7674 subexprs = [] 7675 is_literal = True 7676 is_temp = False 7677 7678 def __init__(self, pos, arg): 7679 super(DefaultLiteralArgNode, self).__init__(pos) 7680 self.arg = arg 7681 self.type = self.arg.type 7682 self.evaluated = False 7683 7684 def analyse_types(self, env): 7685 return self 7686 7687 def generate_result_code(self, code): 7688 pass 7689 7690 def generate_evaluation_code(self, code): 7691 if not self.evaluated: 7692 self.arg.generate_evaluation_code(code) 7693 self.evaluated = True 7694 7695 def result(self): 7696 return self.type.cast_code(self.arg.result()) 7697 7698 7699 class DefaultNonLiteralArgNode(ExprNode): 7700 # CyFunction's non-literal argument default value 7701 7702 subexprs = [] 7703 7704 def __init__(self, pos, arg, defaults_struct): 7705 super(DefaultNonLiteralArgNode, self).__init__(pos) 7706 self.arg = arg 7707 self.defaults_struct = defaults_struct 7708 7709 def analyse_types(self, env): 7710 self.type = self.arg.type 7711 self.is_temp = False 7712 return self 7713 7714 def generate_result_code(self, code): 7715 pass 7716 7717 def result(self): 7718 return '__Pyx_CyFunction_Defaults(%s, %s)->%s' % ( 7719 self.defaults_struct.name, Naming.self_cname, 7720 self.defaults_struct.lookup(self.arg.name).cname) 7721 7722 7723 class DefaultsTupleNode(TupleNode): 7724 # CyFunction's __defaults__ tuple 7725 7726 def __init__(self, pos, defaults, defaults_struct): 7727 args = [] 7728 for arg in defaults: 7729 if not arg.default.is_literal: 7730 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) 7731 else: 7732 arg = arg.default 7733 args.append(arg) 7734 super(DefaultsTupleNode, self).__init__(pos, args=args) 7735 7736 7737 class DefaultsKwDictNode(DictNode): 7738 # CyFunction's __kwdefaults__ dict 7739 7740 def __init__(self, pos, defaults, defaults_struct): 7741 items = [] 7742 for arg in defaults: 7743 name = IdentifierStringNode(arg.pos, value=arg.name) 7744 if not arg.default.is_literal: 7745 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) 7746 else: 7747 arg = arg.default 7748 items.append(DictItemNode(arg.pos, key=name, value=arg)) 7749 super(DefaultsKwDictNode, self).__init__(pos, key_value_pairs=items) 7750 7751 7752 class LambdaNode(InnerFunctionNode): 7753 # Lambda expression node (only used as a function reference) 7754 # 7755 # args [CArgDeclNode] formal arguments 7756 # star_arg PyArgDeclNode or None * argument 7757 # starstar_arg PyArgDeclNode or None ** argument 7758 # lambda_name string a module-globally unique lambda name 7759 # result_expr ExprNode 7760 # def_node DefNode the underlying function 'def' node 7761 7762 child_attrs = ['def_node'] 7763 7764 name = StringEncoding.EncodedString('<lambda>') 7765 7766 def analyse_declarations(self, env): 7767 self.def_node.no_assignment_synthesis = True 7768 self.def_node.pymethdef_required = True 7769 self.def_node.analyse_declarations(env) 7770 self.def_node.is_cyfunction = True 7771 self.pymethdef_cname = self.def_node.entry.pymethdef_cname 7772 env.add_lambda_def(self.def_node) 7773 7774 def analyse_types(self, env): 7775 self.def_node = self.def_node.analyse_expressions(env) 7776 return super(LambdaNode, self).analyse_types(env) 7777 7778 def generate_result_code(self, code): 7779 self.def_node.generate_execution_code(code) 7780 super(LambdaNode, self).generate_result_code(code) 7781 7782 7783 class GeneratorExpressionNode(LambdaNode): 7784 # A generator expression, e.g. (i for i in range(10)) 7785 # 7786 # Result is a generator. 7787 # 7788 # loop ForStatNode the for-loop, containing a YieldExprNode 7789 # def_node DefNode the underlying generator 'def' node 7790 7791 name = StringEncoding.EncodedString('genexpr') 7792 binding = False 7793 7794 def analyse_declarations(self, env): 7795 super(GeneratorExpressionNode, self).analyse_declarations(env) 7796 # No pymethdef required 7797 self.def_node.pymethdef_required = False 7798 self.def_node.py_wrapper_required = False 7799 self.def_node.is_cyfunction = False 7800 # Force genexpr signature 7801 self.def_node.entry.signature = TypeSlots.pyfunction_noargs 7802 7803 def generate_result_code(self, code): 7804 code.putln( 7805 '%s = %s(%s); %s' % ( 7806 self.result(), 7807 self.def_node.entry.pyfunc_cname, 7808 self.self_result_code(), 7809 code.error_goto_if_null(self.result(), self.pos))) 7810 code.put_gotref(self.py_result()) 7811 7812 7813 class YieldExprNode(ExprNode): 7814 # Yield expression node 7815 # 7816 # arg ExprNode the value to return from the generator 7817 # label_num integer yield label number 7818 # is_yield_from boolean is a YieldFromExprNode to delegate to another generator 7819 7820 subexprs = ['arg'] 7821 type = py_object_type 7822 label_num = 0 7823 is_yield_from = False 7824 7825 def analyse_types(self, env): 7826 if not self.label_num: 7827 error(self.pos, "'yield' not supported here") 7828 self.is_temp = 1 7829 if self.arg is not None: 7830 self.arg = self.arg.analyse_types(env) 7831 if not self.arg.type.is_pyobject: 7832 self.coerce_yield_argument(env) 7833 return self 7834 7835 def coerce_yield_argument(self, env): 7836 self.arg = self.arg.coerce_to_pyobject(env) 7837 7838 def generate_evaluation_code(self, code): 7839 if self.arg: 7840 self.arg.generate_evaluation_code(code) 7841 self.arg.make_owned_reference(code) 7842 code.putln( 7843 "%s = %s;" % ( 7844 Naming.retval_cname, 7845 self.arg.result_as(py_object_type))) 7846 self.arg.generate_post_assignment_code(code) 7847 self.arg.free_temps(code) 7848 else: 7849 code.put_init_to_py_none(Naming.retval_cname, py_object_type) 7850 self.generate_yield_code(code) 7851 7852 def generate_yield_code(self, code): 7853 """ 7854 Generate the code to return the argument in 'Naming.retval_cname' 7855 and to continue at the yield label. 7856 """ 7857 label_num, label_name = code.new_yield_label() 7858 code.use_label(label_name) 7859 7860 saved = [] 7861 code.funcstate.closure_temps.reset() 7862 for cname, type, manage_ref in code.funcstate.temps_in_use(): 7863 save_cname = code.funcstate.closure_temps.allocate_temp(type) 7864 saved.append((cname, save_cname, type)) 7865 if type.is_pyobject: 7866 code.put_xgiveref(cname) 7867 code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cname)) 7868 7869 code.put_xgiveref(Naming.retval_cname) 7870 code.put_finish_refcount_context() 7871 code.putln("/* return from generator, yielding value */") 7872 code.putln("%s->resume_label = %d;" % ( 7873 Naming.generator_cname, label_num)) 7874 code.putln("return %s;" % Naming.retval_cname) 7875 7876 code.put_label(label_name) 7877 for cname, save_cname, type in saved: 7878 code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname)) 7879 if type.is_pyobject: 7880 code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname)) 7881 code.put_xgotref(cname) 7882 code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos)) 7883 if self.result_is_used: 7884 self.allocate_temp_result(code) 7885 code.put('%s = %s; ' % (self.result(), Naming.sent_value_cname)) 7886 code.put_incref(self.result(), py_object_type) 7887 7888 7889 class YieldFromExprNode(YieldExprNode): 7890 # "yield from GEN" expression 7891 is_yield_from = True 7892 7893 def coerce_yield_argument(self, env): 7894 if not self.arg.type.is_string: 7895 # FIXME: support C arrays and C++ iterators? 7896 error(self.pos, "yielding from non-Python object not supported") 7897 self.arg = self.arg.coerce_to_pyobject(env) 7898 7899 def generate_evaluation_code(self, code): 7900 code.globalstate.use_utility_code(UtilityCode.load_cached("YieldFrom", "Generator.c")) 7901 7902 self.arg.generate_evaluation_code(code) 7903 code.putln("%s = __Pyx_Generator_Yield_From(%s, %s);" % ( 7904 Naming.retval_cname, 7905 Naming.generator_cname, 7906 self.arg.result_as(py_object_type))) 7907 self.arg.generate_disposal_code(code) 7908 self.arg.free_temps(code) 7909 code.put_xgotref(Naming.retval_cname) 7910 7911 code.putln("if (likely(%s)) {" % Naming.retval_cname) 7912 self.generate_yield_code(code) 7913 code.putln("} else {") 7914 # either error or sub-generator has normally terminated: return value => node result 7915 if self.result_is_used: 7916 # YieldExprNode has allocated the result temp for us 7917 code.putln("%s = NULL;" % self.result()) 7918 code.putln("if (unlikely(__Pyx_PyGen_FetchStopIterationValue(&%s) < 0)) %s" % ( 7919 self.result(), 7920 code.error_goto(self.pos))) 7921 code.put_gotref(self.result()) 7922 else: 7923 code.putln("PyObject* exc_type = PyErr_Occurred();") 7924 code.putln("if (exc_type) {") 7925 code.putln("if (likely(exc_type == PyExc_StopIteration ||" 7926 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();") 7927 code.putln("else %s" % code.error_goto(self.pos)) 7928 code.putln("}") 7929 code.putln("}") 7930 7931 class GlobalsExprNode(AtomicExprNode): 7932 type = dict_type 7933 is_temp = 1 7934 7935 def analyse_types(self, env): 7936 env.use_utility_code(Builtin.globals_utility_code) 7937 return self 7938 7939 gil_message = "Constructing globals dict" 7940 7941 def may_be_none(self): 7942 return False 7943 7944 def generate_result_code(self, code): 7945 code.putln('%s = __Pyx_Globals(); %s' % ( 7946 self.result(), 7947 code.error_goto_if_null(self.result(), self.pos))) 7948 code.put_gotref(self.result()) 7949 7950 7951 class LocalsDictItemNode(DictItemNode): 7952 def analyse_types(self, env): 7953 self.key = self.key.analyse_types(env) 7954 self.value = self.value.analyse_types(env) 7955 self.key = self.key.coerce_to_pyobject(env) 7956 if self.value.type.can_coerce_to_pyobject(env): 7957 self.value = self.value.coerce_to_pyobject(env) 7958 else: 7959 self.value = None 7960 return self 7961 7962 7963 class FuncLocalsExprNode(DictNode): 7964 def __init__(self, pos, env): 7965 local_vars = sorted([ 7966 entry.name for entry in env.entries.values() if entry.name]) 7967 items = [LocalsDictItemNode( 7968 pos, key=IdentifierStringNode(pos, value=var), 7969 value=NameNode(pos, name=var, allow_null=True)) 7970 for var in local_vars] 7971 DictNode.__init__(self, pos, key_value_pairs=items, 7972 exclude_null_values=True) 7973 7974 def analyse_types(self, env): 7975 node = super(FuncLocalsExprNode, self).analyse_types(env) 7976 node.key_value_pairs = [ i for i in node.key_value_pairs 7977 if i.value is not None ] 7978 return node 7979 7980 7981 class PyClassLocalsExprNode(AtomicExprNode): 7982 def __init__(self, pos, pyclass_dict): 7983 AtomicExprNode.__init__(self, pos) 7984 self.pyclass_dict = pyclass_dict 7985 7986 def analyse_types(self, env): 7987 self.type = self.pyclass_dict.type 7988 self.is_temp = False 7989 return self 7990 7991 def may_be_none(self): 7992 return False 7993 7994 def result(self): 7995 return self.pyclass_dict.result() 7996 7997 def generate_result_code(self, code): 7998 pass 7999 8000 8001 def LocalsExprNode(pos, scope_node, env): 8002 if env.is_module_scope: 8003 return GlobalsExprNode(pos) 8004 if env.is_py_class_scope: 8005 return PyClassLocalsExprNode(pos, scope_node.dict) 8006 return FuncLocalsExprNode(pos, env) 8007 8008 8009 #------------------------------------------------------------------- 8010 # 8011 # Unary operator nodes 8012 # 8013 #------------------------------------------------------------------- 8014 8015 compile_time_unary_operators = { 8016 'not': operator.not_, 8017 '~': operator.inv, 8018 '-': operator.neg, 8019 '+': operator.pos, 8020 } 8021 8022 class UnopNode(ExprNode): 8023 # operator string 8024 # operand ExprNode 8025 # 8026 # Processing during analyse_expressions phase: 8027 # 8028 # analyse_c_operation 8029 # Called when the operand is not a pyobject. 8030 # - Check operand type and coerce if needed. 8031 # - Determine result type and result code fragment. 8032 # - Allocate temporary for result if needed. 8033 8034 subexprs = ['operand'] 8035 infix = True 8036 8037 def calculate_constant_result(self): 8038 func = compile_time_unary_operators[self.operator] 8039 self.constant_result = func(self.operand.constant_result) 8040 8041 def compile_time_value(self, denv): 8042 func = compile_time_unary_operators.get(self.operator) 8043 if not func: 8044 error(self.pos, 8045 "Unary '%s' not supported in compile-time expression" 8046 % self.operator) 8047 operand = self.operand.compile_time_value(denv) 8048 try: 8049 return func(operand) 8050 except Exception, e: 8051 self.compile_time_value_error(e) 8052 8053 def infer_type(self, env): 8054 operand_type = self.operand.infer_type(env) 8055 if operand_type.is_cpp_class or operand_type.is_ptr: 8056 cpp_type = operand_type.find_cpp_operation_type(self.operator) 8057 if cpp_type is not None: 8058 return cpp_type 8059 return self.infer_unop_type(env, operand_type) 8060 8061 def infer_unop_type(self, env, operand_type): 8062 if operand_type.is_pyobject: 8063 return py_object_type 8064 else: 8065 return operand_type 8066 8067 def may_be_none(self): 8068 if self.operand.type and self.operand.type.is_builtin_type: 8069 if self.operand.type is not type_type: 8070 return False 8071 return ExprNode.may_be_none(self) 8072 8073 def analyse_types(self, env): 8074 self.operand = self.operand.analyse_types(env) 8075 if self.is_py_operation(): 8076 self.coerce_operand_to_pyobject(env) 8077 self.type = py_object_type 8078 self.is_temp = 1 8079 elif self.is_cpp_operation(): 8080 self.analyse_cpp_operation(env) 8081 else: 8082 self.analyse_c_operation(env) 8083 return self 8084 8085 def check_const(self): 8086 return self.operand.check_const() 8087 8088 def is_py_operation(self): 8089 return self.operand.type.is_pyobject 8090 8091 def nogil_check(self, env): 8092 if self.is_py_operation(): 8093 self.gil_error() 8094 8095 def is_cpp_operation(self): 8096 type = self.operand.type 8097 return type.is_cpp_class 8098 8099 def coerce_operand_to_pyobject(self, env): 8100 self.operand = self.operand.coerce_to_pyobject(env) 8101 8102 def generate_result_code(self, code): 8103 if self.operand.type.is_pyobject: 8104 self.generate_py_operation_code(code) 8105 8106 def generate_py_operation_code(self, code): 8107 function = self.py_operation_function() 8108 code.putln( 8109 "%s = %s(%s); %s" % ( 8110 self.result(), 8111 function, 8112 self.operand.py_result(), 8113 code.error_goto_if_null(self.result(), self.pos))) 8114 code.put_gotref(self.py_result()) 8115 8116 def type_error(self): 8117 if not self.operand.type.is_error: 8118 error(self.pos, "Invalid operand type for '%s' (%s)" % 8119 (self.operator, self.operand.type)) 8120 self.type = PyrexTypes.error_type 8121 8122 def analyse_cpp_operation(self, env): 8123 cpp_type = self.operand.type.find_cpp_operation_type(self.operator) 8124 if cpp_type is None: 8125 error(self.pos, "'%s' operator not defined for %s" % ( 8126 self.operator, type)) 8127 self.type_error() 8128 return 8129 self.type = cpp_type 8130 8131 8132 class NotNode(UnopNode): 8133 # 'not' operator 8134 # 8135 # operand ExprNode 8136 operator = '!' 8137 8138 type = PyrexTypes.c_bint_type 8139 8140 def calculate_constant_result(self): 8141 self.constant_result = not self.operand.constant_result 8142 8143 def compile_time_value(self, denv): 8144 operand = self.operand.compile_time_value(denv) 8145 try: 8146 return not operand 8147 except Exception, e: 8148 self.compile_time_value_error(e) 8149 8150 def infer_unop_type(self, env, operand_type): 8151 return PyrexTypes.c_bint_type 8152 8153 def analyse_types(self, env): 8154 self.operand = self.operand.analyse_types(env) 8155 operand_type = self.operand.type 8156 if operand_type.is_cpp_class: 8157 cpp_type = operand_type.find_cpp_operation_type(self.operator) 8158 if not cpp_type: 8159 error(self.pos, "'!' operator not defined for %s" % operand_type) 8160 self.type = PyrexTypes.error_type 8161 return 8162 self.type = cpp_type 8163 else: 8164 self.operand = self.operand.coerce_to_boolean(env) 8165 return self 8166 8167 def calculate_result_code(self): 8168 return "(!%s)" % self.operand.result() 8169 8170 def generate_result_code(self, code): 8171 pass 8172 8173 8174 class UnaryPlusNode(UnopNode): 8175 # unary '+' operator 8176 8177 operator = '+' 8178 8179 def analyse_c_operation(self, env): 8180 self.type = PyrexTypes.widest_numeric_type( 8181 self.operand.type, PyrexTypes.c_int_type) 8182 8183 def py_operation_function(self): 8184 return "PyNumber_Positive" 8185 8186 def calculate_result_code(self): 8187 if self.is_cpp_operation(): 8188 return "(+%s)" % self.operand.result() 8189 else: 8190 return self.operand.result() 8191 8192 8193 class UnaryMinusNode(UnopNode): 8194 # unary '-' operator 8195 8196 operator = '-' 8197 8198 def analyse_c_operation(self, env): 8199 if self.operand.type.is_numeric: 8200 self.type = PyrexTypes.widest_numeric_type( 8201 self.operand.type, PyrexTypes.c_int_type) 8202 elif self.operand.type.is_enum: 8203 self.type = PyrexTypes.c_int_type 8204 else: 8205 self.type_error() 8206 if self.type.is_complex: 8207 self.infix = False 8208 8209 def py_operation_function(self): 8210 return "PyNumber_Negative" 8211 8212 def calculate_result_code(self): 8213 if self.infix: 8214 return "(-%s)" % self.operand.result() 8215 else: 8216 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result()) 8217 8218 def get_constant_c_result_code(self): 8219 value = self.operand.get_constant_c_result_code() 8220 if value: 8221 return "(-%s)" % value 8222 8223 class TildeNode(UnopNode): 8224 # unary '~' operator 8225 8226 def analyse_c_operation(self, env): 8227 if self.operand.type.is_int: 8228 self.type = PyrexTypes.widest_numeric_type( 8229 self.operand.type, PyrexTypes.c_int_type) 8230 elif self.operand.type.is_enum: 8231 self.type = PyrexTypes.c_int_type 8232 else: 8233 self.type_error() 8234 8235 def py_operation_function(self): 8236 return "PyNumber_Invert" 8237 8238 def calculate_result_code(self): 8239 return "(~%s)" % self.operand.result() 8240 8241 8242 class CUnopNode(UnopNode): 8243 8244 def is_py_operation(self): 8245 return False 8246 8247 class DereferenceNode(CUnopNode): 8248 # unary * operator 8249 8250 operator = '*' 8251 8252 def infer_unop_type(self, env, operand_type): 8253 if operand_type.is_ptr: 8254 return operand_type.base_type 8255 else: 8256 return PyrexTypes.error_type 8257 8258 def analyse_c_operation(self, env): 8259 if self.operand.type.is_ptr: 8260 self.type = self.operand.type.base_type 8261 else: 8262 self.type_error() 8263 8264 def calculate_result_code(self): 8265 return "(*%s)" % self.operand.result() 8266 8267 8268 class DecrementIncrementNode(CUnopNode): 8269 # unary ++/-- operator 8270 8271 def analyse_c_operation(self, env): 8272 if self.operand.type.is_numeric: 8273 self.type = PyrexTypes.widest_numeric_type( 8274 self.operand.type, PyrexTypes.c_int_type) 8275 elif self.operand.type.is_ptr: 8276 self.type = self.operand.type 8277 else: 8278 self.type_error() 8279 8280 def calculate_result_code(self): 8281 if self.is_prefix: 8282 return "(%s%s)" % (self.operator, self.operand.result()) 8283 else: 8284 return "(%s%s)" % (self.operand.result(), self.operator) 8285 8286 def inc_dec_constructor(is_prefix, operator): 8287 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds) 8288 8289 8290 class AmpersandNode(CUnopNode): 8291 # The C address-of operator. 8292 # 8293 # operand ExprNode 8294 operator = '&' 8295 8296 def infer_unop_type(self, env, operand_type): 8297 return PyrexTypes.c_ptr_type(operand_type) 8298 8299 def analyse_types(self, env): 8300 self.operand = self.operand.analyse_types(env) 8301 argtype = self.operand.type 8302 if argtype.is_cpp_class: 8303 cpp_type = argtype.find_cpp_operation_type(self.operator) 8304 if cpp_type is not None: 8305 self.type = cpp_type 8306 return self 8307 if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()): 8308 if argtype.is_memoryviewslice: 8309 self.error("Cannot take address of memoryview slice") 8310 else: 8311 self.error("Taking address of non-lvalue") 8312 return self 8313 if argtype.is_pyobject: 8314 self.error("Cannot take address of Python variable") 8315 return self 8316 self.type = PyrexTypes.c_ptr_type(argtype) 8317 return self 8318 8319 def check_const(self): 8320 return self.operand.check_const_addr() 8321 8322 def error(self, mess): 8323 error(self.pos, mess) 8324 self.type = PyrexTypes.error_type 8325 self.result_code = "<error>" 8326 8327 def calculate_result_code(self): 8328 return "(&%s)" % self.operand.result() 8329 8330 def generate_result_code(self, code): 8331 pass 8332 8333 8334 unop_node_classes = { 8335 "+": UnaryPlusNode, 8336 "-": UnaryMinusNode, 8337 "~": TildeNode, 8338 } 8339 8340 def unop_node(pos, operator, operand): 8341 # Construct unnop node of appropriate class for 8342 # given operator. 8343 if isinstance(operand, IntNode) and operator == '-': 8344 return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)), 8345 longness=operand.longness, unsigned=operand.unsigned) 8346 elif isinstance(operand, UnopNode) and operand.operator == operator in '+-': 8347 warning(pos, "Python has no increment/decrement operator: %s%sx == %s(%sx) == x" % ((operator,)*4), 5) 8348 return unop_node_classes[operator](pos, 8349 operator = operator, 8350 operand = operand) 8351 8352 8353 class TypecastNode(ExprNode): 8354 # C type cast 8355 # 8356 # operand ExprNode 8357 # base_type CBaseTypeNode 8358 # declarator CDeclaratorNode 8359 # typecheck boolean 8360 # 8361 # If used from a transform, one can if wanted specify the attribute 8362 # "type" directly and leave base_type and declarator to None 8363 8364 subexprs = ['operand'] 8365 base_type = declarator = type = None 8366 8367 def type_dependencies(self, env): 8368 return () 8369 8370 def infer_type(self, env): 8371 if self.type is None: 8372 base_type = self.base_type.analyse(env) 8373 _, self.type = self.declarator.analyse(base_type, env) 8374 return self.type 8375 8376 def analyse_types(self, env): 8377 if self.type is None: 8378 base_type = self.base_type.analyse(env) 8379 _, self.type = self.declarator.analyse(base_type, env) 8380 if self.operand.has_constant_result(): 8381 # Must be done after self.type is resolved. 8382 self.calculate_constant_result() 8383 if self.type.is_cfunction: 8384 error(self.pos, 8385 "Cannot cast to a function type") 8386 self.type = PyrexTypes.error_type 8387 self.operand = self.operand.analyse_types(env) 8388 if self.type is PyrexTypes.c_bint_type: 8389 # short circuit this to a coercion 8390 return self.operand.coerce_to_boolean(env) 8391 to_py = self.type.is_pyobject 8392 from_py = self.operand.type.is_pyobject 8393 if from_py and not to_py and self.operand.is_ephemeral(): 8394 if not self.type.is_numeric and not self.type.is_cpp_class: 8395 error(self.pos, "Casting temporary Python object to non-numeric non-Python type") 8396 if to_py and not from_py: 8397 if self.type is bytes_type and self.operand.type.is_int: 8398 return CoerceIntToBytesNode(self.operand, env) 8399 elif self.operand.type.can_coerce_to_pyobject(env): 8400 self.result_ctype = py_object_type 8401 base_type = self.base_type.analyse(env) 8402 self.operand = self.operand.coerce_to(base_type, env) 8403 else: 8404 if self.operand.type.is_ptr: 8405 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct): 8406 error(self.pos, "Python objects cannot be cast from pointers of primitive types") 8407 else: 8408 # Should this be an error? 8409 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type)) 8410 self.operand = self.operand.coerce_to_simple(env) 8411 elif from_py and not to_py: 8412 if self.type.create_from_py_utility_code(env): 8413 self.operand = self.operand.coerce_to(self.type, env) 8414 elif self.type.is_ptr: 8415 if not (self.type.base_type.is_void or self.type.base_type.is_struct): 8416 error(self.pos, "Python objects cannot be cast to pointers of primitive types") 8417 else: 8418 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type)) 8419 elif from_py and to_py: 8420 if self.typecheck: 8421 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True) 8422 elif isinstance(self.operand, SliceIndexNode): 8423 # This cast can influence the created type of string slices. 8424 self.operand = self.operand.coerce_to(self.type, env) 8425 elif self.type.is_complex and self.operand.type.is_complex: 8426 self.operand = self.operand.coerce_to_simple(env) 8427 elif self.operand.type.is_fused: 8428 self.operand = self.operand.coerce_to(self.type, env) 8429 #self.type = self.operand.type 8430 return self 8431 8432 def is_simple(self): 8433 # either temp or a C cast => no side effects other than the operand's 8434 return self.operand.is_simple() 8435 8436 def nonlocally_immutable(self): 8437 return self.is_temp or self.operand.nonlocally_immutable() 8438 8439 def nogil_check(self, env): 8440 if self.type and self.type.is_pyobject and self.is_temp: 8441 self.gil_error() 8442 8443 def check_const(self): 8444 return self.operand.check_const() 8445 8446 def calculate_constant_result(self): 8447 self.constant_result = self.calculate_result_code(self.operand.constant_result) 8448 8449 def calculate_result_code(self, operand_result = None): 8450 if operand_result is None: 8451 operand_result = self.operand.result() 8452 if self.type.is_complex: 8453 operand_result = self.operand.result() 8454 if self.operand.type.is_complex: 8455 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result) 8456 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result) 8457 else: 8458 real_part = self.type.real_type.cast_code(operand_result) 8459 imag_part = "0" 8460 return "%s(%s, %s)" % ( 8461 self.type.from_parts, 8462 real_part, 8463 imag_part) 8464 else: 8465 return self.type.cast_code(operand_result) 8466 8467 def get_constant_c_result_code(self): 8468 operand_result = self.operand.get_constant_c_result_code() 8469 if operand_result: 8470 return self.type.cast_code(operand_result) 8471 8472 def result_as(self, type): 8473 if self.type.is_pyobject and not self.is_temp: 8474 # Optimise away some unnecessary casting 8475 return self.operand.result_as(type) 8476 else: 8477 return ExprNode.result_as(self, type) 8478 8479 def generate_result_code(self, code): 8480 if self.is_temp: 8481 code.putln( 8482 "%s = (PyObject *)%s;" % ( 8483 self.result(), 8484 self.operand.result())) 8485 code.put_incref(self.result(), self.ctype()) 8486 8487 8488 ERR_START = "Start may not be given" 8489 ERR_NOT_STOP = "Stop must be provided to indicate shape" 8490 ERR_STEPS = ("Strides may only be given to indicate contiguity. " 8491 "Consider slicing it after conversion") 8492 ERR_NOT_POINTER = "Can only create cython.array from pointer or array" 8493 ERR_BASE_TYPE = "Pointer base type does not match cython.array base type" 8494 8495 class CythonArrayNode(ExprNode): 8496 """ 8497 Used when a pointer of base_type is cast to a memoryviewslice with that 8498 base type. i.e. 8499 8500 <int[:M:1, :N]> p 8501 8502 creates a fortran-contiguous cython.array. 8503 8504 We leave the type set to object so coercions to object are more efficient 8505 and less work. Acquiring a memoryviewslice from this will be just as 8506 efficient. ExprNode.coerce_to() will do the additional typecheck on 8507 self.compile_time_type 8508 8509 This also handles <int[:, :]> my_c_array 8510 8511 8512 operand ExprNode the thing we're casting 8513 base_type_node MemoryViewSliceTypeNode the cast expression node 8514 """ 8515 8516 subexprs = ['operand', 'shapes'] 8517 8518 shapes = None 8519 is_temp = True 8520 mode = "c" 8521 array_dtype = None 8522 8523 shape_type = PyrexTypes.c_py_ssize_t_type 8524 8525 def analyse_types(self, env): 8526 import MemoryView 8527 8528 self.operand = self.operand.analyse_types(env) 8529 if self.array_dtype: 8530 array_dtype = self.array_dtype 8531 else: 8532 array_dtype = self.base_type_node.base_type_node.analyse(env) 8533 axes = self.base_type_node.axes 8534 8535 MemoryView.validate_memslice_dtype(self.pos, array_dtype) 8536 8537 self.type = error_type 8538 self.shapes = [] 8539 ndim = len(axes) 8540 8541 # Base type of the pointer or C array we are converting 8542 base_type = self.operand.type 8543 8544 if not self.operand.type.is_ptr and not self.operand.type.is_array: 8545 error(self.operand.pos, ERR_NOT_POINTER) 8546 return self 8547 8548 # Dimension sizes of C array 8549 array_dimension_sizes = [] 8550 if base_type.is_array: 8551 while base_type.is_array: 8552 array_dimension_sizes.append(base_type.size) 8553 base_type = base_type.base_type 8554 elif base_type.is_ptr: 8555 base_type = base_type.base_type 8556 else: 8557 error(self.pos, "unexpected base type %s found" % base_type) 8558 return self 8559 8560 if not (base_type.same_as(array_dtype) or base_type.is_void): 8561 error(self.operand.pos, ERR_BASE_TYPE) 8562 return self 8563 elif self.operand.type.is_array and len(array_dimension_sizes) != ndim: 8564 error(self.operand.pos, 8565 "Expected %d dimensions, array has %d dimensions" % 8566 (ndim, len(array_dimension_sizes))) 8567 return self 8568 8569 # Verify the start, stop and step values 8570 # In case of a C array, use the size of C array in each dimension to 8571 # get an automatic cast 8572 for axis_no, axis in enumerate(axes): 8573 if not axis.start.is_none: 8574 error(axis.start.pos, ERR_START) 8575 return self 8576 8577 if axis.stop.is_none: 8578 if array_dimension_sizes: 8579 dimsize = array_dimension_sizes[axis_no] 8580 axis.stop = IntNode(self.pos, value=str(dimsize), 8581 constant_result=dimsize, 8582 type=PyrexTypes.c_int_type) 8583 else: 8584 error(axis.pos, ERR_NOT_STOP) 8585 return self 8586 8587 axis.stop = axis.stop.analyse_types(env) 8588 shape = axis.stop.coerce_to(self.shape_type, env) 8589 if not shape.is_literal: 8590 shape.coerce_to_temp(env) 8591 8592 self.shapes.append(shape) 8593 8594 first_or_last = axis_no in (0, ndim - 1) 8595 if not axis.step.is_none and first_or_last: 8596 # '1' in the first or last dimension denotes F or C contiguity 8597 axis.step = axis.step.analyse_types(env) 8598 if (not axis.step.type.is_int and axis.step.is_literal and not 8599 axis.step.type.is_error): 8600 error(axis.step.pos, "Expected an integer literal") 8601 return self 8602 8603 if axis.step.compile_time_value(env) != 1: 8604 error(axis.step.pos, ERR_STEPS) 8605 return self 8606 8607 if axis_no == 0: 8608 self.mode = "fortran" 8609 8610 elif not axis.step.is_none and not first_or_last: 8611 # step provided in some other dimension 8612 error(axis.step.pos, ERR_STEPS) 8613 return self 8614 8615 if not self.operand.is_name: 8616 self.operand = self.operand.coerce_to_temp(env) 8617 8618 axes = [('direct', 'follow')] * len(axes) 8619 if self.mode == "fortran": 8620 axes[0] = ('direct', 'contig') 8621 else: 8622 axes[-1] = ('direct', 'contig') 8623 8624 self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes) 8625 self.type = self.get_cython_array_type(env) 8626 MemoryView.use_cython_array_utility_code(env) 8627 env.use_utility_code(MemoryView.typeinfo_to_format_code) 8628 return self 8629 8630 def allocate_temp_result(self, code): 8631 if self.temp_code: 8632 raise RuntimeError("temp allocated mulitple times") 8633 8634 self.temp_code = code.funcstate.allocate_temp(self.type, True) 8635 8636 def infer_type(self, env): 8637 return self.get_cython_array_type(env) 8638 8639 def get_cython_array_type(self, env): 8640 return env.global_scope().context.cython_scope.viewscope.lookup("array").type 8641 8642 def generate_result_code(self, code): 8643 import Buffer 8644 8645 shapes = [self.shape_type.cast_code(shape.result()) 8646 for shape in self.shapes] 8647 dtype = self.coercion_type.dtype 8648 8649 shapes_temp = code.funcstate.allocate_temp(py_object_type, True) 8650 format_temp = code.funcstate.allocate_temp(py_object_type, True) 8651 8652 itemsize = "sizeof(%s)" % dtype.declaration_code("") 8653 type_info = Buffer.get_type_information_cname(code, dtype) 8654 8655 if self.operand.type.is_ptr: 8656 code.putln("if (!%s) {" % self.operand.result()) 8657 code.putln( 'PyErr_SetString(PyExc_ValueError,' 8658 '"Cannot create cython.array from NULL pointer");') 8659 code.putln(code.error_goto(self.operand.pos)) 8660 code.putln("}") 8661 8662 code.putln("%s = __pyx_format_from_typeinfo(&%s);" % 8663 (format_temp, type_info)) 8664 buildvalue_fmt = " __PYX_BUILD_PY_SSIZE_T " * len(shapes) 8665 code.putln('%s = Py_BuildValue((char*) "(" %s ")", %s);' % ( 8666 shapes_temp, buildvalue_fmt, ", ".join(shapes))) 8667 8668 err = "!%s || !%s || !PyBytes_AsString(%s)" % (format_temp, 8669 shapes_temp, 8670 format_temp) 8671 code.putln(code.error_goto_if(err, self.pos)) 8672 code.put_gotref(format_temp) 8673 code.put_gotref(shapes_temp) 8674 8675 tup = (self.result(), shapes_temp, itemsize, format_temp, 8676 self.mode, self.operand.result()) 8677 code.putln('%s = __pyx_array_new(' 8678 '%s, %s, PyBytes_AS_STRING(%s), ' 8679 '(char *) "%s", (char *) %s);' % tup) 8680 code.putln(code.error_goto_if_null(self.result(), self.pos)) 8681 code.put_gotref(self.result()) 8682 8683 def dispose(temp): 8684 code.put_decref_clear(temp, py_object_type) 8685 code.funcstate.release_temp(temp) 8686 8687 dispose(shapes_temp) 8688 dispose(format_temp) 8689 8690 @classmethod 8691 def from_carray(cls, src_node, env): 8692 """ 8693 Given a C array type, return a CythonArrayNode 8694 """ 8695 pos = src_node.pos 8696 base_type = src_node.type 8697 8698 none_node = NoneNode(pos) 8699 axes = [] 8700 8701 while base_type.is_array: 8702 axes.append(SliceNode(pos, start=none_node, stop=none_node, 8703 step=none_node)) 8704 base_type = base_type.base_type 8705 axes[-1].step = IntNode(pos, value="1", is_c_literal=True) 8706 8707 memslicenode = Nodes.MemoryViewSliceTypeNode(pos, axes=axes, 8708 base_type_node=base_type) 8709 result = CythonArrayNode(pos, base_type_node=memslicenode, 8710 operand=src_node, array_dtype=base_type) 8711 result = result.analyse_types(env) 8712 return result 8713 8714 class SizeofNode(ExprNode): 8715 # Abstract base class for sizeof(x) expression nodes. 8716 8717 type = PyrexTypes.c_size_t_type 8718 8719 def check_const(self): 8720 return True 8721 8722 def generate_result_code(self, code): 8723 pass 8724 8725 8726 class SizeofTypeNode(SizeofNode): 8727 # C sizeof function applied to a type 8728 # 8729 # base_type CBaseTypeNode 8730 # declarator CDeclaratorNode 8731 8732 subexprs = [] 8733 arg_type = None 8734 8735 def analyse_types(self, env): 8736 # we may have incorrectly interpreted a dotted name as a type rather than an attribute 8737 # this could be better handled by more uniformly treating types as runtime-available objects 8738 if 0 and self.base_type.module_path: 8739 path = self.base_type.module_path 8740 obj = env.lookup(path[0]) 8741 if obj.as_module is None: 8742 operand = NameNode(pos=self.pos, name=path[0]) 8743 for attr in path[1:]: 8744 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr) 8745 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name) 8746 self.operand = operand 8747 self.__class__ = SizeofVarNode 8748 node = self.analyse_types(env) 8749 return node 8750 if self.arg_type is None: 8751 base_type = self.base_type.analyse(env) 8752 _, arg_type = self.declarator.analyse(base_type, env) 8753 self.arg_type = arg_type 8754 self.check_type() 8755 return self 8756 8757 def check_type(self): 8758 arg_type = self.arg_type 8759 if arg_type.is_pyobject and not arg_type.is_extension_type: 8760 error(self.pos, "Cannot take sizeof Python object") 8761 elif arg_type.is_void: 8762 error(self.pos, "Cannot take sizeof void") 8763 elif not arg_type.is_complete(): 8764 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type) 8765 8766 def calculate_result_code(self): 8767 if self.arg_type.is_extension_type: 8768 # the size of the pointer is boring 8769 # we want the size of the actual struct 8770 arg_code = self.arg_type.declaration_code("", deref=1) 8771 else: 8772 arg_code = self.arg_type.declaration_code("") 8773 return "(sizeof(%s))" % arg_code 8774 8775 8776 class SizeofVarNode(SizeofNode): 8777 # C sizeof function applied to a variable 8778 # 8779 # operand ExprNode 8780 8781 subexprs = ['operand'] 8782 8783 def analyse_types(self, env): 8784 # We may actually be looking at a type rather than a variable... 8785 # If we are, traditional analysis would fail... 8786 operand_as_type = self.operand.analyse_as_type(env) 8787 if operand_as_type: 8788 self.arg_type = operand_as_type 8789 if self.arg_type.is_fused: 8790 self.arg_type = self.arg_type.specialize(env.fused_to_specific) 8791 self.__class__ = SizeofTypeNode 8792 self.check_type() 8793 else: 8794 self.operand = self.operand.analyse_types(env) 8795 return self 8796 8797 def calculate_result_code(self): 8798 return "(sizeof(%s))" % self.operand.result() 8799 8800 def generate_result_code(self, code): 8801 pass 8802 8803 class TypeofNode(ExprNode): 8804 # Compile-time type of an expression, as a string. 8805 # 8806 # operand ExprNode 8807 # literal StringNode # internal 8808 8809 literal = None 8810 type = py_object_type 8811 8812 subexprs = ['literal'] # 'operand' will be ignored after type analysis! 8813 8814 def analyse_types(self, env): 8815 self.operand = self.operand.analyse_types(env) 8816 value = StringEncoding.EncodedString(str(self.operand.type)) #self.operand.type.typeof_name()) 8817 literal = StringNode(self.pos, value=value) 8818 literal = literal.analyse_types(env) 8819 self.literal = literal.coerce_to_pyobject(env) 8820 return self 8821 8822 def may_be_none(self): 8823 return False 8824 8825 def generate_evaluation_code(self, code): 8826 self.literal.generate_evaluation_code(code) 8827 8828 def calculate_result_code(self): 8829 return self.literal.calculate_result_code() 8830 8831 #------------------------------------------------------------------- 8832 # 8833 # Binary operator nodes 8834 # 8835 #------------------------------------------------------------------- 8836 8837 compile_time_binary_operators = { 8838 '<': operator.lt, 8839 '<=': operator.le, 8840 '==': operator.eq, 8841 '!=': operator.ne, 8842 '>=': operator.ge, 8843 '>': operator.gt, 8844 'is': operator.is_, 8845 'is_not': operator.is_not, 8846 '+': operator.add, 8847 '&': operator.and_, 8848 '/': operator.truediv, 8849 '//': operator.floordiv, 8850 '<<': operator.lshift, 8851 '%': operator.mod, 8852 '*': operator.mul, 8853 '|': operator.or_, 8854 '**': operator.pow, 8855 '>>': operator.rshift, 8856 '-': operator.sub, 8857 '^': operator.xor, 8858 'in': lambda x, seq: x in seq, 8859 'not_in': lambda x, seq: x not in seq, 8860 } 8861 8862 def get_compile_time_binop(node): 8863 func = compile_time_binary_operators.get(node.operator) 8864 if not func: 8865 error(node.pos, 8866 "Binary '%s' not supported in compile-time expression" 8867 % node.operator) 8868 return func 8869 8870 class BinopNode(ExprNode): 8871 # operator string 8872 # operand1 ExprNode 8873 # operand2 ExprNode 8874 # 8875 # Processing during analyse_expressions phase: 8876 # 8877 # analyse_c_operation 8878 # Called when neither operand is a pyobject. 8879 # - Check operand types and coerce if needed. 8880 # - Determine result type and result code fragment. 8881 # - Allocate temporary for result if needed. 8882 8883 subexprs = ['operand1', 'operand2'] 8884 inplace = False 8885 8886 def calculate_constant_result(self): 8887 func = compile_time_binary_operators[self.operator] 8888 self.constant_result = func( 8889 self.operand1.constant_result, 8890 self.operand2.constant_result) 8891 8892 def compile_time_value(self, denv): 8893 func = get_compile_time_binop(self) 8894 operand1 = self.operand1.compile_time_value(denv) 8895 operand2 = self.operand2.compile_time_value(denv) 8896 try: 8897 return func(operand1, operand2) 8898 except Exception, e: 8899 self.compile_time_value_error(e) 8900 8901 def infer_type(self, env): 8902 return self.result_type(self.operand1.infer_type(env), 8903 self.operand2.infer_type(env)) 8904 8905 def analyse_types(self, env): 8906 self.operand1 = self.operand1.analyse_types(env) 8907 self.operand2 = self.operand2.analyse_types(env) 8908 self.analyse_operation(env) 8909 return self 8910 8911 def analyse_operation(self, env): 8912 if self.is_py_operation(): 8913 self.coerce_operands_to_pyobjects(env) 8914 self.type = self.result_type(self.operand1.type, 8915 self.operand2.type) 8916 assert self.type.is_pyobject 8917 self.is_temp = 1 8918 elif self.is_cpp_operation(): 8919 self.analyse_cpp_operation(env) 8920 else: 8921 self.analyse_c_operation(env) 8922 8923 def is_py_operation(self): 8924 return self.is_py_operation_types(self.operand1.type, self.operand2.type) 8925 8926 def is_py_operation_types(self, type1, type2): 8927 return type1.is_pyobject or type2.is_pyobject 8928 8929 def is_cpp_operation(self): 8930 return (self.operand1.type.is_cpp_class 8931 or self.operand2.type.is_cpp_class) 8932 8933 def analyse_cpp_operation(self, env): 8934 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) 8935 if not entry: 8936 self.type_error() 8937 return 8938 func_type = entry.type 8939 if func_type.is_ptr: 8940 func_type = func_type.base_type 8941 if len(func_type.args) == 1: 8942 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) 8943 else: 8944 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) 8945 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) 8946 self.type = func_type.return_type 8947 8948 def result_type(self, type1, type2): 8949 if self.is_py_operation_types(type1, type2): 8950 if type2.is_string: 8951 type2 = Builtin.bytes_type 8952 elif type2.is_pyunicode_ptr: 8953 type2 = Builtin.unicode_type 8954 if type1.is_string: 8955 type1 = Builtin.bytes_type 8956 elif type1.is_pyunicode_ptr: 8957 type1 = Builtin.unicode_type 8958 if type1.is_builtin_type or type2.is_builtin_type: 8959 if type1 is type2 and self.operator in '**%+|&^': 8960 # FIXME: at least these operators should be safe - others? 8961 return type1 8962 result_type = self.infer_builtin_types_operation(type1, type2) 8963 if result_type is not None: 8964 return result_type 8965 return py_object_type 8966 else: 8967 return self.compute_c_result_type(type1, type2) 8968 8969 def infer_builtin_types_operation(self, type1, type2): 8970 return None 8971 8972 def nogil_check(self, env): 8973 if self.is_py_operation(): 8974 self.gil_error() 8975 8976 def coerce_operands_to_pyobjects(self, env): 8977 self.operand1 = self.operand1.coerce_to_pyobject(env) 8978 self.operand2 = self.operand2.coerce_to_pyobject(env) 8979 8980 def check_const(self): 8981 return self.operand1.check_const() and self.operand2.check_const() 8982 8983 def generate_result_code(self, code): 8984 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ### 8985 if self.operand1.type.is_pyobject: 8986 function = self.py_operation_function() 8987 if self.operator == '**': 8988 extra_args = ", Py_None" 8989 else: 8990 extra_args = "" 8991 code.putln( 8992 "%s = %s(%s, %s%s); %s" % ( 8993 self.result(), 8994 function, 8995 self.operand1.py_result(), 8996 self.operand2.py_result(), 8997 extra_args, 8998 code.error_goto_if_null(self.result(), self.pos))) 8999 code.put_gotref(self.py_result()) 9000 elif self.is_temp: 9001 code.putln("%s = %s;" % (self.result(), self.calculate_result_code())) 9002 9003 def type_error(self): 9004 if not (self.operand1.type.is_error 9005 or self.operand2.type.is_error): 9006 error(self.pos, "Invalid operand types for '%s' (%s; %s)" % 9007 (self.operator, self.operand1.type, 9008 self.operand2.type)) 9009 self.type = PyrexTypes.error_type 9010 9011 9012 class CBinopNode(BinopNode): 9013 9014 def analyse_types(self, env): 9015 node = BinopNode.analyse_types(self, env) 9016 if node.is_py_operation(): 9017 node.type = PyrexTypes.error_type 9018 return node 9019 9020 def py_operation_function(self): 9021 return "" 9022 9023 def calculate_result_code(self): 9024 return "(%s %s %s)" % ( 9025 self.operand1.result(), 9026 self.operator, 9027 self.operand2.result()) 9028 9029 def compute_c_result_type(self, type1, type2): 9030 cpp_type = None 9031 if type1.is_cpp_class or type1.is_ptr: 9032 cpp_type = type1.find_cpp_operation_type(self.operator, type2) 9033 # FIXME: handle the reversed case? 9034 #if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): 9035 # cpp_type = type2.find_cpp_operation_type(self.operator, type1) 9036 # FIXME: do we need to handle other cases here? 9037 return cpp_type 9038 9039 9040 def c_binop_constructor(operator): 9041 def make_binop_node(pos, **operands): 9042 return CBinopNode(pos, operator=operator, **operands) 9043 return make_binop_node 9044 9045 class NumBinopNode(BinopNode): 9046 # Binary operation taking numeric arguments. 9047 9048 infix = True 9049 overflow_check = False 9050 overflow_bit_node = None 9051 9052 def analyse_c_operation(self, env): 9053 type1 = self.operand1.type 9054 type2 = self.operand2.type 9055 self.type = self.compute_c_result_type(type1, type2) 9056 if not self.type: 9057 self.type_error() 9058 return 9059 if self.type.is_complex: 9060 self.infix = False 9061 if (self.type.is_int 9062 and env.directives['overflowcheck'] 9063 and self.operator in self.overflow_op_names): 9064 if (self.operator in ('+', '*') 9065 and self.operand1.has_constant_result() 9066 and not self.operand2.has_constant_result()): 9067 self.operand1, self.operand2 = self.operand2, self.operand1 9068 self.overflow_check = True 9069 self.overflow_fold = env.directives['overflowcheck.fold'] 9070 self.func = self.type.overflow_check_binop( 9071 self.overflow_op_names[self.operator], 9072 env, 9073 const_rhs = self.operand2.has_constant_result()) 9074 self.is_temp = True 9075 if not self.infix or (type1.is_numeric and type2.is_numeric): 9076 self.operand1 = self.operand1.coerce_to(self.type, env) 9077 self.operand2 = self.operand2.coerce_to(self.type, env) 9078 9079 def compute_c_result_type(self, type1, type2): 9080 if self.c_types_okay(type1, type2): 9081 widest_type = PyrexTypes.widest_numeric_type(type1, type2) 9082 if widest_type is PyrexTypes.c_bint_type: 9083 if self.operator not in '|^&': 9084 # False + False == 0 # not False! 9085 widest_type = PyrexTypes.c_int_type 9086 else: 9087 widest_type = PyrexTypes.widest_numeric_type( 9088 widest_type, PyrexTypes.c_int_type) 9089 return widest_type 9090 else: 9091 return None 9092 9093 def may_be_none(self): 9094 if self.type and self.type.is_builtin_type: 9095 # if we know the result type, we know the operation, so it can't be None 9096 return False 9097 type1 = self.operand1.type 9098 type2 = self.operand2.type 9099 if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type: 9100 # XXX: I can't think of any case where a binary operation 9101 # on builtin types evaluates to None - add a special case 9102 # here if there is one. 9103 return False 9104 return super(NumBinopNode, self).may_be_none() 9105 9106 def get_constant_c_result_code(self): 9107 value1 = self.operand1.get_constant_c_result_code() 9108 value2 = self.operand2.get_constant_c_result_code() 9109 if value1 and value2: 9110 return "(%s %s %s)" % (value1, self.operator, value2) 9111 else: 9112 return None 9113 9114 def c_types_okay(self, type1, type2): 9115 #print "NumBinopNode.c_types_okay:", type1, type2 ### 9116 return (type1.is_numeric or type1.is_enum) \ 9117 and (type2.is_numeric or type2.is_enum) 9118 9119 def generate_evaluation_code(self, code): 9120 if self.overflow_check: 9121 self.overflow_bit_node = self 9122 self.overflow_bit = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) 9123 code.putln("%s = 0;" % self.overflow_bit) 9124 super(NumBinopNode, self).generate_evaluation_code(code) 9125 if self.overflow_check: 9126 code.putln("if (unlikely(%s)) {" % self.overflow_bit) 9127 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large");') 9128 code.putln(code.error_goto(self.pos)) 9129 code.putln("}") 9130 code.funcstate.release_temp(self.overflow_bit) 9131 9132 def calculate_result_code(self): 9133 if self.overflow_bit_node is not None: 9134 return "%s(%s, %s, &%s)" % ( 9135 self.func, 9136 self.operand1.result(), 9137 self.operand2.result(), 9138 self.overflow_bit_node.overflow_bit) 9139 elif self.infix: 9140 return "(%s %s %s)" % ( 9141 self.operand1.result(), 9142 self.operator, 9143 self.operand2.result()) 9144 else: 9145 func = self.type.binary_op(self.operator) 9146 if func is None: 9147 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type)) 9148 return "%s(%s, %s)" % ( 9149 func, 9150 self.operand1.result(), 9151 self.operand2.result()) 9152 9153 def is_py_operation_types(self, type1, type2): 9154 return (type1.is_unicode_char or 9155 type2.is_unicode_char or 9156 BinopNode.is_py_operation_types(self, type1, type2)) 9157 9158 def py_operation_function(self): 9159 function_name = self.py_functions[self.operator] 9160 if self.inplace: 9161 function_name = function_name.replace('PyNumber_', 'PyNumber_InPlace') 9162 return function_name 9163 9164 py_functions = { 9165 "|": "PyNumber_Or", 9166 "^": "PyNumber_Xor", 9167 "&": "PyNumber_And", 9168 "<<": "PyNumber_Lshift", 9169 ">>": "PyNumber_Rshift", 9170 "+": "PyNumber_Add", 9171 "-": "PyNumber_Subtract", 9172 "*": "PyNumber_Multiply", 9173 "/": "__Pyx_PyNumber_Divide", 9174 "//": "PyNumber_FloorDivide", 9175 "%": "PyNumber_Remainder", 9176 "**": "PyNumber_Power" 9177 } 9178 9179 overflow_op_names = { 9180 "+": "add", 9181 "-": "sub", 9182 "*": "mul", 9183 "<<": "lshift", 9184 } 9185 9186 9187 class IntBinopNode(NumBinopNode): 9188 # Binary operation taking integer arguments. 9189 9190 def c_types_okay(self, type1, type2): 9191 #print "IntBinopNode.c_types_okay:", type1, type2 ### 9192 return (type1.is_int or type1.is_enum) \ 9193 and (type2.is_int or type2.is_enum) 9194 9195 9196 class AddNode(NumBinopNode): 9197 # '+' operator. 9198 9199 def is_py_operation_types(self, type1, type2): 9200 if type1.is_string and type2.is_string or type1.is_pyunicode_ptr and type2.is_pyunicode_ptr: 9201 return 1 9202 else: 9203 return NumBinopNode.is_py_operation_types(self, type1, type2) 9204 9205 def infer_builtin_types_operation(self, type1, type2): 9206 # b'abc' + 'abc' raises an exception in Py3, 9207 # so we can safely infer the Py2 type for bytes here 9208 string_types = [bytes_type, str_type, basestring_type, unicode_type] # Py2.4 lacks tuple.index() 9209 if type1 in string_types and type2 in string_types: 9210 return string_types[max(string_types.index(type1), 9211 string_types.index(type2))] 9212 return None 9213 9214 def compute_c_result_type(self, type1, type2): 9215 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ### 9216 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): 9217 return type1 9218 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum): 9219 return type2 9220 else: 9221 return NumBinopNode.compute_c_result_type( 9222 self, type1, type2) 9223 9224 def py_operation_function(self): 9225 type1, type2 = self.operand1.type, self.operand2.type 9226 if type1 is unicode_type or type2 is unicode_type: 9227 if type1.is_builtin_type and type2.is_builtin_type: 9228 if self.operand1.may_be_none() or self.operand2.may_be_none(): 9229 return '__Pyx_PyUnicode_ConcatSafe' 9230 else: 9231 return '__Pyx_PyUnicode_Concat' 9232 return super(AddNode, self).py_operation_function() 9233 9234 9235 class SubNode(NumBinopNode): 9236 # '-' operator. 9237 9238 def compute_c_result_type(self, type1, type2): 9239 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): 9240 return type1 9241 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array): 9242 return PyrexTypes.c_ptrdiff_t_type 9243 else: 9244 return NumBinopNode.compute_c_result_type( 9245 self, type1, type2) 9246 9247 9248 class MulNode(NumBinopNode): 9249 # '*' operator. 9250 9251 def is_py_operation_types(self, type1, type2): 9252 if ((type1.is_string and type2.is_int) or 9253 (type2.is_string and type1.is_int)): 9254 return 1 9255 else: 9256 return NumBinopNode.is_py_operation_types(self, type1, type2) 9257 9258 def infer_builtin_types_operation(self, type1, type2): 9259 # let's assume that whatever builtin type you multiply a string with 9260 # will either return a string of the same type or fail with an exception 9261 string_types = (bytes_type, str_type, basestring_type, unicode_type) 9262 if type1 in string_types and type2.is_builtin_type: 9263 return type1 9264 if type2 in string_types and type1.is_builtin_type: 9265 return type2 9266 # multiplication of containers/numbers with an integer value 9267 # always (?) returns the same type 9268 if type1.is_int: 9269 return type2 9270 if type2.is_int: 9271 return type1 9272 return None 9273 9274 9275 class DivNode(NumBinopNode): 9276 # '/' or '//' operator. 9277 9278 cdivision = None 9279 truedivision = None # == "unknown" if operator == '/' 9280 ctruedivision = False 9281 cdivision_warnings = False 9282 zerodivision_check = None 9283 9284 def find_compile_time_binary_operator(self, op1, op2): 9285 func = compile_time_binary_operators[self.operator] 9286 if self.operator == '/' and self.truedivision is None: 9287 # => true div for floats, floor div for integers 9288 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)): 9289 func = compile_time_binary_operators['//'] 9290 return func 9291 9292 def calculate_constant_result(self): 9293 op1 = self.operand1.constant_result 9294 op2 = self.operand2.constant_result 9295 func = self.find_compile_time_binary_operator(op1, op2) 9296 self.constant_result = func( 9297 self.operand1.constant_result, 9298 self.operand2.constant_result) 9299 9300 def compile_time_value(self, denv): 9301 operand1 = self.operand1.compile_time_value(denv) 9302 operand2 = self.operand2.compile_time_value(denv) 9303 try: 9304 func = self.find_compile_time_binary_operator( 9305 operand1, operand2) 9306 return func(operand1, operand2) 9307 except Exception, e: 9308 self.compile_time_value_error(e) 9309 9310 def analyse_operation(self, env): 9311 if self.cdivision or env.directives['cdivision']: 9312 self.ctruedivision = False 9313 else: 9314 self.ctruedivision = self.truedivision 9315 NumBinopNode.analyse_operation(self, env) 9316 if self.is_cpp_operation(): 9317 self.cdivision = True 9318 if not self.type.is_pyobject: 9319 self.zerodivision_check = ( 9320 self.cdivision is None and not env.directives['cdivision'] 9321 and (not self.operand2.has_constant_result() or 9322 self.operand2.constant_result == 0)) 9323 if self.zerodivision_check or env.directives['cdivision_warnings']: 9324 # Need to check ahead of time to warn or raise zero division error 9325 self.operand1 = self.operand1.coerce_to_simple(env) 9326 self.operand2 = self.operand2.coerce_to_simple(env) 9327 9328 def compute_c_result_type(self, type1, type2): 9329 if self.operator == '/' and self.ctruedivision: 9330 if not type1.is_float and not type2.is_float: 9331 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type) 9332 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type) 9333 return widest_type 9334 return NumBinopNode.compute_c_result_type(self, type1, type2) 9335 9336 def zero_division_message(self): 9337 if self.type.is_int: 9338 return "integer division or modulo by zero" 9339 else: 9340 return "float division" 9341 9342 def generate_evaluation_code(self, code): 9343 if not self.type.is_pyobject and not self.type.is_complex: 9344 if self.cdivision is None: 9345 self.cdivision = (code.globalstate.directives['cdivision'] 9346 or not self.type.signed 9347 or self.type.is_float) 9348 if not self.cdivision: 9349 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type)) 9350 NumBinopNode.generate_evaluation_code(self, code) 9351 self.generate_div_warning_code(code) 9352 9353 def generate_div_warning_code(self, code): 9354 if not self.type.is_pyobject: 9355 if self.zerodivision_check: 9356 if not self.infix: 9357 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result()) 9358 else: 9359 zero_test = "%s == 0" % self.operand2.result() 9360 code.putln("if (unlikely(%s)) {" % zero_test) 9361 code.put_ensure_gil() 9362 code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message()) 9363 code.put_release_ensured_gil() 9364 code.putln(code.error_goto(self.pos)) 9365 code.putln("}") 9366 if self.type.is_int and self.type.signed and self.operator != '%': 9367 code.globalstate.use_utility_code(division_overflow_test_code) 9368 if self.operand2.type.signed == 2: 9369 # explicitly signed, no runtime check needed 9370 minus1_check = 'unlikely(%s == -1)' % self.operand2.result() 9371 else: 9372 type_of_op2 = self.operand2.type.declaration_code('') 9373 minus1_check = '(!(((%s)-1) > 0)) && unlikely(%s == (%s)-1)' % ( 9374 type_of_op2, self.operand2.result(), type_of_op2) 9375 code.putln("else if (sizeof(%s) == sizeof(long) && %s " 9376 " && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % ( 9377 self.type.declaration_code(''), 9378 minus1_check, 9379 self.operand1.result())) 9380 code.put_ensure_gil() 9381 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large to perform division");') 9382 code.put_release_ensured_gil() 9383 code.putln(code.error_goto(self.pos)) 9384 code.putln("}") 9385 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/': 9386 code.globalstate.use_utility_code(cdivision_warning_utility_code) 9387 code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % ( 9388 self.operand1.result(), 9389 self.operand2.result())) 9390 code.put_ensure_gil() 9391 code.putln(code.set_error_info(self.pos, used=True)) 9392 code.putln("if (__Pyx_cdivision_warning(%(FILENAME)s, " 9393 "%(LINENO)s)) {" % { 9394 'FILENAME': Naming.filename_cname, 9395 'LINENO': Naming.lineno_cname, 9396 }) 9397 code.put_release_ensured_gil() 9398 code.put_goto(code.error_label) 9399 code.putln("}") 9400 code.put_release_ensured_gil() 9401 code.putln("}") 9402 9403 def calculate_result_code(self): 9404 if self.type.is_complex: 9405 return NumBinopNode.calculate_result_code(self) 9406 elif self.type.is_float and self.operator == '//': 9407 return "floor(%s / %s)" % ( 9408 self.operand1.result(), 9409 self.operand2.result()) 9410 elif self.truedivision or self.cdivision: 9411 op1 = self.operand1.result() 9412 op2 = self.operand2.result() 9413 if self.truedivision: 9414 if self.type != self.operand1.type: 9415 op1 = self.type.cast_code(op1) 9416 if self.type != self.operand2.type: 9417 op2 = self.type.cast_code(op2) 9418 return "(%s / %s)" % (op1, op2) 9419 else: 9420 return "__Pyx_div_%s(%s, %s)" % ( 9421 self.type.specialization_name(), 9422 self.operand1.result(), 9423 self.operand2.result()) 9424 9425 9426 class ModNode(DivNode): 9427 # '%' operator. 9428 9429 def is_py_operation_types(self, type1, type2): 9430 return (type1.is_string 9431 or type2.is_string 9432 or NumBinopNode.is_py_operation_types(self, type1, type2)) 9433 9434 def infer_builtin_types_operation(self, type1, type2): 9435 # b'%s' % xyz raises an exception in Py3, so it's safe to infer the type for Py2 9436 if type1 is unicode_type: 9437 # None + xyz may be implemented by RHS 9438 if type2.is_builtin_type or not self.operand1.may_be_none(): 9439 return type1 9440 elif type1 in (bytes_type, str_type, basestring_type): 9441 if type2 is unicode_type: 9442 return type2 9443 elif type2.is_numeric: 9444 return type1 9445 elif type1 is bytes_type and not type2.is_builtin_type: 9446 return None # RHS might implement '% operator differently in Py3 9447 else: 9448 return basestring_type # either str or unicode, can't tell 9449 return None 9450 9451 def zero_division_message(self): 9452 if self.type.is_int: 9453 return "integer division or modulo by zero" 9454 else: 9455 return "float divmod()" 9456 9457 def analyse_operation(self, env): 9458 DivNode.analyse_operation(self, env) 9459 if not self.type.is_pyobject: 9460 if self.cdivision is None: 9461 self.cdivision = env.directives['cdivision'] or not self.type.signed 9462 if not self.cdivision and not self.type.is_int and not self.type.is_float: 9463 error(self.pos, "mod operator not supported for type '%s'" % self.type) 9464 9465 def generate_evaluation_code(self, code): 9466 if not self.type.is_pyobject and not self.cdivision: 9467 if self.type.is_int: 9468 code.globalstate.use_utility_code( 9469 mod_int_utility_code.specialize(self.type)) 9470 else: # float 9471 code.globalstate.use_utility_code( 9472 mod_float_utility_code.specialize( 9473 self.type, math_h_modifier=self.type.math_h_modifier)) 9474 # note: skipping over DivNode here 9475 NumBinopNode.generate_evaluation_code(self, code) 9476 self.generate_div_warning_code(code) 9477 9478 def calculate_result_code(self): 9479 if self.cdivision: 9480 if self.type.is_float: 9481 return "fmod%s(%s, %s)" % ( 9482 self.type.math_h_modifier, 9483 self.operand1.result(), 9484 self.operand2.result()) 9485 else: 9486 return "(%s %% %s)" % ( 9487 self.operand1.result(), 9488 self.operand2.result()) 9489 else: 9490 return "__Pyx_mod_%s(%s, %s)" % ( 9491 self.type.specialization_name(), 9492 self.operand1.result(), 9493 self.operand2.result()) 9494 9495 def py_operation_function(self): 9496 if self.operand1.type is unicode_type: 9497 if self.operand1.may_be_none(): 9498 return '__Pyx_PyUnicode_FormatSafe' 9499 else: 9500 return 'PyUnicode_Format' 9501 elif self.operand1.type is str_type: 9502 if self.operand1.may_be_none(): 9503 return '__Pyx_PyString_FormatSafe' 9504 else: 9505 return '__Pyx_PyString_Format' 9506 return super(ModNode, self).py_operation_function() 9507 9508 9509 class PowNode(NumBinopNode): 9510 # '**' operator. 9511 9512 def analyse_c_operation(self, env): 9513 NumBinopNode.analyse_c_operation(self, env) 9514 if self.type.is_complex: 9515 if self.type.real_type.is_float: 9516 self.operand1 = self.operand1.coerce_to(self.type, env) 9517 self.operand2 = self.operand2.coerce_to(self.type, env) 9518 self.pow_func = "__Pyx_c_pow" + self.type.real_type.math_h_modifier 9519 else: 9520 error(self.pos, "complex int powers not supported") 9521 self.pow_func = "<error>" 9522 elif self.type.is_float: 9523 self.pow_func = "pow" + self.type.math_h_modifier 9524 elif self.type.is_int: 9525 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_') 9526 env.use_utility_code( 9527 int_pow_utility_code.specialize( 9528 func_name=self.pow_func, 9529 type=self.type.declaration_code(''), 9530 signed=self.type.signed and 1 or 0)) 9531 elif not self.type.is_error: 9532 error(self.pos, "got unexpected types for C power operator: %s, %s" % 9533 (self.operand1.type, self.operand2.type)) 9534 9535 def calculate_result_code(self): 9536 # Work around MSVC overloading ambiguity. 9537 def typecast(operand): 9538 if self.type == operand.type: 9539 return operand.result() 9540 else: 9541 return self.type.cast_code(operand.result()) 9542 return "%s(%s, %s)" % ( 9543 self.pow_func, 9544 typecast(self.operand1), 9545 typecast(self.operand2)) 9546 9547 9548 # Note: This class is temporarily "shut down" into an ineffective temp 9549 # allocation mode. 9550 # 9551 # More sophisticated temp reuse was going on before, one could have a 9552 # look at adding this again after /all/ classes are converted to the 9553 # new temp scheme. (The temp juggling cannot work otherwise). 9554 class BoolBinopNode(ExprNode): 9555 # Short-circuiting boolean operation. 9556 # 9557 # operator string 9558 # operand1 ExprNode 9559 # operand2 ExprNode 9560 9561 subexprs = ['operand1', 'operand2'] 9562 9563 def infer_type(self, env): 9564 type1 = self.operand1.infer_type(env) 9565 type2 = self.operand2.infer_type(env) 9566 return PyrexTypes.independent_spanning_type(type1, type2) 9567 9568 def may_be_none(self): 9569 if self.operator == 'or': 9570 return self.operand2.may_be_none() 9571 else: 9572 return self.operand1.may_be_none() or self.operand2.may_be_none() 9573 9574 def calculate_constant_result(self): 9575 if self.operator == 'and': 9576 self.constant_result = \ 9577 self.operand1.constant_result and \ 9578 self.operand2.constant_result 9579 else: 9580 self.constant_result = \ 9581 self.operand1.constant_result or \ 9582 self.operand2.constant_result 9583 9584 def compile_time_value(self, denv): 9585 if self.operator == 'and': 9586 return self.operand1.compile_time_value(denv) \ 9587 and self.operand2.compile_time_value(denv) 9588 else: 9589 return self.operand1.compile_time_value(denv) \ 9590 or self.operand2.compile_time_value(denv) 9591 9592 def coerce_to_boolean(self, env): 9593 return BoolBinopNode( 9594 self.pos, 9595 operator = self.operator, 9596 operand1 = self.operand1.coerce_to_boolean(env), 9597 operand2 = self.operand2.coerce_to_boolean(env), 9598 type = PyrexTypes.c_bint_type, 9599 is_temp = self.is_temp) 9600 9601 def analyse_types(self, env): 9602 self.operand1 = self.operand1.analyse_types(env) 9603 self.operand2 = self.operand2.analyse_types(env) 9604 self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type) 9605 self.operand1 = self.operand1.coerce_to(self.type, env) 9606 self.operand2 = self.operand2.coerce_to(self.type, env) 9607 9608 # For what we're about to do, it's vital that 9609 # both operands be temp nodes. 9610 self.operand1 = self.operand1.coerce_to_simple(env) 9611 self.operand2 = self.operand2.coerce_to_simple(env) 9612 self.is_temp = 1 9613 return self 9614 9615 gil_message = "Truth-testing Python object" 9616 9617 def check_const(self): 9618 return self.operand1.check_const() and self.operand2.check_const() 9619 9620 def generate_evaluation_code(self, code): 9621 code.mark_pos(self.pos) 9622 self.operand1.generate_evaluation_code(code) 9623 test_result, uses_temp = self.generate_operand1_test(code) 9624 if self.operator == 'and': 9625 sense = "" 9626 else: 9627 sense = "!" 9628 code.putln( 9629 "if (%s%s) {" % ( 9630 sense, 9631 test_result)) 9632 if uses_temp: 9633 code.funcstate.release_temp(test_result) 9634 self.operand1.generate_disposal_code(code) 9635 self.operand2.generate_evaluation_code(code) 9636 self.allocate_temp_result(code) 9637 self.operand2.make_owned_reference(code) 9638 code.putln("%s = %s;" % (self.result(), self.operand2.result())) 9639 self.operand2.generate_post_assignment_code(code) 9640 self.operand2.free_temps(code) 9641 code.putln("} else {") 9642 self.operand1.make_owned_reference(code) 9643 code.putln("%s = %s;" % (self.result(), self.operand1.result())) 9644 self.operand1.generate_post_assignment_code(code) 9645 self.operand1.free_temps(code) 9646 code.putln("}") 9647 9648 def generate_operand1_test(self, code): 9649 # Generate code to test the truth of the first operand. 9650 if self.type.is_pyobject: 9651 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type, 9652 manage_ref=False) 9653 code.putln( 9654 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( 9655 test_result, 9656 self.operand1.py_result(), 9657 code.error_goto_if_neg(test_result, self.pos))) 9658 else: 9659 test_result = self.operand1.result() 9660 return (test_result, self.type.is_pyobject) 9661 9662 9663 class CondExprNode(ExprNode): 9664 # Short-circuiting conditional expression. 9665 # 9666 # test ExprNode 9667 # true_val ExprNode 9668 # false_val ExprNode 9669 9670 true_val = None 9671 false_val = None 9672 9673 subexprs = ['test', 'true_val', 'false_val'] 9674 9675 def type_dependencies(self, env): 9676 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env) 9677 9678 def infer_type(self, env): 9679 return PyrexTypes.independent_spanning_type( 9680 self.true_val.infer_type(env), 9681 self.false_val.infer_type(env)) 9682 9683 def calculate_constant_result(self): 9684 if self.test.constant_result: 9685 self.constant_result = self.true_val.constant_result 9686 else: 9687 self.constant_result = self.false_val.constant_result 9688 9689 def analyse_types(self, env): 9690 self.test = self.test.analyse_types(env).coerce_to_boolean(env) 9691 self.true_val = self.true_val.analyse_types(env) 9692 self.false_val = self.false_val.analyse_types(env) 9693 self.is_temp = 1 9694 return self.analyse_result_type(env) 9695 9696 def analyse_result_type(self, env): 9697 self.type = PyrexTypes.independent_spanning_type( 9698 self.true_val.type, self.false_val.type) 9699 if self.type.is_pyobject: 9700 self.result_ctype = py_object_type 9701 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: 9702 self.true_val = self.true_val.coerce_to(self.type, env) 9703 self.false_val = self.false_val.coerce_to(self.type, env) 9704 if self.type == PyrexTypes.error_type: 9705 self.type_error() 9706 return self 9707 9708 def coerce_to(self, dst_type, env): 9709 self.true_val = self.true_val.coerce_to(dst_type, env) 9710 self.false_val = self.false_val.coerce_to(dst_type, env) 9711 self.result_ctype = None 9712 return self.analyse_result_type(env) 9713 9714 def type_error(self): 9715 if not (self.true_val.type.is_error or self.false_val.type.is_error): 9716 error(self.pos, "Incompatible types in conditional expression (%s; %s)" % 9717 (self.true_val.type, self.false_val.type)) 9718 self.type = PyrexTypes.error_type 9719 9720 def check_const(self): 9721 return (self.test.check_const() 9722 and self.true_val.check_const() 9723 and self.false_val.check_const()) 9724 9725 def generate_evaluation_code(self, code): 9726 # Because subexprs may not be evaluated we can use a more optimal 9727 # subexpr allocation strategy than the default, so override evaluation_code. 9728 9729 code.mark_pos(self.pos) 9730 self.allocate_temp_result(code) 9731 self.test.generate_evaluation_code(code) 9732 code.putln("if (%s) {" % self.test.result() ) 9733 self.eval_and_get(code, self.true_val) 9734 code.putln("} else {") 9735 self.eval_and_get(code, self.false_val) 9736 code.putln("}") 9737 self.test.generate_disposal_code(code) 9738 self.test.free_temps(code) 9739 9740 def eval_and_get(self, code, expr): 9741 expr.generate_evaluation_code(code) 9742 expr.make_owned_reference(code) 9743 code.putln('%s = %s;' % (self.result(), expr.result_as(self.ctype()))) 9744 expr.generate_post_assignment_code(code) 9745 expr.free_temps(code) 9746 9747 richcmp_constants = { 9748 "<" : "Py_LT", 9749 "<=": "Py_LE", 9750 "==": "Py_EQ", 9751 "!=": "Py_NE", 9752 "<>": "Py_NE", 9753 ">" : "Py_GT", 9754 ">=": "Py_GE", 9755 # the following are faked by special compare functions 9756 "in" : "Py_EQ", 9757 "not_in": "Py_NE", 9758 } 9759 9760 class CmpNode(object): 9761 # Mixin class containing code common to PrimaryCmpNodes 9762 # and CascadedCmpNodes. 9763 9764 special_bool_cmp_function = None 9765 special_bool_cmp_utility_code = None 9766 9767 def infer_type(self, env): 9768 # TODO: Actually implement this (after merging with -unstable). 9769 return py_object_type 9770 9771 def calculate_cascaded_constant_result(self, operand1_result): 9772 func = compile_time_binary_operators[self.operator] 9773 operand2_result = self.operand2.constant_result 9774 if (isinstance(operand1_result, (bytes, unicode)) and 9775 isinstance(operand2_result, (bytes, unicode)) and 9776 type(operand1_result) != type(operand2_result)): 9777 # string comparison of different types isn't portable 9778 return 9779 9780 if self.operator in ('in', 'not_in'): 9781 if isinstance(self.operand2, (ListNode, TupleNode, SetNode)): 9782 if not self.operand2.args: 9783 self.constant_result = self.operator == 'not_in' 9784 return 9785 elif isinstance(self.operand2, ListNode) and not self.cascade: 9786 # tuples are more efficient to store than lists 9787 self.operand2 = self.operand2.as_tuple() 9788 elif isinstance(self.operand2, DictNode): 9789 if not self.operand2.key_value_pairs: 9790 self.constant_result = self.operator == 'not_in' 9791 return 9792 9793 self.constant_result = func(operand1_result, operand2_result) 9794 9795 def cascaded_compile_time_value(self, operand1, denv): 9796 func = get_compile_time_binop(self) 9797 operand2 = self.operand2.compile_time_value(denv) 9798 try: 9799 result = func(operand1, operand2) 9800 except Exception, e: 9801 self.compile_time_value_error(e) 9802 result = None 9803 if result: 9804 cascade = self.cascade 9805 if cascade: 9806 result = result and cascade.cascaded_compile_time_value(operand2, denv) 9807 return result 9808 9809 def is_cpp_comparison(self): 9810 return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class 9811 9812 def find_common_int_type(self, env, op, operand1, operand2): 9813 # type1 != type2 and at least one of the types is not a C int 9814 type1 = operand1.type 9815 type2 = operand2.type 9816 type1_can_be_int = False 9817 type2_can_be_int = False 9818 9819 if operand1.is_string_literal and operand1.can_coerce_to_char_literal(): 9820 type1_can_be_int = True 9821 if operand2.is_string_literal and operand2.can_coerce_to_char_literal(): 9822 type2_can_be_int = True 9823 9824 if type1.is_int: 9825 if type2_can_be_int: 9826 return type1 9827 elif type2.is_int: 9828 if type1_can_be_int: 9829 return type2 9830 elif type1_can_be_int: 9831 if type2_can_be_int: 9832 if Builtin.unicode_type in (type1, type2): 9833 return PyrexTypes.c_py_ucs4_type 9834 else: 9835 return PyrexTypes.c_uchar_type 9836 9837 return None 9838 9839 def find_common_type(self, env, op, operand1, common_type=None): 9840 operand2 = self.operand2 9841 type1 = operand1.type 9842 type2 = operand2.type 9843 9844 new_common_type = None 9845 9846 # catch general errors 9847 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or \ 9848 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type)): 9849 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3") 9850 new_common_type = error_type 9851 9852 # try to use numeric comparisons where possible 9853 elif type1.is_complex or type2.is_complex: 9854 if op not in ('==', '!=') \ 9855 and (type1.is_complex or type1.is_numeric) \ 9856 and (type2.is_complex or type2.is_numeric): 9857 error(self.pos, "complex types are unordered") 9858 new_common_type = error_type 9859 elif type1.is_pyobject: 9860 new_common_type = type1 9861 elif type2.is_pyobject: 9862 new_common_type = type2 9863 else: 9864 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) 9865 elif type1.is_numeric and type2.is_numeric: 9866 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) 9867 elif common_type is None or not common_type.is_pyobject: 9868 new_common_type = self.find_common_int_type(env, op, operand1, operand2) 9869 9870 if new_common_type is None: 9871 # fall back to generic type compatibility tests 9872 if type1 == type2: 9873 new_common_type = type1 9874 elif type1.is_pyobject or type2.is_pyobject: 9875 if type2.is_numeric or type2.is_string: 9876 if operand2.check_for_coercion_error(type1, env): 9877 new_common_type = error_type 9878 else: 9879 new_common_type = py_object_type 9880 elif type1.is_numeric or type1.is_string: 9881 if operand1.check_for_coercion_error(type2, env): 9882 new_common_type = error_type 9883 else: 9884 new_common_type = py_object_type 9885 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2): 9886 new_common_type = py_object_type 9887 else: 9888 # one Python type and one non-Python type, not assignable 9889 self.invalid_types_error(operand1, op, operand2) 9890 new_common_type = error_type 9891 elif type1.assignable_from(type2): 9892 new_common_type = type1 9893 elif type2.assignable_from(type1): 9894 new_common_type = type2 9895 else: 9896 # C types that we couldn't handle up to here are an error 9897 self.invalid_types_error(operand1, op, operand2) 9898 new_common_type = error_type 9899 9900 if new_common_type.is_string and (isinstance(operand1, BytesNode) or 9901 isinstance(operand2, BytesNode)): 9902 # special case when comparing char* to bytes literal: must 9903 # compare string values! 9904 new_common_type = bytes_type 9905 9906 # recursively merge types 9907 if common_type is None or new_common_type.is_error: 9908 common_type = new_common_type 9909 else: 9910 # we could do a lot better by splitting the comparison 9911 # into a non-Python part and a Python part, but this is 9912 # safer for now 9913 common_type = PyrexTypes.spanning_type(common_type, new_common_type) 9914 9915 if self.cascade: 9916 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type) 9917 9918 return common_type 9919 9920 def invalid_types_error(self, operand1, op, operand2): 9921 error(self.pos, "Invalid types for '%s' (%s, %s)" % 9922 (op, operand1.type, operand2.type)) 9923 9924 def is_python_comparison(self): 9925 return (not self.is_ptr_contains() 9926 and not self.is_c_string_contains() 9927 and (self.has_python_operands() 9928 or (self.cascade and self.cascade.is_python_comparison()) 9929 or self.operator in ('in', 'not_in'))) 9930 9931 def coerce_operands_to(self, dst_type, env): 9932 operand2 = self.operand2 9933 if operand2.type != dst_type: 9934 self.operand2 = operand2.coerce_to(dst_type, env) 9935 if self.cascade: 9936 self.cascade.coerce_operands_to(dst_type, env) 9937 9938 def is_python_result(self): 9939 return ((self.has_python_operands() and 9940 self.special_bool_cmp_function is None and 9941 self.operator not in ('is', 'is_not', 'in', 'not_in') and 9942 not self.is_c_string_contains() and 9943 not self.is_ptr_contains()) 9944 or (self.cascade and self.cascade.is_python_result())) 9945 9946 def is_c_string_contains(self): 9947 return self.operator in ('in', 'not_in') and \ 9948 ((self.operand1.type.is_int 9949 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or 9950 (self.operand1.type.is_unicode_char 9951 and self.operand2.type is unicode_type)) 9952 9953 def is_ptr_contains(self): 9954 if self.operator in ('in', 'not_in'): 9955 container_type = self.operand2.type 9956 return (container_type.is_ptr or container_type.is_array) \ 9957 and not container_type.is_string 9958 9959 def find_special_bool_compare_function(self, env, operand1, result_is_bool=False): 9960 # note: currently operand1 must get coerced to a Python object if we succeed here! 9961 if self.operator in ('==', '!='): 9962 type1, type2 = operand1.type, self.operand2.type 9963 if result_is_bool or (type1.is_builtin_type and type2.is_builtin_type): 9964 if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type: 9965 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") 9966 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" 9967 return True 9968 elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type: 9969 self.special_bool_cmp_utility_code = UtilityCode.load_cached("BytesEquals", "StringTools.c") 9970 self.special_bool_cmp_function = "__Pyx_PyBytes_Equals" 9971 return True 9972 elif type1 is Builtin.basestring_type or type2 is Builtin.basestring_type: 9973 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") 9974 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" 9975 return True 9976 elif type1 is Builtin.str_type or type2 is Builtin.str_type: 9977 self.special_bool_cmp_utility_code = UtilityCode.load_cached("StrEquals", "StringTools.c") 9978 self.special_bool_cmp_function = "__Pyx_PyString_Equals" 9979 return True 9980 elif self.operator in ('in', 'not_in'): 9981 if self.operand2.type is Builtin.dict_type: 9982 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 9983 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c") 9984 self.special_bool_cmp_function = "__Pyx_PyDict_Contains" 9985 return True 9986 elif self.operand2.type is Builtin.unicode_type: 9987 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 9988 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c") 9989 self.special_bool_cmp_function = "__Pyx_PyUnicode_Contains" 9990 return True 9991 else: 9992 if not self.operand2.type.is_pyobject: 9993 self.operand2 = self.operand2.coerce_to_pyobject(env) 9994 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySequenceContains", "ObjectHandling.c") 9995 self.special_bool_cmp_function = "__Pyx_PySequence_Contains" 9996 return True 9997 return False 9998 9999 def generate_operation_code(self, code, result_code, 10000 operand1, op , operand2): 10001 if self.type.is_pyobject: 10002 error_clause = code.error_goto_if_null 10003 got_ref = "__Pyx_XGOTREF(%s); " % result_code 10004 if self.special_bool_cmp_function: 10005 code.globalstate.use_utility_code( 10006 UtilityCode.load_cached("PyBoolOrNullFromLong", "ObjectHandling.c")) 10007 coerce_result = "__Pyx_PyBoolOrNull_FromLong" 10008 else: 10009 coerce_result = "__Pyx_PyBool_FromLong" 10010 else: 10011 error_clause = code.error_goto_if_neg 10012 got_ref = "" 10013 coerce_result = "" 10014 10015 if self.special_bool_cmp_function: 10016 if operand1.type.is_pyobject: 10017 result1 = operand1.py_result() 10018 else: 10019 result1 = operand1.result() 10020 if operand2.type.is_pyobject: 10021 result2 = operand2.py_result() 10022 else: 10023 result2 = operand2.result() 10024 if self.special_bool_cmp_utility_code: 10025 code.globalstate.use_utility_code(self.special_bool_cmp_utility_code) 10026 code.putln( 10027 "%s = %s(%s(%s, %s, %s)); %s%s" % ( 10028 result_code, 10029 coerce_result, 10030 self.special_bool_cmp_function, 10031 result1, result2, richcmp_constants[op], 10032 got_ref, 10033 error_clause(result_code, self.pos))) 10034 10035 elif operand1.type.is_pyobject and op not in ('is', 'is_not'): 10036 assert op not in ('in', 'not_in'), op 10037 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s%s" % ( 10038 result_code, 10039 operand1.py_result(), 10040 operand2.py_result(), 10041 richcmp_constants[op], 10042 got_ref, 10043 error_clause(result_code, self.pos))) 10044 10045 elif operand1.type.is_complex: 10046 code.putln("%s = %s(%s%s(%s, %s));" % ( 10047 result_code, 10048 coerce_result, 10049 op == "!=" and "!" or "", 10050 operand1.type.unary_op('eq'), 10051 operand1.result(), 10052 operand2.result())) 10053 10054 else: 10055 type1 = operand1.type 10056 type2 = operand2.type 10057 if (type1.is_extension_type or type2.is_extension_type) \ 10058 and not type1.same_as(type2): 10059 common_type = py_object_type 10060 elif type1.is_numeric: 10061 common_type = PyrexTypes.widest_numeric_type(type1, type2) 10062 else: 10063 common_type = type1 10064 code1 = operand1.result_as(common_type) 10065 code2 = operand2.result_as(common_type) 10066 code.putln("%s = %s(%s %s %s);" % ( 10067 result_code, 10068 coerce_result, 10069 code1, 10070 self.c_operator(op), 10071 code2)) 10072 10073 def c_operator(self, op): 10074 if op == 'is': 10075 return "==" 10076 elif op == 'is_not': 10077 return "!=" 10078 else: 10079 return op 10080 10081 class PrimaryCmpNode(ExprNode, CmpNode): 10082 # Non-cascaded comparison or first comparison of 10083 # a cascaded sequence. 10084 # 10085 # operator string 10086 # operand1 ExprNode 10087 # operand2 ExprNode 10088 # cascade CascadedCmpNode 10089 10090 # We don't use the subexprs mechanism, because 10091 # things here are too complicated for it to handle. 10092 # Instead, we override all the framework methods 10093 # which use it. 10094 10095 child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade'] 10096 10097 cascade = None 10098 coerced_operand2 = None 10099 is_memslice_nonecheck = False 10100 10101 def infer_type(self, env): 10102 # TODO: Actually implement this (after merging with -unstable). 10103 return py_object_type 10104 10105 def type_dependencies(self, env): 10106 return () 10107 10108 def calculate_constant_result(self): 10109 assert not self.cascade 10110 self.calculate_cascaded_constant_result(self.operand1.constant_result) 10111 10112 def compile_time_value(self, denv): 10113 operand1 = self.operand1.compile_time_value(denv) 10114 return self.cascaded_compile_time_value(operand1, denv) 10115 10116 def analyse_types(self, env): 10117 self.operand1 = self.operand1.analyse_types(env) 10118 self.operand2 = self.operand2.analyse_types(env) 10119 if self.is_cpp_comparison(): 10120 self.analyse_cpp_comparison(env) 10121 if self.cascade: 10122 error(self.pos, "Cascading comparison not yet supported for cpp types.") 10123 return self 10124 10125 if self.analyse_memoryviewslice_comparison(env): 10126 return self 10127 10128 if self.cascade: 10129 self.cascade = self.cascade.analyse_types(env) 10130 10131 if self.operator in ('in', 'not_in'): 10132 if self.is_c_string_contains(): 10133 self.is_pycmp = False 10134 common_type = None 10135 if self.cascade: 10136 error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.") 10137 return self 10138 if self.operand2.type is unicode_type: 10139 env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicode", "StringTools.c")) 10140 else: 10141 if self.operand1.type is PyrexTypes.c_uchar_type: 10142 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env) 10143 if self.operand2.type is not bytes_type: 10144 self.operand2 = self.operand2.coerce_to(bytes_type, env) 10145 env.use_utility_code(UtilityCode.load_cached("BytesContains", "StringTools.c")) 10146 self.operand2 = self.operand2.as_none_safe_node( 10147 "argument of type 'NoneType' is not iterable") 10148 elif self.is_ptr_contains(): 10149 if self.cascade: 10150 error(self.pos, "Cascading comparison not supported for 'val in sliced pointer'.") 10151 self.type = PyrexTypes.c_bint_type 10152 # Will be transformed by IterationTransform 10153 return self 10154 elif self.find_special_bool_compare_function(env, self.operand1): 10155 if not self.operand1.type.is_pyobject: 10156 self.operand1 = self.operand1.coerce_to_pyobject(env) 10157 common_type = None # if coercion needed, the method call above has already done it 10158 self.is_pycmp = False # result is bint 10159 else: 10160 common_type = py_object_type 10161 self.is_pycmp = True 10162 elif self.find_special_bool_compare_function(env, self.operand1): 10163 if not self.operand1.type.is_pyobject: 10164 self.operand1 = self.operand1.coerce_to_pyobject(env) 10165 common_type = None # if coercion needed, the method call above has already done it 10166 self.is_pycmp = False # result is bint 10167 else: 10168 common_type = self.find_common_type(env, self.operator, self.operand1) 10169 self.is_pycmp = common_type.is_pyobject 10170 10171 if common_type is not None and not common_type.is_error: 10172 if self.operand1.type != common_type: 10173 self.operand1 = self.operand1.coerce_to(common_type, env) 10174 self.coerce_operands_to(common_type, env) 10175 10176 if self.cascade: 10177 self.operand2 = self.operand2.coerce_to_simple(env) 10178 self.cascade.coerce_cascaded_operands_to_temp(env) 10179 operand2 = self.cascade.optimise_comparison(self.operand2, env) 10180 if operand2 is not self.operand2: 10181 self.coerced_operand2 = operand2 10182 if self.is_python_result(): 10183 self.type = PyrexTypes.py_object_type 10184 else: 10185 self.type = PyrexTypes.c_bint_type 10186 cdr = self.cascade 10187 while cdr: 10188 cdr.type = self.type 10189 cdr = cdr.cascade 10190 if self.is_pycmp or self.cascade or self.special_bool_cmp_function: 10191 # 1) owned reference, 2) reused value, 3) potential function error return value 10192 self.is_temp = 1 10193 return self 10194 10195 def analyse_cpp_comparison(self, env): 10196 type1 = self.operand1.type 10197 type2 = self.operand2.type 10198 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) 10199 if entry is None: 10200 error(self.pos, "Invalid types for '%s' (%s, %s)" % 10201 (self.operator, type1, type2)) 10202 self.type = PyrexTypes.error_type 10203 self.result_code = "<error>" 10204 return 10205 func_type = entry.type 10206 if func_type.is_ptr: 10207 func_type = func_type.base_type 10208 if len(func_type.args) == 1: 10209 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) 10210 else: 10211 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) 10212 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) 10213 self.is_pycmp = False 10214 self.type = func_type.return_type 10215 10216 def analyse_memoryviewslice_comparison(self, env): 10217 have_none = self.operand1.is_none or self.operand2.is_none 10218 have_slice = (self.operand1.type.is_memoryviewslice or 10219 self.operand2.type.is_memoryviewslice) 10220 ops = ('==', '!=', 'is', 'is_not') 10221 if have_slice and have_none and self.operator in ops: 10222 self.is_pycmp = False 10223 self.type = PyrexTypes.c_bint_type 10224 self.is_memslice_nonecheck = True 10225 return True 10226 10227 return False 10228 10229 def coerce_to_boolean(self, env): 10230 if self.is_pycmp: 10231 # coercing to bool => may allow for more efficient comparison code 10232 if self.find_special_bool_compare_function( 10233 env, self.operand1, result_is_bool=True): 10234 self.is_pycmp = False 10235 self.type = PyrexTypes.c_bint_type 10236 self.is_temp = 1 10237 if self.cascade: 10238 operand2 = self.cascade.optimise_comparison( 10239 self.operand2, env, result_is_bool=True) 10240 if operand2 is not self.operand2: 10241 self.coerced_operand2 = operand2 10242 return self 10243 # TODO: check if we can optimise parts of the cascade here 10244 return ExprNode.coerce_to_boolean(self, env) 10245 10246 def has_python_operands(self): 10247 return (self.operand1.type.is_pyobject 10248 or self.operand2.type.is_pyobject) 10249 10250 def check_const(self): 10251 if self.cascade: 10252 self.not_const() 10253 return False 10254 else: 10255 return self.operand1.check_const() and self.operand2.check_const() 10256 10257 def calculate_result_code(self): 10258 if self.operand1.type.is_complex: 10259 if self.operator == "!=": 10260 negation = "!" 10261 else: 10262 negation = "" 10263 return "(%s%s(%s, %s))" % ( 10264 negation, 10265 self.operand1.type.binary_op('=='), 10266 self.operand1.result(), 10267 self.operand2.result()) 10268 elif self.is_c_string_contains(): 10269 if self.operand2.type is unicode_type: 10270 method = "__Pyx_UnicodeContainsUCS4" 10271 else: 10272 method = "__Pyx_BytesContains" 10273 if self.operator == "not_in": 10274 negation = "!" 10275 else: 10276 negation = "" 10277 return "(%s%s(%s, %s))" % ( 10278 negation, 10279 method, 10280 self.operand2.result(), 10281 self.operand1.result()) 10282 else: 10283 result1 = self.operand1.result() 10284 result2 = self.operand2.result() 10285 if self.is_memslice_nonecheck: 10286 if self.operand1.type.is_memoryviewslice: 10287 result1 = "((PyObject *) %s.memview)" % result1 10288 else: 10289 result2 = "((PyObject *) %s.memview)" % result2 10290 10291 return "(%s %s %s)" % ( 10292 result1, 10293 self.c_operator(self.operator), 10294 result2) 10295 10296 def generate_evaluation_code(self, code): 10297 self.operand1.generate_evaluation_code(code) 10298 self.operand2.generate_evaluation_code(code) 10299 if self.is_temp: 10300 self.allocate_temp_result(code) 10301 self.generate_operation_code(code, self.result(), 10302 self.operand1, self.operator, self.operand2) 10303 if self.cascade: 10304 self.cascade.generate_evaluation_code( 10305 code, self.result(), self.coerced_operand2 or self.operand2, 10306 needs_evaluation=self.coerced_operand2 is not None) 10307 self.operand1.generate_disposal_code(code) 10308 self.operand1.free_temps(code) 10309 self.operand2.generate_disposal_code(code) 10310 self.operand2.free_temps(code) 10311 10312 def generate_subexpr_disposal_code(self, code): 10313 # If this is called, it is a non-cascaded cmp, 10314 # so only need to dispose of the two main operands. 10315 self.operand1.generate_disposal_code(code) 10316 self.operand2.generate_disposal_code(code) 10317 10318 def free_subexpr_temps(self, code): 10319 # If this is called, it is a non-cascaded cmp, 10320 # so only need to dispose of the two main operands. 10321 self.operand1.free_temps(code) 10322 self.operand2.free_temps(code) 10323 10324 def annotate(self, code): 10325 self.operand1.annotate(code) 10326 self.operand2.annotate(code) 10327 if self.cascade: 10328 self.cascade.annotate(code) 10329 10330 10331 class CascadedCmpNode(Node, CmpNode): 10332 # A CascadedCmpNode is not a complete expression node. It 10333 # hangs off the side of another comparison node, shares 10334 # its left operand with that node, and shares its result 10335 # with the PrimaryCmpNode at the head of the chain. 10336 # 10337 # operator string 10338 # operand2 ExprNode 10339 # cascade CascadedCmpNode 10340 10341 child_attrs = ['operand2', 'coerced_operand2', 'cascade'] 10342 10343 cascade = None 10344 coerced_operand2 = None 10345 constant_result = constant_value_not_set # FIXME: where to calculate this? 10346 10347 def infer_type(self, env): 10348 # TODO: Actually implement this (after merging with -unstable). 10349 return py_object_type 10350 10351 def type_dependencies(self, env): 10352 return () 10353 10354 def has_constant_result(self): 10355 return self.constant_result is not constant_value_not_set and \ 10356 self.constant_result is not not_a_constant 10357 10358 def analyse_types(self, env): 10359 self.operand2 = self.operand2.analyse_types(env) 10360 if self.cascade: 10361 self.cascade = self.cascade.analyse_types(env) 10362 return self 10363 10364 def has_python_operands(self): 10365 return self.operand2.type.is_pyobject 10366 10367 def optimise_comparison(self, operand1, env, result_is_bool=False): 10368 if self.find_special_bool_compare_function(env, operand1, result_is_bool): 10369 self.is_pycmp = False 10370 self.type = PyrexTypes.c_bint_type 10371 if not operand1.type.is_pyobject: 10372 operand1 = operand1.coerce_to_pyobject(env) 10373 if self.cascade: 10374 operand2 = self.cascade.optimise_comparison(self.operand2, env, result_is_bool) 10375 if operand2 is not self.operand2: 10376 self.coerced_operand2 = operand2 10377 return operand1 10378 10379 def coerce_operands_to_pyobjects(self, env): 10380 self.operand2 = self.operand2.coerce_to_pyobject(env) 10381 if self.operand2.type is dict_type and self.operator in ('in', 'not_in'): 10382 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 10383 if self.cascade: 10384 self.cascade.coerce_operands_to_pyobjects(env) 10385 10386 def coerce_cascaded_operands_to_temp(self, env): 10387 if self.cascade: 10388 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT 10389 self.operand2 = self.operand2.coerce_to_simple(env) 10390 self.cascade.coerce_cascaded_operands_to_temp(env) 10391 10392 def generate_evaluation_code(self, code, result, operand1, needs_evaluation=False): 10393 if self.type.is_pyobject: 10394 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result) 10395 code.put_decref(result, self.type) 10396 else: 10397 code.putln("if (%s) {" % result) 10398 if needs_evaluation: 10399 operand1.generate_evaluation_code(code) 10400 self.operand2.generate_evaluation_code(code) 10401 self.generate_operation_code(code, result, 10402 operand1, self.operator, self.operand2) 10403 if self.cascade: 10404 self.cascade.generate_evaluation_code( 10405 code, result, self.coerced_operand2 or self.operand2, 10406 needs_evaluation=self.coerced_operand2 is not None) 10407 if needs_evaluation: 10408 operand1.generate_disposal_code(code) 10409 operand1.free_temps(code) 10410 # Cascaded cmp result is always temp 10411 self.operand2.generate_disposal_code(code) 10412 self.operand2.free_temps(code) 10413 code.putln("}") 10414 10415 def annotate(self, code): 10416 self.operand2.annotate(code) 10417 if self.cascade: 10418 self.cascade.annotate(code) 10419 10420 10421 binop_node_classes = { 10422 "or": BoolBinopNode, 10423 "and": BoolBinopNode, 10424 "|": IntBinopNode, 10425 "^": IntBinopNode, 10426 "&": IntBinopNode, 10427 "<<": IntBinopNode, 10428 ">>": IntBinopNode, 10429 "+": AddNode, 10430 "-": SubNode, 10431 "*": MulNode, 10432 "/": DivNode, 10433 "//": DivNode, 10434 "%": ModNode, 10435 "**": PowNode 10436 } 10437 10438 def binop_node(pos, operator, operand1, operand2, inplace=False): 10439 # Construct binop node of appropriate class for 10440 # given operator. 10441 return binop_node_classes[operator](pos, 10442 operator = operator, 10443 operand1 = operand1, 10444 operand2 = operand2, 10445 inplace = inplace) 10446 10447 #------------------------------------------------------------------- 10448 # 10449 # Coercion nodes 10450 # 10451 # Coercion nodes are special in that they are created during 10452 # the analyse_types phase of parse tree processing. 10453 # Their __init__ methods consequently incorporate some aspects 10454 # of that phase. 10455 # 10456 #------------------------------------------------------------------- 10457 10458 class CoercionNode(ExprNode): 10459 # Abstract base class for coercion nodes. 10460 # 10461 # arg ExprNode node being coerced 10462 10463 subexprs = ['arg'] 10464 constant_result = not_a_constant 10465 10466 def __init__(self, arg): 10467 super(CoercionNode, self).__init__(arg.pos) 10468 self.arg = arg 10469 if debug_coercion: 10470 print("%s Coercing %s" % (self, self.arg)) 10471 10472 def calculate_constant_result(self): 10473 # constant folding can break type coercion, so this is disabled 10474 pass 10475 10476 def annotate(self, code): 10477 self.arg.annotate(code) 10478 if self.arg.type != self.type: 10479 file, line, col = self.pos 10480 code.annotate((file, line, col-1), AnnotationItem( 10481 style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type))) 10482 10483 class CoerceToMemViewSliceNode(CoercionNode): 10484 """ 10485 Coerce an object to a memoryview slice. This holds a new reference in 10486 a managed temp. 10487 """ 10488 10489 def __init__(self, arg, dst_type, env): 10490 assert dst_type.is_memoryviewslice 10491 assert not arg.type.is_memoryviewslice 10492 CoercionNode.__init__(self, arg) 10493 self.type = dst_type 10494 self.is_temp = 1 10495 self.env = env 10496 self.use_managed_ref = True 10497 self.arg = arg 10498 10499 def generate_result_code(self, code): 10500 self.type.create_from_py_utility_code(self.env) 10501 code.putln("%s = %s(%s);" % (self.result(), 10502 self.type.from_py_function, 10503 self.arg.py_result())) 10504 10505 error_cond = self.type.error_condition(self.result()) 10506 code.putln(code.error_goto_if(error_cond, self.pos)) 10507 10508 10509 class CastNode(CoercionNode): 10510 # Wrap a node in a C type cast. 10511 10512 def __init__(self, arg, new_type): 10513 CoercionNode.__init__(self, arg) 10514 self.type = new_type 10515 10516 def may_be_none(self): 10517 return self.arg.may_be_none() 10518 10519 def calculate_result_code(self): 10520 return self.arg.result_as(self.type) 10521 10522 def generate_result_code(self, code): 10523 self.arg.generate_result_code(code) 10524 10525 10526 class PyTypeTestNode(CoercionNode): 10527 # This node is used to check that a generic Python 10528 # object is an instance of a particular extension type. 10529 # This node borrows the result of its argument node. 10530 10531 exact_builtin_type = True 10532 10533 def __init__(self, arg, dst_type, env, notnone=False): 10534 # The arg is know to be a Python object, and 10535 # the dst_type is known to be an extension type. 10536 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type" 10537 CoercionNode.__init__(self, arg) 10538 self.type = dst_type 10539 self.result_ctype = arg.ctype() 10540 self.notnone = notnone 10541 10542 nogil_check = Node.gil_error 10543 gil_message = "Python type test" 10544 10545 def analyse_types(self, env): 10546 return self 10547 10548 def may_be_none(self): 10549 if self.notnone: 10550 return False 10551 return self.arg.may_be_none() 10552 10553 def is_simple(self): 10554 return self.arg.is_simple() 10555 10556 def result_in_temp(self): 10557 return self.arg.result_in_temp() 10558 10559 def is_ephemeral(self): 10560 return self.arg.is_ephemeral() 10561 10562 def nonlocally_immutable(self): 10563 return self.arg.nonlocally_immutable() 10564 10565 def calculate_constant_result(self): 10566 # FIXME 10567 pass 10568 10569 def calculate_result_code(self): 10570 return self.arg.result() 10571 10572 def generate_result_code(self, code): 10573 if self.type.typeobj_is_available(): 10574 if self.type.is_builtin_type: 10575 type_test = self.type.type_test_code( 10576 self.arg.py_result(), 10577 self.notnone, exact=self.exact_builtin_type) 10578 else: 10579 type_test = self.type.type_test_code( 10580 self.arg.py_result(), self.notnone) 10581 code.globalstate.use_utility_code( 10582 UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c")) 10583 code.putln("if (!(%s)) %s" % ( 10584 type_test, code.error_goto(self.pos))) 10585 else: 10586 error(self.pos, "Cannot test type of extern C class " 10587 "without type object name specification") 10588 10589 def generate_post_assignment_code(self, code): 10590 self.arg.generate_post_assignment_code(code) 10591 10592 def free_temps(self, code): 10593 self.arg.free_temps(code) 10594 10595 10596 class NoneCheckNode(CoercionNode): 10597 # This node is used to check that a Python object is not None and 10598 # raises an appropriate exception (as specified by the creating 10599 # transform). 10600 10601 is_nonecheck = True 10602 10603 def __init__(self, arg, exception_type_cname, exception_message, 10604 exception_format_args): 10605 CoercionNode.__init__(self, arg) 10606 self.type = arg.type 10607 self.result_ctype = arg.ctype() 10608 self.exception_type_cname = exception_type_cname 10609 self.exception_message = exception_message 10610 self.exception_format_args = tuple(exception_format_args or ()) 10611 10612 nogil_check = None # this node only guards an operation that would fail already 10613 10614 def analyse_types(self, env): 10615 return self 10616 10617 def may_be_none(self): 10618 return False 10619 10620 def is_simple(self): 10621 return self.arg.is_simple() 10622 10623 def result_in_temp(self): 10624 return self.arg.result_in_temp() 10625 10626 def nonlocally_immutable(self): 10627 return self.arg.nonlocally_immutable() 10628 10629 def calculate_result_code(self): 10630 return self.arg.result() 10631 10632 def condition(self): 10633 if self.type.is_pyobject: 10634 return self.arg.py_result() 10635 elif self.type.is_memoryviewslice: 10636 return "((PyObject *) %s.memview)" % self.arg.result() 10637 else: 10638 raise Exception("unsupported type") 10639 10640 def put_nonecheck(self, code): 10641 code.putln( 10642 "if (unlikely(%s == Py_None)) {" % self.condition()) 10643 10644 if self.in_nogil_context: 10645 code.put_ensure_gil() 10646 10647 escape = StringEncoding.escape_byte_string 10648 if self.exception_format_args: 10649 code.putln('PyErr_Format(%s, "%s", %s);' % ( 10650 self.exception_type_cname, 10651 StringEncoding.escape_byte_string( 10652 self.exception_message.encode('UTF-8')), 10653 ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8')) 10654 for arg in self.exception_format_args ]))) 10655 else: 10656 code.putln('PyErr_SetString(%s, "%s");' % ( 10657 self.exception_type_cname, 10658 escape(self.exception_message.encode('UTF-8')))) 10659 10660 if self.in_nogil_context: 10661 code.put_release_ensured_gil() 10662 10663 code.putln(code.error_goto(self.pos)) 10664 code.putln("}") 10665 10666 def generate_result_code(self, code): 10667 self.put_nonecheck(code) 10668 10669 def generate_post_assignment_code(self, code): 10670 self.arg.generate_post_assignment_code(code) 10671 10672 def free_temps(self, code): 10673 self.arg.free_temps(code) 10674 10675 10676 class CoerceToPyTypeNode(CoercionNode): 10677 # This node is used to convert a C data type 10678 # to a Python object. 10679 10680 type = py_object_type 10681 is_temp = 1 10682 10683 def __init__(self, arg, env, type=py_object_type): 10684 if not arg.type.create_to_py_utility_code(env): 10685 error(arg.pos, "Cannot convert '%s' to Python object" % arg.type) 10686 elif arg.type.is_complex: 10687 # special case: complex coercion is so complex that it 10688 # uses a macro ("__pyx_PyComplex_FromComplex()"), for 10689 # which the argument must be simple 10690 arg = arg.coerce_to_simple(env) 10691 CoercionNode.__init__(self, arg) 10692 if type is py_object_type: 10693 # be specific about some known types 10694 if arg.type.is_string or arg.type.is_cpp_string: 10695 self.type = default_str_type(env) 10696 elif arg.type.is_pyunicode_ptr or arg.type.is_unicode_char: 10697 self.type = unicode_type 10698 elif arg.type.is_complex: 10699 self.type = Builtin.complex_type 10700 elif arg.type.is_string or arg.type.is_cpp_string: 10701 if (type not in (bytes_type, bytearray_type) 10702 and not env.directives['c_string_encoding']): 10703 error(arg.pos, 10704 "default encoding required for conversion from '%s' to '%s'" % 10705 (arg.type, type)) 10706 self.type = type 10707 else: 10708 # FIXME: check that the target type and the resulting type are compatible 10709 pass 10710 10711 if arg.type.is_memoryviewslice: 10712 # Register utility codes at this point 10713 arg.type.get_to_py_function(env, arg) 10714 10715 self.env = env 10716 10717 gil_message = "Converting to Python object" 10718 10719 def may_be_none(self): 10720 # FIXME: is this always safe? 10721 return False 10722 10723 def coerce_to_boolean(self, env): 10724 arg_type = self.arg.type 10725 if (arg_type == PyrexTypes.c_bint_type or 10726 (arg_type.is_pyobject and arg_type.name == 'bool')): 10727 return self.arg.coerce_to_temp(env) 10728 else: 10729 return CoerceToBooleanNode(self, env) 10730 10731 def coerce_to_integer(self, env): 10732 # If not already some C integer type, coerce to longint. 10733 if self.arg.type.is_int: 10734 return self.arg 10735 else: 10736 return self.arg.coerce_to(PyrexTypes.c_long_type, env) 10737 10738 def analyse_types(self, env): 10739 # The arg is always already analysed 10740 return self 10741 10742 def generate_result_code(self, code): 10743 arg_type = self.arg.type 10744 if arg_type.is_memoryviewslice: 10745 funccall = arg_type.get_to_py_function(self.env, self.arg) 10746 else: 10747 func = arg_type.to_py_function 10748 if arg_type.is_string or arg_type.is_cpp_string: 10749 if self.type in (bytes_type, str_type, unicode_type): 10750 func = func.replace("Object", self.type.name.title()) 10751 elif self.type is bytearray_type: 10752 func = func.replace("Object", "ByteArray") 10753 funccall = "%s(%s)" % (func, self.arg.result()) 10754 10755 code.putln('%s = %s; %s' % ( 10756 self.result(), 10757 funccall, 10758 code.error_goto_if_null(self.result(), self.pos))) 10759 10760 code.put_gotref(self.py_result()) 10761 10762 10763 class CoerceIntToBytesNode(CoerceToPyTypeNode): 10764 # This node is used to convert a C int type to a Python bytes 10765 # object. 10766 10767 is_temp = 1 10768 10769 def __init__(self, arg, env): 10770 arg = arg.coerce_to_simple(env) 10771 CoercionNode.__init__(self, arg) 10772 self.type = Builtin.bytes_type 10773 10774 def generate_result_code(self, code): 10775 arg = self.arg 10776 arg_result = arg.result() 10777 if arg.type not in (PyrexTypes.c_char_type, 10778 PyrexTypes.c_uchar_type, 10779 PyrexTypes.c_schar_type): 10780 if arg.type.signed: 10781 code.putln("if ((%s < 0) || (%s > 255)) {" % ( 10782 arg_result, arg_result)) 10783 else: 10784 code.putln("if (%s > 255) {" % arg_result) 10785 code.putln('PyErr_SetString(PyExc_OverflowError, ' 10786 '"value too large to pack into a byte"); %s' % ( 10787 code.error_goto(self.pos))) 10788 code.putln('}') 10789 temp = None 10790 if arg.type is not PyrexTypes.c_char_type: 10791 temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False) 10792 code.putln("%s = (char)%s;" % (temp, arg_result)) 10793 arg_result = temp 10794 code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % ( 10795 self.result(), 10796 arg_result, 10797 code.error_goto_if_null(self.result(), self.pos))) 10798 if temp is not None: 10799 code.funcstate.release_temp(temp) 10800 code.put_gotref(self.py_result()) 10801 10802 10803 class CoerceFromPyTypeNode(CoercionNode): 10804 # This node is used to convert a Python object 10805 # to a C data type. 10806 10807 def __init__(self, result_type, arg, env): 10808 CoercionNode.__init__(self, arg) 10809 self.type = result_type 10810 self.is_temp = 1 10811 if not result_type.create_from_py_utility_code(env): 10812 error(arg.pos, 10813 "Cannot convert Python object to '%s'" % result_type) 10814 if self.type.is_string or self.type.is_pyunicode_ptr: 10815 if self.arg.is_ephemeral(): 10816 error(arg.pos, 10817 "Obtaining '%s' from temporary Python value" % result_type) 10818 elif self.arg.is_name and self.arg.entry and self.arg.entry.is_pyglobal: 10819 warning(arg.pos, 10820 "Obtaining '%s' from externally modifiable global Python value" % result_type, 10821 level=1) 10822 10823 def analyse_types(self, env): 10824 # The arg is always already analysed 10825 return self 10826 10827 def generate_result_code(self, code): 10828 function = self.type.from_py_function 10829 operand = self.arg.py_result() 10830 rhs = "%s(%s)" % (function, operand) 10831 if self.type.is_enum: 10832 rhs = typecast(self.type, c_long_type, rhs) 10833 code.putln('%s = %s; %s' % ( 10834 self.result(), 10835 rhs, 10836 code.error_goto_if(self.type.error_condition(self.result()), self.pos))) 10837 if self.type.is_pyobject: 10838 code.put_gotref(self.py_result()) 10839 10840 def nogil_check(self, env): 10841 error(self.pos, "Coercion from Python not allowed without the GIL") 10842 10843 10844 class CoerceToBooleanNode(CoercionNode): 10845 # This node is used when a result needs to be used 10846 # in a boolean context. 10847 10848 type = PyrexTypes.c_bint_type 10849 10850 _special_builtins = { 10851 Builtin.list_type : 'PyList_GET_SIZE', 10852 Builtin.tuple_type : 'PyTuple_GET_SIZE', 10853 Builtin.bytes_type : 'PyBytes_GET_SIZE', 10854 Builtin.unicode_type : 'PyUnicode_GET_SIZE', 10855 } 10856 10857 def __init__(self, arg, env): 10858 CoercionNode.__init__(self, arg) 10859 if arg.type.is_pyobject: 10860 self.is_temp = 1 10861 10862 def nogil_check(self, env): 10863 if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None: 10864 self.gil_error() 10865 10866 gil_message = "Truth-testing Python object" 10867 10868 def check_const(self): 10869 if self.is_temp: 10870 self.not_const() 10871 return False 10872 return self.arg.check_const() 10873 10874 def calculate_result_code(self): 10875 return "(%s != 0)" % self.arg.result() 10876 10877 def generate_result_code(self, code): 10878 if not self.is_temp: 10879 return 10880 test_func = self._special_builtins.get(self.arg.type) 10881 if test_func is not None: 10882 code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % ( 10883 self.result(), 10884 self.arg.py_result(), 10885 test_func, 10886 self.arg.py_result())) 10887 else: 10888 code.putln( 10889 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( 10890 self.result(), 10891 self.arg.py_result(), 10892 code.error_goto_if_neg(self.result(), self.pos))) 10893 10894 class CoerceToComplexNode(CoercionNode): 10895 10896 def __init__(self, arg, dst_type, env): 10897 if arg.type.is_complex: 10898 arg = arg.coerce_to_simple(env) 10899 self.type = dst_type 10900 CoercionNode.__init__(self, arg) 10901 dst_type.create_declaration_utility_code(env) 10902 10903 def calculate_result_code(self): 10904 if self.arg.type.is_complex: 10905 real_part = "__Pyx_CREAL(%s)" % self.arg.result() 10906 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result() 10907 else: 10908 real_part = self.arg.result() 10909 imag_part = "0" 10910 return "%s(%s, %s)" % ( 10911 self.type.from_parts, 10912 real_part, 10913 imag_part) 10914 10915 def generate_result_code(self, code): 10916 pass 10917 10918 class CoerceToTempNode(CoercionNode): 10919 # This node is used to force the result of another node 10920 # to be stored in a temporary. It is only used if the 10921 # argument node's result is not already in a temporary. 10922 10923 def __init__(self, arg, env): 10924 CoercionNode.__init__(self, arg) 10925 self.type = self.arg.type.as_argument_type() 10926 self.constant_result = self.arg.constant_result 10927 self.is_temp = 1 10928 if self.type.is_pyobject: 10929 self.result_ctype = py_object_type 10930 10931 gil_message = "Creating temporary Python reference" 10932 10933 def analyse_types(self, env): 10934 # The arg is always already analysed 10935 return self 10936 10937 def coerce_to_boolean(self, env): 10938 self.arg = self.arg.coerce_to_boolean(env) 10939 if self.arg.is_simple(): 10940 return self.arg 10941 self.type = self.arg.type 10942 self.result_ctype = self.type 10943 return self 10944 10945 def generate_result_code(self, code): 10946 #self.arg.generate_evaluation_code(code) # Already done 10947 # by generic generate_subexpr_evaluation_code! 10948 code.putln("%s = %s;" % ( 10949 self.result(), self.arg.result_as(self.ctype()))) 10950 if self.use_managed_ref: 10951 if self.type.is_pyobject: 10952 code.put_incref(self.result(), self.ctype()) 10953 elif self.type.is_memoryviewslice: 10954 code.put_incref_memoryviewslice(self.result(), 10955 not self.in_nogil_context) 10956 10957 class ProxyNode(CoercionNode): 10958 """ 10959 A node that should not be replaced by transforms or other means, 10960 and hence can be useful to wrap the argument to a clone node 10961 10962 MyNode -> ProxyNode -> ArgNode 10963 CloneNode -^ 10964 """ 10965 10966 nogil_check = None 10967 10968 def __init__(self, arg): 10969 super(ProxyNode, self).__init__(arg) 10970 self.constant_result = arg.constant_result 10971 self._proxy_type() 10972 10973 def analyse_expressions(self, env): 10974 self.arg = self.arg.analyse_expressions(env) 10975 self._proxy_type() 10976 return self 10977 10978 def _proxy_type(self): 10979 if hasattr(self.arg, 'type'): 10980 self.type = self.arg.type 10981 self.result_ctype = self.arg.result_ctype 10982 if hasattr(self.arg, 'entry'): 10983 self.entry = self.arg.entry 10984 10985 def generate_result_code(self, code): 10986 self.arg.generate_result_code(code) 10987 10988 def result(self): 10989 return self.arg.result() 10990 10991 def is_simple(self): 10992 return self.arg.is_simple() 10993 10994 def may_be_none(self): 10995 return self.arg.may_be_none() 10996 10997 def generate_evaluation_code(self, code): 10998 self.arg.generate_evaluation_code(code) 10999 11000 def generate_result_code(self, code): 11001 self.arg.generate_result_code(code) 11002 11003 def generate_disposal_code(self, code): 11004 self.arg.generate_disposal_code(code) 11005 11006 def free_temps(self, code): 11007 self.arg.free_temps(code) 11008 11009 class CloneNode(CoercionNode): 11010 # This node is employed when the result of another node needs 11011 # to be used multiple times. The argument node's result must 11012 # be in a temporary. This node "borrows" the result from the 11013 # argument node, and does not generate any evaluation or 11014 # disposal code for it. The original owner of the argument 11015 # node is responsible for doing those things. 11016 11017 subexprs = [] # Arg is not considered a subexpr 11018 nogil_check = None 11019 11020 def __init__(self, arg): 11021 CoercionNode.__init__(self, arg) 11022 self.constant_result = arg.constant_result 11023 if hasattr(arg, 'type'): 11024 self.type = arg.type 11025 self.result_ctype = arg.result_ctype 11026 if hasattr(arg, 'entry'): 11027 self.entry = arg.entry 11028 11029 def result(self): 11030 return self.arg.result() 11031 11032 def may_be_none(self): 11033 return self.arg.may_be_none() 11034 11035 def type_dependencies(self, env): 11036 return self.arg.type_dependencies(env) 11037 11038 def infer_type(self, env): 11039 return self.arg.infer_type(env) 11040 11041 def analyse_types(self, env): 11042 self.type = self.arg.type 11043 self.result_ctype = self.arg.result_ctype 11044 self.is_temp = 1 11045 if hasattr(self.arg, 'entry'): 11046 self.entry = self.arg.entry 11047 return self 11048 11049 def is_simple(self): 11050 return True # result is always in a temp (or a name) 11051 11052 def generate_evaluation_code(self, code): 11053 pass 11054 11055 def generate_result_code(self, code): 11056 pass 11057 11058 def generate_disposal_code(self, code): 11059 pass 11060 11061 def free_temps(self, code): 11062 pass 11063 11064 11065 class CMethodSelfCloneNode(CloneNode): 11066 # Special CloneNode for the self argument of builtin C methods 11067 # that accepts subtypes of the builtin type. This is safe only 11068 # for 'final' subtypes, as subtypes of the declared type may 11069 # override the C method. 11070 11071 def coerce_to(self, dst_type, env): 11072 if dst_type.is_builtin_type and self.type.subtype_of(dst_type): 11073 return self 11074 return CloneNode.coerce_to(self, dst_type, env) 11075 11076 11077 class ModuleRefNode(ExprNode): 11078 # Simple returns the module object 11079 11080 type = py_object_type 11081 is_temp = False 11082 subexprs = [] 11083 11084 def analyse_types(self, env): 11085 return self 11086 11087 def may_be_none(self): 11088 return False 11089 11090 def calculate_result_code(self): 11091 return Naming.module_cname 11092 11093 def generate_result_code(self, code): 11094 pass 11095 11096 class DocstringRefNode(ExprNode): 11097 # Extracts the docstring of the body element 11098 11099 subexprs = ['body'] 11100 type = py_object_type 11101 is_temp = True 11102 11103 def __init__(self, pos, body): 11104 ExprNode.__init__(self, pos) 11105 assert body.type.is_pyobject 11106 self.body = body 11107 11108 def analyse_types(self, env): 11109 return self 11110 11111 def generate_result_code(self, code): 11112 code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % ( 11113 self.result(), self.body.result(), 11114 code.intern_identifier(StringEncoding.EncodedString("__doc__")), 11115 code.error_goto_if_null(self.result(), self.pos))) 11116 code.put_gotref(self.result()) 11117 11118 11119 11120 #------------------------------------------------------------------------------------ 11121 # 11122 # Runtime support code 11123 # 11124 #------------------------------------------------------------------------------------ 11125 11126 pyerr_occurred_withgil_utility_code= UtilityCode( 11127 proto = """ 11128 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */ 11129 """, 11130 impl = """ 11131 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { 11132 int err; 11133 #ifdef WITH_THREAD 11134 PyGILState_STATE _save = PyGILState_Ensure(); 11135 #endif 11136 err = !!PyErr_Occurred(); 11137 #ifdef WITH_THREAD 11138 PyGILState_Release(_save); 11139 #endif 11140 return err; 11141 } 11142 """ 11143 ) 11144 11145 #------------------------------------------------------------------------------------ 11146 11147 raise_unbound_local_error_utility_code = UtilityCode( 11148 proto = """ 11149 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); 11150 """, 11151 impl = """ 11152 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { 11153 PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); 11154 } 11155 """) 11156 11157 raise_closure_name_error_utility_code = UtilityCode( 11158 proto = """ 11159 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname); 11160 """, 11161 impl = """ 11162 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) { 11163 PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname); 11164 } 11165 """) 11166 11167 # Don't inline the function, it should really never be called in production 11168 raise_unbound_memoryview_utility_code_nogil = UtilityCode( 11169 proto = """ 11170 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname); 11171 """, 11172 impl = """ 11173 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) { 11174 #ifdef WITH_THREAD 11175 PyGILState_STATE gilstate = PyGILState_Ensure(); 11176 #endif 11177 __Pyx_RaiseUnboundLocalError(varname); 11178 #ifdef WITH_THREAD 11179 PyGILState_Release(gilstate); 11180 #endif 11181 } 11182 """, 11183 requires = [raise_unbound_local_error_utility_code]) 11184 11185 #------------------------------------------------------------------------------------ 11186 11187 raise_too_many_values_to_unpack = UtilityCode.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c") 11188 raise_need_more_values_to_unpack = UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c") 11189 tuple_unpacking_error_code = UtilityCode.load_cached("UnpackTupleError", "ObjectHandling.c") 11190 11191 #------------------------------------------------------------------------------------ 11192 11193 int_pow_utility_code = UtilityCode( 11194 proto=""" 11195 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */ 11196 """, 11197 impl=""" 11198 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) { 11199 %(type)s t = b; 11200 switch (e) { 11201 case 3: 11202 t *= b; 11203 case 2: 11204 t *= b; 11205 case 1: 11206 return t; 11207 case 0: 11208 return 1; 11209 } 11210 #if %(signed)s 11211 if (unlikely(e<0)) return 0; 11212 #endif 11213 t = 1; 11214 while (likely(e)) { 11215 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */ 11216 b *= b; 11217 e >>= 1; 11218 } 11219 return t; 11220 } 11221 """) 11222 11223 # ------------------------------ Division ------------------------------------ 11224 11225 div_int_utility_code = UtilityCode( 11226 proto=""" 11227 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */ 11228 """, 11229 impl=""" 11230 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) { 11231 %(type)s q = a / b; 11232 %(type)s r = a - q*b; 11233 q -= ((r != 0) & ((r ^ b) < 0)); 11234 return q; 11235 } 11236 """) 11237 11238 mod_int_utility_code = UtilityCode( 11239 proto=""" 11240 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */ 11241 """, 11242 impl=""" 11243 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { 11244 %(type)s r = a %% b; 11245 r += ((r != 0) & ((r ^ b) < 0)) * b; 11246 return r; 11247 } 11248 """) 11249 11250 mod_float_utility_code = UtilityCode( 11251 proto=""" 11252 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */ 11253 """, 11254 impl=""" 11255 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { 11256 %(type)s r = fmod%(math_h_modifier)s(a, b); 11257 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b; 11258 return r; 11259 } 11260 """) 11261 11262 cdivision_warning_utility_code = UtilityCode( 11263 proto=""" 11264 static int __Pyx_cdivision_warning(const char *, int); /* proto */ 11265 """, 11266 impl=""" 11267 static int __Pyx_cdivision_warning(const char *filename, int lineno) { 11268 #if CYTHON_COMPILING_IN_PYPY 11269 filename++; // avoid compiler warnings 11270 lineno++; 11271 return PyErr_Warn(PyExc_RuntimeWarning, 11272 "division with oppositely signed operands, C and Python semantics differ"); 11273 #else 11274 return PyErr_WarnExplicit(PyExc_RuntimeWarning, 11275 "division with oppositely signed operands, C and Python semantics differ", 11276 filename, 11277 lineno, 11278 __Pyx_MODULE_NAME, 11279 NULL); 11280 #endif 11281 } 11282 """) 11283 11284 # from intobject.c 11285 division_overflow_test_code = UtilityCode( 11286 proto=""" 11287 #define UNARY_NEG_WOULD_OVERFLOW(x) \ 11288 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) 11289 """) 11290