1# 2# Parse tree nodes for expressions 3# 4 5from __future__ import absolute_import 6 7import cython 8cython.declare(error=object, warning=object, warn_once=object, InternalError=object, 9 CompileError=object, UtilityCode=object, TempitaUtilityCode=object, 10 StringEncoding=object, operator=object, local_errors=object, report_error=object, 11 Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object, 12 list_type=object, tuple_type=object, set_type=object, dict_type=object, 13 unicode_type=object, str_type=object, bytes_type=object, type_type=object, 14 Builtin=object, Symtab=object, Utils=object, find_coercion_error=object, 15 debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object, 16 bytearray_type=object, slice_type=object, _py_int_types=object, 17 IS_PYTHON3=cython.bint) 18 19import re 20import sys 21import copy 22import os.path 23import operator 24 25from .Errors import ( 26 error, warning, InternalError, CompileError, report_error, local_errors) 27from .Code import UtilityCode, TempitaUtilityCode 28from . import StringEncoding 29from . import Naming 30from . import Nodes 31from .Nodes import Node, utility_code_for_imports, analyse_type_annotation 32from . import PyrexTypes 33from .PyrexTypes import py_object_type, c_long_type, typecast, error_type, \ 34 unspecified_type 35from . import TypeSlots 36from .Builtin import list_type, tuple_type, set_type, dict_type, type_type, \ 37 unicode_type, str_type, bytes_type, bytearray_type, basestring_type, slice_type 38from . import Builtin 39from . import Symtab 40from .. import Utils 41from .Annotate import AnnotationItem 42from . import Future 43from ..Debugging import print_call_chain 44from .DebugFlags import debug_disposal_code, debug_temp_alloc, \ 45 debug_coercion 46from .Pythran import (to_pythran, is_pythran_supported_type, is_pythran_supported_operation_type, 47 is_pythran_expr, pythran_func_type, pythran_binop_type, pythran_unaryop_type, has_np_pythran, 48 pythran_indexing_code, pythran_indexing_type, is_pythran_supported_node_or_none, pythran_type, 49 pythran_is_numpy_func_supported, pythran_get_func_include_file, pythran_functor) 50from .PyrexTypes import PythranExpr 51 52try: 53 from __builtin__ import basestring 54except ImportError: 55 # Python 3 56 basestring = str 57 any_string_type = (bytes, str) 58else: 59 # Python 2 60 any_string_type = (bytes, unicode) 61 62 63if sys.version_info[0] >= 3: 64 IS_PYTHON3 = True 65 _py_int_types = int 66else: 67 IS_PYTHON3 = False 68 _py_int_types = (int, long) 69 70 71class NotConstant(object): 72 _obj = None 73 74 def __new__(cls): 75 if NotConstant._obj is None: 76 NotConstant._obj = super(NotConstant, cls).__new__(cls) 77 78 return NotConstant._obj 79 80 def __repr__(self): 81 return "<NOT CONSTANT>" 82 83not_a_constant = NotConstant() 84constant_value_not_set = object() 85 86# error messages when coercing from key[0] to key[1] 87coercion_error_dict = { 88 # string related errors 89 (unicode_type, str_type): ("Cannot convert Unicode string to 'str' implicitly." 90 " This is not portable and requires explicit encoding."), 91 (unicode_type, bytes_type): "Cannot convert Unicode string to 'bytes' implicitly, encoding required.", 92 (unicode_type, PyrexTypes.c_char_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", 93 (unicode_type, PyrexTypes.c_const_char_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", 94 (unicode_type, PyrexTypes.c_uchar_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", 95 (unicode_type, PyrexTypes.c_const_uchar_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.", 96 (bytes_type, unicode_type): "Cannot convert 'bytes' object to unicode implicitly, decoding required", 97 (bytes_type, str_type): "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.", 98 (bytes_type, basestring_type): ("Cannot convert 'bytes' object to basestring implicitly." 99 " This is not portable to Py3."), 100 (bytes_type, PyrexTypes.c_py_unicode_ptr_type): "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.", 101 (bytes_type, PyrexTypes.c_const_py_unicode_ptr_type): ( 102 "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'."), 103 (basestring_type, bytes_type): "Cannot convert 'basestring' object to bytes implicitly. This is not portable.", 104 (str_type, unicode_type): ("str objects do not support coercion to unicode," 105 " use a unicode string literal instead (u'')"), 106 (str_type, bytes_type): "Cannot convert 'str' to 'bytes' implicitly. This is not portable.", 107 (str_type, PyrexTypes.c_char_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", 108 (str_type, PyrexTypes.c_const_char_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", 109 (str_type, PyrexTypes.c_uchar_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", 110 (str_type, PyrexTypes.c_const_uchar_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).", 111 (str_type, PyrexTypes.c_py_unicode_ptr_type): "'str' objects do not support coercion to C types (use 'unicode'?).", 112 (str_type, PyrexTypes.c_const_py_unicode_ptr_type): ( 113 "'str' objects do not support coercion to C types (use 'unicode'?)."), 114 (PyrexTypes.c_char_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required", 115 (PyrexTypes.c_const_char_ptr_type, unicode_type): ( 116 "Cannot convert 'char*' to unicode implicitly, decoding required"), 117 (PyrexTypes.c_uchar_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required", 118 (PyrexTypes.c_const_uchar_ptr_type, unicode_type): ( 119 "Cannot convert 'char*' to unicode implicitly, decoding required"), 120} 121 122def find_coercion_error(type_tuple, default, env): 123 err = coercion_error_dict.get(type_tuple) 124 if err is None: 125 return default 126 elif (env.directives['c_string_encoding'] and 127 any(t in type_tuple for t in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_uchar_ptr_type, 128 PyrexTypes.c_const_char_ptr_type, PyrexTypes.c_const_uchar_ptr_type))): 129 if type_tuple[1].is_pyobject: 130 return default 131 elif env.directives['c_string_encoding'] in ('ascii', 'default'): 132 return default 133 else: 134 return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple[0].name 135 else: 136 return err 137 138 139def default_str_type(env): 140 return { 141 'bytes': bytes_type, 142 'bytearray': bytearray_type, 143 'str': str_type, 144 'unicode': unicode_type 145 }.get(env.directives['c_string_type']) 146 147 148def check_negative_indices(*nodes): 149 """ 150 Raise a warning on nodes that are known to have negative numeric values. 151 Used to find (potential) bugs inside of "wraparound=False" sections. 152 """ 153 for node in nodes: 154 if node is None or ( 155 not isinstance(node.constant_result, _py_int_types) and 156 not isinstance(node.constant_result, float)): 157 continue 158 if node.constant_result < 0: 159 warning(node.pos, 160 "the result of using negative indices inside of " 161 "code sections marked as 'wraparound=False' is " 162 "undefined", level=1) 163 164 165def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None): 166 if not seq_node.is_sequence_constructor: 167 if seq_type is None: 168 seq_type = seq_node.infer_type(env) 169 if seq_type is tuple_type: 170 # tuples are immutable => we can safely follow assignments 171 if seq_node.cf_state and len(seq_node.cf_state) == 1: 172 try: 173 seq_node = seq_node.cf_state[0].rhs 174 except AttributeError: 175 pass 176 if seq_node is not None and seq_node.is_sequence_constructor: 177 if index_node is not None and index_node.has_constant_result(): 178 try: 179 item = seq_node.args[index_node.constant_result] 180 except (ValueError, TypeError, IndexError): 181 pass 182 else: 183 return item.infer_type(env) 184 # if we're lucky, all items have the same type 185 item_types = set([item.infer_type(env) for item in seq_node.args]) 186 if len(item_types) == 1: 187 return item_types.pop() 188 return None 189 190 191def make_dedup_key(outer_type, item_nodes): 192 """ 193 Recursively generate a deduplication key from a sequence of values. 194 Includes Cython node types to work around the fact that (1, 2.0) == (1.0, 2), for example. 195 196 @param outer_type: The type of the outer container. 197 @param item_nodes: A sequence of constant nodes that will be traversed recursively. 198 @return: A tuple that can be used as a dict key for deduplication. 199 """ 200 item_keys = [ 201 (py_object_type, None, type(None)) if node is None 202 # For sequences and their "mult_factor", see TupleNode. 203 else make_dedup_key(node.type, [node.mult_factor if node.is_literal else None] + node.args) if node.is_sequence_constructor 204 else make_dedup_key(node.type, (node.start, node.stop, node.step)) if node.is_slice 205 # For constants, look at the Python value type if we don't know the concrete Cython type. 206 else (node.type, node.constant_result, 207 type(node.constant_result) if node.type is py_object_type else None) if node.has_constant_result() 208 else None # something we cannot handle => short-circuit below 209 for node in item_nodes 210 ] 211 if None in item_keys: 212 return None 213 return outer_type, tuple(item_keys) 214 215 216# Returns a block of code to translate the exception, 217# plus a boolean indicating whether to check for Python exceptions. 218def get_exception_handler(exception_value): 219 if exception_value is None: 220 return "__Pyx_CppExn2PyErr();", False 221 elif (exception_value.type == PyrexTypes.c_char_type 222 and exception_value.value == '*'): 223 return "__Pyx_CppExn2PyErr();", True 224 elif exception_value.type.is_pyobject: 225 return ( 226 'try { throw; } catch(const std::exception& exn) {' 227 'PyErr_SetString(%s, exn.what());' 228 '} catch(...) { PyErr_SetNone(%s); }' % ( 229 exception_value.entry.cname, 230 exception_value.entry.cname), 231 False) 232 else: 233 return ( 234 '%s(); if (!PyErr_Occurred())' 235 'PyErr_SetString(PyExc_RuntimeError, ' 236 '"Error converting c++ exception.");' % ( 237 exception_value.entry.cname), 238 False) 239 240def maybe_check_py_error(code, check_py_exception, pos, nogil): 241 if check_py_exception: 242 if nogil: 243 code.putln(code.error_goto_if("__Pyx_ErrOccurredWithGIL()", pos)) 244 else: 245 code.putln(code.error_goto_if("PyErr_Occurred()", pos)) 246 247def translate_cpp_exception(code, pos, inside, py_result, exception_value, nogil): 248 raise_py_exception, check_py_exception = get_exception_handler(exception_value) 249 code.putln("try {") 250 code.putln("%s" % inside) 251 if py_result: 252 code.putln(code.error_goto_if_null(py_result, pos)) 253 maybe_check_py_error(code, check_py_exception, pos, nogil) 254 code.putln("} catch(...) {") 255 if nogil: 256 code.put_ensure_gil(declare_gilstate=True) 257 code.putln(raise_py_exception) 258 if nogil: 259 code.put_release_ensured_gil() 260 code.putln(code.error_goto(pos)) 261 code.putln("}") 262 263# Used to handle the case where an lvalue expression and an overloaded assignment 264# both have an exception declaration. 265def translate_double_cpp_exception(code, pos, lhs_type, lhs_code, rhs_code, 266 lhs_exc_val, assign_exc_val, nogil): 267 handle_lhs_exc, lhc_check_py_exc = get_exception_handler(lhs_exc_val) 268 handle_assignment_exc, assignment_check_py_exc = get_exception_handler(assign_exc_val) 269 code.putln("try {") 270 code.putln(lhs_type.declaration_code("__pyx_local_lvalue = %s;" % lhs_code)) 271 maybe_check_py_error(code, lhc_check_py_exc, pos, nogil) 272 code.putln("try {") 273 code.putln("__pyx_local_lvalue = %s;" % rhs_code) 274 maybe_check_py_error(code, assignment_check_py_exc, pos, nogil) 275 # Catch any exception from the overloaded assignment. 276 code.putln("} catch(...) {") 277 if nogil: 278 code.put_ensure_gil(declare_gilstate=True) 279 code.putln(handle_assignment_exc) 280 if nogil: 281 code.put_release_ensured_gil() 282 code.putln(code.error_goto(pos)) 283 code.putln("}") 284 # Catch any exception from evaluating lhs. 285 code.putln("} catch(...) {") 286 if nogil: 287 code.put_ensure_gil(declare_gilstate=True) 288 code.putln(handle_lhs_exc) 289 if nogil: 290 code.put_release_ensured_gil() 291 code.putln(code.error_goto(pos)) 292 code.putln('}') 293 294 295class ExprNode(Node): 296 # subexprs [string] Class var holding names of subexpr node attrs 297 # type PyrexType Type of the result 298 # result_code string Code fragment 299 # result_ctype string C type of result_code if different from type 300 # is_temp boolean Result is in a temporary variable 301 # is_sequence_constructor 302 # boolean Is a list or tuple constructor expression 303 # is_starred boolean Is a starred expression (e.g. '*a') 304 # saved_subexpr_nodes 305 # [ExprNode or [ExprNode or None] or None] 306 # Cached result of subexpr_nodes() 307 # use_managed_ref boolean use ref-counted temps/assignments/etc. 308 # result_is_used boolean indicates that the result will be dropped and the 309 # is_numpy_attribute boolean Is a Numpy module attribute 310 # result_code/temp_result can safely be set to None 311 # annotation ExprNode or None PEP526 annotation for names or expressions 312 313 result_ctype = None 314 type = None 315 annotation = None 316 temp_code = None 317 old_temp = None # error checker for multiple frees etc. 318 use_managed_ref = True # can be set by optimisation transforms 319 result_is_used = True 320 is_numpy_attribute = False 321 322 # The Analyse Expressions phase for expressions is split 323 # into two sub-phases: 324 # 325 # Analyse Types 326 # Determines the result type of the expression based 327 # on the types of its sub-expressions, and inserts 328 # coercion nodes into the expression tree where needed. 329 # Marks nodes which will need to have temporary variables 330 # allocated. 331 # 332 # Allocate Temps 333 # Allocates temporary variables where needed, and fills 334 # in the result_code field of each node. 335 # 336 # ExprNode provides some convenience routines which 337 # perform both of the above phases. These should only 338 # be called from statement nodes, and only when no 339 # coercion nodes need to be added around the expression 340 # being analysed. In that case, the above two phases 341 # should be invoked separately. 342 # 343 # Framework code in ExprNode provides much of the common 344 # processing for the various phases. It makes use of the 345 # 'subexprs' class attribute of ExprNodes, which should 346 # contain a list of the names of attributes which can 347 # hold sub-nodes or sequences of sub-nodes. 348 # 349 # The framework makes use of a number of abstract methods. 350 # Their responsibilities are as follows. 351 # 352 # Declaration Analysis phase 353 # 354 # analyse_target_declaration 355 # Called during the Analyse Declarations phase to analyse 356 # the LHS of an assignment or argument of a del statement. 357 # Nodes which cannot be the LHS of an assignment need not 358 # implement it. 359 # 360 # Expression Analysis phase 361 # 362 # analyse_types 363 # - Call analyse_types on all sub-expressions. 364 # - Check operand types, and wrap coercion nodes around 365 # sub-expressions where needed. 366 # - Set the type of this node. 367 # - If a temporary variable will be required for the 368 # result, set the is_temp flag of this node. 369 # 370 # analyse_target_types 371 # Called during the Analyse Types phase to analyse 372 # the LHS of an assignment or argument of a del 373 # statement. Similar responsibilities to analyse_types. 374 # 375 # target_code 376 # Called by the default implementation of allocate_target_temps. 377 # Should return a C lvalue for assigning to the node. The default 378 # implementation calls calculate_result_code. 379 # 380 # check_const 381 # - Check that this node and its subnodes form a 382 # legal constant expression. If so, do nothing, 383 # otherwise call not_const. 384 # 385 # The default implementation of check_const 386 # assumes that the expression is not constant. 387 # 388 # check_const_addr 389 # - Same as check_const, except check that the 390 # expression is a C lvalue whose address is 391 # constant. Otherwise, call addr_not_const. 392 # 393 # The default implementation of calc_const_addr 394 # assumes that the expression is not a constant 395 # lvalue. 396 # 397 # Code Generation phase 398 # 399 # generate_evaluation_code 400 # - Call generate_evaluation_code for sub-expressions. 401 # - Perform the functions of generate_result_code 402 # (see below). 403 # - If result is temporary, call generate_disposal_code 404 # on all sub-expressions. 405 # 406 # A default implementation of generate_evaluation_code 407 # is provided which uses the following abstract methods: 408 # 409 # generate_result_code 410 # - Generate any C statements necessary to calculate 411 # the result of this node from the results of its 412 # sub-expressions. 413 # 414 # calculate_result_code 415 # - Should return a C code fragment evaluating to the 416 # result. This is only called when the result is not 417 # a temporary. 418 # 419 # generate_assignment_code 420 # Called on the LHS of an assignment. 421 # - Call generate_evaluation_code for sub-expressions. 422 # - Generate code to perform the assignment. 423 # - If the assignment absorbed a reference, call 424 # generate_post_assignment_code on the RHS, 425 # otherwise call generate_disposal_code on it. 426 # 427 # generate_deletion_code 428 # Called on an argument of a del statement. 429 # - Call generate_evaluation_code for sub-expressions. 430 # - Generate code to perform the deletion. 431 # - Call generate_disposal_code on all sub-expressions. 432 # 433 # 434 435 is_sequence_constructor = False 436 is_dict_literal = False 437 is_set_literal = False 438 is_string_literal = False 439 is_attribute = False 440 is_subscript = False 441 is_slice = False 442 443 is_buffer_access = False 444 is_memview_index = False 445 is_memview_slice = False 446 is_memview_broadcast = False 447 is_memview_copy_assignment = False 448 449 saved_subexpr_nodes = None 450 is_temp = False 451 is_target = False 452 is_starred = False 453 454 constant_result = constant_value_not_set 455 456 child_attrs = property(fget=operator.attrgetter('subexprs')) 457 458 def not_implemented(self, method_name): 459 print_call_chain(method_name, "not implemented") ### 460 raise InternalError( 461 "%s.%s not implemented" % 462 (self.__class__.__name__, method_name)) 463 464 def is_lvalue(self): 465 return 0 466 467 def is_addressable(self): 468 return self.is_lvalue() and not self.type.is_memoryviewslice 469 470 def is_ephemeral(self): 471 # An ephemeral node is one whose result is in 472 # a Python temporary and we suspect there are no 473 # other references to it. Certain operations are 474 # disallowed on such values, since they are 475 # likely to result in a dangling pointer. 476 return self.type.is_pyobject and self.is_temp 477 478 def subexpr_nodes(self): 479 # Extract a list of subexpression nodes based 480 # on the contents of the subexprs class attribute. 481 nodes = [] 482 for name in self.subexprs: 483 item = getattr(self, name) 484 if item is not None: 485 if type(item) is list: 486 nodes.extend(item) 487 else: 488 nodes.append(item) 489 return nodes 490 491 def result(self): 492 if self.is_temp: 493 #if not self.temp_code: 494 # pos = (os.path.basename(self.pos[0].get_description()),) + self.pos[1:] if self.pos else '(?)' 495 # raise RuntimeError("temp result name not set in %s at %r" % ( 496 # self.__class__.__name__, pos)) 497 return self.temp_code 498 else: 499 return self.calculate_result_code() 500 501 def pythran_result(self, type_=None): 502 if is_pythran_supported_node_or_none(self): 503 return to_pythran(self) 504 505 assert(type_ is not None) 506 return to_pythran(self, type_) 507 508 def is_c_result_required(self): 509 """ 510 Subtypes may return False here if result temp allocation can be skipped. 511 """ 512 return True 513 514 def result_as(self, type = None): 515 # Return the result code cast to the specified C type. 516 if (self.is_temp and self.type.is_pyobject and 517 type != py_object_type): 518 # Allocated temporaries are always PyObject *, which may not 519 # reflect the actual type (e.g. an extension type) 520 return typecast(type, py_object_type, self.result()) 521 return typecast(type, self.ctype(), self.result()) 522 523 def py_result(self): 524 # Return the result code cast to PyObject *. 525 return self.result_as(py_object_type) 526 527 def ctype(self): 528 # Return the native C type of the result (i.e. the 529 # C type of the result_code expression). 530 return self.result_ctype or self.type 531 532 def get_constant_c_result_code(self): 533 # Return the constant value of this node as a result code 534 # string, or None if the node is not constant. This method 535 # can be called when the constant result code is required 536 # before the code generation phase. 537 # 538 # The return value is a string that can represent a simple C 539 # value, a constant C name or a constant C expression. If the 540 # node type depends on Python code, this must return None. 541 return None 542 543 def calculate_constant_result(self): 544 # Calculate the constant compile time result value of this 545 # expression and store it in ``self.constant_result``. Does 546 # nothing by default, thus leaving ``self.constant_result`` 547 # unknown. If valid, the result can be an arbitrary Python 548 # value. 549 # 550 # This must only be called when it is assured that all 551 # sub-expressions have a valid constant_result value. The 552 # ConstantFolding transform will do this. 553 pass 554 555 def has_constant_result(self): 556 return self.constant_result is not constant_value_not_set and \ 557 self.constant_result is not not_a_constant 558 559 def compile_time_value(self, denv): 560 # Return value of compile-time expression, or report error. 561 error(self.pos, "Invalid compile-time expression") 562 563 def compile_time_value_error(self, e): 564 error(self.pos, "Error in compile-time expression: %s: %s" % ( 565 e.__class__.__name__, e)) 566 567 # ------------- Declaration Analysis ---------------- 568 569 def analyse_target_declaration(self, env): 570 error(self.pos, "Cannot assign to or delete this") 571 572 # ------------- Expression Analysis ---------------- 573 574 def analyse_const_expression(self, env): 575 # Called during the analyse_declarations phase of a 576 # constant expression. Analyses the expression's type, 577 # checks whether it is a legal const expression, 578 # and determines its value. 579 node = self.analyse_types(env) 580 node.check_const() 581 return node 582 583 def analyse_expressions(self, env): 584 # Convenience routine performing both the Type 585 # Analysis and Temp Allocation phases for a whole 586 # expression. 587 return self.analyse_types(env) 588 589 def analyse_target_expression(self, env, rhs): 590 # Convenience routine performing both the Type 591 # Analysis and Temp Allocation phases for the LHS of 592 # an assignment. 593 return self.analyse_target_types(env) 594 595 def analyse_boolean_expression(self, env): 596 # Analyse expression and coerce to a boolean. 597 node = self.analyse_types(env) 598 bool = node.coerce_to_boolean(env) 599 return bool 600 601 def analyse_temp_boolean_expression(self, env): 602 # Analyse boolean expression and coerce result into 603 # a temporary. This is used when a branch is to be 604 # performed on the result and we won't have an 605 # opportunity to ensure disposal code is executed 606 # afterwards. By forcing the result into a temporary, 607 # we ensure that all disposal has been done by the 608 # time we get the result. 609 node = self.analyse_types(env) 610 return node.coerce_to_boolean(env).coerce_to_simple(env) 611 612 # --------------- Type Inference ----------------- 613 614 def type_dependencies(self, env): 615 # Returns the list of entries whose types must be determined 616 # before the type of self can be inferred. 617 if hasattr(self, 'type') and self.type is not None: 618 return () 619 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ()) 620 621 def infer_type(self, env): 622 # Attempt to deduce the type of self. 623 # Differs from analyse_types as it avoids unnecessary 624 # analysis of subexpressions, but can assume everything 625 # in self.type_dependencies() has been resolved. 626 if hasattr(self, 'type') and self.type is not None: 627 return self.type 628 elif hasattr(self, 'entry') and self.entry is not None: 629 return self.entry.type 630 else: 631 self.not_implemented("infer_type") 632 633 def nonlocally_immutable(self): 634 # Returns whether this variable is a safe reference, i.e. 635 # can't be modified as part of globals or closures. 636 return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction 637 638 def inferable_item_node(self, index=0): 639 """ 640 Return a node that represents the (type) result of an indexing operation, 641 e.g. for tuple unpacking or iteration. 642 """ 643 return IndexNode(self.pos, base=self, index=IntNode( 644 self.pos, value=str(index), constant_result=index, type=PyrexTypes.c_py_ssize_t_type)) 645 646 # --------------- Type Analysis ------------------ 647 648 def analyse_as_module(self, env): 649 # If this node can be interpreted as a reference to a 650 # cimported module, return its scope, else None. 651 return None 652 653 def analyse_as_type(self, env): 654 # If this node can be interpreted as a reference to a 655 # type, return that type, else None. 656 return None 657 658 def analyse_as_extension_type(self, env): 659 # If this node can be interpreted as a reference to an 660 # extension type or builtin type, return its type, else None. 661 return None 662 663 def analyse_types(self, env): 664 self.not_implemented("analyse_types") 665 666 def analyse_target_types(self, env): 667 return self.analyse_types(env) 668 669 def nogil_check(self, env): 670 # By default, any expression based on Python objects is 671 # prevented in nogil environments. Subtypes must override 672 # this if they can work without the GIL. 673 if self.type and self.type.is_pyobject: 674 self.gil_error() 675 676 def gil_assignment_check(self, env): 677 if env.nogil and self.type.is_pyobject: 678 error(self.pos, "Assignment of Python object not allowed without gil") 679 680 def check_const(self): 681 self.not_const() 682 return False 683 684 def not_const(self): 685 error(self.pos, "Not allowed in a constant expression") 686 687 def check_const_addr(self): 688 self.addr_not_const() 689 return False 690 691 def addr_not_const(self): 692 error(self.pos, "Address is not constant") 693 694 # ----------------- Result Allocation ----------------- 695 696 def result_in_temp(self): 697 # Return true if result is in a temporary owned by 698 # this node or one of its subexpressions. Overridden 699 # by certain nodes which can share the result of 700 # a subnode. 701 return self.is_temp 702 703 def target_code(self): 704 # Return code fragment for use as LHS of a C assignment. 705 return self.calculate_result_code() 706 707 def calculate_result_code(self): 708 self.not_implemented("calculate_result_code") 709 710# def release_target_temp(self, env): 711# # Release temporaries used by LHS of an assignment. 712# self.release_subexpr_temps(env) 713 714 def allocate_temp_result(self, code): 715 if self.temp_code: 716 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self.__class__.__name__, self.pos)) 717 type = self.type 718 if not type.is_void: 719 if type.is_pyobject: 720 type = PyrexTypes.py_object_type 721 elif not (self.result_is_used or type.is_memoryviewslice or self.is_c_result_required()): 722 self.temp_code = None 723 return 724 self.temp_code = code.funcstate.allocate_temp( 725 type, manage_ref=self.use_managed_ref) 726 else: 727 self.temp_code = None 728 729 def release_temp_result(self, code): 730 if not self.temp_code: 731 if not self.result_is_used: 732 # not used anyway, so ignore if not set up 733 return 734 pos = (os.path.basename(self.pos[0].get_description()),) + self.pos[1:] if self.pos else '(?)' 735 if self.old_temp: 736 raise RuntimeError("temp %s released multiple times in %s at %r" % ( 737 self.old_temp, self.__class__.__name__, pos)) 738 else: 739 raise RuntimeError("no temp, but release requested in %s at %r" % ( 740 self.__class__.__name__, pos)) 741 code.funcstate.release_temp(self.temp_code) 742 self.old_temp = self.temp_code 743 self.temp_code = None 744 745 # ---------------- Code Generation ----------------- 746 747 def make_owned_reference(self, code): 748 """ 749 If result is a pyobject, make sure we own a reference to it. 750 If the result is in a temp, it is already a new reference. 751 """ 752 if self.type.is_pyobject and not self.result_in_temp(): 753 code.put_incref(self.result(), self.ctype()) 754 755 def make_owned_memoryviewslice(self, code): 756 """ 757 Make sure we own the reference to this memoryview slice. 758 """ 759 if not self.result_in_temp(): 760 code.put_incref_memoryviewslice(self.result(), 761 have_gil=self.in_nogil_context) 762 763 def generate_evaluation_code(self, code): 764 # Generate code to evaluate this node and 765 # its sub-expressions, and dispose of any 766 # temporary results of its sub-expressions. 767 self.generate_subexpr_evaluation_code(code) 768 769 code.mark_pos(self.pos) 770 if self.is_temp: 771 self.allocate_temp_result(code) 772 773 self.generate_result_code(code) 774 if self.is_temp and not (self.type.is_string or self.type.is_pyunicode_ptr): 775 # If we are temp we do not need to wait until this node is disposed 776 # before disposing children. 777 self.generate_subexpr_disposal_code(code) 778 self.free_subexpr_temps(code) 779 780 def generate_subexpr_evaluation_code(self, code): 781 for node in self.subexpr_nodes(): 782 node.generate_evaluation_code(code) 783 784 def generate_result_code(self, code): 785 self.not_implemented("generate_result_code") 786 787 def generate_disposal_code(self, code): 788 if self.is_temp: 789 if self.type.is_string or self.type.is_pyunicode_ptr: 790 # postponed from self.generate_evaluation_code() 791 self.generate_subexpr_disposal_code(code) 792 self.free_subexpr_temps(code) 793 if self.result(): 794 if self.type.is_pyobject: 795 code.put_decref_clear(self.result(), self.ctype()) 796 elif self.type.is_memoryviewslice: 797 code.put_xdecref_memoryviewslice( 798 self.result(), have_gil=not self.in_nogil_context) 799 code.putln("%s.memview = NULL;" % self.result()) 800 code.putln("%s.data = NULL;" % self.result()) 801 else: 802 # Already done if self.is_temp 803 self.generate_subexpr_disposal_code(code) 804 805 def generate_subexpr_disposal_code(self, code): 806 # Generate code to dispose of temporary results 807 # of all sub-expressions. 808 for node in self.subexpr_nodes(): 809 node.generate_disposal_code(code) 810 811 def generate_post_assignment_code(self, code): 812 if self.is_temp: 813 if self.type.is_string or self.type.is_pyunicode_ptr: 814 # postponed from self.generate_evaluation_code() 815 self.generate_subexpr_disposal_code(code) 816 self.free_subexpr_temps(code) 817 elif self.type.is_pyobject: 818 code.putln("%s = 0;" % self.result()) 819 elif self.type.is_memoryviewslice: 820 code.putln("%s.memview = NULL;" % self.result()) 821 code.putln("%s.data = NULL;" % self.result()) 822 else: 823 self.generate_subexpr_disposal_code(code) 824 825 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 826 exception_check=None, exception_value=None): 827 # Stub method for nodes which are not legal as 828 # the LHS of an assignment. An error will have 829 # been reported earlier. 830 pass 831 832 def generate_deletion_code(self, code, ignore_nonexisting=False): 833 # Stub method for nodes that are not legal as 834 # the argument of a del statement. An error 835 # will have been reported earlier. 836 pass 837 838 def free_temps(self, code): 839 if self.is_temp: 840 if not self.type.is_void: 841 self.release_temp_result(code) 842 else: 843 self.free_subexpr_temps(code) 844 845 def free_subexpr_temps(self, code): 846 for sub in self.subexpr_nodes(): 847 sub.free_temps(code) 848 849 def generate_function_definitions(self, env, code): 850 pass 851 852 # ---------------- Annotation --------------------- 853 854 def annotate(self, code): 855 for node in self.subexpr_nodes(): 856 node.annotate(code) 857 858 # ----------------- Coercion ---------------------- 859 860 def coerce_to(self, dst_type, env): 861 # Coerce the result so that it can be assigned to 862 # something of type dst_type. If processing is necessary, 863 # wraps this node in a coercion node and returns that. 864 # Otherwise, returns this node unchanged. 865 # 866 # This method is called during the analyse_expressions 867 # phase of the src_node's processing. 868 # 869 # Note that subclasses that override this (especially 870 # ConstNodes) must not (re-)set their own .type attribute 871 # here. Since expression nodes may turn up in different 872 # places in the tree (e.g. inside of CloneNodes in cascaded 873 # assignments), this method must return a new node instance 874 # if it changes the type. 875 # 876 src = self 877 src_type = self.type 878 879 if self.check_for_coercion_error(dst_type, env): 880 return self 881 882 used_as_reference = dst_type.is_reference 883 if used_as_reference and not src_type.is_reference: 884 dst_type = dst_type.ref_base_type 885 886 if src_type.is_const: 887 src_type = src_type.const_base_type 888 889 if src_type.is_fused or dst_type.is_fused: 890 # See if we are coercing a fused function to a pointer to a 891 # specialized function 892 if (src_type.is_cfunction and not dst_type.is_fused and 893 dst_type.is_ptr and dst_type.base_type.is_cfunction): 894 895 dst_type = dst_type.base_type 896 897 for signature in src_type.get_all_specialized_function_types(): 898 if signature.same_as(dst_type): 899 src.type = signature 900 src.entry = src.type.entry 901 src.entry.used = True 902 return self 903 904 if src_type.is_fused: 905 error(self.pos, "Type is not specialized") 906 elif src_type.is_null_ptr and dst_type.is_ptr: 907 # NULL can be implicitly cast to any pointer type 908 return self 909 else: 910 error(self.pos, "Cannot coerce to a type that is not specialized") 911 912 self.type = error_type 913 return self 914 915 if self.coercion_type is not None: 916 # This is purely for error checking purposes! 917 node = NameNode(self.pos, name='', type=self.coercion_type) 918 node.coerce_to(dst_type, env) 919 920 if dst_type.is_memoryviewslice: 921 from . import MemoryView 922 if not src.type.is_memoryviewslice: 923 if src.type.is_pyobject: 924 src = CoerceToMemViewSliceNode(src, dst_type, env) 925 elif src.type.is_array: 926 src = CythonArrayNode.from_carray(src, env).coerce_to(dst_type, env) 927 elif not src_type.is_error: 928 error(self.pos, 929 "Cannot convert '%s' to memoryviewslice" % (src_type,)) 930 else: 931 if src.type.writable_needed: 932 dst_type.writable_needed = True 933 if not src.type.conforms_to(dst_type, broadcast=self.is_memview_broadcast, 934 copying=self.is_memview_copy_assignment): 935 if src.type.dtype.same_as(dst_type.dtype): 936 msg = "Memoryview '%s' not conformable to memoryview '%s'." 937 tup = src.type, dst_type 938 else: 939 msg = "Different base types for memoryviews (%s, %s)" 940 tup = src.type.dtype, dst_type.dtype 941 942 error(self.pos, msg % tup) 943 944 elif dst_type.is_pyobject: 945 if not src.type.is_pyobject: 946 if dst_type is bytes_type and src.type.is_int: 947 src = CoerceIntToBytesNode(src, env) 948 else: 949 src = CoerceToPyTypeNode(src, env, type=dst_type) 950 if not src.type.subtype_of(dst_type): 951 if src.constant_result is not None: 952 src = PyTypeTestNode(src, dst_type, env) 953 elif is_pythran_expr(dst_type) and is_pythran_supported_type(src.type): 954 # We let the compiler decide whether this is valid 955 return src 956 elif is_pythran_expr(src.type): 957 if is_pythran_supported_type(dst_type): 958 # Match the case were a pythran expr is assigned to a value, or vice versa. 959 # We let the C++ compiler decide whether this is valid or not! 960 return src 961 # Else, we need to convert the Pythran expression to a Python object 962 src = CoerceToPyTypeNode(src, env, type=dst_type) 963 elif src.type.is_pyobject: 964 if used_as_reference and dst_type.is_cpp_class: 965 warning( 966 self.pos, 967 "Cannot pass Python object as C++ data structure reference (%s &), will pass by copy." % dst_type) 968 src = CoerceFromPyTypeNode(dst_type, src, env) 969 elif (dst_type.is_complex 970 and src_type != dst_type 971 and dst_type.assignable_from(src_type)): 972 src = CoerceToComplexNode(src, dst_type, env) 973 else: # neither src nor dst are py types 974 # Added the string comparison, since for c types that 975 # is enough, but Cython gets confused when the types are 976 # in different pxi files. 977 # TODO: Remove this hack and require shared declarations. 978 if not (src.type == dst_type or str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)): 979 self.fail_assignment(dst_type) 980 return src 981 982 def fail_assignment(self, dst_type): 983 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type)) 984 985 def check_for_coercion_error(self, dst_type, env, fail=False, default=None): 986 if fail and not default: 987 default = "Cannot assign type '%(FROM)s' to '%(TO)s'" 988 message = find_coercion_error((self.type, dst_type), default, env) 989 if message is not None: 990 error(self.pos, message % {'FROM': self.type, 'TO': dst_type}) 991 return True 992 if fail: 993 self.fail_assignment(dst_type) 994 return True 995 return False 996 997 def coerce_to_pyobject(self, env): 998 return self.coerce_to(PyrexTypes.py_object_type, env) 999 1000 def coerce_to_boolean(self, env): 1001 # Coerce result to something acceptable as 1002 # a boolean value. 1003 1004 # if it's constant, calculate the result now 1005 if self.has_constant_result(): 1006 bool_value = bool(self.constant_result) 1007 return BoolNode(self.pos, value=bool_value, 1008 constant_result=bool_value) 1009 1010 type = self.type 1011 if type.is_enum or type.is_error: 1012 return self 1013 elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float: 1014 return CoerceToBooleanNode(self, env) 1015 elif type.is_cpp_class: 1016 return SimpleCallNode( 1017 self.pos, 1018 function=AttributeNode( 1019 self.pos, obj=self, attribute='operator bool'), 1020 args=[]).analyse_types(env) 1021 elif type.is_ctuple: 1022 bool_value = len(type.components) == 0 1023 return BoolNode(self.pos, value=bool_value, 1024 constant_result=bool_value) 1025 else: 1026 error(self.pos, "Type '%s' not acceptable as a boolean" % type) 1027 return self 1028 1029 def coerce_to_integer(self, env): 1030 # If not already some C integer type, coerce to longint. 1031 if self.type.is_int: 1032 return self 1033 else: 1034 return self.coerce_to(PyrexTypes.c_long_type, env) 1035 1036 def coerce_to_temp(self, env): 1037 # Ensure that the result is in a temporary. 1038 if self.result_in_temp(): 1039 return self 1040 else: 1041 return CoerceToTempNode(self, env) 1042 1043 def coerce_to_simple(self, env): 1044 # Ensure that the result is simple (see is_simple). 1045 if self.is_simple(): 1046 return self 1047 else: 1048 return self.coerce_to_temp(env) 1049 1050 def is_simple(self): 1051 # A node is simple if its result is something that can 1052 # be referred to without performing any operations, e.g. 1053 # a constant, local var, C global var, struct member 1054 # reference, or temporary. 1055 return self.result_in_temp() 1056 1057 def may_be_none(self): 1058 if self.type and not (self.type.is_pyobject or 1059 self.type.is_memoryviewslice): 1060 return False 1061 if self.has_constant_result(): 1062 return self.constant_result is not None 1063 return True 1064 1065 def as_cython_attribute(self): 1066 return None 1067 1068 def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()): 1069 # Wraps the node in a NoneCheckNode if it is not known to be 1070 # not-None (e.g. because it is a Python literal). 1071 if self.may_be_none(): 1072 return NoneCheckNode(self, error, message, format_args) 1073 else: 1074 return self 1075 1076 @classmethod 1077 def from_node(cls, node, **kwargs): 1078 """Instantiate this node class from another node, properly 1079 copying over all attributes that one would forget otherwise. 1080 """ 1081 attributes = "cf_state cf_maybe_null cf_is_null constant_result".split() 1082 for attr_name in attributes: 1083 if attr_name in kwargs: 1084 continue 1085 try: 1086 value = getattr(node, attr_name) 1087 except AttributeError: 1088 pass 1089 else: 1090 kwargs[attr_name] = value 1091 return cls(node.pos, **kwargs) 1092 1093 1094class AtomicExprNode(ExprNode): 1095 # Abstract base class for expression nodes which have 1096 # no sub-expressions. 1097 1098 subexprs = [] 1099 1100 # Override to optimize -- we know we have no children 1101 def generate_subexpr_evaluation_code(self, code): 1102 pass 1103 def generate_subexpr_disposal_code(self, code): 1104 pass 1105 1106class PyConstNode(AtomicExprNode): 1107 # Abstract base class for constant Python values. 1108 1109 is_literal = 1 1110 type = py_object_type 1111 1112 def is_simple(self): 1113 return 1 1114 1115 def may_be_none(self): 1116 return False 1117 1118 def analyse_types(self, env): 1119 return self 1120 1121 def calculate_result_code(self): 1122 return self.value 1123 1124 def generate_result_code(self, code): 1125 pass 1126 1127 1128class NoneNode(PyConstNode): 1129 # The constant value None 1130 1131 is_none = 1 1132 value = "Py_None" 1133 1134 constant_result = None 1135 1136 nogil_check = None 1137 1138 def compile_time_value(self, denv): 1139 return None 1140 1141 def may_be_none(self): 1142 return True 1143 1144 def coerce_to(self, dst_type, env): 1145 if not (dst_type.is_pyobject or dst_type.is_memoryviewslice or dst_type.is_error): 1146 # Catch this error early and loudly. 1147 error(self.pos, "Cannot assign None to %s" % dst_type) 1148 return super(NoneNode, self).coerce_to(dst_type, env) 1149 1150 1151class EllipsisNode(PyConstNode): 1152 # '...' in a subscript list. 1153 1154 value = "Py_Ellipsis" 1155 1156 constant_result = Ellipsis 1157 1158 def compile_time_value(self, denv): 1159 return Ellipsis 1160 1161 1162class ConstNode(AtomicExprNode): 1163 # Abstract base type for literal constant nodes. 1164 # 1165 # value string C code fragment 1166 1167 is_literal = 1 1168 nogil_check = None 1169 1170 def is_simple(self): 1171 return 1 1172 1173 def nonlocally_immutable(self): 1174 return 1 1175 1176 def may_be_none(self): 1177 return False 1178 1179 def analyse_types(self, env): 1180 return self # Types are held in class variables 1181 1182 def check_const(self): 1183 return True 1184 1185 def get_constant_c_result_code(self): 1186 return self.calculate_result_code() 1187 1188 def calculate_result_code(self): 1189 return str(self.value) 1190 1191 def generate_result_code(self, code): 1192 pass 1193 1194 1195class BoolNode(ConstNode): 1196 type = PyrexTypes.c_bint_type 1197 # The constant value True or False 1198 1199 def calculate_constant_result(self): 1200 self.constant_result = self.value 1201 1202 def compile_time_value(self, denv): 1203 return self.value 1204 1205 def calculate_result_code(self): 1206 if self.type.is_pyobject: 1207 return self.value and 'Py_True' or 'Py_False' 1208 else: 1209 return str(int(self.value)) 1210 1211 def coerce_to(self, dst_type, env): 1212 if dst_type == self.type: 1213 return self 1214 if dst_type is py_object_type and self.type is Builtin.bool_type: 1215 return self 1216 if dst_type.is_pyobject and self.type.is_int: 1217 return BoolNode( 1218 self.pos, value=self.value, 1219 constant_result=self.constant_result, 1220 type=Builtin.bool_type) 1221 if dst_type.is_int and self.type.is_pyobject: 1222 return BoolNode( 1223 self.pos, value=self.value, 1224 constant_result=self.constant_result, 1225 type=PyrexTypes.c_bint_type) 1226 return ConstNode.coerce_to(self, dst_type, env) 1227 1228 1229class NullNode(ConstNode): 1230 type = PyrexTypes.c_null_ptr_type 1231 value = "NULL" 1232 constant_result = 0 1233 1234 def get_constant_c_result_code(self): 1235 return self.value 1236 1237 1238class CharNode(ConstNode): 1239 type = PyrexTypes.c_char_type 1240 1241 def calculate_constant_result(self): 1242 self.constant_result = ord(self.value) 1243 1244 def compile_time_value(self, denv): 1245 return ord(self.value) 1246 1247 def calculate_result_code(self): 1248 return "'%s'" % StringEncoding.escape_char(self.value) 1249 1250 1251class IntNode(ConstNode): 1252 1253 # unsigned "" or "U" 1254 # longness "" or "L" or "LL" 1255 # is_c_literal True/False/None creator considers this a C integer literal 1256 1257 unsigned = "" 1258 longness = "" 1259 is_c_literal = None # unknown 1260 1261 def __init__(self, pos, **kwds): 1262 ExprNode.__init__(self, pos, **kwds) 1263 if 'type' not in kwds: 1264 self.type = self.find_suitable_type_for_value() 1265 1266 def find_suitable_type_for_value(self): 1267 if self.constant_result is constant_value_not_set: 1268 try: 1269 self.calculate_constant_result() 1270 except ValueError: 1271 pass 1272 # we ignore 'is_c_literal = True' and instead map signed 32bit 1273 # integers as C long values 1274 if self.is_c_literal or \ 1275 not self.has_constant_result() or \ 1276 self.unsigned or self.longness == 'LL': 1277 # clearly a C literal 1278 rank = (self.longness == 'LL') and 2 or 1 1279 suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"] 1280 if self.type: 1281 suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type) 1282 else: 1283 # C literal or Python literal - split at 32bit boundary 1284 if -2**31 <= self.constant_result < 2**31: 1285 if self.type and self.type.is_int: 1286 suitable_type = self.type 1287 else: 1288 suitable_type = PyrexTypes.c_long_type 1289 else: 1290 suitable_type = PyrexTypes.py_object_type 1291 return suitable_type 1292 1293 def coerce_to(self, dst_type, env): 1294 if self.type is dst_type: 1295 return self 1296 elif dst_type.is_float: 1297 if self.has_constant_result(): 1298 return FloatNode(self.pos, value='%d.0' % int(self.constant_result), type=dst_type, 1299 constant_result=float(self.constant_result)) 1300 else: 1301 return FloatNode(self.pos, value=self.value, type=dst_type, 1302 constant_result=not_a_constant) 1303 if dst_type.is_numeric and not dst_type.is_complex: 1304 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1305 type=dst_type, is_c_literal=True, 1306 unsigned=self.unsigned, longness=self.longness) 1307 return node 1308 elif dst_type.is_pyobject: 1309 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1310 type=PyrexTypes.py_object_type, is_c_literal=False, 1311 unsigned=self.unsigned, longness=self.longness) 1312 else: 1313 # FIXME: not setting the type here to keep it working with 1314 # complex numbers. Should they be special cased? 1315 node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, 1316 unsigned=self.unsigned, longness=self.longness) 1317 # We still need to perform normal coerce_to processing on the 1318 # result, because we might be coercing to an extension type, 1319 # in which case a type test node will be needed. 1320 return ConstNode.coerce_to(node, dst_type, env) 1321 1322 def coerce_to_boolean(self, env): 1323 return IntNode( 1324 self.pos, value=self.value, 1325 constant_result=self.constant_result, 1326 type=PyrexTypes.c_bint_type, 1327 unsigned=self.unsigned, longness=self.longness) 1328 1329 def generate_evaluation_code(self, code): 1330 if self.type.is_pyobject: 1331 # pre-allocate a Python version of the number 1332 plain_integer_string = str(Utils.str_to_number(self.value)) 1333 self.result_code = code.get_py_int(plain_integer_string, self.longness) 1334 else: 1335 self.result_code = self.get_constant_c_result_code() 1336 1337 def get_constant_c_result_code(self): 1338 unsigned, longness = self.unsigned, self.longness 1339 literal = self.value_as_c_integer_string() 1340 if not (unsigned or longness) and self.type.is_int and literal[0] == '-' and literal[1] != '0': 1341 # negative decimal literal => guess longness from type to prevent wrap-around 1342 if self.type.rank >= PyrexTypes.c_longlong_type.rank: 1343 longness = 'LL' 1344 elif self.type.rank >= PyrexTypes.c_long_type.rank: 1345 longness = 'L' 1346 return literal + unsigned + longness 1347 1348 def value_as_c_integer_string(self): 1349 value = self.value 1350 if len(value) <= 2: 1351 # too short to go wrong (and simplifies code below) 1352 return value 1353 neg_sign = '' 1354 if value[0] == '-': 1355 neg_sign = '-' 1356 value = value[1:] 1357 if value[0] == '0': 1358 literal_type = value[1] # 0'o' - 0'b' - 0'x' 1359 # 0x123 hex literals and 0123 octal literals work nicely in C 1360 # but C-incompatible Py3 oct/bin notations need conversion 1361 if neg_sign and literal_type in 'oOxX0123456789' and value[2:].isdigit(): 1362 # negative hex/octal literal => prevent C compiler from using 1363 # unsigned integer types by converting to decimal (see C standard 6.4.4.1) 1364 value = str(Utils.str_to_number(value)) 1365 elif literal_type in 'oO': 1366 value = '0' + value[2:] # '0o123' => '0123' 1367 elif literal_type in 'bB': 1368 value = str(int(value[2:], 2)) 1369 elif value.isdigit() and not self.unsigned and not self.longness: 1370 if not neg_sign: 1371 # C compilers do not consider unsigned types for decimal literals, 1372 # but they do for hex (see C standard 6.4.4.1) 1373 value = '0x%X' % int(value) 1374 return neg_sign + value 1375 1376 def calculate_result_code(self): 1377 return self.result_code 1378 1379 def calculate_constant_result(self): 1380 self.constant_result = Utils.str_to_number(self.value) 1381 1382 def compile_time_value(self, denv): 1383 return Utils.str_to_number(self.value) 1384 1385class FloatNode(ConstNode): 1386 type = PyrexTypes.c_double_type 1387 1388 def calculate_constant_result(self): 1389 self.constant_result = float(self.value) 1390 1391 def compile_time_value(self, denv): 1392 return float(self.value) 1393 1394 def coerce_to(self, dst_type, env): 1395 if dst_type.is_pyobject and self.type.is_float: 1396 return FloatNode( 1397 self.pos, value=self.value, 1398 constant_result=self.constant_result, 1399 type=Builtin.float_type) 1400 if dst_type.is_float and self.type.is_pyobject: 1401 return FloatNode( 1402 self.pos, value=self.value, 1403 constant_result=self.constant_result, 1404 type=dst_type) 1405 return ConstNode.coerce_to(self, dst_type, env) 1406 1407 def calculate_result_code(self): 1408 return self.result_code 1409 1410 def get_constant_c_result_code(self): 1411 strval = self.value 1412 assert isinstance(strval, basestring) 1413 cmpval = repr(float(strval)) 1414 if cmpval == 'nan': 1415 return "(Py_HUGE_VAL * 0)" 1416 elif cmpval == 'inf': 1417 return "Py_HUGE_VAL" 1418 elif cmpval == '-inf': 1419 return "(-Py_HUGE_VAL)" 1420 else: 1421 return strval 1422 1423 def generate_evaluation_code(self, code): 1424 c_value = self.get_constant_c_result_code() 1425 if self.type.is_pyobject: 1426 self.result_code = code.get_py_float(self.value, c_value) 1427 else: 1428 self.result_code = c_value 1429 1430 1431def _analyse_name_as_type(name, pos, env): 1432 type = PyrexTypes.parse_basic_type(name) 1433 if type is not None: 1434 return type 1435 1436 global_entry = env.global_scope().lookup(name) 1437 if global_entry and global_entry.type and ( 1438 global_entry.type.is_extension_type 1439 or global_entry.type.is_struct_or_union 1440 or global_entry.type.is_builtin_type 1441 or global_entry.type.is_cpp_class): 1442 return global_entry.type 1443 1444 from .TreeFragment import TreeFragment 1445 with local_errors(ignore=True): 1446 pos = (pos[0], pos[1], pos[2]-7) 1447 try: 1448 declaration = TreeFragment(u"sizeof(%s)" % name, name=pos[0].filename, initial_pos=pos) 1449 except CompileError: 1450 pass 1451 else: 1452 sizeof_node = declaration.root.stats[0].expr 1453 if isinstance(sizeof_node, SizeofTypeNode): 1454 sizeof_node = sizeof_node.analyse_types(env) 1455 if isinstance(sizeof_node, SizeofTypeNode): 1456 return sizeof_node.arg_type 1457 return None 1458 1459 1460class BytesNode(ConstNode): 1461 # A char* or bytes literal 1462 # 1463 # value BytesLiteral 1464 1465 is_string_literal = True 1466 # start off as Python 'bytes' to support len() in O(1) 1467 type = bytes_type 1468 1469 def calculate_constant_result(self): 1470 self.constant_result = self.value 1471 1472 def as_sliced_node(self, start, stop, step=None): 1473 value = StringEncoding.bytes_literal(self.value[start:stop:step], self.value.encoding) 1474 return BytesNode(self.pos, value=value, constant_result=value) 1475 1476 def compile_time_value(self, denv): 1477 return self.value.byteencode() 1478 1479 def analyse_as_type(self, env): 1480 return _analyse_name_as_type(self.value.decode('ISO8859-1'), self.pos, env) 1481 1482 def can_coerce_to_char_literal(self): 1483 return len(self.value) == 1 1484 1485 def coerce_to_boolean(self, env): 1486 # This is special because testing a C char* for truth directly 1487 # would yield the wrong result. 1488 bool_value = bool(self.value) 1489 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) 1490 1491 def coerce_to(self, dst_type, env): 1492 if self.type == dst_type: 1493 return self 1494 if dst_type.is_int: 1495 if not self.can_coerce_to_char_literal(): 1496 error(self.pos, "Only single-character string literals can be coerced into ints.") 1497 return self 1498 if dst_type.is_unicode_char: 1499 error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.") 1500 return self 1501 return CharNode(self.pos, value=self.value, 1502 constant_result=ord(self.value)) 1503 1504 node = BytesNode(self.pos, value=self.value, constant_result=self.constant_result) 1505 if dst_type.is_pyobject: 1506 if dst_type in (py_object_type, Builtin.bytes_type): 1507 node.type = Builtin.bytes_type 1508 else: 1509 self.check_for_coercion_error(dst_type, env, fail=True) 1510 return node 1511 elif dst_type in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_const_char_ptr_type): 1512 node.type = dst_type 1513 return node 1514 elif dst_type in (PyrexTypes.c_uchar_ptr_type, PyrexTypes.c_const_uchar_ptr_type, PyrexTypes.c_void_ptr_type): 1515 node.type = (PyrexTypes.c_const_char_ptr_type if dst_type == PyrexTypes.c_const_uchar_ptr_type 1516 else PyrexTypes.c_char_ptr_type) 1517 return CastNode(node, dst_type) 1518 elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type): 1519 # Exclude the case of passing a C string literal into a non-const C++ string. 1520 if not dst_type.is_cpp_class or dst_type.is_const: 1521 node.type = dst_type 1522 return node 1523 1524 # We still need to perform normal coerce_to processing on the 1525 # result, because we might be coercing to an extension type, 1526 # in which case a type test node will be needed. 1527 return ConstNode.coerce_to(node, dst_type, env) 1528 1529 def generate_evaluation_code(self, code): 1530 if self.type.is_pyobject: 1531 result = code.get_py_string_const(self.value) 1532 elif self.type.is_const: 1533 result = code.get_string_const(self.value) 1534 else: 1535 # not const => use plain C string literal and cast to mutable type 1536 literal = self.value.as_c_string_literal() 1537 # C++ may require a cast 1538 result = typecast(self.type, PyrexTypes.c_void_ptr_type, literal) 1539 self.result_code = result 1540 1541 def get_constant_c_result_code(self): 1542 return None # FIXME 1543 1544 def calculate_result_code(self): 1545 return self.result_code 1546 1547 1548class UnicodeNode(ConstNode): 1549 # A Py_UNICODE* or unicode literal 1550 # 1551 # value EncodedString 1552 # bytes_value BytesLiteral the literal parsed as bytes string 1553 # ('-3' unicode literals only) 1554 1555 is_string_literal = True 1556 bytes_value = None 1557 type = unicode_type 1558 1559 def calculate_constant_result(self): 1560 self.constant_result = self.value 1561 1562 def analyse_as_type(self, env): 1563 return _analyse_name_as_type(self.value, self.pos, env) 1564 1565 def as_sliced_node(self, start, stop, step=None): 1566 if StringEncoding.string_contains_surrogates(self.value[:stop]): 1567 # this is unsafe as it may give different results 1568 # in different runtimes 1569 return None 1570 value = StringEncoding.EncodedString(self.value[start:stop:step]) 1571 value.encoding = self.value.encoding 1572 if self.bytes_value is not None: 1573 bytes_value = StringEncoding.bytes_literal( 1574 self.bytes_value[start:stop:step], self.bytes_value.encoding) 1575 else: 1576 bytes_value = None 1577 return UnicodeNode( 1578 self.pos, value=value, bytes_value=bytes_value, 1579 constant_result=value) 1580 1581 def coerce_to(self, dst_type, env): 1582 if dst_type is self.type: 1583 pass 1584 elif dst_type.is_unicode_char: 1585 if not self.can_coerce_to_char_literal(): 1586 error(self.pos, 1587 "Only single-character Unicode string literals or " 1588 "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.") 1589 return self 1590 int_value = ord(self.value) 1591 return IntNode(self.pos, type=dst_type, value=str(int_value), 1592 constant_result=int_value) 1593 elif not dst_type.is_pyobject: 1594 if dst_type.is_string and self.bytes_value is not None: 1595 # special case: '-3' enforced unicode literal used in a 1596 # C char* context 1597 return BytesNode(self.pos, value=self.bytes_value 1598 ).coerce_to(dst_type, env) 1599 if dst_type.is_pyunicode_ptr: 1600 node = UnicodeNode(self.pos, value=self.value) 1601 node.type = dst_type 1602 return node 1603 error(self.pos, 1604 "Unicode literals do not support coercion to C types other " 1605 "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* " 1606 "(for strings).") 1607 elif dst_type not in (py_object_type, Builtin.basestring_type): 1608 self.check_for_coercion_error(dst_type, env, fail=True) 1609 return self 1610 1611 def can_coerce_to_char_literal(self): 1612 return len(self.value) == 1 1613 ## or (len(self.value) == 2 1614 ## and (0xD800 <= self.value[0] <= 0xDBFF) 1615 ## and (0xDC00 <= self.value[1] <= 0xDFFF)) 1616 1617 def coerce_to_boolean(self, env): 1618 bool_value = bool(self.value) 1619 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) 1620 1621 def contains_surrogates(self): 1622 return StringEncoding.string_contains_surrogates(self.value) 1623 1624 def generate_evaluation_code(self, code): 1625 if self.type.is_pyobject: 1626 # FIXME: this should go away entirely! 1627 # Since string_contains_lone_surrogates() returns False for surrogate pairs in Py2/UCS2, 1628 # Py2 can generate different code from Py3 here. Let's hope we get away with claiming that 1629 # the processing of surrogate pairs in code was always ambiguous and lead to different results 1630 # on P16/32bit Unicode platforms. 1631 if StringEncoding.string_contains_lone_surrogates(self.value): 1632 # lone (unpaired) surrogates are not really portable and cannot be 1633 # decoded by the UTF-8 codec in Py3.3 1634 self.result_code = code.get_py_const(py_object_type, 'ustring') 1635 data_cname = code.get_string_const( 1636 StringEncoding.BytesLiteral(self.value.encode('unicode_escape'))) 1637 const_code = code.get_cached_constants_writer(self.result_code) 1638 if const_code is None: 1639 return # already initialised 1640 const_code.mark_pos(self.pos) 1641 const_code.putln( 1642 "%s = PyUnicode_DecodeUnicodeEscape(%s, sizeof(%s) - 1, NULL); %s" % ( 1643 self.result_code, 1644 data_cname, 1645 data_cname, 1646 const_code.error_goto_if_null(self.result_code, self.pos))) 1647 const_code.put_error_if_neg( 1648 self.pos, "__Pyx_PyUnicode_READY(%s)" % self.result_code) 1649 else: 1650 self.result_code = code.get_py_string_const(self.value) 1651 else: 1652 self.result_code = code.get_pyunicode_ptr_const(self.value) 1653 1654 def calculate_result_code(self): 1655 return self.result_code 1656 1657 def compile_time_value(self, env): 1658 return self.value 1659 1660 1661class StringNode(PyConstNode): 1662 # A Python str object, i.e. a byte string in Python 2.x and a 1663 # unicode string in Python 3.x 1664 # 1665 # value BytesLiteral (or EncodedString with ASCII content) 1666 # unicode_value EncodedString or None 1667 # is_identifier boolean 1668 1669 type = str_type 1670 is_string_literal = True 1671 is_identifier = None 1672 unicode_value = None 1673 1674 def calculate_constant_result(self): 1675 if self.unicode_value is not None: 1676 # only the Unicode value is portable across Py2/3 1677 self.constant_result = self.unicode_value 1678 1679 def analyse_as_type(self, env): 1680 return _analyse_name_as_type(self.unicode_value or self.value.decode('ISO8859-1'), self.pos, env) 1681 1682 def as_sliced_node(self, start, stop, step=None): 1683 value = type(self.value)(self.value[start:stop:step]) 1684 value.encoding = self.value.encoding 1685 if self.unicode_value is not None: 1686 if StringEncoding.string_contains_surrogates(self.unicode_value[:stop]): 1687 # this is unsafe as it may give different results in different runtimes 1688 return None 1689 unicode_value = StringEncoding.EncodedString( 1690 self.unicode_value[start:stop:step]) 1691 else: 1692 unicode_value = None 1693 return StringNode( 1694 self.pos, value=value, unicode_value=unicode_value, 1695 constant_result=value, is_identifier=self.is_identifier) 1696 1697 def coerce_to(self, dst_type, env): 1698 if dst_type is not py_object_type and not str_type.subtype_of(dst_type): 1699# if dst_type is Builtin.bytes_type: 1700# # special case: bytes = 'str literal' 1701# return BytesNode(self.pos, value=self.value) 1702 if not dst_type.is_pyobject: 1703 return BytesNode(self.pos, value=self.value).coerce_to(dst_type, env) 1704 if dst_type is not Builtin.basestring_type: 1705 self.check_for_coercion_error(dst_type, env, fail=True) 1706 return self 1707 1708 def can_coerce_to_char_literal(self): 1709 return not self.is_identifier and len(self.value) == 1 1710 1711 def generate_evaluation_code(self, code): 1712 self.result_code = code.get_py_string_const( 1713 self.value, identifier=self.is_identifier, is_str=True, 1714 unicode_value=self.unicode_value) 1715 1716 def get_constant_c_result_code(self): 1717 return None 1718 1719 def calculate_result_code(self): 1720 return self.result_code 1721 1722 def compile_time_value(self, env): 1723 if self.value.is_unicode: 1724 return self.value 1725 if not IS_PYTHON3: 1726 # use plain str/bytes object in Py2 1727 return self.value.byteencode() 1728 # in Py3, always return a Unicode string 1729 if self.unicode_value is not None: 1730 return self.unicode_value 1731 return self.value.decode('iso8859-1') 1732 1733 1734class IdentifierStringNode(StringNode): 1735 # A special str value that represents an identifier (bytes in Py2, 1736 # unicode in Py3). 1737 is_identifier = True 1738 1739 1740class ImagNode(AtomicExprNode): 1741 # Imaginary number literal 1742 # 1743 # value string imaginary part (float value) 1744 1745 type = PyrexTypes.c_double_complex_type 1746 1747 def calculate_constant_result(self): 1748 self.constant_result = complex(0.0, float(self.value)) 1749 1750 def compile_time_value(self, denv): 1751 return complex(0.0, float(self.value)) 1752 1753 def analyse_types(self, env): 1754 self.type.create_declaration_utility_code(env) 1755 return self 1756 1757 def may_be_none(self): 1758 return False 1759 1760 def coerce_to(self, dst_type, env): 1761 if self.type is dst_type: 1762 return self 1763 node = ImagNode(self.pos, value=self.value) 1764 if dst_type.is_pyobject: 1765 node.is_temp = 1 1766 node.type = Builtin.complex_type 1767 # We still need to perform normal coerce_to processing on the 1768 # result, because we might be coercing to an extension type, 1769 # in which case a type test node will be needed. 1770 return AtomicExprNode.coerce_to(node, dst_type, env) 1771 1772 gil_message = "Constructing complex number" 1773 1774 def calculate_result_code(self): 1775 if self.type.is_pyobject: 1776 return self.result() 1777 else: 1778 return "%s(0, %r)" % (self.type.from_parts, float(self.value)) 1779 1780 def generate_result_code(self, code): 1781 if self.type.is_pyobject: 1782 code.putln( 1783 "%s = PyComplex_FromDoubles(0.0, %r); %s" % ( 1784 self.result(), 1785 float(self.value), 1786 code.error_goto_if_null(self.result(), self.pos))) 1787 code.put_gotref(self.py_result()) 1788 1789 1790class NewExprNode(AtomicExprNode): 1791 1792 # C++ new statement 1793 # 1794 # cppclass node c++ class to create 1795 1796 type = None 1797 1798 def infer_type(self, env): 1799 type = self.cppclass.analyse_as_type(env) 1800 if type is None or not type.is_cpp_class: 1801 error(self.pos, "new operator can only be applied to a C++ class") 1802 self.type = error_type 1803 return 1804 self.cpp_check(env) 1805 constructor = type.get_constructor(self.pos) 1806 self.class_type = type 1807 self.entry = constructor 1808 self.type = constructor.type 1809 return self.type 1810 1811 def analyse_types(self, env): 1812 if self.type is None: 1813 self.infer_type(env) 1814 return self 1815 1816 def may_be_none(self): 1817 return False 1818 1819 def generate_result_code(self, code): 1820 pass 1821 1822 def calculate_result_code(self): 1823 return "new " + self.class_type.empty_declaration_code() 1824 1825 1826class NameNode(AtomicExprNode): 1827 # Reference to a local or global variable name. 1828 # 1829 # name string Python name of the variable 1830 # entry Entry Symbol table entry 1831 # type_entry Entry For extension type names, the original type entry 1832 # cf_is_null boolean Is uninitialized before this node 1833 # cf_maybe_null boolean Maybe uninitialized before this node 1834 # allow_null boolean Don't raise UnboundLocalError 1835 # nogil boolean Whether it is used in a nogil context 1836 1837 is_name = True 1838 is_cython_module = False 1839 cython_attribute = None 1840 lhs_of_first_assignment = False # TODO: remove me 1841 is_used_as_rvalue = 0 1842 entry = None 1843 type_entry = None 1844 cf_maybe_null = True 1845 cf_is_null = False 1846 allow_null = False 1847 nogil = False 1848 inferred_type = None 1849 1850 def as_cython_attribute(self): 1851 return self.cython_attribute 1852 1853 def type_dependencies(self, env): 1854 if self.entry is None: 1855 self.entry = env.lookup(self.name) 1856 if self.entry is not None and self.entry.type.is_unspecified: 1857 return (self,) 1858 else: 1859 return () 1860 1861 def infer_type(self, env): 1862 if self.entry is None: 1863 self.entry = env.lookup(self.name) 1864 if self.entry is None or self.entry.type is unspecified_type: 1865 if self.inferred_type is not None: 1866 return self.inferred_type 1867 return py_object_type 1868 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_type) and \ 1869 self.name == self.entry.type.name: 1870 # Unfortunately the type attribute of type objects 1871 # is used for the pointer to the type they represent. 1872 return type_type 1873 elif self.entry.type.is_cfunction: 1874 if self.entry.scope.is_builtin_scope: 1875 # special case: optimised builtin functions must be treated as Python objects 1876 return py_object_type 1877 else: 1878 # special case: referring to a C function must return its pointer 1879 return PyrexTypes.CPtrType(self.entry.type) 1880 else: 1881 # If entry is inferred as pyobject it's safe to use local 1882 # NameNode's inferred_type. 1883 if self.entry.type.is_pyobject and self.inferred_type: 1884 # Overflow may happen if integer 1885 if not (self.inferred_type.is_int and self.entry.might_overflow): 1886 return self.inferred_type 1887 return self.entry.type 1888 1889 def compile_time_value(self, denv): 1890 try: 1891 return denv.lookup(self.name) 1892 except KeyError: 1893 error(self.pos, "Compile-time name '%s' not defined" % self.name) 1894 1895 def get_constant_c_result_code(self): 1896 if not self.entry or self.entry.type.is_pyobject: 1897 return None 1898 return self.entry.cname 1899 1900 def coerce_to(self, dst_type, env): 1901 # If coercing to a generic pyobject and this is a builtin 1902 # C function with a Python equivalent, manufacture a NameNode 1903 # referring to the Python builtin. 1904 #print "NameNode.coerce_to:", self.name, dst_type ### 1905 if dst_type is py_object_type: 1906 entry = self.entry 1907 if entry and entry.is_cfunction: 1908 var_entry = entry.as_variable 1909 if var_entry: 1910 if var_entry.is_builtin and var_entry.is_const: 1911 var_entry = env.declare_builtin(var_entry.name, self.pos) 1912 node = NameNode(self.pos, name = self.name) 1913 node.entry = var_entry 1914 node.analyse_rvalue_entry(env) 1915 return node 1916 1917 return super(NameNode, self).coerce_to(dst_type, env) 1918 1919 def declare_from_annotation(self, env, as_target=False): 1920 """Implements PEP 526 annotation typing in a fairly relaxed way. 1921 1922 Annotations are ignored for global variables, Python class attributes and already declared variables. 1923 String literals are allowed and ignored. 1924 The ambiguous Python types 'int' and 'long' are ignored and the 'cython.int' form must be used instead. 1925 """ 1926 if not env.directives['annotation_typing']: 1927 return 1928 if env.is_module_scope or env.is_py_class_scope: 1929 # annotations never create global cdef names and Python classes don't support them anyway 1930 return 1931 name = self.name 1932 if self.entry or env.lookup_here(name) is not None: 1933 # already declared => ignore annotation 1934 return 1935 1936 annotation = self.annotation 1937 if annotation.is_string_literal: 1938 # name: "description" => not a type, but still a declared variable or attribute 1939 atype = None 1940 else: 1941 _, atype = analyse_type_annotation(annotation, env) 1942 if atype is None: 1943 atype = unspecified_type if as_target and env.directives['infer_types'] != False else py_object_type 1944 self.entry = env.declare_var(name, atype, self.pos, is_cdef=not as_target) 1945 self.entry.annotation = annotation 1946 1947 def analyse_as_module(self, env): 1948 # Try to interpret this as a reference to a cimported module. 1949 # Returns the module scope, or None. 1950 entry = self.entry 1951 if not entry: 1952 entry = env.lookup(self.name) 1953 if entry and entry.as_module: 1954 return entry.as_module 1955 return None 1956 1957 def analyse_as_type(self, env): 1958 if self.cython_attribute: 1959 type = PyrexTypes.parse_basic_type(self.cython_attribute) 1960 else: 1961 type = PyrexTypes.parse_basic_type(self.name) 1962 if type: 1963 return type 1964 entry = self.entry 1965 if not entry: 1966 entry = env.lookup(self.name) 1967 if entry and entry.is_type: 1968 return entry.type 1969 else: 1970 return None 1971 1972 def analyse_as_extension_type(self, env): 1973 # Try to interpret this as a reference to an extension type. 1974 # Returns the extension type, or None. 1975 entry = self.entry 1976 if not entry: 1977 entry = env.lookup(self.name) 1978 if entry and entry.is_type: 1979 if entry.type.is_extension_type or entry.type.is_builtin_type: 1980 return entry.type 1981 return None 1982 1983 def analyse_target_declaration(self, env): 1984 if not self.entry: 1985 self.entry = env.lookup_here(self.name) 1986 if not self.entry and self.annotation is not None: 1987 # name : type = ... 1988 self.declare_from_annotation(env, as_target=True) 1989 if not self.entry: 1990 if env.directives['warn.undeclared']: 1991 warning(self.pos, "implicit declaration of '%s'" % self.name, 1) 1992 if env.directives['infer_types'] != False: 1993 type = unspecified_type 1994 else: 1995 type = py_object_type 1996 self.entry = env.declare_var(self.name, type, self.pos) 1997 if self.entry.is_declared_generic: 1998 self.result_ctype = py_object_type 1999 if self.entry.as_module: 2000 # cimported modules namespace can shadow actual variables 2001 self.entry.is_variable = 1 2002 2003 def analyse_types(self, env): 2004 self.initialized_check = env.directives['initializedcheck'] 2005 entry = self.entry 2006 if entry is None: 2007 entry = env.lookup(self.name) 2008 if not entry: 2009 entry = env.declare_builtin(self.name, self.pos) 2010 if entry and entry.is_builtin and entry.is_const: 2011 self.is_literal = True 2012 if not entry: 2013 self.type = PyrexTypes.error_type 2014 return self 2015 self.entry = entry 2016 entry.used = 1 2017 if entry.type.is_buffer: 2018 from . import Buffer 2019 Buffer.used_buffer_aux_vars(entry) 2020 self.analyse_rvalue_entry(env) 2021 return self 2022 2023 def analyse_target_types(self, env): 2024 self.analyse_entry(env, is_target=True) 2025 2026 entry = self.entry 2027 if entry.is_cfunction and entry.as_variable: 2028 # FIXME: unify "is_overridable" flags below 2029 if (entry.is_overridable or entry.type.is_overridable) or not self.is_lvalue() and entry.fused_cfunction: 2030 # We need this for assigning to cpdef names and for the fused 'def' TreeFragment 2031 entry = self.entry = entry.as_variable 2032 self.type = entry.type 2033 2034 if self.type.is_const: 2035 error(self.pos, "Assignment to const '%s'" % self.name) 2036 if self.type.is_reference: 2037 error(self.pos, "Assignment to reference '%s'" % self.name) 2038 if not self.is_lvalue(): 2039 error(self.pos, "Assignment to non-lvalue '%s'" % self.name) 2040 self.type = PyrexTypes.error_type 2041 entry.used = 1 2042 if entry.type.is_buffer: 2043 from . import Buffer 2044 Buffer.used_buffer_aux_vars(entry) 2045 return self 2046 2047 def analyse_rvalue_entry(self, env): 2048 #print "NameNode.analyse_rvalue_entry:", self.name ### 2049 #print "Entry:", self.entry.__dict__ ### 2050 self.analyse_entry(env) 2051 entry = self.entry 2052 2053 if entry.is_declared_generic: 2054 self.result_ctype = py_object_type 2055 2056 if entry.is_pyglobal or entry.is_builtin: 2057 if entry.is_builtin and entry.is_const: 2058 self.is_temp = 0 2059 else: 2060 self.is_temp = 1 2061 2062 self.is_used_as_rvalue = 1 2063 elif entry.type.is_memoryviewslice: 2064 self.is_temp = False 2065 self.is_used_as_rvalue = True 2066 self.use_managed_ref = True 2067 return self 2068 2069 def nogil_check(self, env): 2070 self.nogil = True 2071 if self.is_used_as_rvalue: 2072 entry = self.entry 2073 if entry.is_builtin: 2074 if not entry.is_const: # cached builtins are ok 2075 self.gil_error() 2076 elif entry.is_pyglobal: 2077 self.gil_error() 2078 2079 gil_message = "Accessing Python global or builtin" 2080 2081 def analyse_entry(self, env, is_target=False): 2082 #print "NameNode.analyse_entry:", self.name ### 2083 self.check_identifier_kind() 2084 entry = self.entry 2085 type = entry.type 2086 if (not is_target and type.is_pyobject and self.inferred_type and 2087 self.inferred_type.is_builtin_type): 2088 # assume that type inference is smarter than the static entry 2089 type = self.inferred_type 2090 self.type = type 2091 2092 def check_identifier_kind(self): 2093 # Check that this is an appropriate kind of name for use in an 2094 # expression. Also finds the variable entry associated with 2095 # an extension type. 2096 entry = self.entry 2097 if entry.is_type and entry.type.is_extension_type: 2098 self.type_entry = entry 2099 if entry.is_type and entry.type.is_enum: 2100 py_entry = Symtab.Entry(self.name, None, py_object_type) 2101 py_entry.is_pyglobal = True 2102 py_entry.scope = self.entry.scope 2103 self.entry = py_entry 2104 elif not (entry.is_const or entry.is_variable or 2105 entry.is_builtin or entry.is_cfunction or 2106 entry.is_cpp_class): 2107 if self.entry.as_variable: 2108 self.entry = self.entry.as_variable 2109 elif not self.is_cython_module: 2110 error(self.pos, "'%s' is not a constant, variable or function identifier" % self.name) 2111 2112 def is_cimported_module_without_shadow(self, env): 2113 if self.is_cython_module or self.cython_attribute: 2114 return False 2115 entry = self.entry or env.lookup(self.name) 2116 return entry.as_module and not entry.is_variable 2117 2118 def is_simple(self): 2119 # If it's not a C variable, it'll be in a temp. 2120 return 1 2121 2122 def may_be_none(self): 2123 if self.cf_state and self.type and (self.type.is_pyobject or 2124 self.type.is_memoryviewslice): 2125 # gard against infinite recursion on self-dependencies 2126 if getattr(self, '_none_checking', False): 2127 # self-dependency - either this node receives a None 2128 # value from *another* node, or it can not reference 2129 # None at this point => safe to assume "not None" 2130 return False 2131 self._none_checking = True 2132 # evaluate control flow state to see if there were any 2133 # potential None values assigned to the node so far 2134 may_be_none = False 2135 for assignment in self.cf_state: 2136 if assignment.rhs.may_be_none(): 2137 may_be_none = True 2138 break 2139 del self._none_checking 2140 return may_be_none 2141 return super(NameNode, self).may_be_none() 2142 2143 def nonlocally_immutable(self): 2144 if ExprNode.nonlocally_immutable(self): 2145 return True 2146 entry = self.entry 2147 if not entry or entry.in_closure: 2148 return False 2149 return entry.is_local or entry.is_arg or entry.is_builtin or entry.is_readonly 2150 2151 def calculate_target_results(self, env): 2152 pass 2153 2154 def check_const(self): 2155 entry = self.entry 2156 if entry is not None and not ( 2157 entry.is_const or 2158 entry.is_cfunction or 2159 entry.is_builtin or 2160 entry.type.is_const): 2161 self.not_const() 2162 return False 2163 return True 2164 2165 def check_const_addr(self): 2166 entry = self.entry 2167 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin): 2168 self.addr_not_const() 2169 return False 2170 return True 2171 2172 def is_lvalue(self): 2173 return ( 2174 self.entry.is_variable and 2175 not self.entry.is_readonly 2176 ) or ( 2177 self.entry.is_cfunction and 2178 self.entry.is_overridable 2179 ) 2180 2181 def is_addressable(self): 2182 return self.entry.is_variable and not self.type.is_memoryviewslice 2183 2184 def is_ephemeral(self): 2185 # Name nodes are never ephemeral, even if the 2186 # result is in a temporary. 2187 return 0 2188 2189 def calculate_result_code(self): 2190 entry = self.entry 2191 if not entry: 2192 return "<error>" # There was an error earlier 2193 return entry.cname 2194 2195 def generate_result_code(self, code): 2196 assert hasattr(self, 'entry') 2197 entry = self.entry 2198 if entry is None: 2199 return # There was an error earlier 2200 if entry.utility_code: 2201 code.globalstate.use_utility_code(entry.utility_code) 2202 if entry.is_builtin and entry.is_const: 2203 return # Lookup already cached 2204 elif entry.is_pyclass_attr: 2205 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 2206 interned_cname = code.intern_identifier(self.entry.name) 2207 if entry.is_builtin: 2208 namespace = Naming.builtins_cname 2209 else: # entry.is_pyglobal 2210 namespace = entry.scope.namespace_cname 2211 if not self.cf_is_null: 2212 code.putln( 2213 '%s = PyObject_GetItem(%s, %s);' % ( 2214 self.result(), 2215 namespace, 2216 interned_cname)) 2217 code.putln('if (unlikely(!%s)) {' % self.result()) 2218 code.putln('PyErr_Clear();') 2219 code.globalstate.use_utility_code( 2220 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) 2221 code.putln( 2222 '__Pyx_GetModuleGlobalName(%s, %s);' % ( 2223 self.result(), 2224 interned_cname)) 2225 if not self.cf_is_null: 2226 code.putln("}") 2227 code.putln(code.error_goto_if_null(self.result(), self.pos)) 2228 code.put_gotref(self.py_result()) 2229 2230 elif entry.is_builtin and not entry.scope.is_module_scope: 2231 # known builtin 2232 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 2233 interned_cname = code.intern_identifier(self.entry.name) 2234 code.globalstate.use_utility_code( 2235 UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c")) 2236 code.putln( 2237 '%s = __Pyx_GetBuiltinName(%s); %s' % ( 2238 self.result(), 2239 interned_cname, 2240 code.error_goto_if_null(self.result(), self.pos))) 2241 code.put_gotref(self.py_result()) 2242 2243 elif entry.is_pyglobal or (entry.is_builtin and entry.scope.is_module_scope): 2244 # name in class body, global name or unknown builtin 2245 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 2246 interned_cname = code.intern_identifier(self.entry.name) 2247 if entry.scope.is_module_scope: 2248 code.globalstate.use_utility_code( 2249 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c")) 2250 code.putln( 2251 '__Pyx_GetModuleGlobalName(%s, %s); %s' % ( 2252 self.result(), 2253 interned_cname, 2254 code.error_goto_if_null(self.result(), self.pos))) 2255 else: 2256 # FIXME: is_pyglobal is also used for class namespace 2257 code.globalstate.use_utility_code( 2258 UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c")) 2259 code.putln( 2260 '__Pyx_GetNameInClass(%s, %s, %s); %s' % ( 2261 self.result(), 2262 entry.scope.namespace_cname, 2263 interned_cname, 2264 code.error_goto_if_null(self.result(), self.pos))) 2265 code.put_gotref(self.py_result()) 2266 2267 elif entry.is_local or entry.in_closure or entry.from_closure or entry.type.is_memoryviewslice: 2268 # Raise UnboundLocalError for objects and memoryviewslices 2269 raise_unbound = ( 2270 (self.cf_maybe_null or self.cf_is_null) and not self.allow_null) 2271 null_code = entry.type.check_for_null_code(entry.cname) 2272 2273 memslice_check = entry.type.is_memoryviewslice and self.initialized_check 2274 2275 if null_code and raise_unbound and (entry.type.is_pyobject or memslice_check): 2276 code.put_error_if_unbound(self.pos, entry, self.in_nogil_context) 2277 2278 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 2279 exception_check=None, exception_value=None): 2280 #print "NameNode.generate_assignment_code:", self.name ### 2281 entry = self.entry 2282 if entry is None: 2283 return # There was an error earlier 2284 2285 if (self.entry.type.is_ptr and isinstance(rhs, ListNode) 2286 and not self.lhs_of_first_assignment and not rhs.in_module_scope): 2287 error(self.pos, "Literal list must be assigned to pointer at time of declaration") 2288 2289 # is_pyglobal seems to be True for module level-globals only. 2290 # We use this to access class->tp_dict if necessary. 2291 if entry.is_pyglobal: 2292 assert entry.type.is_pyobject, "Python global or builtin not a Python object" 2293 interned_cname = code.intern_identifier(self.entry.name) 2294 namespace = self.entry.scope.namespace_cname 2295 if entry.is_member: 2296 # if the entry is a member we have to cheat: SetAttr does not work 2297 # on types, so we create a descriptor which is then added to tp_dict 2298 setter = 'PyDict_SetItem' 2299 namespace = '%s->tp_dict' % namespace 2300 elif entry.scope.is_module_scope: 2301 setter = 'PyDict_SetItem' 2302 namespace = Naming.moddict_cname 2303 elif entry.is_pyclass_attr: 2304 code.globalstate.use_utility_code(UtilityCode.load_cached("SetNameInClass", "ObjectHandling.c")) 2305 setter = '__Pyx_SetNameInClass' 2306 else: 2307 assert False, repr(entry) 2308 code.put_error_if_neg( 2309 self.pos, 2310 '%s(%s, %s, %s)' % ( 2311 setter, 2312 namespace, 2313 interned_cname, 2314 rhs.py_result())) 2315 if debug_disposal_code: 2316 print("NameNode.generate_assignment_code:") 2317 print("...generating disposal code for %s" % rhs) 2318 rhs.generate_disposal_code(code) 2319 rhs.free_temps(code) 2320 if entry.is_member: 2321 # in Py2.6+, we need to invalidate the method cache 2322 code.putln("PyType_Modified(%s);" % 2323 entry.scope.parent_type.typeptr_cname) 2324 else: 2325 if self.type.is_memoryviewslice: 2326 self.generate_acquire_memoryviewslice(rhs, code) 2327 2328 elif self.type.is_buffer: 2329 # Generate code for doing the buffer release/acquisition. 2330 # This might raise an exception in which case the assignment (done 2331 # below) will not happen. 2332 # 2333 # The reason this is not in a typetest-like node is because the 2334 # variables that the acquired buffer info is stored to is allocated 2335 # per entry and coupled with it. 2336 self.generate_acquire_buffer(rhs, code) 2337 assigned = False 2338 if self.type.is_pyobject: 2339 #print "NameNode.generate_assignment_code: to", self.name ### 2340 #print "...from", rhs ### 2341 #print "...LHS type", self.type, "ctype", self.ctype() ### 2342 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ### 2343 if self.use_managed_ref: 2344 rhs.make_owned_reference(code) 2345 is_external_ref = entry.is_cglobal or self.entry.in_closure or self.entry.from_closure 2346 if is_external_ref: 2347 if not self.cf_is_null: 2348 if self.cf_maybe_null: 2349 code.put_xgotref(self.py_result()) 2350 else: 2351 code.put_gotref(self.py_result()) 2352 assigned = True 2353 if entry.is_cglobal: 2354 code.put_decref_set( 2355 self.result(), rhs.result_as(self.ctype())) 2356 else: 2357 if not self.cf_is_null: 2358 if self.cf_maybe_null: 2359 code.put_xdecref_set( 2360 self.result(), rhs.result_as(self.ctype())) 2361 else: 2362 code.put_decref_set( 2363 self.result(), rhs.result_as(self.ctype())) 2364 else: 2365 assigned = False 2366 if is_external_ref: 2367 code.put_giveref(rhs.py_result()) 2368 if not self.type.is_memoryviewslice: 2369 if not assigned: 2370 if overloaded_assignment: 2371 result = rhs.result() 2372 if exception_check == '+': 2373 translate_cpp_exception( 2374 code, self.pos, 2375 '%s = %s;' % (self.result(), result), 2376 self.result() if self.type.is_pyobject else None, 2377 exception_value, self.in_nogil_context) 2378 else: 2379 code.putln('%s = %s;' % (self.result(), result)) 2380 else: 2381 result = rhs.result_as(self.ctype()) 2382 2383 if is_pythran_expr(self.type): 2384 code.putln('new (&%s) decltype(%s){%s};' % (self.result(), self.result(), result)) 2385 elif result != self.result(): 2386 code.putln('%s = %s;' % (self.result(), result)) 2387 if debug_disposal_code: 2388 print("NameNode.generate_assignment_code:") 2389 print("...generating post-assignment code for %s" % rhs) 2390 rhs.generate_post_assignment_code(code) 2391 elif rhs.result_in_temp(): 2392 rhs.generate_post_assignment_code(code) 2393 2394 rhs.free_temps(code) 2395 2396 def generate_acquire_memoryviewslice(self, rhs, code): 2397 """ 2398 Slices, coercions from objects, return values etc are new references. 2399 We have a borrowed reference in case of dst = src 2400 """ 2401 from . import MemoryView 2402 2403 MemoryView.put_acquire_memoryviewslice( 2404 lhs_cname=self.result(), 2405 lhs_type=self.type, 2406 lhs_pos=self.pos, 2407 rhs=rhs, 2408 code=code, 2409 have_gil=not self.in_nogil_context, 2410 first_assignment=self.cf_is_null) 2411 2412 def generate_acquire_buffer(self, rhs, code): 2413 # rhstmp is only used in case the rhs is a complicated expression leading to 2414 # the object, to avoid repeating the same C expression for every reference 2415 # to the rhs. It does NOT hold a reference. 2416 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp 2417 if pretty_rhs: 2418 rhstmp = rhs.result_as(self.ctype()) 2419 else: 2420 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False) 2421 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) 2422 2423 from . import Buffer 2424 Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry, 2425 is_initialized=not self.lhs_of_first_assignment, 2426 pos=self.pos, code=code) 2427 2428 if not pretty_rhs: 2429 code.putln("%s = 0;" % rhstmp) 2430 code.funcstate.release_temp(rhstmp) 2431 2432 def generate_deletion_code(self, code, ignore_nonexisting=False): 2433 if self.entry is None: 2434 return # There was an error earlier 2435 elif self.entry.is_pyclass_attr: 2436 namespace = self.entry.scope.namespace_cname 2437 interned_cname = code.intern_identifier(self.entry.name) 2438 if ignore_nonexisting: 2439 key_error_code = 'PyErr_Clear(); else' 2440 else: 2441 # minor hack: fake a NameError on KeyError 2442 key_error_code = ( 2443 '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' % 2444 self.entry.name) 2445 code.putln( 2446 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {' 2447 ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s' 2448 ' %s ' 2449 '}' % (namespace, interned_cname, 2450 key_error_code, 2451 code.error_goto(self.pos))) 2452 elif self.entry.is_pyglobal: 2453 code.globalstate.use_utility_code( 2454 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 2455 interned_cname = code.intern_identifier(self.entry.name) 2456 del_code = '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( 2457 Naming.module_cname, interned_cname) 2458 if ignore_nonexisting: 2459 code.putln( 2460 'if (unlikely(%s < 0)) {' 2461 ' if (likely(PyErr_ExceptionMatches(PyExc_AttributeError))) PyErr_Clear(); else %s ' 2462 '}' % (del_code, code.error_goto(self.pos))) 2463 else: 2464 code.put_error_if_neg(self.pos, del_code) 2465 elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice: 2466 if not self.cf_is_null: 2467 if self.cf_maybe_null and not ignore_nonexisting: 2468 code.put_error_if_unbound(self.pos, self.entry) 2469 2470 if self.entry.type.is_pyobject: 2471 if self.entry.in_closure: 2472 # generator 2473 if ignore_nonexisting and self.cf_maybe_null: 2474 code.put_xgotref(self.result()) 2475 else: 2476 code.put_gotref(self.result()) 2477 if ignore_nonexisting and self.cf_maybe_null: 2478 code.put_xdecref(self.result(), self.ctype()) 2479 else: 2480 code.put_decref(self.result(), self.ctype()) 2481 code.putln('%s = NULL;' % self.result()) 2482 else: 2483 code.put_xdecref_memoryviewslice(self.entry.cname, 2484 have_gil=not self.nogil) 2485 else: 2486 error(self.pos, "Deletion of C names not supported") 2487 2488 def annotate(self, code): 2489 if hasattr(self, 'is_called') and self.is_called: 2490 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1) 2491 if self.type.is_pyobject: 2492 style, text = 'py_call', 'python function (%s)' 2493 else: 2494 style, text = 'c_call', 'c function (%s)' 2495 code.annotate(pos, AnnotationItem(style, text % self.type, size=len(self.name))) 2496 2497class BackquoteNode(ExprNode): 2498 # `expr` 2499 # 2500 # arg ExprNode 2501 2502 type = py_object_type 2503 2504 subexprs = ['arg'] 2505 2506 def analyse_types(self, env): 2507 self.arg = self.arg.analyse_types(env) 2508 self.arg = self.arg.coerce_to_pyobject(env) 2509 self.is_temp = 1 2510 return self 2511 2512 gil_message = "Backquote expression" 2513 2514 def calculate_constant_result(self): 2515 self.constant_result = repr(self.arg.constant_result) 2516 2517 def generate_result_code(self, code): 2518 code.putln( 2519 "%s = PyObject_Repr(%s); %s" % ( 2520 self.result(), 2521 self.arg.py_result(), 2522 code.error_goto_if_null(self.result(), self.pos))) 2523 code.put_gotref(self.py_result()) 2524 2525 2526class ImportNode(ExprNode): 2527 # Used as part of import statement implementation. 2528 # Implements result = 2529 # __import__(module_name, globals(), None, name_list, level) 2530 # 2531 # module_name StringNode dotted name of module. Empty module 2532 # name means importing the parent package according 2533 # to level 2534 # name_list ListNode or None list of names to be imported 2535 # level int relative import level: 2536 # -1: attempt both relative import and absolute import; 2537 # 0: absolute import; 2538 # >0: the number of parent directories to search 2539 # relative to the current module. 2540 # None: decide the level according to language level and 2541 # directives 2542 2543 type = py_object_type 2544 2545 subexprs = ['module_name', 'name_list'] 2546 2547 def analyse_types(self, env): 2548 if self.level is None: 2549 if (env.directives['py2_import'] or 2550 Future.absolute_import not in env.global_scope().context.future_directives): 2551 self.level = -1 2552 else: 2553 self.level = 0 2554 module_name = self.module_name.analyse_types(env) 2555 self.module_name = module_name.coerce_to_pyobject(env) 2556 if self.name_list: 2557 name_list = self.name_list.analyse_types(env) 2558 self.name_list = name_list.coerce_to_pyobject(env) 2559 self.is_temp = 1 2560 return self 2561 2562 gil_message = "Python import" 2563 2564 def generate_result_code(self, code): 2565 if self.name_list: 2566 name_list_code = self.name_list.py_result() 2567 else: 2568 name_list_code = "0" 2569 2570 code.globalstate.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c")) 2571 import_code = "__Pyx_Import(%s, %s, %d)" % ( 2572 self.module_name.py_result(), 2573 name_list_code, 2574 self.level) 2575 2576 if (self.level <= 0 and 2577 self.module_name.is_string_literal and 2578 self.module_name.value in utility_code_for_imports): 2579 helper_func, code_name, code_file = utility_code_for_imports[self.module_name.value] 2580 code.globalstate.use_utility_code(UtilityCode.load_cached(code_name, code_file)) 2581 import_code = '%s(%s)' % (helper_func, import_code) 2582 2583 code.putln("%s = %s; %s" % ( 2584 self.result(), 2585 import_code, 2586 code.error_goto_if_null(self.result(), self.pos))) 2587 code.put_gotref(self.py_result()) 2588 2589 2590class IteratorNode(ExprNode): 2591 # Used as part of for statement implementation. 2592 # 2593 # Implements result = iter(sequence) 2594 # 2595 # sequence ExprNode 2596 2597 type = py_object_type 2598 iter_func_ptr = None 2599 counter_cname = None 2600 cpp_iterator_cname = None 2601 reversed = False # currently only used for list/tuple types (see Optimize.py) 2602 is_async = False 2603 2604 subexprs = ['sequence'] 2605 2606 def analyse_types(self, env): 2607 self.sequence = self.sequence.analyse_types(env) 2608 if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \ 2609 not self.sequence.type.is_string: 2610 # C array iteration will be transformed later on 2611 self.type = self.sequence.type 2612 elif self.sequence.type.is_cpp_class: 2613 self.analyse_cpp_types(env) 2614 else: 2615 self.sequence = self.sequence.coerce_to_pyobject(env) 2616 if self.sequence.type in (list_type, tuple_type): 2617 self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable") 2618 self.is_temp = 1 2619 return self 2620 2621 gil_message = "Iterating over Python object" 2622 2623 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( 2624 PyrexTypes.py_object_type, [ 2625 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), 2626 ])) 2627 2628 def type_dependencies(self, env): 2629 return self.sequence.type_dependencies(env) 2630 2631 def infer_type(self, env): 2632 sequence_type = self.sequence.infer_type(env) 2633 if sequence_type.is_array or sequence_type.is_ptr: 2634 return sequence_type 2635 elif sequence_type.is_cpp_class: 2636 begin = sequence_type.scope.lookup("begin") 2637 if begin is not None: 2638 return begin.type.return_type 2639 elif sequence_type.is_pyobject: 2640 return sequence_type 2641 return py_object_type 2642 2643 def analyse_cpp_types(self, env): 2644 sequence_type = self.sequence.type 2645 if sequence_type.is_ptr: 2646 sequence_type = sequence_type.base_type 2647 begin = sequence_type.scope.lookup("begin") 2648 end = sequence_type.scope.lookup("end") 2649 if (begin is None 2650 or not begin.type.is_cfunction 2651 or begin.type.args): 2652 error(self.pos, "missing begin() on %s" % self.sequence.type) 2653 self.type = error_type 2654 return 2655 if (end is None 2656 or not end.type.is_cfunction 2657 or end.type.args): 2658 error(self.pos, "missing end() on %s" % self.sequence.type) 2659 self.type = error_type 2660 return 2661 iter_type = begin.type.return_type 2662 if iter_type.is_cpp_class: 2663 if env.lookup_operator_for_types( 2664 self.pos, 2665 "!=", 2666 [iter_type, end.type.return_type]) is None: 2667 error(self.pos, "missing operator!= on result of begin() on %s" % self.sequence.type) 2668 self.type = error_type 2669 return 2670 if env.lookup_operator_for_types(self.pos, '++', [iter_type]) is None: 2671 error(self.pos, "missing operator++ on result of begin() on %s" % self.sequence.type) 2672 self.type = error_type 2673 return 2674 if env.lookup_operator_for_types(self.pos, '*', [iter_type]) is None: 2675 error(self.pos, "missing operator* on result of begin() on %s" % self.sequence.type) 2676 self.type = error_type 2677 return 2678 self.type = iter_type 2679 elif iter_type.is_ptr: 2680 if not (iter_type == end.type.return_type): 2681 error(self.pos, "incompatible types for begin() and end()") 2682 self.type = iter_type 2683 else: 2684 error(self.pos, "result type of begin() on %s must be a C++ class or pointer" % self.sequence.type) 2685 self.type = error_type 2686 return 2687 2688 def generate_result_code(self, code): 2689 sequence_type = self.sequence.type 2690 if sequence_type.is_cpp_class: 2691 if self.sequence.is_name: 2692 # safe: C++ won't allow you to reassign to class references 2693 begin_func = "%s.begin" % self.sequence.result() 2694 else: 2695 sequence_type = PyrexTypes.c_ptr_type(sequence_type) 2696 self.cpp_iterator_cname = code.funcstate.allocate_temp(sequence_type, manage_ref=False) 2697 code.putln("%s = &%s;" % (self.cpp_iterator_cname, self.sequence.result())) 2698 begin_func = "%s->begin" % self.cpp_iterator_cname 2699 # TODO: Limit scope. 2700 code.putln("%s = %s();" % (self.result(), begin_func)) 2701 return 2702 if sequence_type.is_array or sequence_type.is_ptr: 2703 raise InternalError("for in carray slice not transformed") 2704 2705 is_builtin_sequence = sequence_type in (list_type, tuple_type) 2706 if not is_builtin_sequence: 2707 # reversed() not currently optimised (see Optimize.py) 2708 assert not self.reversed, "internal error: reversed() only implemented for list/tuple objects" 2709 self.may_be_a_sequence = not sequence_type.is_builtin_type 2710 if self.may_be_a_sequence: 2711 code.putln( 2712 "if (likely(PyList_CheckExact(%s)) || PyTuple_CheckExact(%s)) {" % ( 2713 self.sequence.py_result(), 2714 self.sequence.py_result())) 2715 2716 if is_builtin_sequence or self.may_be_a_sequence: 2717 self.counter_cname = code.funcstate.allocate_temp( 2718 PyrexTypes.c_py_ssize_t_type, manage_ref=False) 2719 if self.reversed: 2720 if sequence_type is list_type: 2721 init_value = 'PyList_GET_SIZE(%s) - 1' % self.result() 2722 else: 2723 init_value = 'PyTuple_GET_SIZE(%s) - 1' % self.result() 2724 else: 2725 init_value = '0' 2726 code.putln("%s = %s; __Pyx_INCREF(%s); %s = %s;" % ( 2727 self.result(), 2728 self.sequence.py_result(), 2729 self.result(), 2730 self.counter_cname, 2731 init_value)) 2732 if not is_builtin_sequence: 2733 self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) 2734 if self.may_be_a_sequence: 2735 code.putln("%s = NULL;" % self.iter_func_ptr) 2736 code.putln("} else {") 2737 code.put("%s = -1; " % self.counter_cname) 2738 2739 code.putln("%s = PyObject_GetIter(%s); %s" % ( 2740 self.result(), 2741 self.sequence.py_result(), 2742 code.error_goto_if_null(self.result(), self.pos))) 2743 code.put_gotref(self.py_result()) 2744 2745 # PyObject_GetIter() fails if "tp_iternext" is not set, but the check below 2746 # makes it visible to the C compiler that the pointer really isn't NULL, so that 2747 # it can distinguish between the special cases and the generic case 2748 code.putln("%s = Py_TYPE(%s)->tp_iternext; %s" % ( 2749 self.iter_func_ptr, self.py_result(), 2750 code.error_goto_if_null(self.iter_func_ptr, self.pos))) 2751 if self.may_be_a_sequence: 2752 code.putln("}") 2753 2754 def generate_next_sequence_item(self, test_name, result_name, code): 2755 assert self.counter_cname, "internal error: counter_cname temp not prepared" 2756 final_size = 'Py%s_GET_SIZE(%s)' % (test_name, self.py_result()) 2757 if self.sequence.is_sequence_constructor: 2758 item_count = len(self.sequence.args) 2759 if self.sequence.mult_factor is None: 2760 final_size = item_count 2761 elif isinstance(self.sequence.mult_factor.constant_result, _py_int_types): 2762 final_size = item_count * self.sequence.mult_factor.constant_result 2763 code.putln("if (%s >= %s) break;" % (self.counter_cname, final_size)) 2764 if self.reversed: 2765 inc_dec = '--' 2766 else: 2767 inc_dec = '++' 2768 code.putln("#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS") 2769 code.putln( 2770 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % ( 2771 result_name, 2772 test_name, 2773 self.py_result(), 2774 self.counter_cname, 2775 result_name, 2776 self.counter_cname, 2777 inc_dec, 2778 # use the error label to avoid C compiler warnings if we only use it below 2779 code.error_goto_if_neg('0', self.pos) 2780 )) 2781 code.putln("#else") 2782 code.putln( 2783 "%s = PySequence_ITEM(%s, %s); %s%s; %s" % ( 2784 result_name, 2785 self.py_result(), 2786 self.counter_cname, 2787 self.counter_cname, 2788 inc_dec, 2789 code.error_goto_if_null(result_name, self.pos))) 2790 code.put_gotref(result_name) 2791 code.putln("#endif") 2792 2793 def generate_iter_next_result_code(self, result_name, code): 2794 sequence_type = self.sequence.type 2795 if self.reversed: 2796 code.putln("if (%s < 0) break;" % self.counter_cname) 2797 if sequence_type.is_cpp_class: 2798 if self.cpp_iterator_cname: 2799 end_func = "%s->end" % self.cpp_iterator_cname 2800 else: 2801 end_func = "%s.end" % self.sequence.result() 2802 # TODO: Cache end() call? 2803 code.putln("if (!(%s != %s())) break;" % ( 2804 self.result(), 2805 end_func)) 2806 code.putln("%s = *%s;" % ( 2807 result_name, 2808 self.result())) 2809 code.putln("++%s;" % self.result()) 2810 return 2811 elif sequence_type is list_type: 2812 self.generate_next_sequence_item('List', result_name, code) 2813 return 2814 elif sequence_type is tuple_type: 2815 self.generate_next_sequence_item('Tuple', result_name, code) 2816 return 2817 2818 if self.may_be_a_sequence: 2819 code.putln("if (likely(!%s)) {" % self.iter_func_ptr) 2820 code.putln("if (likely(PyList_CheckExact(%s))) {" % self.py_result()) 2821 self.generate_next_sequence_item('List', result_name, code) 2822 code.putln("} else {") 2823 self.generate_next_sequence_item('Tuple', result_name, code) 2824 code.putln("}") 2825 code.put("} else ") 2826 2827 code.putln("{") 2828 code.putln( 2829 "%s = %s(%s);" % ( 2830 result_name, 2831 self.iter_func_ptr, 2832 self.py_result())) 2833 code.putln("if (unlikely(!%s)) {" % result_name) 2834 code.putln("PyObject* exc_type = PyErr_Occurred();") 2835 code.putln("if (exc_type) {") 2836 code.putln("if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();") 2837 code.putln("else %s" % code.error_goto(self.pos)) 2838 code.putln("}") 2839 code.putln("break;") 2840 code.putln("}") 2841 code.put_gotref(result_name) 2842 code.putln("}") 2843 2844 def free_temps(self, code): 2845 if self.counter_cname: 2846 code.funcstate.release_temp(self.counter_cname) 2847 if self.iter_func_ptr: 2848 code.funcstate.release_temp(self.iter_func_ptr) 2849 self.iter_func_ptr = None 2850 if self.cpp_iterator_cname: 2851 code.funcstate.release_temp(self.cpp_iterator_cname) 2852 ExprNode.free_temps(self, code) 2853 2854 2855class NextNode(AtomicExprNode): 2856 # Used as part of for statement implementation. 2857 # Implements result = next(iterator) 2858 # Created during analyse_types phase. 2859 # The iterator is not owned by this node. 2860 # 2861 # iterator IteratorNode 2862 2863 def __init__(self, iterator): 2864 AtomicExprNode.__init__(self, iterator.pos) 2865 self.iterator = iterator 2866 2867 def nogil_check(self, env): 2868 # ignore - errors (if any) are already handled by IteratorNode 2869 pass 2870 2871 def type_dependencies(self, env): 2872 return self.iterator.type_dependencies(env) 2873 2874 def infer_type(self, env, iterator_type=None): 2875 if iterator_type is None: 2876 iterator_type = self.iterator.infer_type(env) 2877 if iterator_type.is_ptr or iterator_type.is_array: 2878 return iterator_type.base_type 2879 elif iterator_type.is_cpp_class: 2880 item_type = env.lookup_operator_for_types(self.pos, "*", [iterator_type]).type.return_type 2881 if item_type.is_reference: 2882 item_type = item_type.ref_base_type 2883 if item_type.is_const: 2884 item_type = item_type.const_base_type 2885 return item_type 2886 else: 2887 # Avoid duplication of complicated logic. 2888 fake_index_node = IndexNode( 2889 self.pos, 2890 base=self.iterator.sequence, 2891 index=IntNode(self.pos, value='PY_SSIZE_T_MAX', 2892 type=PyrexTypes.c_py_ssize_t_type)) 2893 return fake_index_node.infer_type(env) 2894 2895 def analyse_types(self, env): 2896 self.type = self.infer_type(env, self.iterator.type) 2897 self.is_temp = 1 2898 return self 2899 2900 def generate_result_code(self, code): 2901 self.iterator.generate_iter_next_result_code(self.result(), code) 2902 2903 2904class AsyncIteratorNode(ExprNode): 2905 # Used as part of 'async for' statement implementation. 2906 # 2907 # Implements result = sequence.__aiter__() 2908 # 2909 # sequence ExprNode 2910 2911 subexprs = ['sequence'] 2912 2913 is_async = True 2914 type = py_object_type 2915 is_temp = 1 2916 2917 def infer_type(self, env): 2918 return py_object_type 2919 2920 def analyse_types(self, env): 2921 self.sequence = self.sequence.analyse_types(env) 2922 if not self.sequence.type.is_pyobject: 2923 error(self.pos, "async for loops not allowed on C/C++ types") 2924 self.sequence = self.sequence.coerce_to_pyobject(env) 2925 return self 2926 2927 def generate_result_code(self, code): 2928 code.globalstate.use_utility_code(UtilityCode.load_cached("AsyncIter", "Coroutine.c")) 2929 code.putln("%s = __Pyx_Coroutine_GetAsyncIter(%s); %s" % ( 2930 self.result(), 2931 self.sequence.py_result(), 2932 code.error_goto_if_null(self.result(), self.pos))) 2933 code.put_gotref(self.result()) 2934 2935 2936class AsyncNextNode(AtomicExprNode): 2937 # Used as part of 'async for' statement implementation. 2938 # Implements result = iterator.__anext__() 2939 # Created during analyse_types phase. 2940 # The iterator is not owned by this node. 2941 # 2942 # iterator IteratorNode 2943 2944 type = py_object_type 2945 is_temp = 1 2946 2947 def __init__(self, iterator): 2948 AtomicExprNode.__init__(self, iterator.pos) 2949 self.iterator = iterator 2950 2951 def infer_type(self, env): 2952 return py_object_type 2953 2954 def analyse_types(self, env): 2955 return self 2956 2957 def generate_result_code(self, code): 2958 code.globalstate.use_utility_code(UtilityCode.load_cached("AsyncIter", "Coroutine.c")) 2959 code.putln("%s = __Pyx_Coroutine_AsyncIterNext(%s); %s" % ( 2960 self.result(), 2961 self.iterator.py_result(), 2962 code.error_goto_if_null(self.result(), self.pos))) 2963 code.put_gotref(self.result()) 2964 2965 2966class WithExitCallNode(ExprNode): 2967 # The __exit__() call of a 'with' statement. Used in both the 2968 # except and finally clauses. 2969 2970 # with_stat WithStatNode the surrounding 'with' statement 2971 # args TupleNode or ResultStatNode the exception info tuple 2972 # await_expr AwaitExprNode the await expression of an 'async with' statement 2973 2974 subexprs = ['args', 'await_expr'] 2975 test_if_run = True 2976 await_expr = None 2977 2978 def analyse_types(self, env): 2979 self.args = self.args.analyse_types(env) 2980 if self.await_expr: 2981 self.await_expr = self.await_expr.analyse_types(env) 2982 self.type = PyrexTypes.c_bint_type 2983 self.is_temp = True 2984 return self 2985 2986 def generate_evaluation_code(self, code): 2987 if self.test_if_run: 2988 # call only if it was not already called (and decref-cleared) 2989 code.putln("if (%s) {" % self.with_stat.exit_var) 2990 2991 self.args.generate_evaluation_code(code) 2992 result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=False) 2993 2994 code.mark_pos(self.pos) 2995 code.globalstate.use_utility_code(UtilityCode.load_cached( 2996 "PyObjectCall", "ObjectHandling.c")) 2997 code.putln("%s = __Pyx_PyObject_Call(%s, %s, NULL);" % ( 2998 result_var, 2999 self.with_stat.exit_var, 3000 self.args.result())) 3001 code.put_decref_clear(self.with_stat.exit_var, type=py_object_type) 3002 self.args.generate_disposal_code(code) 3003 self.args.free_temps(code) 3004 3005 code.putln(code.error_goto_if_null(result_var, self.pos)) 3006 code.put_gotref(result_var) 3007 3008 if self.await_expr: 3009 # FIXME: result_var temp currently leaks into the closure 3010 self.await_expr.generate_evaluation_code(code, source_cname=result_var, decref_source=True) 3011 code.putln("%s = %s;" % (result_var, self.await_expr.py_result())) 3012 self.await_expr.generate_post_assignment_code(code) 3013 self.await_expr.free_temps(code) 3014 3015 if self.result_is_used: 3016 self.allocate_temp_result(code) 3017 code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), result_var)) 3018 code.put_decref_clear(result_var, type=py_object_type) 3019 if self.result_is_used: 3020 code.put_error_if_neg(self.pos, self.result()) 3021 code.funcstate.release_temp(result_var) 3022 if self.test_if_run: 3023 code.putln("}") 3024 3025 3026class ExcValueNode(AtomicExprNode): 3027 # Node created during analyse_types phase 3028 # of an ExceptClauseNode to fetch the current 3029 # exception value. 3030 3031 type = py_object_type 3032 3033 def __init__(self, pos): 3034 ExprNode.__init__(self, pos) 3035 3036 def set_var(self, var): 3037 self.var = var 3038 3039 def calculate_result_code(self): 3040 return self.var 3041 3042 def generate_result_code(self, code): 3043 pass 3044 3045 def analyse_types(self, env): 3046 return self 3047 3048 3049class TempNode(ExprNode): 3050 # Node created during analyse_types phase 3051 # of some nodes to hold a temporary value. 3052 # 3053 # Note: One must call "allocate" and "release" on 3054 # the node during code generation to get/release the temp. 3055 # This is because the temp result is often used outside of 3056 # the regular cycle. 3057 3058 subexprs = [] 3059 3060 def __init__(self, pos, type, env=None): 3061 ExprNode.__init__(self, pos) 3062 self.type = type 3063 if type.is_pyobject: 3064 self.result_ctype = py_object_type 3065 self.is_temp = 1 3066 3067 def analyse_types(self, env): 3068 return self 3069 3070 def analyse_target_declaration(self, env): 3071 pass 3072 3073 def generate_result_code(self, code): 3074 pass 3075 3076 def allocate(self, code): 3077 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True) 3078 3079 def release(self, code): 3080 code.funcstate.release_temp(self.temp_cname) 3081 self.temp_cname = None 3082 3083 def result(self): 3084 try: 3085 return self.temp_cname 3086 except: 3087 assert False, "Remember to call allocate/release on TempNode" 3088 raise 3089 3090 # Do not participate in normal temp alloc/dealloc: 3091 def allocate_temp_result(self, code): 3092 pass 3093 3094 def release_temp_result(self, code): 3095 pass 3096 3097class PyTempNode(TempNode): 3098 # TempNode holding a Python value. 3099 3100 def __init__(self, pos, env): 3101 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env) 3102 3103class RawCNameExprNode(ExprNode): 3104 subexprs = [] 3105 3106 def __init__(self, pos, type=None, cname=None): 3107 ExprNode.__init__(self, pos, type=type) 3108 if cname is not None: 3109 self.cname = cname 3110 3111 def analyse_types(self, env): 3112 return self 3113 3114 def set_cname(self, cname): 3115 self.cname = cname 3116 3117 def result(self): 3118 return self.cname 3119 3120 def generate_result_code(self, code): 3121 pass 3122 3123 3124#------------------------------------------------------------------- 3125# 3126# F-strings 3127# 3128#------------------------------------------------------------------- 3129 3130 3131class JoinedStrNode(ExprNode): 3132 # F-strings 3133 # 3134 # values [UnicodeNode|FormattedValueNode] Substrings of the f-string 3135 # 3136 type = unicode_type 3137 is_temp = True 3138 3139 subexprs = ['values'] 3140 3141 def analyse_types(self, env): 3142 self.values = [v.analyse_types(env).coerce_to_pyobject(env) for v in self.values] 3143 return self 3144 3145 def may_be_none(self): 3146 # PyUnicode_Join() always returns a Unicode string or raises an exception 3147 return False 3148 3149 def generate_evaluation_code(self, code): 3150 code.mark_pos(self.pos) 3151 num_items = len(self.values) 3152 list_var = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 3153 ulength_var = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) 3154 max_char_var = code.funcstate.allocate_temp(PyrexTypes.c_py_ucs4_type, manage_ref=False) 3155 3156 code.putln('%s = PyTuple_New(%s); %s' % ( 3157 list_var, 3158 num_items, 3159 code.error_goto_if_null(list_var, self.pos))) 3160 code.put_gotref(list_var) 3161 code.putln("%s = 0;" % ulength_var) 3162 code.putln("%s = 127;" % max_char_var) # at least ASCII character range 3163 3164 for i, node in enumerate(self.values): 3165 node.generate_evaluation_code(code) 3166 node.make_owned_reference(code) 3167 3168 ulength = "__Pyx_PyUnicode_GET_LENGTH(%s)" % node.py_result() 3169 max_char_value = "__Pyx_PyUnicode_MAX_CHAR_VALUE(%s)" % node.py_result() 3170 is_ascii = False 3171 if isinstance(node, UnicodeNode): 3172 try: 3173 # most strings will be ASCII or at least Latin-1 3174 node.value.encode('iso8859-1') 3175 max_char_value = '255' 3176 node.value.encode('us-ascii') 3177 is_ascii = True 3178 except UnicodeEncodeError: 3179 if max_char_value != '255': 3180 # not ISO8859-1 => check BMP limit 3181 max_char = max(map(ord, node.value)) 3182 if max_char < 0xD800: 3183 # BMP-only, no surrogate pairs used 3184 max_char_value = '65535' 3185 ulength = str(len(node.value)) 3186 elif max_char >= 65536: 3187 # cleary outside of BMP, and not on a 16-bit Unicode system 3188 max_char_value = '1114111' 3189 ulength = str(len(node.value)) 3190 else: 3191 # not really worth implementing a check for surrogate pairs here 3192 # drawback: C code can differ when generating on Py2 with 2-byte Unicode 3193 pass 3194 else: 3195 ulength = str(len(node.value)) 3196 elif isinstance(node, FormattedValueNode) and node.value.type.is_numeric: 3197 is_ascii = True # formatted C numbers are always ASCII 3198 3199 if not is_ascii: 3200 code.putln("%s = (%s > %s) ? %s : %s;" % ( 3201 max_char_var, max_char_value, max_char_var, max_char_value, max_char_var)) 3202 code.putln("%s += %s;" % (ulength_var, ulength)) 3203 3204 code.put_giveref(node.py_result()) 3205 code.putln('PyTuple_SET_ITEM(%s, %s, %s);' % (list_var, i, node.py_result())) 3206 node.generate_post_assignment_code(code) 3207 node.free_temps(code) 3208 3209 code.mark_pos(self.pos) 3210 self.allocate_temp_result(code) 3211 code.globalstate.use_utility_code(UtilityCode.load_cached("JoinPyUnicode", "StringTools.c")) 3212 code.putln('%s = __Pyx_PyUnicode_Join(%s, %d, %s, %s); %s' % ( 3213 self.result(), 3214 list_var, 3215 num_items, 3216 ulength_var, 3217 max_char_var, 3218 code.error_goto_if_null(self.py_result(), self.pos))) 3219 code.put_gotref(self.py_result()) 3220 3221 code.put_decref_clear(list_var, py_object_type) 3222 code.funcstate.release_temp(list_var) 3223 code.funcstate.release_temp(ulength_var) 3224 code.funcstate.release_temp(max_char_var) 3225 3226 3227class FormattedValueNode(ExprNode): 3228 # {}-delimited portions of an f-string 3229 # 3230 # value ExprNode The expression itself 3231 # conversion_char str or None Type conversion (!s, !r, !a, or none, or 'd' for integer conversion) 3232 # format_spec JoinedStrNode or None Format string passed to __format__ 3233 # c_format_spec str or None If not None, formatting can be done at the C level 3234 3235 subexprs = ['value', 'format_spec'] 3236 3237 type = unicode_type 3238 is_temp = True 3239 c_format_spec = None 3240 3241 find_conversion_func = { 3242 's': 'PyObject_Unicode', 3243 'r': 'PyObject_Repr', 3244 'a': 'PyObject_ASCII', # NOTE: mapped to PyObject_Repr() in Py2 3245 'd': '__Pyx_PyNumber_IntOrLong', # NOTE: internal mapping for '%d' formatting 3246 }.get 3247 3248 def may_be_none(self): 3249 # PyObject_Format() always returns a Unicode string or raises an exception 3250 return False 3251 3252 def analyse_types(self, env): 3253 self.value = self.value.analyse_types(env) 3254 if not self.format_spec or self.format_spec.is_string_literal: 3255 c_format_spec = self.format_spec.value if self.format_spec else self.value.type.default_format_spec 3256 if self.value.type.can_coerce_to_pystring(env, format_spec=c_format_spec): 3257 self.c_format_spec = c_format_spec 3258 3259 if self.format_spec: 3260 self.format_spec = self.format_spec.analyse_types(env).coerce_to_pyobject(env) 3261 if self.c_format_spec is None: 3262 self.value = self.value.coerce_to_pyobject(env) 3263 if not self.format_spec and (not self.conversion_char or self.conversion_char == 's'): 3264 if self.value.type is unicode_type and not self.value.may_be_none(): 3265 # value is definitely a unicode string and we don't format it any special 3266 return self.value 3267 return self 3268 3269 def generate_result_code(self, code): 3270 if self.c_format_spec is not None and not self.value.type.is_pyobject: 3271 convert_func_call = self.value.type.convert_to_pystring( 3272 self.value.result(), code, self.c_format_spec) 3273 code.putln("%s = %s; %s" % ( 3274 self.result(), 3275 convert_func_call, 3276 code.error_goto_if_null(self.result(), self.pos))) 3277 code.put_gotref(self.py_result()) 3278 return 3279 3280 value_result = self.value.py_result() 3281 value_is_unicode = self.value.type is unicode_type and not self.value.may_be_none() 3282 if self.format_spec: 3283 format_func = '__Pyx_PyObject_Format' 3284 format_spec = self.format_spec.py_result() 3285 else: 3286 # common case: expect simple Unicode pass-through if no format spec 3287 format_func = '__Pyx_PyObject_FormatSimple' 3288 # passing a Unicode format string in Py2 forces PyObject_Format() to also return a Unicode string 3289 format_spec = Naming.empty_unicode 3290 3291 conversion_char = self.conversion_char 3292 if conversion_char == 's' and value_is_unicode: 3293 # no need to pipe unicode strings through str() 3294 conversion_char = None 3295 3296 if conversion_char: 3297 fn = self.find_conversion_func(conversion_char) 3298 assert fn is not None, "invalid conversion character found: '%s'" % conversion_char 3299 value_result = '%s(%s)' % (fn, value_result) 3300 code.globalstate.use_utility_code( 3301 UtilityCode.load_cached("PyObjectFormatAndDecref", "StringTools.c")) 3302 format_func += 'AndDecref' 3303 elif self.format_spec: 3304 code.globalstate.use_utility_code( 3305 UtilityCode.load_cached("PyObjectFormat", "StringTools.c")) 3306 else: 3307 code.globalstate.use_utility_code( 3308 UtilityCode.load_cached("PyObjectFormatSimple", "StringTools.c")) 3309 3310 code.putln("%s = %s(%s, %s); %s" % ( 3311 self.result(), 3312 format_func, 3313 value_result, 3314 format_spec, 3315 code.error_goto_if_null(self.result(), self.pos))) 3316 code.put_gotref(self.py_result()) 3317 3318 3319#------------------------------------------------------------------- 3320# 3321# Parallel nodes (cython.parallel.thread(savailable|id)) 3322# 3323#------------------------------------------------------------------- 3324 3325class ParallelThreadsAvailableNode(AtomicExprNode): 3326 """ 3327 Note: this is disabled and not a valid directive at this moment 3328 3329 Implements cython.parallel.threadsavailable(). If we are called from the 3330 sequential part of the application, we need to call omp_get_max_threads(), 3331 and in the parallel part we can just call omp_get_num_threads() 3332 """ 3333 3334 type = PyrexTypes.c_int_type 3335 3336 def analyse_types(self, env): 3337 self.is_temp = True 3338 # env.add_include_file("omp.h") 3339 return self 3340 3341 def generate_result_code(self, code): 3342 code.putln("#ifdef _OPENMP") 3343 code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" % 3344 self.temp_code) 3345 code.putln("else %s = omp_get_num_threads();" % self.temp_code) 3346 code.putln("#else") 3347 code.putln("%s = 1;" % self.temp_code) 3348 code.putln("#endif") 3349 3350 def result(self): 3351 return self.temp_code 3352 3353 3354class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode): 3355 """ 3356 Implements cython.parallel.threadid() 3357 """ 3358 3359 type = PyrexTypes.c_int_type 3360 3361 def analyse_types(self, env): 3362 self.is_temp = True 3363 # env.add_include_file("omp.h") 3364 return self 3365 3366 def generate_result_code(self, code): 3367 code.putln("#ifdef _OPENMP") 3368 code.putln("%s = omp_get_thread_num();" % self.temp_code) 3369 code.putln("#else") 3370 code.putln("%s = 0;" % self.temp_code) 3371 code.putln("#endif") 3372 3373 def result(self): 3374 return self.temp_code 3375 3376 3377#------------------------------------------------------------------- 3378# 3379# Trailer nodes 3380# 3381#------------------------------------------------------------------- 3382 3383 3384class _IndexingBaseNode(ExprNode): 3385 # Base class for indexing nodes. 3386 # 3387 # base ExprNode the value being indexed 3388 3389 def is_ephemeral(self): 3390 # in most cases, indexing will return a safe reference to an object in a container, 3391 # so we consider the result safe if the base object is 3392 return self.base.is_ephemeral() or self.base.type in ( 3393 basestring_type, str_type, bytes_type, bytearray_type, unicode_type) 3394 3395 def check_const_addr(self): 3396 return self.base.check_const_addr() and self.index.check_const() 3397 3398 def is_lvalue(self): 3399 # NOTE: references currently have both is_reference and is_ptr 3400 # set. Since pointers and references have different lvalue 3401 # rules, we must be careful to separate the two. 3402 if self.type.is_reference: 3403 if self.type.ref_base_type.is_array: 3404 # fixed-sized arrays aren't l-values 3405 return False 3406 elif self.type.is_ptr: 3407 # non-const pointers can always be reassigned 3408 return True 3409 # Just about everything else returned by the index operator 3410 # can be an lvalue. 3411 return True 3412 3413 3414class IndexNode(_IndexingBaseNode): 3415 # Sequence indexing. 3416 # 3417 # base ExprNode 3418 # index ExprNode 3419 # type_indices [PyrexType] 3420 # 3421 # is_fused_index boolean Whether the index is used to specialize a 3422 # c(p)def function 3423 3424 subexprs = ['base', 'index'] 3425 type_indices = None 3426 3427 is_subscript = True 3428 is_fused_index = False 3429 3430 def calculate_constant_result(self): 3431 self.constant_result = self.base.constant_result[self.index.constant_result] 3432 3433 def compile_time_value(self, denv): 3434 base = self.base.compile_time_value(denv) 3435 index = self.index.compile_time_value(denv) 3436 try: 3437 return base[index] 3438 except Exception as e: 3439 self.compile_time_value_error(e) 3440 3441 def is_simple(self): 3442 base = self.base 3443 return (base.is_simple() and self.index.is_simple() 3444 and base.type and (base.type.is_ptr or base.type.is_array)) 3445 3446 def may_be_none(self): 3447 base_type = self.base.type 3448 if base_type: 3449 if base_type.is_string: 3450 return False 3451 if isinstance(self.index, SliceNode): 3452 # slicing! 3453 if base_type in (bytes_type, bytearray_type, str_type, unicode_type, 3454 basestring_type, list_type, tuple_type): 3455 return False 3456 return ExprNode.may_be_none(self) 3457 3458 def analyse_target_declaration(self, env): 3459 pass 3460 3461 def analyse_as_type(self, env): 3462 base_type = self.base.analyse_as_type(env) 3463 if base_type and not base_type.is_pyobject: 3464 if base_type.is_cpp_class: 3465 if isinstance(self.index, TupleNode): 3466 template_values = self.index.args 3467 else: 3468 template_values = [self.index] 3469 type_node = Nodes.TemplatedTypeNode( 3470 pos=self.pos, 3471 positional_args=template_values, 3472 keyword_args=None) 3473 return type_node.analyse(env, base_type=base_type) 3474 elif self.index.is_slice or self.index.is_sequence_constructor: 3475 # memory view 3476 from . import MemoryView 3477 env.use_utility_code(MemoryView.view_utility_code) 3478 axes = [self.index] if self.index.is_slice else list(self.index.args) 3479 return PyrexTypes.MemoryViewSliceType(base_type, MemoryView.get_axes_specs(env, axes)) 3480 else: 3481 # C array 3482 index = self.index.compile_time_value(env) 3483 if index is not None: 3484 try: 3485 index = int(index) 3486 except (ValueError, TypeError): 3487 pass 3488 else: 3489 return PyrexTypes.CArrayType(base_type, index) 3490 error(self.pos, "Array size must be a compile time constant") 3491 return None 3492 3493 def type_dependencies(self, env): 3494 return self.base.type_dependencies(env) + self.index.type_dependencies(env) 3495 3496 def infer_type(self, env): 3497 base_type = self.base.infer_type(env) 3498 if self.index.is_slice: 3499 # slicing! 3500 if base_type.is_string: 3501 # sliced C strings must coerce to Python 3502 return bytes_type 3503 elif base_type.is_pyunicode_ptr: 3504 # sliced Py_UNICODE* strings must coerce to Python 3505 return unicode_type 3506 elif base_type in (unicode_type, bytes_type, str_type, 3507 bytearray_type, list_type, tuple_type): 3508 # slicing these returns the same type 3509 return base_type 3510 else: 3511 # TODO: Handle buffers (hopefully without too much redundancy). 3512 return py_object_type 3513 3514 index_type = self.index.infer_type(env) 3515 if index_type and index_type.is_int or isinstance(self.index, IntNode): 3516 # indexing! 3517 if base_type is unicode_type: 3518 # Py_UCS4 will automatically coerce to a unicode string 3519 # if required, so this is safe. We only infer Py_UCS4 3520 # when the index is a C integer type. Otherwise, we may 3521 # need to use normal Python item access, in which case 3522 # it's faster to return the one-char unicode string than 3523 # to receive it, throw it away, and potentially rebuild it 3524 # on a subsequent PyObject coercion. 3525 return PyrexTypes.c_py_ucs4_type 3526 elif base_type is str_type: 3527 # always returns str - Py2: bytes, Py3: unicode 3528 return base_type 3529 elif base_type is bytearray_type: 3530 return PyrexTypes.c_uchar_type 3531 elif isinstance(self.base, BytesNode): 3532 #if env.global_scope().context.language_level >= 3: 3533 # # inferring 'char' can be made to work in Python 3 mode 3534 # return PyrexTypes.c_char_type 3535 # Py2/3 return different types on indexing bytes objects 3536 return py_object_type 3537 elif base_type in (tuple_type, list_type): 3538 # if base is a literal, take a look at its values 3539 item_type = infer_sequence_item_type( 3540 env, self.base, self.index, seq_type=base_type) 3541 if item_type is not None: 3542 return item_type 3543 elif base_type.is_ptr or base_type.is_array: 3544 return base_type.base_type 3545 elif base_type.is_ctuple and isinstance(self.index, IntNode): 3546 if self.index.has_constant_result(): 3547 index = self.index.constant_result 3548 if index < 0: 3549 index += base_type.size 3550 if 0 <= index < base_type.size: 3551 return base_type.components[index] 3552 3553 if base_type.is_cpp_class: 3554 class FakeOperand: 3555 def __init__(self, **kwds): 3556 self.__dict__.update(kwds) 3557 operands = [ 3558 FakeOperand(pos=self.pos, type=base_type), 3559 FakeOperand(pos=self.pos, type=index_type), 3560 ] 3561 index_func = env.lookup_operator('[]', operands) 3562 if index_func is not None: 3563 return index_func.type.return_type 3564 3565 if is_pythran_expr(base_type) and is_pythran_expr(index_type): 3566 index_with_type = (self.index, index_type) 3567 return PythranExpr(pythran_indexing_type(base_type, [index_with_type])) 3568 3569 # may be slicing or indexing, we don't know 3570 if base_type in (unicode_type, str_type): 3571 # these types always returns their own type on Python indexing/slicing 3572 return base_type 3573 else: 3574 # TODO: Handle buffers (hopefully without too much redundancy). 3575 return py_object_type 3576 3577 def analyse_types(self, env): 3578 return self.analyse_base_and_index_types(env, getting=True) 3579 3580 def analyse_target_types(self, env): 3581 node = self.analyse_base_and_index_types(env, setting=True) 3582 if node.type.is_const: 3583 error(self.pos, "Assignment to const dereference") 3584 if node is self and not node.is_lvalue(): 3585 error(self.pos, "Assignment to non-lvalue of type '%s'" % node.type) 3586 return node 3587 3588 def analyse_base_and_index_types(self, env, getting=False, setting=False, 3589 analyse_base=True): 3590 # Note: This might be cleaned up by having IndexNode 3591 # parsed in a saner way and only construct the tuple if 3592 # needed. 3593 if analyse_base: 3594 self.base = self.base.analyse_types(env) 3595 3596 if self.base.type.is_error: 3597 # Do not visit child tree if base is undeclared to avoid confusing 3598 # error messages 3599 self.type = PyrexTypes.error_type 3600 return self 3601 3602 is_slice = self.index.is_slice 3603 if not env.directives['wraparound']: 3604 if is_slice: 3605 check_negative_indices(self.index.start, self.index.stop) 3606 else: 3607 check_negative_indices(self.index) 3608 3609 # Potentially overflowing index value. 3610 if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value): 3611 self.index = self.index.coerce_to_pyobject(env) 3612 3613 is_memslice = self.base.type.is_memoryviewslice 3614 # Handle the case where base is a literal char* (and we expect a string, not an int) 3615 if not is_memslice and (isinstance(self.base, BytesNode) or is_slice): 3616 if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array): 3617 self.base = self.base.coerce_to_pyobject(env) 3618 3619 replacement_node = self.analyse_as_buffer_operation(env, getting) 3620 if replacement_node is not None: 3621 return replacement_node 3622 3623 self.nogil = env.nogil 3624 base_type = self.base.type 3625 3626 if not base_type.is_cfunction: 3627 self.index = self.index.analyse_types(env) 3628 self.original_index_type = self.index.type 3629 3630 if base_type.is_unicode_char: 3631 # we infer Py_UNICODE/Py_UCS4 for unicode strings in some 3632 # cases, but indexing must still work for them 3633 if setting: 3634 warning(self.pos, "cannot assign to Unicode string index", level=1) 3635 elif self.index.constant_result in (0, -1): 3636 # uchar[0] => uchar 3637 return self.base 3638 self.base = self.base.coerce_to_pyobject(env) 3639 base_type = self.base.type 3640 3641 if base_type.is_pyobject: 3642 return self.analyse_as_pyobject(env, is_slice, getting, setting) 3643 elif base_type.is_ptr or base_type.is_array: 3644 return self.analyse_as_c_array(env, is_slice) 3645 elif base_type.is_cpp_class: 3646 return self.analyse_as_cpp(env, setting) 3647 elif base_type.is_cfunction: 3648 return self.analyse_as_c_function(env) 3649 elif base_type.is_ctuple: 3650 return self.analyse_as_c_tuple(env, getting, setting) 3651 else: 3652 error(self.pos, 3653 "Attempting to index non-array type '%s'" % 3654 base_type) 3655 self.type = PyrexTypes.error_type 3656 return self 3657 3658 def analyse_as_pyobject(self, env, is_slice, getting, setting): 3659 base_type = self.base.type 3660 if self.index.type.is_unicode_char and base_type is not dict_type: 3661 # TODO: eventually fold into case below and remove warning, once people have adapted their code 3662 warning(self.pos, 3663 "Item lookup of unicode character codes now always converts to a Unicode string. " 3664 "Use an explicit C integer cast to get back the previous integer lookup behaviour.", level=1) 3665 self.index = self.index.coerce_to_pyobject(env) 3666 self.is_temp = 1 3667 elif self.index.type.is_int and base_type is not dict_type: 3668 if (getting 3669 and (base_type in (list_type, tuple_type, bytearray_type)) 3670 and (not self.index.type.signed 3671 or not env.directives['wraparound'] 3672 or (isinstance(self.index, IntNode) and 3673 self.index.has_constant_result() and self.index.constant_result >= 0)) 3674 and not env.directives['boundscheck']): 3675 self.is_temp = 0 3676 else: 3677 self.is_temp = 1 3678 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env) 3679 self.original_index_type.create_to_py_utility_code(env) 3680 else: 3681 self.index = self.index.coerce_to_pyobject(env) 3682 self.is_temp = 1 3683 3684 if self.index.type.is_int and base_type is unicode_type: 3685 # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string 3686 # if required, so this is fast and safe 3687 self.type = PyrexTypes.c_py_ucs4_type 3688 elif self.index.type.is_int and base_type is bytearray_type: 3689 if setting: 3690 self.type = PyrexTypes.c_uchar_type 3691 else: 3692 # not using 'uchar' to enable fast and safe error reporting as '-1' 3693 self.type = PyrexTypes.c_int_type 3694 elif is_slice and base_type in (bytes_type, bytearray_type, str_type, unicode_type, list_type, tuple_type): 3695 self.type = base_type 3696 else: 3697 item_type = None 3698 if base_type in (list_type, tuple_type) and self.index.type.is_int: 3699 item_type = infer_sequence_item_type( 3700 env, self.base, self.index, seq_type=base_type) 3701 if item_type is None: 3702 item_type = py_object_type 3703 self.type = item_type 3704 if base_type in (list_type, tuple_type, dict_type): 3705 # do the None check explicitly (not in a helper) to allow optimising it away 3706 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") 3707 3708 self.wrap_in_nonecheck_node(env, getting) 3709 return self 3710 3711 def analyse_as_c_array(self, env, is_slice): 3712 base_type = self.base.type 3713 self.type = base_type.base_type 3714 if is_slice: 3715 self.type = base_type 3716 elif self.index.type.is_pyobject: 3717 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env) 3718 elif not self.index.type.is_int: 3719 error(self.pos, "Invalid index type '%s'" % self.index.type) 3720 return self 3721 3722 def analyse_as_cpp(self, env, setting): 3723 base_type = self.base.type 3724 function = env.lookup_operator("[]", [self.base, self.index]) 3725 if function is None: 3726 error(self.pos, "Indexing '%s' not supported for index type '%s'" % (base_type, self.index.type)) 3727 self.type = PyrexTypes.error_type 3728 self.result_code = "<error>" 3729 return self 3730 func_type = function.type 3731 if func_type.is_ptr: 3732 func_type = func_type.base_type 3733 self.exception_check = func_type.exception_check 3734 self.exception_value = func_type.exception_value 3735 if self.exception_check: 3736 if not setting: 3737 self.is_temp = True 3738 if self.exception_value is None: 3739 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 3740 self.index = self.index.coerce_to(func_type.args[0].type, env) 3741 self.type = func_type.return_type 3742 if setting and not func_type.return_type.is_reference: 3743 error(self.pos, "Can't set non-reference result '%s'" % self.type) 3744 return self 3745 3746 def analyse_as_c_function(self, env): 3747 base_type = self.base.type 3748 if base_type.is_fused: 3749 self.parse_indexed_fused_cdef(env) 3750 else: 3751 self.type_indices = self.parse_index_as_types(env) 3752 self.index = None # FIXME: use a dedicated Node class instead of generic IndexNode 3753 if base_type.templates is None: 3754 error(self.pos, "Can only parameterize template functions.") 3755 self.type = error_type 3756 elif self.type_indices is None: 3757 # Error recorded earlier. 3758 self.type = error_type 3759 elif len(base_type.templates) != len(self.type_indices): 3760 error(self.pos, "Wrong number of template arguments: expected %s, got %s" % ( 3761 (len(base_type.templates), len(self.type_indices)))) 3762 self.type = error_type 3763 else: 3764 self.type = base_type.specialize(dict(zip(base_type.templates, self.type_indices))) 3765 # FIXME: use a dedicated Node class instead of generic IndexNode 3766 return self 3767 3768 def analyse_as_c_tuple(self, env, getting, setting): 3769 base_type = self.base.type 3770 if isinstance(self.index, IntNode) and self.index.has_constant_result(): 3771 index = self.index.constant_result 3772 if -base_type.size <= index < base_type.size: 3773 if index < 0: 3774 index += base_type.size 3775 self.type = base_type.components[index] 3776 else: 3777 error(self.pos, 3778 "Index %s out of bounds for '%s'" % 3779 (index, base_type)) 3780 self.type = PyrexTypes.error_type 3781 return self 3782 else: 3783 self.base = self.base.coerce_to_pyobject(env) 3784 return self.analyse_base_and_index_types(env, getting=getting, setting=setting, analyse_base=False) 3785 3786 def analyse_as_buffer_operation(self, env, getting): 3787 """ 3788 Analyse buffer indexing and memoryview indexing/slicing 3789 """ 3790 if isinstance(self.index, TupleNode): 3791 indices = self.index.args 3792 else: 3793 indices = [self.index] 3794 3795 base = self.base 3796 base_type = base.type 3797 replacement_node = None 3798 if base_type.is_memoryviewslice: 3799 # memoryviewslice indexing or slicing 3800 from . import MemoryView 3801 if base.is_memview_slice: 3802 # For memory views, "view[i][j]" is the same as "view[i, j]" => use the latter for speed. 3803 merged_indices = base.merged_indices(indices) 3804 if merged_indices is not None: 3805 base = base.base 3806 base_type = base.type 3807 indices = merged_indices 3808 have_slices, indices, newaxes = MemoryView.unellipsify(indices, base_type.ndim) 3809 if have_slices: 3810 replacement_node = MemoryViewSliceNode(self.pos, indices=indices, base=base) 3811 else: 3812 replacement_node = MemoryViewIndexNode(self.pos, indices=indices, base=base) 3813 elif base_type.is_buffer or base_type.is_pythran_expr: 3814 if base_type.is_pythran_expr or len(indices) == base_type.ndim: 3815 # Buffer indexing 3816 is_buffer_access = True 3817 indices = [index.analyse_types(env) for index in indices] 3818 if base_type.is_pythran_expr: 3819 do_replacement = all( 3820 index.type.is_int or index.is_slice or index.type.is_pythran_expr 3821 for index in indices) 3822 if do_replacement: 3823 for i,index in enumerate(indices): 3824 if index.is_slice: 3825 index = SliceIntNode(index.pos, start=index.start, stop=index.stop, step=index.step) 3826 index = index.analyse_types(env) 3827 indices[i] = index 3828 else: 3829 do_replacement = all(index.type.is_int for index in indices) 3830 if do_replacement: 3831 replacement_node = BufferIndexNode(self.pos, indices=indices, base=base) 3832 # On cloning, indices is cloned. Otherwise, unpack index into indices. 3833 assert not isinstance(self.index, CloneNode) 3834 3835 if replacement_node is not None: 3836 replacement_node = replacement_node.analyse_types(env, getting) 3837 return replacement_node 3838 3839 def wrap_in_nonecheck_node(self, env, getting): 3840 if not env.directives['nonecheck'] or not self.base.may_be_none(): 3841 return 3842 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") 3843 3844 def parse_index_as_types(self, env, required=True): 3845 if isinstance(self.index, TupleNode): 3846 indices = self.index.args 3847 else: 3848 indices = [self.index] 3849 type_indices = [] 3850 for index in indices: 3851 type_indices.append(index.analyse_as_type(env)) 3852 if type_indices[-1] is None: 3853 if required: 3854 error(index.pos, "not parsable as a type") 3855 return None 3856 return type_indices 3857 3858 def parse_indexed_fused_cdef(self, env): 3859 """ 3860 Interpret fused_cdef_func[specific_type1, ...] 3861 3862 Note that if this method is called, we are an indexed cdef function 3863 with fused argument types, and this IndexNode will be replaced by the 3864 NameNode with specific entry just after analysis of expressions by 3865 AnalyseExpressionsTransform. 3866 """ 3867 self.type = PyrexTypes.error_type 3868 3869 self.is_fused_index = True 3870 3871 base_type = self.base.type 3872 positions = [] 3873 3874 if self.index.is_name or self.index.is_attribute: 3875 positions.append(self.index.pos) 3876 elif isinstance(self.index, TupleNode): 3877 for arg in self.index.args: 3878 positions.append(arg.pos) 3879 specific_types = self.parse_index_as_types(env, required=False) 3880 3881 if specific_types is None: 3882 self.index = self.index.analyse_types(env) 3883 3884 if not self.base.entry.as_variable: 3885 error(self.pos, "Can only index fused functions with types") 3886 else: 3887 # A cpdef function indexed with Python objects 3888 self.base.entry = self.entry = self.base.entry.as_variable 3889 self.base.type = self.type = self.entry.type 3890 3891 self.base.is_temp = True 3892 self.is_temp = True 3893 3894 self.entry.used = True 3895 3896 self.is_fused_index = False 3897 return 3898 3899 for i, type in enumerate(specific_types): 3900 specific_types[i] = type.specialize_fused(env) 3901 3902 fused_types = base_type.get_fused_types() 3903 if len(specific_types) > len(fused_types): 3904 return error(self.pos, "Too many types specified") 3905 elif len(specific_types) < len(fused_types): 3906 t = fused_types[len(specific_types)] 3907 return error(self.pos, "Not enough types specified to specialize " 3908 "the function, %s is still fused" % t) 3909 3910 # See if our index types form valid specializations 3911 for pos, specific_type, fused_type in zip(positions, 3912 specific_types, 3913 fused_types): 3914 if not any([specific_type.same_as(t) for t in fused_type.types]): 3915 return error(pos, "Type not in fused type") 3916 3917 if specific_type is None or specific_type.is_error: 3918 return 3919 3920 fused_to_specific = dict(zip(fused_types, specific_types)) 3921 type = base_type.specialize(fused_to_specific) 3922 3923 if type.is_fused: 3924 # Only partially specific, this is invalid 3925 error(self.pos, 3926 "Index operation makes function only partially specific") 3927 else: 3928 # Fully specific, find the signature with the specialized entry 3929 for signature in self.base.type.get_all_specialized_function_types(): 3930 if type.same_as(signature): 3931 self.type = signature 3932 3933 if self.base.is_attribute: 3934 # Pretend to be a normal attribute, for cdef extension 3935 # methods 3936 self.entry = signature.entry 3937 self.is_attribute = True 3938 self.obj = self.base.obj 3939 3940 self.type.entry.used = True 3941 self.base.type = signature 3942 self.base.entry = signature.entry 3943 3944 break 3945 else: 3946 # This is a bug 3947 raise InternalError("Couldn't find the right signature") 3948 3949 gil_message = "Indexing Python object" 3950 3951 def calculate_result_code(self): 3952 if self.base.type in (list_type, tuple_type, bytearray_type): 3953 if self.base.type is list_type: 3954 index_code = "PyList_GET_ITEM(%s, %s)" 3955 elif self.base.type is tuple_type: 3956 index_code = "PyTuple_GET_ITEM(%s, %s)" 3957 elif self.base.type is bytearray_type: 3958 index_code = "((unsigned char)(PyByteArray_AS_STRING(%s)[%s]))" 3959 else: 3960 assert False, "unexpected base type in indexing: %s" % self.base.type 3961 elif self.base.type.is_cfunction: 3962 return "%s<%s>" % ( 3963 self.base.result(), 3964 ",".join([param.empty_declaration_code() for param in self.type_indices])) 3965 elif self.base.type.is_ctuple: 3966 index = self.index.constant_result 3967 if index < 0: 3968 index += self.base.type.size 3969 return "%s.f%s" % (self.base.result(), index) 3970 else: 3971 if (self.type.is_ptr or self.type.is_array) and self.type == self.base.type: 3972 error(self.pos, "Invalid use of pointer slice") 3973 return 3974 index_code = "(%s[%s])" 3975 return index_code % (self.base.result(), self.index.result()) 3976 3977 def extra_index_params(self, code): 3978 if self.index.type.is_int: 3979 is_list = self.base.type is list_type 3980 wraparound = ( 3981 bool(code.globalstate.directives['wraparound']) and 3982 self.original_index_type.signed and 3983 not (isinstance(self.index.constant_result, _py_int_types) 3984 and self.index.constant_result >= 0)) 3985 boundscheck = bool(code.globalstate.directives['boundscheck']) 3986 return ", %s, %d, %s, %d, %d, %d" % ( 3987 self.original_index_type.empty_declaration_code(), 3988 self.original_index_type.signed and 1 or 0, 3989 self.original_index_type.to_py_function, 3990 is_list, wraparound, boundscheck) 3991 else: 3992 return "" 3993 3994 def generate_result_code(self, code): 3995 if not self.is_temp: 3996 # all handled in self.calculate_result_code() 3997 return 3998 3999 utility_code = None 4000 if self.type.is_pyobject: 4001 error_value = 'NULL' 4002 if self.index.type.is_int: 4003 if self.base.type is list_type: 4004 function = "__Pyx_GetItemInt_List" 4005 elif self.base.type is tuple_type: 4006 function = "__Pyx_GetItemInt_Tuple" 4007 else: 4008 function = "__Pyx_GetItemInt" 4009 utility_code = TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c") 4010 else: 4011 if self.base.type is dict_type: 4012 function = "__Pyx_PyDict_GetItem" 4013 utility_code = UtilityCode.load_cached("DictGetItem", "ObjectHandling.c") 4014 elif self.base.type is py_object_type and self.index.type in (str_type, unicode_type): 4015 # obj[str] is probably doing a dict lookup 4016 function = "__Pyx_PyObject_Dict_GetItem" 4017 utility_code = UtilityCode.load_cached("DictGetItem", "ObjectHandling.c") 4018 else: 4019 function = "__Pyx_PyObject_GetItem" 4020 code.globalstate.use_utility_code( 4021 TempitaUtilityCode.load_cached("GetItemInt", "ObjectHandling.c")) 4022 utility_code = UtilityCode.load_cached("ObjectGetItem", "ObjectHandling.c") 4023 elif self.type.is_unicode_char and self.base.type is unicode_type: 4024 assert self.index.type.is_int 4025 function = "__Pyx_GetItemInt_Unicode" 4026 error_value = '(Py_UCS4)-1' 4027 utility_code = UtilityCode.load_cached("GetItemIntUnicode", "StringTools.c") 4028 elif self.base.type is bytearray_type: 4029 assert self.index.type.is_int 4030 assert self.type.is_int 4031 function = "__Pyx_GetItemInt_ByteArray" 4032 error_value = '-1' 4033 utility_code = UtilityCode.load_cached("GetItemIntByteArray", "StringTools.c") 4034 elif not (self.base.type.is_cpp_class and self.exception_check): 4035 assert False, "unexpected type %s and base type %s for indexing" % ( 4036 self.type, self.base.type) 4037 4038 if utility_code is not None: 4039 code.globalstate.use_utility_code(utility_code) 4040 4041 if self.index.type.is_int: 4042 index_code = self.index.result() 4043 else: 4044 index_code = self.index.py_result() 4045 4046 if self.base.type.is_cpp_class and self.exception_check: 4047 translate_cpp_exception(code, self.pos, 4048 "%s = %s[%s];" % (self.result(), self.base.result(), 4049 self.index.result()), 4050 self.result() if self.type.is_pyobject else None, 4051 self.exception_value, self.in_nogil_context) 4052 else: 4053 error_check = '!%s' if error_value == 'NULL' else '%%s == %s' % error_value 4054 code.putln( 4055 "%s = %s(%s, %s%s); %s" % ( 4056 self.result(), 4057 function, 4058 self.base.py_result(), 4059 index_code, 4060 self.extra_index_params(code), 4061 code.error_goto_if(error_check % self.result(), self.pos))) 4062 if self.type.is_pyobject: 4063 code.put_gotref(self.py_result()) 4064 4065 def generate_setitem_code(self, value_code, code): 4066 if self.index.type.is_int: 4067 if self.base.type is bytearray_type: 4068 code.globalstate.use_utility_code( 4069 UtilityCode.load_cached("SetItemIntByteArray", "StringTools.c")) 4070 function = "__Pyx_SetItemInt_ByteArray" 4071 else: 4072 code.globalstate.use_utility_code( 4073 UtilityCode.load_cached("SetItemInt", "ObjectHandling.c")) 4074 function = "__Pyx_SetItemInt" 4075 index_code = self.index.result() 4076 else: 4077 index_code = self.index.py_result() 4078 if self.base.type is dict_type: 4079 function = "PyDict_SetItem" 4080 # It would seem that we could specialized lists/tuples, but that 4081 # shouldn't happen here. 4082 # Both PyList_SetItem() and PyTuple_SetItem() take a Py_ssize_t as 4083 # index instead of an object, and bad conversion here would give 4084 # the wrong exception. Also, tuples are supposed to be immutable, 4085 # and raise a TypeError when trying to set their entries 4086 # (PyTuple_SetItem() is for creating new tuples from scratch). 4087 else: 4088 function = "PyObject_SetItem" 4089 code.putln(code.error_goto_if_neg( 4090 "%s(%s, %s, %s%s)" % ( 4091 function, 4092 self.base.py_result(), 4093 index_code, 4094 value_code, 4095 self.extra_index_params(code)), 4096 self.pos)) 4097 4098 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 4099 exception_check=None, exception_value=None): 4100 self.generate_subexpr_evaluation_code(code) 4101 4102 if self.type.is_pyobject: 4103 self.generate_setitem_code(rhs.py_result(), code) 4104 elif self.base.type is bytearray_type: 4105 value_code = self._check_byte_value(code, rhs) 4106 self.generate_setitem_code(value_code, code) 4107 elif self.base.type.is_cpp_class and self.exception_check and self.exception_check == '+': 4108 if overloaded_assignment and exception_check and \ 4109 self.exception_value != exception_value: 4110 # Handle the case that both the index operator and the assignment 4111 # operator have a c++ exception handler and they are not the same. 4112 translate_double_cpp_exception(code, self.pos, self.type, 4113 self.result(), rhs.result(), self.exception_value, 4114 exception_value, self.in_nogil_context) 4115 else: 4116 # Handle the case that only the index operator has a 4117 # c++ exception handler, or that 4118 # both exception handlers are the same. 4119 translate_cpp_exception(code, self.pos, 4120 "%s = %s;" % (self.result(), rhs.result()), 4121 self.result() if self.type.is_pyobject else None, 4122 self.exception_value, self.in_nogil_context) 4123 else: 4124 code.putln( 4125 "%s = %s;" % (self.result(), rhs.result())) 4126 4127 self.generate_subexpr_disposal_code(code) 4128 self.free_subexpr_temps(code) 4129 rhs.generate_disposal_code(code) 4130 rhs.free_temps(code) 4131 4132 def _check_byte_value(self, code, rhs): 4133 # TODO: should we do this generally on downcasts, or just here? 4134 assert rhs.type.is_int, repr(rhs.type) 4135 value_code = rhs.result() 4136 if rhs.has_constant_result(): 4137 if 0 <= rhs.constant_result < 256: 4138 return value_code 4139 needs_cast = True # make at least the C compiler happy 4140 warning(rhs.pos, 4141 "value outside of range(0, 256)" 4142 " when assigning to byte: %s" % rhs.constant_result, 4143 level=1) 4144 else: 4145 needs_cast = rhs.type != PyrexTypes.c_uchar_type 4146 4147 if not self.nogil: 4148 conditions = [] 4149 if rhs.is_literal or rhs.type.signed: 4150 conditions.append('%s < 0' % value_code) 4151 if (rhs.is_literal or not 4152 (rhs.is_temp and rhs.type in ( 4153 PyrexTypes.c_uchar_type, PyrexTypes.c_char_type, 4154 PyrexTypes.c_schar_type))): 4155 conditions.append('%s > 255' % value_code) 4156 if conditions: 4157 code.putln("if (unlikely(%s)) {" % ' || '.join(conditions)) 4158 code.putln( 4159 'PyErr_SetString(PyExc_ValueError,' 4160 ' "byte must be in range(0, 256)"); %s' % 4161 code.error_goto(self.pos)) 4162 code.putln("}") 4163 4164 if needs_cast: 4165 value_code = '((unsigned char)%s)' % value_code 4166 return value_code 4167 4168 def generate_deletion_code(self, code, ignore_nonexisting=False): 4169 self.generate_subexpr_evaluation_code(code) 4170 #if self.type.is_pyobject: 4171 if self.index.type.is_int: 4172 function = "__Pyx_DelItemInt" 4173 index_code = self.index.result() 4174 code.globalstate.use_utility_code( 4175 UtilityCode.load_cached("DelItemInt", "ObjectHandling.c")) 4176 else: 4177 index_code = self.index.py_result() 4178 if self.base.type is dict_type: 4179 function = "PyDict_DelItem" 4180 else: 4181 function = "PyObject_DelItem" 4182 code.putln(code.error_goto_if_neg( 4183 "%s(%s, %s%s)" % ( 4184 function, 4185 self.base.py_result(), 4186 index_code, 4187 self.extra_index_params(code)), 4188 self.pos)) 4189 self.generate_subexpr_disposal_code(code) 4190 self.free_subexpr_temps(code) 4191 4192 4193class BufferIndexNode(_IndexingBaseNode): 4194 """ 4195 Indexing of buffers and memoryviews. This node is created during type 4196 analysis from IndexNode and replaces it. 4197 4198 Attributes: 4199 base - base node being indexed 4200 indices - list of indexing expressions 4201 """ 4202 4203 subexprs = ['base', 'indices'] 4204 4205 is_buffer_access = True 4206 4207 # Whether we're assigning to a buffer (in that case it needs to be writable) 4208 writable_needed = False 4209 4210 # Any indexing temp variables that we need to clean up. 4211 index_temps = () 4212 4213 def analyse_target_types(self, env): 4214 self.analyse_types(env, getting=False) 4215 4216 def analyse_types(self, env, getting=True): 4217 """ 4218 Analyse types for buffer indexing only. Overridden by memoryview 4219 indexing and slicing subclasses 4220 """ 4221 # self.indices are already analyzed 4222 if not self.base.is_name and not is_pythran_expr(self.base.type): 4223 error(self.pos, "Can only index buffer variables") 4224 self.type = error_type 4225 return self 4226 4227 if not getting: 4228 if not self.base.entry.type.writable: 4229 error(self.pos, "Writing to readonly buffer") 4230 else: 4231 self.writable_needed = True 4232 if self.base.type.is_buffer: 4233 self.base.entry.buffer_aux.writable_needed = True 4234 4235 self.none_error_message = "'NoneType' object is not subscriptable" 4236 self.analyse_buffer_index(env, getting) 4237 self.wrap_in_nonecheck_node(env) 4238 return self 4239 4240 def analyse_buffer_index(self, env, getting): 4241 if is_pythran_expr(self.base.type): 4242 index_with_type_list = [(idx, idx.type) for idx in self.indices] 4243 self.type = PythranExpr(pythran_indexing_type(self.base.type, index_with_type_list)) 4244 else: 4245 self.base = self.base.coerce_to_simple(env) 4246 self.type = self.base.type.dtype 4247 self.buffer_type = self.base.type 4248 4249 if getting and (self.type.is_pyobject or self.type.is_pythran_expr): 4250 self.is_temp = True 4251 4252 def analyse_assignment(self, rhs): 4253 """ 4254 Called by IndexNode when this node is assigned to, 4255 with the rhs of the assignment 4256 """ 4257 4258 def wrap_in_nonecheck_node(self, env): 4259 if not env.directives['nonecheck'] or not self.base.may_be_none(): 4260 return 4261 self.base = self.base.as_none_safe_node(self.none_error_message) 4262 4263 def nogil_check(self, env): 4264 if self.is_buffer_access or self.is_memview_index: 4265 if self.type.is_pyobject: 4266 error(self.pos, "Cannot access buffer with object dtype without gil") 4267 self.type = error_type 4268 4269 def calculate_result_code(self): 4270 return "(*%s)" % self.buffer_ptr_code 4271 4272 def buffer_entry(self): 4273 base = self.base 4274 if self.base.is_nonecheck: 4275 base = base.arg 4276 return base.type.get_entry(base) 4277 4278 def get_index_in_temp(self, code, ivar): 4279 ret = code.funcstate.allocate_temp( 4280 PyrexTypes.widest_numeric_type( 4281 ivar.type, 4282 PyrexTypes.c_ssize_t_type if ivar.type.signed else PyrexTypes.c_size_t_type), 4283 manage_ref=False) 4284 code.putln("%s = %s;" % (ret, ivar.result())) 4285 return ret 4286 4287 def buffer_lookup_code(self, code): 4288 """ 4289 ndarray[1, 2, 3] and memslice[1, 2, 3] 4290 """ 4291 if self.in_nogil_context: 4292 if self.is_buffer_access or self.is_memview_index: 4293 if code.globalstate.directives['boundscheck']: 4294 warning(self.pos, "Use boundscheck(False) for faster access", level=1) 4295 4296 # Assign indices to temps of at least (s)size_t to allow further index calculations. 4297 self.index_temps = index_temps = [self.get_index_in_temp(code,ivar) for ivar in self.indices] 4298 4299 # Generate buffer access code using these temps 4300 from . import Buffer 4301 buffer_entry = self.buffer_entry() 4302 if buffer_entry.type.is_buffer: 4303 negative_indices = buffer_entry.type.negative_indices 4304 else: 4305 negative_indices = Buffer.buffer_defaults['negative_indices'] 4306 4307 return buffer_entry, Buffer.put_buffer_lookup_code( 4308 entry=buffer_entry, 4309 index_signeds=[ivar.type.signed for ivar in self.indices], 4310 index_cnames=index_temps, 4311 directives=code.globalstate.directives, 4312 pos=self.pos, code=code, 4313 negative_indices=negative_indices, 4314 in_nogil_context=self.in_nogil_context) 4315 4316 def generate_assignment_code(self, rhs, code, overloaded_assignment=False): 4317 self.generate_subexpr_evaluation_code(code) 4318 self.generate_buffer_setitem_code(rhs, code) 4319 self.generate_subexpr_disposal_code(code) 4320 self.free_subexpr_temps(code) 4321 rhs.generate_disposal_code(code) 4322 rhs.free_temps(code) 4323 4324 def generate_buffer_setitem_code(self, rhs, code, op=""): 4325 base_type = self.base.type 4326 if is_pythran_expr(base_type) and is_pythran_supported_type(rhs.type): 4327 obj = code.funcstate.allocate_temp(PythranExpr(pythran_type(self.base.type)), manage_ref=False) 4328 # We have got to do this because we have to declare pythran objects 4329 # at the beginning of the functions. 4330 # Indeed, Cython uses "goto" statement for error management, and 4331 # RAII doesn't work with that kind of construction. 4332 # Moreover, the way Pythran expressions are made is that they don't 4333 # support move-assignation easily. 4334 # This, we explicitly destroy then in-place new objects in this 4335 # case. 4336 code.putln("__Pyx_call_destructor(%s);" % obj) 4337 code.putln("new (&%s) decltype(%s){%s};" % (obj, obj, self.base.pythran_result())) 4338 code.putln("%s%s %s= %s;" % ( 4339 obj, 4340 pythran_indexing_code(self.indices), 4341 op, 4342 rhs.pythran_result())) 4343 code.funcstate.release_temp(obj) 4344 return 4345 4346 # Used from generate_assignment_code and InPlaceAssignmentNode 4347 buffer_entry, ptrexpr = self.buffer_lookup_code(code) 4348 4349 if self.buffer_type.dtype.is_pyobject: 4350 # Must manage refcounts. Decref what is already there 4351 # and incref what we put in. 4352 ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type, 4353 manage_ref=False) 4354 rhs_code = rhs.result() 4355 code.putln("%s = %s;" % (ptr, ptrexpr)) 4356 code.put_gotref("*%s" % ptr) 4357 code.putln("__Pyx_INCREF(%s); __Pyx_DECREF(*%s);" % ( 4358 rhs_code, ptr)) 4359 code.putln("*%s %s= %s;" % (ptr, op, rhs_code)) 4360 code.put_giveref("*%s" % ptr) 4361 code.funcstate.release_temp(ptr) 4362 else: 4363 # Simple case 4364 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result())) 4365 4366 def generate_result_code(self, code): 4367 if is_pythran_expr(self.base.type): 4368 res = self.result() 4369 code.putln("__Pyx_call_destructor(%s);" % res) 4370 code.putln("new (&%s) decltype(%s){%s%s};" % ( 4371 res, 4372 res, 4373 self.base.pythran_result(), 4374 pythran_indexing_code(self.indices))) 4375 return 4376 buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code) 4377 if self.type.is_pyobject: 4378 # is_temp is True, so must pull out value and incref it. 4379 # NOTE: object temporary results for nodes are declared 4380 # as PyObject *, so we need a cast 4381 code.putln("%s = (PyObject *) *%s;" % (self.result(), self.buffer_ptr_code)) 4382 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result()) 4383 4384 def free_subexpr_temps(self, code): 4385 for temp in self.index_temps: 4386 code.funcstate.release_temp(temp) 4387 self.index_temps = () 4388 super(BufferIndexNode, self).free_subexpr_temps(code) 4389 4390 4391class MemoryViewIndexNode(BufferIndexNode): 4392 4393 is_memview_index = True 4394 is_buffer_access = False 4395 warned_untyped_idx = False 4396 4397 def analyse_types(self, env, getting=True): 4398 # memoryviewslice indexing or slicing 4399 from . import MemoryView 4400 4401 self.is_pythran_mode = has_np_pythran(env) 4402 indices = self.indices 4403 have_slices, indices, newaxes = MemoryView.unellipsify(indices, self.base.type.ndim) 4404 4405 if not getting: 4406 self.writable_needed = True 4407 if self.base.is_name or self.base.is_attribute: 4408 self.base.entry.type.writable_needed = True 4409 4410 self.memslice_index = (not newaxes and len(indices) == self.base.type.ndim) 4411 axes = [] 4412 4413 index_type = PyrexTypes.c_py_ssize_t_type 4414 new_indices = [] 4415 4416 if len(indices) - len(newaxes) > self.base.type.ndim: 4417 self.type = error_type 4418 error(indices[self.base.type.ndim].pos, 4419 "Too many indices specified for type %s" % self.base.type) 4420 return self 4421 4422 axis_idx = 0 4423 for i, index in enumerate(indices[:]): 4424 index = index.analyse_types(env) 4425 if index.is_none: 4426 self.is_memview_slice = True 4427 new_indices.append(index) 4428 axes.append(('direct', 'strided')) 4429 continue 4430 4431 access, packing = self.base.type.axes[axis_idx] 4432 axis_idx += 1 4433 4434 if index.is_slice: 4435 self.is_memview_slice = True 4436 if index.step.is_none: 4437 axes.append((access, packing)) 4438 else: 4439 axes.append((access, 'strided')) 4440 4441 # Coerce start, stop and step to temps of the right type 4442 for attr in ('start', 'stop', 'step'): 4443 value = getattr(index, attr) 4444 if not value.is_none: 4445 value = value.coerce_to(index_type, env) 4446 #value = value.coerce_to_temp(env) 4447 setattr(index, attr, value) 4448 new_indices.append(value) 4449 4450 elif index.type.is_int or index.type.is_pyobject: 4451 if index.type.is_pyobject and not self.warned_untyped_idx: 4452 warning(index.pos, "Index should be typed for more efficient access", level=2) 4453 MemoryViewIndexNode.warned_untyped_idx = True 4454 4455 self.is_memview_index = True 4456 index = index.coerce_to(index_type, env) 4457 indices[i] = index 4458 new_indices.append(index) 4459 4460 else: 4461 self.type = error_type 4462 error(index.pos, "Invalid index for memoryview specified, type %s" % index.type) 4463 return self 4464 4465 ### FIXME: replace by MemoryViewSliceNode if is_memview_slice ? 4466 self.is_memview_index = self.is_memview_index and not self.is_memview_slice 4467 self.indices = new_indices 4468 # All indices with all start/stop/step for slices. 4469 # We need to keep this around. 4470 self.original_indices = indices 4471 self.nogil = env.nogil 4472 4473 self.analyse_operation(env, getting, axes) 4474 self.wrap_in_nonecheck_node(env) 4475 return self 4476 4477 def analyse_operation(self, env, getting, axes): 4478 self.none_error_message = "Cannot index None memoryview slice" 4479 self.analyse_buffer_index(env, getting) 4480 4481 def analyse_broadcast_operation(self, rhs): 4482 """ 4483 Support broadcasting for slice assignment. 4484 E.g. 4485 m_2d[...] = m_1d # or, 4486 m_1d[...] = m_2d # if the leading dimension has extent 1 4487 """ 4488 if self.type.is_memoryviewslice: 4489 lhs = self 4490 if lhs.is_memview_broadcast or rhs.is_memview_broadcast: 4491 lhs.is_memview_broadcast = True 4492 rhs.is_memview_broadcast = True 4493 4494 def analyse_as_memview_scalar_assignment(self, rhs): 4495 lhs = self.analyse_assignment(rhs) 4496 if lhs: 4497 rhs.is_memview_copy_assignment = lhs.is_memview_copy_assignment 4498 return lhs 4499 return self 4500 4501 4502class MemoryViewSliceNode(MemoryViewIndexNode): 4503 4504 is_memview_slice = True 4505 4506 # No-op slicing operation, this node will be replaced 4507 is_ellipsis_noop = False 4508 is_memview_scalar_assignment = False 4509 is_memview_index = False 4510 is_memview_broadcast = False 4511 4512 def analyse_ellipsis_noop(self, env, getting): 4513 """Slicing operations needing no evaluation, i.e. m[...] or m[:, :]""" 4514 ### FIXME: replace directly 4515 self.is_ellipsis_noop = all( 4516 index.is_slice and index.start.is_none and index.stop.is_none and index.step.is_none 4517 for index in self.indices) 4518 4519 if self.is_ellipsis_noop: 4520 self.type = self.base.type 4521 4522 def analyse_operation(self, env, getting, axes): 4523 from . import MemoryView 4524 4525 if not getting: 4526 self.is_memview_broadcast = True 4527 self.none_error_message = "Cannot assign to None memoryview slice" 4528 else: 4529 self.none_error_message = "Cannot slice None memoryview slice" 4530 4531 self.analyse_ellipsis_noop(env, getting) 4532 if self.is_ellipsis_noop: 4533 return 4534 4535 self.index = None 4536 self.is_temp = True 4537 self.use_managed_ref = True 4538 4539 if not MemoryView.validate_axes(self.pos, axes): 4540 self.type = error_type 4541 return 4542 4543 self.type = PyrexTypes.MemoryViewSliceType(self.base.type.dtype, axes) 4544 4545 if not (self.base.is_simple() or self.base.result_in_temp()): 4546 self.base = self.base.coerce_to_temp(env) 4547 4548 def analyse_assignment(self, rhs): 4549 if not rhs.type.is_memoryviewslice and ( 4550 self.type.dtype.assignable_from(rhs.type) or 4551 rhs.type.is_pyobject): 4552 # scalar assignment 4553 return MemoryCopyScalar(self.pos, self) 4554 else: 4555 return MemoryCopySlice(self.pos, self) 4556 4557 def merged_indices(self, indices): 4558 """Return a new list of indices/slices with 'indices' merged into the current ones 4559 according to slicing rules. 4560 Is used to implement "view[i][j]" => "view[i, j]". 4561 Return None if the indices cannot (easily) be merged at compile time. 4562 """ 4563 if not indices: 4564 return None 4565 # NOTE: Need to evaluate "self.original_indices" here as they might differ from "self.indices". 4566 new_indices = self.original_indices[:] 4567 indices = indices[:] 4568 for i, s in enumerate(self.original_indices): 4569 if s.is_slice: 4570 if s.start.is_none and s.stop.is_none and s.step.is_none: 4571 # Full slice found, replace by index. 4572 new_indices[i] = indices[0] 4573 indices.pop(0) 4574 if not indices: 4575 return new_indices 4576 else: 4577 # Found something non-trivial, e.g. a partial slice. 4578 return None 4579 elif not s.type.is_int: 4580 # Not a slice, not an integer index => could be anything... 4581 return None 4582 if indices: 4583 if len(new_indices) + len(indices) > self.base.type.ndim: 4584 return None 4585 new_indices += indices 4586 return new_indices 4587 4588 def is_simple(self): 4589 if self.is_ellipsis_noop: 4590 # TODO: fix SimpleCallNode.is_simple() 4591 return self.base.is_simple() or self.base.result_in_temp() 4592 4593 return self.result_in_temp() 4594 4595 def calculate_result_code(self): 4596 """This is called in case this is a no-op slicing node""" 4597 return self.base.result() 4598 4599 def generate_result_code(self, code): 4600 if self.is_ellipsis_noop: 4601 return ### FIXME: remove 4602 buffer_entry = self.buffer_entry() 4603 have_gil = not self.in_nogil_context 4604 4605 # TODO Mark: this is insane, do it better 4606 have_slices = False 4607 it = iter(self.indices) 4608 for index in self.original_indices: 4609 if index.is_slice: 4610 have_slices = True 4611 if not index.start.is_none: 4612 index.start = next(it) 4613 if not index.stop.is_none: 4614 index.stop = next(it) 4615 if not index.step.is_none: 4616 index.step = next(it) 4617 else: 4618 next(it) 4619 4620 assert not list(it) 4621 4622 buffer_entry.generate_buffer_slice_code( 4623 code, self.original_indices, self.result(), 4624 have_gil=have_gil, have_slices=have_slices, 4625 directives=code.globalstate.directives) 4626 4627 def generate_assignment_code(self, rhs, code, overloaded_assignment=False): 4628 if self.is_ellipsis_noop: 4629 self.generate_subexpr_evaluation_code(code) 4630 else: 4631 self.generate_evaluation_code(code) 4632 4633 if self.is_memview_scalar_assignment: 4634 self.generate_memoryviewslice_assign_scalar_code(rhs, code) 4635 else: 4636 self.generate_memoryviewslice_setslice_code(rhs, code) 4637 4638 if self.is_ellipsis_noop: 4639 self.generate_subexpr_disposal_code(code) 4640 else: 4641 self.generate_disposal_code(code) 4642 4643 rhs.generate_disposal_code(code) 4644 rhs.free_temps(code) 4645 4646 4647class MemoryCopyNode(ExprNode): 4648 """ 4649 Wraps a memoryview slice for slice assignment. 4650 4651 dst: destination mememoryview slice 4652 """ 4653 4654 subexprs = ['dst'] 4655 4656 def __init__(self, pos, dst): 4657 super(MemoryCopyNode, self).__init__(pos) 4658 self.dst = dst 4659 self.type = dst.type 4660 4661 def generate_assignment_code(self, rhs, code, overloaded_assignment=False): 4662 self.dst.generate_evaluation_code(code) 4663 self._generate_assignment_code(rhs, code) 4664 self.dst.generate_disposal_code(code) 4665 self.dst.free_temps(code) 4666 rhs.generate_disposal_code(code) 4667 rhs.free_temps(code) 4668 4669 4670class MemoryCopySlice(MemoryCopyNode): 4671 """ 4672 Copy the contents of slice src to slice dst. Does not support indirect 4673 slices. 4674 4675 memslice1[...] = memslice2 4676 memslice1[:] = memslice2 4677 """ 4678 4679 is_memview_copy_assignment = True 4680 copy_slice_cname = "__pyx_memoryview_copy_contents" 4681 4682 def _generate_assignment_code(self, src, code): 4683 dst = self.dst 4684 4685 src.type.assert_direct_dims(src.pos) 4686 dst.type.assert_direct_dims(dst.pos) 4687 4688 code.putln(code.error_goto_if_neg( 4689 "%s(%s, %s, %d, %d, %d)" % (self.copy_slice_cname, 4690 src.result(), dst.result(), 4691 src.type.ndim, dst.type.ndim, 4692 dst.type.dtype.is_pyobject), 4693 dst.pos)) 4694 4695 4696class MemoryCopyScalar(MemoryCopyNode): 4697 """ 4698 Assign a scalar to a slice. dst must be simple, scalar will be assigned 4699 to a correct type and not just something assignable. 4700 4701 memslice1[...] = 0.0 4702 memslice1[:] = 0.0 4703 """ 4704 4705 def __init__(self, pos, dst): 4706 super(MemoryCopyScalar, self).__init__(pos, dst) 4707 self.type = dst.type.dtype 4708 4709 def _generate_assignment_code(self, scalar, code): 4710 from . import MemoryView 4711 4712 self.dst.type.assert_direct_dims(self.dst.pos) 4713 4714 dtype = self.dst.type.dtype 4715 type_decl = dtype.declaration_code("") 4716 slice_decl = self.dst.type.declaration_code("") 4717 4718 code.begin_block() 4719 code.putln("%s __pyx_temp_scalar = %s;" % (type_decl, scalar.result())) 4720 if self.dst.result_in_temp() or self.dst.is_simple(): 4721 dst_temp = self.dst.result() 4722 else: 4723 code.putln("%s __pyx_temp_slice = %s;" % (slice_decl, self.dst.result())) 4724 dst_temp = "__pyx_temp_slice" 4725 4726 slice_iter_obj = MemoryView.slice_iter(self.dst.type, dst_temp, 4727 self.dst.type.ndim, code) 4728 p = slice_iter_obj.start_loops() 4729 4730 if dtype.is_pyobject: 4731 code.putln("Py_DECREF(*(PyObject **) %s);" % p) 4732 4733 code.putln("*((%s *) %s) = __pyx_temp_scalar;" % (type_decl, p)) 4734 4735 if dtype.is_pyobject: 4736 code.putln("Py_INCREF(__pyx_temp_scalar);") 4737 4738 slice_iter_obj.end_loops() 4739 code.end_block() 4740 4741 4742class SliceIndexNode(ExprNode): 4743 # 2-element slice indexing 4744 # 4745 # base ExprNode 4746 # start ExprNode or None 4747 # stop ExprNode or None 4748 # slice ExprNode or None constant slice object 4749 4750 subexprs = ['base', 'start', 'stop', 'slice'] 4751 4752 slice = None 4753 4754 def infer_type(self, env): 4755 base_type = self.base.infer_type(env) 4756 if base_type.is_string or base_type.is_cpp_class: 4757 return bytes_type 4758 elif base_type.is_pyunicode_ptr: 4759 return unicode_type 4760 elif base_type in (bytes_type, bytearray_type, str_type, unicode_type, 4761 basestring_type, list_type, tuple_type): 4762 return base_type 4763 elif base_type.is_ptr or base_type.is_array: 4764 return PyrexTypes.c_array_type(base_type.base_type, None) 4765 return py_object_type 4766 4767 def inferable_item_node(self, index=0): 4768 # slicing shouldn't change the result type of the base, but the index might 4769 if index is not not_a_constant and self.start: 4770 if self.start.has_constant_result(): 4771 index += self.start.constant_result 4772 else: 4773 index = not_a_constant 4774 return self.base.inferable_item_node(index) 4775 4776 def may_be_none(self): 4777 base_type = self.base.type 4778 if base_type: 4779 if base_type.is_string: 4780 return False 4781 if base_type in (bytes_type, str_type, unicode_type, 4782 basestring_type, list_type, tuple_type): 4783 return False 4784 return ExprNode.may_be_none(self) 4785 4786 def calculate_constant_result(self): 4787 if self.start is None: 4788 start = None 4789 else: 4790 start = self.start.constant_result 4791 if self.stop is None: 4792 stop = None 4793 else: 4794 stop = self.stop.constant_result 4795 self.constant_result = self.base.constant_result[start:stop] 4796 4797 def compile_time_value(self, denv): 4798 base = self.base.compile_time_value(denv) 4799 if self.start is None: 4800 start = 0 4801 else: 4802 start = self.start.compile_time_value(denv) 4803 if self.stop is None: 4804 stop = None 4805 else: 4806 stop = self.stop.compile_time_value(denv) 4807 try: 4808 return base[start:stop] 4809 except Exception as e: 4810 self.compile_time_value_error(e) 4811 4812 def analyse_target_declaration(self, env): 4813 pass 4814 4815 def analyse_target_types(self, env): 4816 node = self.analyse_types(env, getting=False) 4817 # when assigning, we must accept any Python type 4818 if node.type.is_pyobject: 4819 node.type = py_object_type 4820 return node 4821 4822 def analyse_types(self, env, getting=True): 4823 self.base = self.base.analyse_types(env) 4824 4825 if self.base.type.is_buffer or self.base.type.is_pythran_expr or self.base.type.is_memoryviewslice: 4826 none_node = NoneNode(self.pos) 4827 index = SliceNode(self.pos, 4828 start=self.start or none_node, 4829 stop=self.stop or none_node, 4830 step=none_node) 4831 index_node = IndexNode(self.pos, index=index, base=self.base) 4832 return index_node.analyse_base_and_index_types( 4833 env, getting=getting, setting=not getting, 4834 analyse_base=False) 4835 4836 if self.start: 4837 self.start = self.start.analyse_types(env) 4838 if self.stop: 4839 self.stop = self.stop.analyse_types(env) 4840 4841 if not env.directives['wraparound']: 4842 check_negative_indices(self.start, self.stop) 4843 4844 base_type = self.base.type 4845 if base_type.is_array and not getting: 4846 # cannot assign directly to C array => try to assign by making a copy 4847 if not self.start and not self.stop: 4848 self.type = base_type 4849 else: 4850 self.type = PyrexTypes.CPtrType(base_type.base_type) 4851 elif base_type.is_string or base_type.is_cpp_string: 4852 self.type = default_str_type(env) 4853 elif base_type.is_pyunicode_ptr: 4854 self.type = unicode_type 4855 elif base_type.is_ptr: 4856 self.type = base_type 4857 elif base_type.is_array: 4858 # we need a ptr type here instead of an array type, as 4859 # array types can result in invalid type casts in the C 4860 # code 4861 self.type = PyrexTypes.CPtrType(base_type.base_type) 4862 else: 4863 self.base = self.base.coerce_to_pyobject(env) 4864 self.type = py_object_type 4865 if base_type.is_builtin_type: 4866 # slicing builtin types returns something of the same type 4867 self.type = base_type 4868 self.base = self.base.as_none_safe_node("'NoneType' object is not subscriptable") 4869 4870 if self.type is py_object_type: 4871 if (not self.start or self.start.is_literal) and \ 4872 (not self.stop or self.stop.is_literal): 4873 # cache the constant slice object, in case we need it 4874 none_node = NoneNode(self.pos) 4875 self.slice = SliceNode( 4876 self.pos, 4877 start=copy.deepcopy(self.start or none_node), 4878 stop=copy.deepcopy(self.stop or none_node), 4879 step=none_node 4880 ).analyse_types(env) 4881 else: 4882 c_int = PyrexTypes.c_py_ssize_t_type 4883 4884 def allow_none(node, default_value, env): 4885 # Coerce to Py_ssize_t, but allow None as meaning the default slice bound. 4886 from .UtilNodes import EvalWithTempExprNode, ResultRefNode 4887 4888 node_ref = ResultRefNode(node) 4889 new_expr = CondExprNode( 4890 node.pos, 4891 true_val=IntNode( 4892 node.pos, 4893 type=c_int, 4894 value=default_value, 4895 constant_result=int(default_value) if default_value.isdigit() else not_a_constant, 4896 ), 4897 false_val=node_ref.coerce_to(c_int, env), 4898 test=PrimaryCmpNode( 4899 node.pos, 4900 operand1=node_ref, 4901 operator='is', 4902 operand2=NoneNode(node.pos), 4903 ).analyse_types(env) 4904 ).analyse_result_type(env) 4905 return EvalWithTempExprNode(node_ref, new_expr) 4906 4907 if self.start: 4908 if self.start.type.is_pyobject: 4909 self.start = allow_none(self.start, '0', env) 4910 self.start = self.start.coerce_to(c_int, env) 4911 if self.stop: 4912 if self.stop.type.is_pyobject: 4913 self.stop = allow_none(self.stop, 'PY_SSIZE_T_MAX', env) 4914 self.stop = self.stop.coerce_to(c_int, env) 4915 self.is_temp = 1 4916 return self 4917 4918 def analyse_as_type(self, env): 4919 base_type = self.base.analyse_as_type(env) 4920 if base_type and not base_type.is_pyobject: 4921 if not self.start and not self.stop: 4922 # memory view 4923 from . import MemoryView 4924 env.use_utility_code(MemoryView.view_utility_code) 4925 none_node = NoneNode(self.pos) 4926 slice_node = SliceNode( 4927 self.pos, 4928 start=none_node, 4929 stop=none_node, 4930 step=none_node, 4931 ) 4932 return PyrexTypes.MemoryViewSliceType( 4933 base_type, MemoryView.get_axes_specs(env, [slice_node])) 4934 return None 4935 4936 nogil_check = Node.gil_error 4937 gil_message = "Slicing Python object" 4938 4939 get_slice_utility_code = TempitaUtilityCode.load( 4940 "SliceObject", "ObjectHandling.c", context={'access': 'Get'}) 4941 4942 set_slice_utility_code = TempitaUtilityCode.load( 4943 "SliceObject", "ObjectHandling.c", context={'access': 'Set'}) 4944 4945 def coerce_to(self, dst_type, env): 4946 if ((self.base.type.is_string or self.base.type.is_cpp_string) 4947 and dst_type in (bytes_type, bytearray_type, str_type, unicode_type)): 4948 if (dst_type not in (bytes_type, bytearray_type) 4949 and not env.directives['c_string_encoding']): 4950 error(self.pos, 4951 "default encoding required for conversion from '%s' to '%s'" % 4952 (self.base.type, dst_type)) 4953 self.type = dst_type 4954 if dst_type.is_array and self.base.type.is_array: 4955 if not self.start and not self.stop: 4956 # redundant slice building, copy C arrays directly 4957 return self.base.coerce_to(dst_type, env) 4958 # else: check array size if possible 4959 return super(SliceIndexNode, self).coerce_to(dst_type, env) 4960 4961 def generate_result_code(self, code): 4962 if not self.type.is_pyobject: 4963 error(self.pos, 4964 "Slicing is not currently supported for '%s'." % self.type) 4965 return 4966 4967 base_result = self.base.result() 4968 result = self.result() 4969 start_code = self.start_code() 4970 stop_code = self.stop_code() 4971 if self.base.type.is_string: 4972 base_result = self.base.result() 4973 if self.base.type not in (PyrexTypes.c_char_ptr_type, PyrexTypes.c_const_char_ptr_type): 4974 base_result = '((const char*)%s)' % base_result 4975 if self.type is bytearray_type: 4976 type_name = 'ByteArray' 4977 else: 4978 type_name = self.type.name.title() 4979 if self.stop is None: 4980 code.putln( 4981 "%s = __Pyx_Py%s_FromString(%s + %s); %s" % ( 4982 result, 4983 type_name, 4984 base_result, 4985 start_code, 4986 code.error_goto_if_null(result, self.pos))) 4987 else: 4988 code.putln( 4989 "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % ( 4990 result, 4991 type_name, 4992 base_result, 4993 start_code, 4994 stop_code, 4995 start_code, 4996 code.error_goto_if_null(result, self.pos))) 4997 elif self.base.type.is_pyunicode_ptr: 4998 base_result = self.base.result() 4999 if self.base.type != PyrexTypes.c_py_unicode_ptr_type: 5000 base_result = '((const Py_UNICODE*)%s)' % base_result 5001 if self.stop is None: 5002 code.putln( 5003 "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % ( 5004 result, 5005 base_result, 5006 start_code, 5007 code.error_goto_if_null(result, self.pos))) 5008 else: 5009 code.putln( 5010 "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % ( 5011 result, 5012 base_result, 5013 start_code, 5014 stop_code, 5015 start_code, 5016 code.error_goto_if_null(result, self.pos))) 5017 5018 elif self.base.type is unicode_type: 5019 code.globalstate.use_utility_code( 5020 UtilityCode.load_cached("PyUnicode_Substring", "StringTools.c")) 5021 code.putln( 5022 "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % ( 5023 result, 5024 base_result, 5025 start_code, 5026 stop_code, 5027 code.error_goto_if_null(result, self.pos))) 5028 elif self.type is py_object_type: 5029 code.globalstate.use_utility_code(self.get_slice_utility_code) 5030 (has_c_start, has_c_stop, c_start, c_stop, 5031 py_start, py_stop, py_slice) = self.get_slice_config() 5032 code.putln( 5033 "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % ( 5034 result, 5035 self.base.py_result(), 5036 c_start, c_stop, 5037 py_start, py_stop, py_slice, 5038 has_c_start, has_c_stop, 5039 bool(code.globalstate.directives['wraparound']), 5040 code.error_goto_if_null(result, self.pos))) 5041 else: 5042 if self.base.type is list_type: 5043 code.globalstate.use_utility_code( 5044 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) 5045 cfunc = '__Pyx_PyList_GetSlice' 5046 elif self.base.type is tuple_type: 5047 code.globalstate.use_utility_code( 5048 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectHandling.c")) 5049 cfunc = '__Pyx_PyTuple_GetSlice' 5050 else: 5051 cfunc = 'PySequence_GetSlice' 5052 code.putln( 5053 "%s = %s(%s, %s, %s); %s" % ( 5054 result, 5055 cfunc, 5056 self.base.py_result(), 5057 start_code, 5058 stop_code, 5059 code.error_goto_if_null(result, self.pos))) 5060 code.put_gotref(self.py_result()) 5061 5062 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 5063 exception_check=None, exception_value=None): 5064 self.generate_subexpr_evaluation_code(code) 5065 if self.type.is_pyobject: 5066 code.globalstate.use_utility_code(self.set_slice_utility_code) 5067 (has_c_start, has_c_stop, c_start, c_stop, 5068 py_start, py_stop, py_slice) = self.get_slice_config() 5069 code.put_error_if_neg(self.pos, 5070 "__Pyx_PyObject_SetSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( 5071 self.base.py_result(), 5072 rhs.py_result(), 5073 c_start, c_stop, 5074 py_start, py_stop, py_slice, 5075 has_c_start, has_c_stop, 5076 bool(code.globalstate.directives['wraparound']))) 5077 else: 5078 start_offset = self.start_code() if self.start else '0' 5079 if rhs.type.is_array: 5080 array_length = rhs.type.size 5081 self.generate_slice_guard_code(code, array_length) 5082 else: 5083 array_length = '%s - %s' % (self.stop_code(), start_offset) 5084 5085 code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStringH", "StringTools.c")) 5086 code.putln("memcpy(&(%s[%s]), %s, sizeof(%s[0]) * (%s));" % ( 5087 self.base.result(), start_offset, 5088 rhs.result(), 5089 self.base.result(), array_length 5090 )) 5091 5092 self.generate_subexpr_disposal_code(code) 5093 self.free_subexpr_temps(code) 5094 rhs.generate_disposal_code(code) 5095 rhs.free_temps(code) 5096 5097 def generate_deletion_code(self, code, ignore_nonexisting=False): 5098 if not self.base.type.is_pyobject: 5099 error(self.pos, 5100 "Deleting slices is only supported for Python types, not '%s'." % self.type) 5101 return 5102 self.generate_subexpr_evaluation_code(code) 5103 code.globalstate.use_utility_code(self.set_slice_utility_code) 5104 (has_c_start, has_c_stop, c_start, c_stop, 5105 py_start, py_stop, py_slice) = self.get_slice_config() 5106 code.put_error_if_neg(self.pos, 5107 "__Pyx_PyObject_DelSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( 5108 self.base.py_result(), 5109 c_start, c_stop, 5110 py_start, py_stop, py_slice, 5111 has_c_start, has_c_stop, 5112 bool(code.globalstate.directives['wraparound']))) 5113 self.generate_subexpr_disposal_code(code) 5114 self.free_subexpr_temps(code) 5115 5116 def get_slice_config(self): 5117 has_c_start, c_start, py_start = False, '0', 'NULL' 5118 if self.start: 5119 has_c_start = not self.start.type.is_pyobject 5120 if has_c_start: 5121 c_start = self.start.result() 5122 else: 5123 py_start = '&%s' % self.start.py_result() 5124 has_c_stop, c_stop, py_stop = False, '0', 'NULL' 5125 if self.stop: 5126 has_c_stop = not self.stop.type.is_pyobject 5127 if has_c_stop: 5128 c_stop = self.stop.result() 5129 else: 5130 py_stop = '&%s' % self.stop.py_result() 5131 py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL' 5132 return (has_c_start, has_c_stop, c_start, c_stop, 5133 py_start, py_stop, py_slice) 5134 5135 def generate_slice_guard_code(self, code, target_size): 5136 if not self.base.type.is_array: 5137 return 5138 slice_size = self.base.type.size 5139 try: 5140 total_length = slice_size = int(slice_size) 5141 except ValueError: 5142 total_length = None 5143 5144 start = stop = None 5145 if self.stop: 5146 stop = self.stop.result() 5147 try: 5148 stop = int(stop) 5149 if stop < 0: 5150 if total_length is None: 5151 slice_size = '%s + %d' % (slice_size, stop) 5152 else: 5153 slice_size += stop 5154 else: 5155 slice_size = stop 5156 stop = None 5157 except ValueError: 5158 pass 5159 5160 if self.start: 5161 start = self.start.result() 5162 try: 5163 start = int(start) 5164 if start < 0: 5165 if total_length is None: 5166 start = '%s + %d' % (self.base.type.size, start) 5167 else: 5168 start += total_length 5169 if isinstance(slice_size, _py_int_types): 5170 slice_size -= start 5171 else: 5172 slice_size = '%s - (%s)' % (slice_size, start) 5173 start = None 5174 except ValueError: 5175 pass 5176 5177 runtime_check = None 5178 compile_time_check = False 5179 try: 5180 int_target_size = int(target_size) 5181 except ValueError: 5182 int_target_size = None 5183 else: 5184 compile_time_check = isinstance(slice_size, _py_int_types) 5185 5186 if compile_time_check and slice_size < 0: 5187 if int_target_size > 0: 5188 error(self.pos, "Assignment to empty slice.") 5189 elif compile_time_check and start is None and stop is None: 5190 # we know the exact slice length 5191 if int_target_size != slice_size: 5192 error(self.pos, "Assignment to slice of wrong length, expected %s, got %s" % ( 5193 slice_size, target_size)) 5194 elif start is not None: 5195 if stop is None: 5196 stop = slice_size 5197 runtime_check = "(%s)-(%s)" % (stop, start) 5198 elif stop is not None: 5199 runtime_check = stop 5200 else: 5201 runtime_check = slice_size 5202 5203 if runtime_check: 5204 code.putln("if (unlikely((%s) != (%s))) {" % (runtime_check, target_size)) 5205 code.putln( 5206 'PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length,' 5207 ' expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_T "d",' 5208 ' (Py_ssize_t)(%s), (Py_ssize_t)(%s));' % ( 5209 target_size, runtime_check)) 5210 code.putln(code.error_goto(self.pos)) 5211 code.putln("}") 5212 5213 def start_code(self): 5214 if self.start: 5215 return self.start.result() 5216 else: 5217 return "0" 5218 5219 def stop_code(self): 5220 if self.stop: 5221 return self.stop.result() 5222 elif self.base.type.is_array: 5223 return self.base.type.size 5224 else: 5225 return "PY_SSIZE_T_MAX" 5226 5227 def calculate_result_code(self): 5228 # self.result() is not used, but this method must exist 5229 return "<unused>" 5230 5231 5232class SliceNode(ExprNode): 5233 # start:stop:step in subscript list 5234 # 5235 # start ExprNode 5236 # stop ExprNode 5237 # step ExprNode 5238 5239 subexprs = ['start', 'stop', 'step'] 5240 is_slice = True 5241 type = slice_type 5242 is_temp = 1 5243 5244 def calculate_constant_result(self): 5245 self.constant_result = slice( 5246 self.start.constant_result, 5247 self.stop.constant_result, 5248 self.step.constant_result) 5249 5250 def compile_time_value(self, denv): 5251 start = self.start.compile_time_value(denv) 5252 stop = self.stop.compile_time_value(denv) 5253 step = self.step.compile_time_value(denv) 5254 try: 5255 return slice(start, stop, step) 5256 except Exception as e: 5257 self.compile_time_value_error(e) 5258 5259 def may_be_none(self): 5260 return False 5261 5262 def analyse_types(self, env): 5263 start = self.start.analyse_types(env) 5264 stop = self.stop.analyse_types(env) 5265 step = self.step.analyse_types(env) 5266 self.start = start.coerce_to_pyobject(env) 5267 self.stop = stop.coerce_to_pyobject(env) 5268 self.step = step.coerce_to_pyobject(env) 5269 if self.start.is_literal and self.stop.is_literal and self.step.is_literal: 5270 self.is_literal = True 5271 self.is_temp = False 5272 return self 5273 5274 gil_message = "Constructing Python slice object" 5275 5276 def calculate_result_code(self): 5277 return self.result_code 5278 5279 def generate_result_code(self, code): 5280 if self.is_literal: 5281 dedup_key = make_dedup_key(self.type, (self,)) 5282 self.result_code = code.get_py_const(py_object_type, 'slice', cleanup_level=2, dedup_key=dedup_key) 5283 code = code.get_cached_constants_writer(self.result_code) 5284 if code is None: 5285 return # already initialised 5286 code.mark_pos(self.pos) 5287 5288 code.putln( 5289 "%s = PySlice_New(%s, %s, %s); %s" % ( 5290 self.result(), 5291 self.start.py_result(), 5292 self.stop.py_result(), 5293 self.step.py_result(), 5294 code.error_goto_if_null(self.result(), self.pos))) 5295 code.put_gotref(self.py_result()) 5296 if self.is_literal: 5297 code.put_giveref(self.py_result()) 5298 5299class SliceIntNode(SliceNode): 5300 # start:stop:step in subscript list 5301 # This is just a node to hold start,stop and step nodes that can be 5302 # converted to integers. This does not generate a slice python object. 5303 # 5304 # start ExprNode 5305 # stop ExprNode 5306 # step ExprNode 5307 5308 is_temp = 0 5309 5310 def calculate_constant_result(self): 5311 self.constant_result = slice( 5312 self.start.constant_result, 5313 self.stop.constant_result, 5314 self.step.constant_result) 5315 5316 def compile_time_value(self, denv): 5317 start = self.start.compile_time_value(denv) 5318 stop = self.stop.compile_time_value(denv) 5319 step = self.step.compile_time_value(denv) 5320 try: 5321 return slice(start, stop, step) 5322 except Exception as e: 5323 self.compile_time_value_error(e) 5324 5325 def may_be_none(self): 5326 return False 5327 5328 def analyse_types(self, env): 5329 self.start = self.start.analyse_types(env) 5330 self.stop = self.stop.analyse_types(env) 5331 self.step = self.step.analyse_types(env) 5332 5333 if not self.start.is_none: 5334 self.start = self.start.coerce_to_integer(env) 5335 if not self.stop.is_none: 5336 self.stop = self.stop.coerce_to_integer(env) 5337 if not self.step.is_none: 5338 self.step = self.step.coerce_to_integer(env) 5339 5340 if self.start.is_literal and self.stop.is_literal and self.step.is_literal: 5341 self.is_literal = True 5342 self.is_temp = False 5343 return self 5344 5345 def calculate_result_code(self): 5346 pass 5347 5348 def generate_result_code(self, code): 5349 for a in self.start,self.stop,self.step: 5350 if isinstance(a, CloneNode): 5351 a.arg.result() 5352 5353 5354class CallNode(ExprNode): 5355 5356 # allow overriding the default 'may_be_none' behaviour 5357 may_return_none = None 5358 5359 def infer_type(self, env): 5360 # TODO(robertwb): Reduce redundancy with analyse_types. 5361 function = self.function 5362 func_type = function.infer_type(env) 5363 if isinstance(function, NewExprNode): 5364 # note: needs call to infer_type() above 5365 return PyrexTypes.CPtrType(function.class_type) 5366 if func_type is py_object_type: 5367 # function might have lied for safety => try to find better type 5368 entry = getattr(function, 'entry', None) 5369 if entry is not None: 5370 func_type = entry.type or func_type 5371 if func_type.is_ptr: 5372 func_type = func_type.base_type 5373 if func_type.is_cfunction: 5374 if getattr(self.function, 'entry', None) and hasattr(self, 'args'): 5375 alternatives = self.function.entry.all_alternatives() 5376 arg_types = [arg.infer_type(env) for arg in self.args] 5377 func_entry = PyrexTypes.best_match(arg_types, alternatives) 5378 if func_entry: 5379 func_type = func_entry.type 5380 if func_type.is_ptr: 5381 func_type = func_type.base_type 5382 return func_type.return_type 5383 return func_type.return_type 5384 elif func_type is type_type: 5385 if function.is_name and function.entry and function.entry.type: 5386 result_type = function.entry.type 5387 if result_type.is_extension_type: 5388 return result_type 5389 elif result_type.is_builtin_type: 5390 if function.entry.name == 'float': 5391 return PyrexTypes.c_double_type 5392 elif function.entry.name in Builtin.types_that_construct_their_instance: 5393 return result_type 5394 return py_object_type 5395 5396 def type_dependencies(self, env): 5397 # TODO: Update when Danilo's C++ code merged in to handle the 5398 # the case of function overloading. 5399 return self.function.type_dependencies(env) 5400 5401 def is_simple(self): 5402 # C function calls could be considered simple, but they may 5403 # have side-effects that may hit when multiple operations must 5404 # be effected in order, e.g. when constructing the argument 5405 # sequence for a function call or comparing values. 5406 return False 5407 5408 def may_be_none(self): 5409 if self.may_return_none is not None: 5410 return self.may_return_none 5411 func_type = self.function.type 5412 if func_type is type_type and self.function.is_name: 5413 entry = self.function.entry 5414 if entry.type.is_extension_type: 5415 return False 5416 if (entry.type.is_builtin_type and 5417 entry.name in Builtin.types_that_construct_their_instance): 5418 return False 5419 return ExprNode.may_be_none(self) 5420 5421 def set_py_result_type(self, function, func_type=None): 5422 if func_type is None: 5423 func_type = function.type 5424 if func_type is Builtin.type_type and ( 5425 function.is_name and 5426 function.entry and 5427 function.entry.is_builtin and 5428 function.entry.name in Builtin.types_that_construct_their_instance): 5429 # calling a builtin type that returns a specific object type 5430 if function.entry.name == 'float': 5431 # the following will come true later on in a transform 5432 self.type = PyrexTypes.c_double_type 5433 self.result_ctype = PyrexTypes.c_double_type 5434 else: 5435 self.type = Builtin.builtin_types[function.entry.name] 5436 self.result_ctype = py_object_type 5437 self.may_return_none = False 5438 elif function.is_name and function.type_entry: 5439 # We are calling an extension type constructor. As long as we do not 5440 # support __new__(), the result type is clear 5441 self.type = function.type_entry.type 5442 self.result_ctype = py_object_type 5443 self.may_return_none = False 5444 else: 5445 self.type = py_object_type 5446 5447 def analyse_as_type_constructor(self, env): 5448 type = self.function.analyse_as_type(env) 5449 if type and type.is_struct_or_union: 5450 args, kwds = self.explicit_args_kwds() 5451 items = [] 5452 for arg, member in zip(args, type.scope.var_entries): 5453 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.pos, value=member.name), value=arg)) 5454 if kwds: 5455 items += kwds.key_value_pairs 5456 self.key_value_pairs = items 5457 self.__class__ = DictNode 5458 self.analyse_types(env) # FIXME 5459 self.coerce_to(type, env) 5460 return True 5461 elif type and type.is_cpp_class: 5462 self.args = [ arg.analyse_types(env) for arg in self.args ] 5463 constructor = type.scope.lookup("<init>") 5464 if not constructor: 5465 error(self.function.pos, "no constructor found for C++ type '%s'" % self.function.name) 5466 self.type = error_type 5467 return self 5468 self.function = RawCNameExprNode(self.function.pos, constructor.type) 5469 self.function.entry = constructor 5470 self.function.set_cname(type.empty_declaration_code()) 5471 self.analyse_c_function_call(env) 5472 self.type = type 5473 return True 5474 5475 def is_lvalue(self): 5476 return self.type.is_reference 5477 5478 def nogil_check(self, env): 5479 func_type = self.function_type() 5480 if func_type.is_pyobject: 5481 self.gil_error() 5482 elif not func_type.is_error and not getattr(func_type, 'nogil', False): 5483 self.gil_error() 5484 5485 gil_message = "Calling gil-requiring function" 5486 5487 5488class SimpleCallNode(CallNode): 5489 # Function call without keyword, * or ** args. 5490 # 5491 # function ExprNode 5492 # args [ExprNode] 5493 # arg_tuple ExprNode or None used internally 5494 # self ExprNode or None used internally 5495 # coerced_self ExprNode or None used internally 5496 # wrapper_call bool used internally 5497 # has_optional_args bool used internally 5498 # nogil bool used internally 5499 5500 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] 5501 5502 self = None 5503 coerced_self = None 5504 arg_tuple = None 5505 wrapper_call = False 5506 has_optional_args = False 5507 nogil = False 5508 analysed = False 5509 overflowcheck = False 5510 5511 def compile_time_value(self, denv): 5512 function = self.function.compile_time_value(denv) 5513 args = [arg.compile_time_value(denv) for arg in self.args] 5514 try: 5515 return function(*args) 5516 except Exception as e: 5517 self.compile_time_value_error(e) 5518 5519 def analyse_as_type(self, env): 5520 attr = self.function.as_cython_attribute() 5521 if attr == 'pointer': 5522 if len(self.args) != 1: 5523 error(self.args.pos, "only one type allowed.") 5524 else: 5525 type = self.args[0].analyse_as_type(env) 5526 if not type: 5527 error(self.args[0].pos, "Unknown type") 5528 else: 5529 return PyrexTypes.CPtrType(type) 5530 elif attr == 'typeof': 5531 if len(self.args) != 1: 5532 error(self.args.pos, "only one type allowed.") 5533 operand = self.args[0].analyse_types(env) 5534 return operand.type 5535 5536 def explicit_args_kwds(self): 5537 return self.args, None 5538 5539 def analyse_types(self, env): 5540 if self.analyse_as_type_constructor(env): 5541 return self 5542 if self.analysed: 5543 return self 5544 self.analysed = True 5545 self.function.is_called = 1 5546 self.function = self.function.analyse_types(env) 5547 function = self.function 5548 5549 if function.is_attribute and function.entry and function.entry.is_cmethod: 5550 # Take ownership of the object from which the attribute 5551 # was obtained, because we need to pass it as 'self'. 5552 self.self = function.obj 5553 function.obj = CloneNode(self.self) 5554 5555 func_type = self.function_type() 5556 self.is_numpy_call_with_exprs = False 5557 if (has_np_pythran(env) and function.is_numpy_attribute and 5558 pythran_is_numpy_func_supported(function)): 5559 has_pythran_args = True 5560 self.arg_tuple = TupleNode(self.pos, args = self.args) 5561 self.arg_tuple = self.arg_tuple.analyse_types(env) 5562 for arg in self.arg_tuple.args: 5563 has_pythran_args &= is_pythran_supported_node_or_none(arg) 5564 self.is_numpy_call_with_exprs = bool(has_pythran_args) 5565 if self.is_numpy_call_with_exprs: 5566 env.add_include_file(pythran_get_func_include_file(function)) 5567 return NumPyMethodCallNode.from_node( 5568 self, 5569 function_cname=pythran_functor(function), 5570 arg_tuple=self.arg_tuple, 5571 type=PythranExpr(pythran_func_type(function, self.arg_tuple.args)), 5572 ) 5573 elif func_type.is_pyobject: 5574 self.arg_tuple = TupleNode(self.pos, args = self.args) 5575 self.arg_tuple = self.arg_tuple.analyse_types(env).coerce_to_pyobject(env) 5576 self.args = None 5577 self.set_py_result_type(function, func_type) 5578 self.is_temp = 1 5579 else: 5580 self.args = [ arg.analyse_types(env) for arg in self.args ] 5581 self.analyse_c_function_call(env) 5582 if func_type.exception_check == '+': 5583 self.is_temp = True 5584 return self 5585 5586 def function_type(self): 5587 # Return the type of the function being called, coercing a function 5588 # pointer to a function if necessary. If the function has fused 5589 # arguments, return the specific type. 5590 func_type = self.function.type 5591 5592 if func_type.is_ptr: 5593 func_type = func_type.base_type 5594 5595 return func_type 5596 5597 def analyse_c_function_call(self, env): 5598 func_type = self.function.type 5599 if func_type is error_type: 5600 self.type = error_type 5601 return 5602 5603 if func_type.is_cfunction and func_type.is_static_method: 5604 if self.self and self.self.type.is_extension_type: 5605 # To support this we'd need to pass self to determine whether 5606 # it was overloaded in Python space (possibly via a Cython 5607 # superclass turning a cdef method into a cpdef one). 5608 error(self.pos, "Cannot call a static method on an instance variable.") 5609 args = self.args 5610 elif self.self: 5611 args = [self.self] + self.args 5612 else: 5613 args = self.args 5614 5615 if func_type.is_cpp_class: 5616 overloaded_entry = self.function.type.scope.lookup("operator()") 5617 if overloaded_entry is None: 5618 self.type = PyrexTypes.error_type 5619 self.result_code = "<error>" 5620 return 5621 elif hasattr(self.function, 'entry'): 5622 overloaded_entry = self.function.entry 5623 elif self.function.is_subscript and self.function.is_fused_index: 5624 overloaded_entry = self.function.type.entry 5625 else: 5626 overloaded_entry = None 5627 5628 if overloaded_entry: 5629 if self.function.type.is_fused: 5630 functypes = self.function.type.get_all_specialized_function_types() 5631 alternatives = [f.entry for f in functypes] 5632 else: 5633 alternatives = overloaded_entry.all_alternatives() 5634 5635 entry = PyrexTypes.best_match( 5636 [arg.type for arg in args], alternatives, self.pos, env, args) 5637 5638 if not entry: 5639 self.type = PyrexTypes.error_type 5640 self.result_code = "<error>" 5641 return 5642 5643 entry.used = True 5644 if not func_type.is_cpp_class: 5645 self.function.entry = entry 5646 self.function.type = entry.type 5647 func_type = self.function_type() 5648 else: 5649 entry = None 5650 func_type = self.function_type() 5651 if not func_type.is_cfunction: 5652 error(self.pos, "Calling non-function type '%s'" % func_type) 5653 self.type = PyrexTypes.error_type 5654 self.result_code = "<error>" 5655 return 5656 5657 # Check no. of args 5658 max_nargs = len(func_type.args) 5659 expected_nargs = max_nargs - func_type.optional_arg_count 5660 actual_nargs = len(args) 5661 if func_type.optional_arg_count and expected_nargs != actual_nargs: 5662 self.has_optional_args = 1 5663 self.is_temp = 1 5664 5665 # check 'self' argument 5666 if entry and entry.is_cmethod and func_type.args and not func_type.is_static_method: 5667 formal_arg = func_type.args[0] 5668 arg = args[0] 5669 if formal_arg.not_none: 5670 if self.self: 5671 self.self = self.self.as_none_safe_node( 5672 "'NoneType' object has no attribute '%{0}s'".format('.30' if len(entry.name) <= 30 else ''), 5673 error='PyExc_AttributeError', 5674 format_args=[entry.name]) 5675 else: 5676 # unbound method 5677 arg = arg.as_none_safe_node( 5678 "descriptor '%s' requires a '%s' object but received a 'NoneType'", 5679 format_args=[entry.name, formal_arg.type.name]) 5680 if self.self: 5681 if formal_arg.accept_builtin_subtypes: 5682 arg = CMethodSelfCloneNode(self.self) 5683 else: 5684 arg = CloneNode(self.self) 5685 arg = self.coerced_self = arg.coerce_to(formal_arg.type, env) 5686 elif formal_arg.type.is_builtin_type: 5687 # special case: unbound methods of builtins accept subtypes 5688 arg = arg.coerce_to(formal_arg.type, env) 5689 if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode): 5690 arg.exact_builtin_type = False 5691 args[0] = arg 5692 5693 # Coerce arguments 5694 some_args_in_temps = False 5695 for i in range(min(max_nargs, actual_nargs)): 5696 formal_arg = func_type.args[i] 5697 formal_type = formal_arg.type 5698 arg = args[i].coerce_to(formal_type, env) 5699 if formal_arg.not_none: 5700 # C methods must do the None checks at *call* time 5701 arg = arg.as_none_safe_node( 5702 "cannot pass None into a C function argument that is declared 'not None'") 5703 if arg.is_temp: 5704 if i > 0: 5705 # first argument in temp doesn't impact subsequent arguments 5706 some_args_in_temps = True 5707 elif arg.type.is_pyobject and not env.nogil: 5708 if i == 0 and self.self is not None: 5709 # a method's cloned "self" argument is ok 5710 pass 5711 elif arg.nonlocally_immutable(): 5712 # plain local variables are ok 5713 pass 5714 else: 5715 # we do not safely own the argument's reference, 5716 # but we must make sure it cannot be collected 5717 # before we return from the function, so we create 5718 # an owned temp reference to it 5719 if i > 0: # first argument doesn't matter 5720 some_args_in_temps = True 5721 arg = arg.coerce_to_temp(env) 5722 args[i] = arg 5723 5724 # handle additional varargs parameters 5725 for i in range(max_nargs, actual_nargs): 5726 arg = args[i] 5727 if arg.type.is_pyobject: 5728 if arg.type is str_type: 5729 arg_ctype = PyrexTypes.c_char_ptr_type 5730 else: 5731 arg_ctype = arg.type.default_coerced_ctype() 5732 if arg_ctype is None: 5733 error(self.args[i].pos, 5734 "Python object cannot be passed as a varargs parameter") 5735 else: 5736 args[i] = arg = arg.coerce_to(arg_ctype, env) 5737 if arg.is_temp and i > 0: 5738 some_args_in_temps = True 5739 5740 if some_args_in_temps: 5741 # if some args are temps and others are not, they may get 5742 # constructed in the wrong order (temps first) => make 5743 # sure they are either all temps or all not temps (except 5744 # for the last argument, which is evaluated last in any 5745 # case) 5746 for i in range(actual_nargs-1): 5747 if i == 0 and self.self is not None: 5748 continue # self is ok 5749 arg = args[i] 5750 if arg.nonlocally_immutable(): 5751 # locals, C functions, unassignable types are safe. 5752 pass 5753 elif arg.type.is_cpp_class: 5754 # Assignment has side effects, avoid. 5755 pass 5756 elif env.nogil and arg.type.is_pyobject: 5757 # can't copy a Python reference into a temp in nogil 5758 # env (this is safe: a construction would fail in 5759 # nogil anyway) 5760 pass 5761 else: 5762 #self.args[i] = arg.coerce_to_temp(env) 5763 # instead: issue a warning 5764 if i > 0 or i == 1 and self.self is not None: # skip first arg 5765 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) 5766 break 5767 5768 self.args[:] = args 5769 5770 # Calc result type and code fragment 5771 if isinstance(self.function, NewExprNode): 5772 self.type = PyrexTypes.CPtrType(self.function.class_type) 5773 else: 5774 self.type = func_type.return_type 5775 5776 if self.function.is_name or self.function.is_attribute: 5777 func_entry = self.function.entry 5778 if func_entry and (func_entry.utility_code or func_entry.utility_code_definition): 5779 self.is_temp = 1 # currently doesn't work for self.calculate_result_code() 5780 5781 if self.type.is_pyobject: 5782 self.result_ctype = py_object_type 5783 self.is_temp = 1 5784 elif func_type.exception_value is not None or func_type.exception_check: 5785 self.is_temp = 1 5786 elif self.type.is_memoryviewslice: 5787 self.is_temp = 1 5788 # func_type.exception_check = True 5789 5790 if self.is_temp and self.type.is_reference: 5791 self.type = PyrexTypes.CFakeReferenceType(self.type.ref_base_type) 5792 5793 # Called in 'nogil' context? 5794 self.nogil = env.nogil 5795 if (self.nogil and 5796 func_type.exception_check and 5797 func_type.exception_check != '+'): 5798 env.use_utility_code(pyerr_occurred_withgil_utility_code) 5799 # C++ exception handler 5800 if func_type.exception_check == '+': 5801 if func_type.exception_value is None: 5802 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 5803 5804 self.overflowcheck = env.directives['overflowcheck'] 5805 5806 def calculate_result_code(self): 5807 return self.c_call_code() 5808 5809 def c_call_code(self): 5810 func_type = self.function_type() 5811 if self.type is PyrexTypes.error_type or not func_type.is_cfunction: 5812 return "<error>" 5813 formal_args = func_type.args 5814 arg_list_code = [] 5815 args = list(zip(formal_args, self.args)) 5816 max_nargs = len(func_type.args) 5817 expected_nargs = max_nargs - func_type.optional_arg_count 5818 actual_nargs = len(self.args) 5819 for formal_arg, actual_arg in args[:expected_nargs]: 5820 arg_code = actual_arg.result_as(formal_arg.type) 5821 arg_list_code.append(arg_code) 5822 5823 if func_type.is_overridable: 5824 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod))) 5825 5826 if func_type.optional_arg_count: 5827 if expected_nargs == actual_nargs: 5828 optional_args = 'NULL' 5829 else: 5830 optional_args = "&%s" % self.opt_arg_struct 5831 arg_list_code.append(optional_args) 5832 5833 for actual_arg in self.args[len(formal_args):]: 5834 arg_list_code.append(actual_arg.result()) 5835 5836 result = "%s(%s)" % (self.function.result(), ', '.join(arg_list_code)) 5837 return result 5838 5839 def is_c_result_required(self): 5840 func_type = self.function_type() 5841 if not func_type.exception_value or func_type.exception_check == '+': 5842 return False # skip allocation of unused result temp 5843 return True 5844 5845 def generate_evaluation_code(self, code): 5846 function = self.function 5847 if function.is_name or function.is_attribute: 5848 code.globalstate.use_entry_utility_code(function.entry) 5849 5850 abs_function_cnames = ('abs', 'labs', '__Pyx_abs_longlong') 5851 is_signed_int = self.type.is_int and self.type.signed 5852 if self.overflowcheck and is_signed_int and function.result() in abs_function_cnames: 5853 code.globalstate.use_utility_code(UtilityCode.load_cached("Common", "Overflow.c")) 5854 code.putln('if (unlikely(%s == __PYX_MIN(%s))) {\ 5855 PyErr_SetString(PyExc_OverflowError,\ 5856 "Trying to take the absolute value of the most negative integer is not defined."); %s; }' % ( 5857 self.args[0].result(), 5858 self.args[0].type.empty_declaration_code(), 5859 code.error_goto(self.pos))) 5860 5861 if not function.type.is_pyobject or len(self.arg_tuple.args) > 1 or ( 5862 self.arg_tuple.args and self.arg_tuple.is_literal): 5863 super(SimpleCallNode, self).generate_evaluation_code(code) 5864 return 5865 5866 # Special case 0-args and try to avoid explicit tuple creation for Python calls with 1 arg. 5867 arg = self.arg_tuple.args[0] if self.arg_tuple.args else None 5868 subexprs = (self.self, self.coerced_self, function, arg) 5869 for subexpr in subexprs: 5870 if subexpr is not None: 5871 subexpr.generate_evaluation_code(code) 5872 5873 code.mark_pos(self.pos) 5874 assert self.is_temp 5875 self.allocate_temp_result(code) 5876 5877 if arg is None: 5878 code.globalstate.use_utility_code(UtilityCode.load_cached( 5879 "PyObjectCallNoArg", "ObjectHandling.c")) 5880 code.putln( 5881 "%s = __Pyx_PyObject_CallNoArg(%s); %s" % ( 5882 self.result(), 5883 function.py_result(), 5884 code.error_goto_if_null(self.result(), self.pos))) 5885 else: 5886 code.globalstate.use_utility_code(UtilityCode.load_cached( 5887 "PyObjectCallOneArg", "ObjectHandling.c")) 5888 code.putln( 5889 "%s = __Pyx_PyObject_CallOneArg(%s, %s); %s" % ( 5890 self.result(), 5891 function.py_result(), 5892 arg.py_result(), 5893 code.error_goto_if_null(self.result(), self.pos))) 5894 5895 code.put_gotref(self.py_result()) 5896 5897 for subexpr in subexprs: 5898 if subexpr is not None: 5899 subexpr.generate_disposal_code(code) 5900 subexpr.free_temps(code) 5901 5902 def generate_result_code(self, code): 5903 func_type = self.function_type() 5904 if func_type.is_pyobject: 5905 arg_code = self.arg_tuple.py_result() 5906 code.globalstate.use_utility_code(UtilityCode.load_cached( 5907 "PyObjectCall", "ObjectHandling.c")) 5908 code.putln( 5909 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % ( 5910 self.result(), 5911 self.function.py_result(), 5912 arg_code, 5913 code.error_goto_if_null(self.result(), self.pos))) 5914 code.put_gotref(self.py_result()) 5915 elif func_type.is_cfunction: 5916 if self.has_optional_args: 5917 actual_nargs = len(self.args) 5918 expected_nargs = len(func_type.args) - func_type.optional_arg_count 5919 self.opt_arg_struct = code.funcstate.allocate_temp( 5920 func_type.op_arg_struct.base_type, manage_ref=True) 5921 code.putln("%s.%s = %s;" % ( 5922 self.opt_arg_struct, 5923 Naming.pyrex_prefix + "n", 5924 len(self.args) - expected_nargs)) 5925 args = list(zip(func_type.args, self.args)) 5926 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]: 5927 code.putln("%s.%s = %s;" % ( 5928 self.opt_arg_struct, 5929 func_type.opt_arg_cname(formal_arg.name), 5930 actual_arg.result_as(formal_arg.type))) 5931 exc_checks = [] 5932 if self.type.is_pyobject and self.is_temp: 5933 exc_checks.append("!%s" % self.result()) 5934 elif self.type.is_memoryviewslice: 5935 assert self.is_temp 5936 exc_checks.append(self.type.error_condition(self.result())) 5937 elif func_type.exception_check != '+': 5938 exc_val = func_type.exception_value 5939 exc_check = func_type.exception_check 5940 if exc_val is not None: 5941 exc_checks.append("%s == %s" % (self.result(), func_type.return_type.cast_code(exc_val))) 5942 if exc_check: 5943 if self.nogil: 5944 exc_checks.append("__Pyx_ErrOccurredWithGIL()") 5945 else: 5946 exc_checks.append("PyErr_Occurred()") 5947 if self.is_temp or exc_checks: 5948 rhs = self.c_call_code() 5949 if self.result(): 5950 lhs = "%s = " % self.result() 5951 if self.is_temp and self.type.is_pyobject: 5952 #return_type = self.type # func_type.return_type 5953 #print "SimpleCallNode.generate_result_code: casting", rhs, \ 5954 # "from", return_type, "to pyobject" ### 5955 rhs = typecast(py_object_type, self.type, rhs) 5956 else: 5957 lhs = "" 5958 if func_type.exception_check == '+': 5959 translate_cpp_exception(code, self.pos, '%s%s;' % (lhs, rhs), 5960 self.result() if self.type.is_pyobject else None, 5961 func_type.exception_value, self.nogil) 5962 else: 5963 if exc_checks: 5964 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos) 5965 else: 5966 goto_error = "" 5967 code.putln("%s%s; %s" % (lhs, rhs, goto_error)) 5968 if self.type.is_pyobject and self.result(): 5969 code.put_gotref(self.py_result()) 5970 if self.has_optional_args: 5971 code.funcstate.release_temp(self.opt_arg_struct) 5972 5973 5974class NumPyMethodCallNode(ExprNode): 5975 # Pythran call to a NumPy function or method. 5976 # 5977 # function_cname string the function/method to call 5978 # arg_tuple TupleNode the arguments as an args tuple 5979 5980 subexprs = ['arg_tuple'] 5981 is_temp = True 5982 may_return_none = True 5983 5984 def generate_evaluation_code(self, code): 5985 code.mark_pos(self.pos) 5986 self.allocate_temp_result(code) 5987 5988 assert self.arg_tuple.mult_factor is None 5989 args = self.arg_tuple.args 5990 for arg in args: 5991 arg.generate_evaluation_code(code) 5992 5993 code.putln("// function evaluation code for numpy function") 5994 code.putln("__Pyx_call_destructor(%s);" % self.result()) 5995 code.putln("new (&%s) decltype(%s){%s{}(%s)};" % ( 5996 self.result(), 5997 self.result(), 5998 self.function_cname, 5999 ", ".join(a.pythran_result() for a in args))) 6000 6001 6002class PyMethodCallNode(SimpleCallNode): 6003 # Specialised call to a (potential) PyMethodObject with non-constant argument tuple. 6004 # Allows the self argument to be injected directly instead of repacking a tuple for it. 6005 # 6006 # function ExprNode the function/method object to call 6007 # arg_tuple TupleNode the arguments for the args tuple 6008 6009 subexprs = ['function', 'arg_tuple'] 6010 is_temp = True 6011 6012 def generate_evaluation_code(self, code): 6013 code.mark_pos(self.pos) 6014 self.allocate_temp_result(code) 6015 6016 self.function.generate_evaluation_code(code) 6017 assert self.arg_tuple.mult_factor is None 6018 args = self.arg_tuple.args 6019 for arg in args: 6020 arg.generate_evaluation_code(code) 6021 6022 # make sure function is in temp so that we can replace the reference below if it's a method 6023 reuse_function_temp = self.function.is_temp 6024 if reuse_function_temp: 6025 function = self.function.result() 6026 else: 6027 function = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 6028 self.function.make_owned_reference(code) 6029 code.put("%s = %s; " % (function, self.function.py_result())) 6030 self.function.generate_disposal_code(code) 6031 self.function.free_temps(code) 6032 6033 self_arg = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 6034 code.putln("%s = NULL;" % self_arg) 6035 arg_offset_cname = None 6036 if len(args) > 1: 6037 arg_offset_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) 6038 code.putln("%s = 0;" % arg_offset_cname) 6039 6040 def attribute_is_likely_method(attr): 6041 obj = attr.obj 6042 if obj.is_name and obj.entry.is_pyglobal: 6043 return False # more likely to be a function 6044 return True 6045 6046 if self.function.is_attribute: 6047 likely_method = 'likely' if attribute_is_likely_method(self.function) else 'unlikely' 6048 elif self.function.is_name and self.function.cf_state: 6049 # not an attribute itself, but might have been assigned from one (e.g. bound method) 6050 for assignment in self.function.cf_state: 6051 value = assignment.rhs 6052 if value and value.is_attribute and value.obj.type and value.obj.type.is_pyobject: 6053 if attribute_is_likely_method(value): 6054 likely_method = 'likely' 6055 break 6056 else: 6057 likely_method = 'unlikely' 6058 else: 6059 likely_method = 'unlikely' 6060 6061 code.putln("if (CYTHON_UNPACK_METHODS && %s(PyMethod_Check(%s))) {" % (likely_method, function)) 6062 code.putln("%s = PyMethod_GET_SELF(%s);" % (self_arg, function)) 6063 # the following is always true in Py3 (kept only for safety), 6064 # but is false for unbound methods in Py2 6065 code.putln("if (likely(%s)) {" % self_arg) 6066 code.putln("PyObject* function = PyMethod_GET_FUNCTION(%s);" % function) 6067 code.put_incref(self_arg, py_object_type) 6068 code.put_incref("function", py_object_type) 6069 # free method object as early to possible to enable reuse from CPython's freelist 6070 code.put_decref_set(function, "function") 6071 if len(args) > 1: 6072 code.putln("%s = 1;" % arg_offset_cname) 6073 code.putln("}") 6074 code.putln("}") 6075 6076 if not args: 6077 # fastest special case: try to avoid tuple creation 6078 code.globalstate.use_utility_code( 6079 UtilityCode.load_cached("PyObjectCallNoArg", "ObjectHandling.c")) 6080 code.globalstate.use_utility_code( 6081 UtilityCode.load_cached("PyObjectCallOneArg", "ObjectHandling.c")) 6082 code.putln( 6083 "%s = (%s) ? __Pyx_PyObject_CallOneArg(%s, %s) : __Pyx_PyObject_CallNoArg(%s);" % ( 6084 self.result(), self_arg, 6085 function, self_arg, 6086 function)) 6087 code.put_xdecref_clear(self_arg, py_object_type) 6088 code.funcstate.release_temp(self_arg) 6089 code.putln(code.error_goto_if_null(self.result(), self.pos)) 6090 code.put_gotref(self.py_result()) 6091 elif len(args) == 1: 6092 # fastest special case: try to avoid tuple creation 6093 code.globalstate.use_utility_code( 6094 UtilityCode.load_cached("PyObjectCall2Args", "ObjectHandling.c")) 6095 code.globalstate.use_utility_code( 6096 UtilityCode.load_cached("PyObjectCallOneArg", "ObjectHandling.c")) 6097 arg = args[0] 6098 code.putln( 6099 "%s = (%s) ? __Pyx_PyObject_Call2Args(%s, %s, %s) : __Pyx_PyObject_CallOneArg(%s, %s);" % ( 6100 self.result(), self_arg, 6101 function, self_arg, arg.py_result(), 6102 function, arg.py_result())) 6103 code.put_xdecref_clear(self_arg, py_object_type) 6104 code.funcstate.release_temp(self_arg) 6105 arg.generate_disposal_code(code) 6106 arg.free_temps(code) 6107 code.putln(code.error_goto_if_null(self.result(), self.pos)) 6108 code.put_gotref(self.py_result()) 6109 else: 6110 code.globalstate.use_utility_code( 6111 UtilityCode.load_cached("PyFunctionFastCall", "ObjectHandling.c")) 6112 code.globalstate.use_utility_code( 6113 UtilityCode.load_cached("PyCFunctionFastCall", "ObjectHandling.c")) 6114 for test_func, call_prefix in [('PyFunction_Check', 'Py'), ('__Pyx_PyFastCFunction_Check', 'PyC')]: 6115 code.putln("#if CYTHON_FAST_%sCALL" % call_prefix.upper()) 6116 code.putln("if (%s(%s)) {" % (test_func, function)) 6117 code.putln("PyObject *%s[%d] = {%s, %s};" % ( 6118 Naming.quick_temp_cname, 6119 len(args)+1, 6120 self_arg, 6121 ', '.join(arg.py_result() for arg in args))) 6122 code.putln("%s = __Pyx_%sFunction_FastCall(%s, %s+1-%s, %d+%s); %s" % ( 6123 self.result(), 6124 call_prefix, 6125 function, 6126 Naming.quick_temp_cname, 6127 arg_offset_cname, 6128 len(args), 6129 arg_offset_cname, 6130 code.error_goto_if_null(self.result(), self.pos))) 6131 code.put_xdecref_clear(self_arg, py_object_type) 6132 code.put_gotref(self.py_result()) 6133 for arg in args: 6134 arg.generate_disposal_code(code) 6135 code.putln("} else") 6136 code.putln("#endif") 6137 6138 code.putln("{") 6139 args_tuple = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 6140 code.putln("%s = PyTuple_New(%d+%s); %s" % ( 6141 args_tuple, len(args), arg_offset_cname, 6142 code.error_goto_if_null(args_tuple, self.pos))) 6143 code.put_gotref(args_tuple) 6144 6145 if len(args) > 1: 6146 code.putln("if (%s) {" % self_arg) 6147 code.putln("__Pyx_GIVEREF(%s); PyTuple_SET_ITEM(%s, 0, %s); %s = NULL;" % ( 6148 self_arg, args_tuple, self_arg, self_arg)) # stealing owned ref in this case 6149 code.funcstate.release_temp(self_arg) 6150 if len(args) > 1: 6151 code.putln("}") 6152 6153 for i, arg in enumerate(args): 6154 arg.make_owned_reference(code) 6155 code.put_giveref(arg.py_result()) 6156 code.putln("PyTuple_SET_ITEM(%s, %d+%s, %s);" % ( 6157 args_tuple, i, arg_offset_cname, arg.py_result())) 6158 if len(args) > 1: 6159 code.funcstate.release_temp(arg_offset_cname) 6160 6161 for arg in args: 6162 arg.generate_post_assignment_code(code) 6163 arg.free_temps(code) 6164 6165 code.globalstate.use_utility_code( 6166 UtilityCode.load_cached("PyObjectCall", "ObjectHandling.c")) 6167 code.putln( 6168 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % ( 6169 self.result(), 6170 function, args_tuple, 6171 code.error_goto_if_null(self.result(), self.pos))) 6172 code.put_gotref(self.py_result()) 6173 6174 code.put_decref_clear(args_tuple, py_object_type) 6175 code.funcstate.release_temp(args_tuple) 6176 6177 if len(args) == 1: 6178 code.putln("}") 6179 code.putln("}") # !CYTHON_FAST_PYCALL 6180 6181 if reuse_function_temp: 6182 self.function.generate_disposal_code(code) 6183 self.function.free_temps(code) 6184 else: 6185 code.put_decref_clear(function, py_object_type) 6186 code.funcstate.release_temp(function) 6187 6188 6189class InlinedDefNodeCallNode(CallNode): 6190 # Inline call to defnode 6191 # 6192 # function PyCFunctionNode 6193 # function_name NameNode 6194 # args [ExprNode] 6195 6196 subexprs = ['args', 'function_name'] 6197 is_temp = 1 6198 type = py_object_type 6199 function = None 6200 function_name = None 6201 6202 def can_be_inlined(self): 6203 func_type= self.function.def_node 6204 if func_type.star_arg or func_type.starstar_arg: 6205 return False 6206 if len(func_type.args) != len(self.args): 6207 return False 6208 if func_type.num_kwonly_args: 6209 return False # actually wrong number of arguments 6210 return True 6211 6212 def analyse_types(self, env): 6213 self.function_name = self.function_name.analyse_types(env) 6214 6215 self.args = [ arg.analyse_types(env) for arg in self.args ] 6216 func_type = self.function.def_node 6217 actual_nargs = len(self.args) 6218 6219 # Coerce arguments 6220 some_args_in_temps = False 6221 for i in range(actual_nargs): 6222 formal_type = func_type.args[i].type 6223 arg = self.args[i].coerce_to(formal_type, env) 6224 if arg.is_temp: 6225 if i > 0: 6226 # first argument in temp doesn't impact subsequent arguments 6227 some_args_in_temps = True 6228 elif arg.type.is_pyobject and not env.nogil: 6229 if arg.nonlocally_immutable(): 6230 # plain local variables are ok 6231 pass 6232 else: 6233 # we do not safely own the argument's reference, 6234 # but we must make sure it cannot be collected 6235 # before we return from the function, so we create 6236 # an owned temp reference to it 6237 if i > 0: # first argument doesn't matter 6238 some_args_in_temps = True 6239 arg = arg.coerce_to_temp(env) 6240 self.args[i] = arg 6241 6242 if some_args_in_temps: 6243 # if some args are temps and others are not, they may get 6244 # constructed in the wrong order (temps first) => make 6245 # sure they are either all temps or all not temps (except 6246 # for the last argument, which is evaluated last in any 6247 # case) 6248 for i in range(actual_nargs-1): 6249 arg = self.args[i] 6250 if arg.nonlocally_immutable(): 6251 # locals, C functions, unassignable types are safe. 6252 pass 6253 elif arg.type.is_cpp_class: 6254 # Assignment has side effects, avoid. 6255 pass 6256 elif env.nogil and arg.type.is_pyobject: 6257 # can't copy a Python reference into a temp in nogil 6258 # env (this is safe: a construction would fail in 6259 # nogil anyway) 6260 pass 6261 else: 6262 #self.args[i] = arg.coerce_to_temp(env) 6263 # instead: issue a warning 6264 if i > 0: 6265 warning(arg.pos, "Argument evaluation order in C function call is undefined and may not be as expected", 0) 6266 break 6267 return self 6268 6269 def generate_result_code(self, code): 6270 arg_code = [self.function_name.py_result()] 6271 func_type = self.function.def_node 6272 for arg, proto_arg in zip(self.args, func_type.args): 6273 if arg.type.is_pyobject: 6274 arg_code.append(arg.result_as(proto_arg.type)) 6275 else: 6276 arg_code.append(arg.result()) 6277 arg_code = ', '.join(arg_code) 6278 code.putln( 6279 "%s = %s(%s); %s" % ( 6280 self.result(), 6281 self.function.def_node.entry.pyfunc_cname, 6282 arg_code, 6283 code.error_goto_if_null(self.result(), self.pos))) 6284 code.put_gotref(self.py_result()) 6285 6286 6287class PythonCapiFunctionNode(ExprNode): 6288 subexprs = [] 6289 6290 def __init__(self, pos, py_name, cname, func_type, utility_code = None): 6291 ExprNode.__init__(self, pos, name=py_name, cname=cname, 6292 type=func_type, utility_code=utility_code) 6293 6294 def analyse_types(self, env): 6295 return self 6296 6297 def generate_result_code(self, code): 6298 if self.utility_code: 6299 code.globalstate.use_utility_code(self.utility_code) 6300 6301 def calculate_result_code(self): 6302 return self.cname 6303 6304 6305class PythonCapiCallNode(SimpleCallNode): 6306 # Python C-API Function call (only created in transforms) 6307 6308 # By default, we assume that the call never returns None, as this 6309 # is true for most C-API functions in CPython. If this does not 6310 # apply to a call, set the following to True (or None to inherit 6311 # the default behaviour). 6312 may_return_none = False 6313 6314 def __init__(self, pos, function_name, func_type, 6315 utility_code = None, py_name=None, **kwargs): 6316 self.type = func_type.return_type 6317 self.result_ctype = self.type 6318 self.function = PythonCapiFunctionNode( 6319 pos, py_name, function_name, func_type, 6320 utility_code = utility_code) 6321 # call this last so that we can override the constructed 6322 # attributes above with explicit keyword arguments if required 6323 SimpleCallNode.__init__(self, pos, **kwargs) 6324 6325 6326class CachedBuiltinMethodCallNode(CallNode): 6327 # Python call to a method of a known Python builtin (only created in transforms) 6328 6329 subexprs = ['obj', 'args'] 6330 is_temp = True 6331 6332 def __init__(self, call_node, obj, method_name, args): 6333 super(CachedBuiltinMethodCallNode, self).__init__( 6334 call_node.pos, 6335 obj=obj, method_name=method_name, args=args, 6336 may_return_none=call_node.may_return_none, 6337 type=call_node.type) 6338 6339 def may_be_none(self): 6340 if self.may_return_none is not None: 6341 return self.may_return_none 6342 return ExprNode.may_be_none(self) 6343 6344 def generate_result_code(self, code): 6345 type_cname = self.obj.type.cname 6346 obj_cname = self.obj.py_result() 6347 args = [arg.py_result() for arg in self.args] 6348 call_code = code.globalstate.cached_unbound_method_call_code( 6349 obj_cname, type_cname, self.method_name, args) 6350 code.putln("%s = %s; %s" % ( 6351 self.result(), call_code, 6352 code.error_goto_if_null(self.result(), self.pos) 6353 )) 6354 code.put_gotref(self.result()) 6355 6356 6357class GeneralCallNode(CallNode): 6358 # General Python function call, including keyword, 6359 # * and ** arguments. 6360 # 6361 # function ExprNode 6362 # positional_args ExprNode Tuple of positional arguments 6363 # keyword_args ExprNode or None Dict of keyword arguments 6364 6365 type = py_object_type 6366 6367 subexprs = ['function', 'positional_args', 'keyword_args'] 6368 6369 nogil_check = Node.gil_error 6370 6371 def compile_time_value(self, denv): 6372 function = self.function.compile_time_value(denv) 6373 positional_args = self.positional_args.compile_time_value(denv) 6374 keyword_args = self.keyword_args.compile_time_value(denv) 6375 try: 6376 return function(*positional_args, **keyword_args) 6377 except Exception as e: 6378 self.compile_time_value_error(e) 6379 6380 def explicit_args_kwds(self): 6381 if (self.keyword_args and not self.keyword_args.is_dict_literal or 6382 not self.positional_args.is_sequence_constructor): 6383 raise CompileError(self.pos, 6384 'Compile-time keyword arguments must be explicit.') 6385 return self.positional_args.args, self.keyword_args 6386 6387 def analyse_types(self, env): 6388 if self.analyse_as_type_constructor(env): 6389 return self 6390 self.function = self.function.analyse_types(env) 6391 if not self.function.type.is_pyobject: 6392 if self.function.type.is_error: 6393 self.type = error_type 6394 return self 6395 if hasattr(self.function, 'entry'): 6396 node = self.map_to_simple_call_node() 6397 if node is not None and node is not self: 6398 return node.analyse_types(env) 6399 elif self.function.entry.as_variable: 6400 self.function = self.function.coerce_to_pyobject(env) 6401 elif node is self: 6402 error(self.pos, 6403 "Non-trivial keyword arguments and starred " 6404 "arguments not allowed in cdef functions.") 6405 else: 6406 # error was already reported 6407 pass 6408 else: 6409 self.function = self.function.coerce_to_pyobject(env) 6410 if self.keyword_args: 6411 self.keyword_args = self.keyword_args.analyse_types(env) 6412 self.positional_args = self.positional_args.analyse_types(env) 6413 self.positional_args = \ 6414 self.positional_args.coerce_to_pyobject(env) 6415 self.set_py_result_type(self.function) 6416 self.is_temp = 1 6417 return self 6418 6419 def map_to_simple_call_node(self): 6420 """ 6421 Tries to map keyword arguments to declared positional arguments. 6422 Returns self to try a Python call, None to report an error 6423 or a SimpleCallNode if the mapping succeeds. 6424 """ 6425 if not isinstance(self.positional_args, TupleNode): 6426 # has starred argument 6427 return self 6428 if not self.keyword_args.is_dict_literal: 6429 # keywords come from arbitrary expression => nothing to do here 6430 return self 6431 function = self.function 6432 entry = getattr(function, 'entry', None) 6433 if not entry: 6434 return self 6435 function_type = entry.type 6436 if function_type.is_ptr: 6437 function_type = function_type.base_type 6438 if not function_type.is_cfunction: 6439 return self 6440 6441 pos_args = self.positional_args.args 6442 kwargs = self.keyword_args 6443 declared_args = function_type.args 6444 if entry.is_cmethod: 6445 declared_args = declared_args[1:] # skip 'self' 6446 6447 if len(pos_args) > len(declared_args): 6448 error(self.pos, "function call got too many positional arguments, " 6449 "expected %d, got %s" % (len(declared_args), 6450 len(pos_args))) 6451 return None 6452 6453 matched_args = set([ arg.name for arg in declared_args[:len(pos_args)] 6454 if arg.name ]) 6455 unmatched_args = declared_args[len(pos_args):] 6456 matched_kwargs_count = 0 6457 args = list(pos_args) 6458 6459 # check for duplicate keywords 6460 seen = set(matched_args) 6461 has_errors = False 6462 for arg in kwargs.key_value_pairs: 6463 name = arg.key.value 6464 if name in seen: 6465 error(arg.pos, "argument '%s' passed twice" % name) 6466 has_errors = True 6467 # continue to report more errors if there are any 6468 seen.add(name) 6469 6470 # match keywords that are passed in order 6471 for decl_arg, arg in zip(unmatched_args, kwargs.key_value_pairs): 6472 name = arg.key.value 6473 if decl_arg.name == name: 6474 matched_args.add(name) 6475 matched_kwargs_count += 1 6476 args.append(arg.value) 6477 else: 6478 break 6479 6480 # match keyword arguments that are passed out-of-order, but keep 6481 # the evaluation of non-simple arguments in order by moving them 6482 # into temps 6483 from .UtilNodes import EvalWithTempExprNode, LetRefNode 6484 temps = [] 6485 if len(kwargs.key_value_pairs) > matched_kwargs_count: 6486 unmatched_args = declared_args[len(args):] 6487 keywords = dict([ (arg.key.value, (i+len(pos_args), arg)) 6488 for i, arg in enumerate(kwargs.key_value_pairs) ]) 6489 first_missing_keyword = None 6490 for decl_arg in unmatched_args: 6491 name = decl_arg.name 6492 if name not in keywords: 6493 # missing keyword argument => either done or error 6494 if not first_missing_keyword: 6495 first_missing_keyword = name 6496 continue 6497 elif first_missing_keyword: 6498 if entry.as_variable: 6499 # we might be able to convert the function to a Python 6500 # object, which then allows full calling semantics 6501 # with default values in gaps - currently, we only 6502 # support optional arguments at the end 6503 return self 6504 # wasn't the last keyword => gaps are not supported 6505 error(self.pos, "C function call is missing " 6506 "argument '%s'" % first_missing_keyword) 6507 return None 6508 pos, arg = keywords[name] 6509 matched_args.add(name) 6510 matched_kwargs_count += 1 6511 if arg.value.is_simple(): 6512 args.append(arg.value) 6513 else: 6514 temp = LetRefNode(arg.value) 6515 assert temp.is_simple() 6516 args.append(temp) 6517 temps.append((pos, temp)) 6518 6519 if temps: 6520 # may have to move preceding non-simple args into temps 6521 final_args = [] 6522 new_temps = [] 6523 first_temp_arg = temps[0][-1] 6524 for arg_value in args: 6525 if arg_value is first_temp_arg: 6526 break # done 6527 if arg_value.is_simple(): 6528 final_args.append(arg_value) 6529 else: 6530 temp = LetRefNode(arg_value) 6531 new_temps.append(temp) 6532 final_args.append(temp) 6533 if new_temps: 6534 args = final_args 6535 temps = new_temps + [ arg for i,arg in sorted(temps) ] 6536 6537 # check for unexpected keywords 6538 for arg in kwargs.key_value_pairs: 6539 name = arg.key.value 6540 if name not in matched_args: 6541 has_errors = True 6542 error(arg.pos, 6543 "C function got unexpected keyword argument '%s'" % 6544 name) 6545 6546 if has_errors: 6547 # error was reported already 6548 return None 6549 6550 # all keywords mapped to positional arguments 6551 # if we are missing arguments, SimpleCallNode will figure it out 6552 node = SimpleCallNode(self.pos, function=function, args=args) 6553 for temp in temps[::-1]: 6554 node = EvalWithTempExprNode(temp, node) 6555 return node 6556 6557 def generate_result_code(self, code): 6558 if self.type.is_error: return 6559 if self.keyword_args: 6560 kwargs = self.keyword_args.py_result() 6561 else: 6562 kwargs = 'NULL' 6563 code.globalstate.use_utility_code(UtilityCode.load_cached( 6564 "PyObjectCall", "ObjectHandling.c")) 6565 code.putln( 6566 "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % ( 6567 self.result(), 6568 self.function.py_result(), 6569 self.positional_args.py_result(), 6570 kwargs, 6571 code.error_goto_if_null(self.result(), self.pos))) 6572 code.put_gotref(self.py_result()) 6573 6574 6575class AsTupleNode(ExprNode): 6576 # Convert argument to tuple. Used for normalising 6577 # the * argument of a function call. 6578 # 6579 # arg ExprNode 6580 6581 subexprs = ['arg'] 6582 is_temp = 1 6583 6584 def calculate_constant_result(self): 6585 self.constant_result = tuple(self.arg.constant_result) 6586 6587 def compile_time_value(self, denv): 6588 arg = self.arg.compile_time_value(denv) 6589 try: 6590 return tuple(arg) 6591 except Exception as e: 6592 self.compile_time_value_error(e) 6593 6594 def analyse_types(self, env): 6595 self.arg = self.arg.analyse_types(env).coerce_to_pyobject(env) 6596 if self.arg.type is tuple_type: 6597 return self.arg.as_none_safe_node("'NoneType' object is not iterable") 6598 self.type = tuple_type 6599 return self 6600 6601 def may_be_none(self): 6602 return False 6603 6604 nogil_check = Node.gil_error 6605 gil_message = "Constructing Python tuple" 6606 6607 def generate_result_code(self, code): 6608 cfunc = "__Pyx_PySequence_Tuple" if self.arg.type in (py_object_type, tuple_type) else "PySequence_Tuple" 6609 code.putln( 6610 "%s = %s(%s); %s" % ( 6611 self.result(), 6612 cfunc, self.arg.py_result(), 6613 code.error_goto_if_null(self.result(), self.pos))) 6614 code.put_gotref(self.py_result()) 6615 6616 6617class MergedDictNode(ExprNode): 6618 # Helper class for keyword arguments and other merged dicts. 6619 # 6620 # keyword_args [DictNode or other ExprNode] 6621 6622 subexprs = ['keyword_args'] 6623 is_temp = 1 6624 type = dict_type 6625 reject_duplicates = True 6626 6627 def calculate_constant_result(self): 6628 result = {} 6629 reject_duplicates = self.reject_duplicates 6630 for item in self.keyword_args: 6631 if item.is_dict_literal: 6632 # process items in order 6633 items = ((key.constant_result, value.constant_result) 6634 for key, value in item.key_value_pairs) 6635 else: 6636 items = item.constant_result.iteritems() 6637 6638 for key, value in items: 6639 if reject_duplicates and key in result: 6640 raise ValueError("duplicate keyword argument found: %s" % key) 6641 result[key] = value 6642 6643 self.constant_result = result 6644 6645 def compile_time_value(self, denv): 6646 result = {} 6647 reject_duplicates = self.reject_duplicates 6648 for item in self.keyword_args: 6649 if item.is_dict_literal: 6650 # process items in order 6651 items = [(key.compile_time_value(denv), value.compile_time_value(denv)) 6652 for key, value in item.key_value_pairs] 6653 else: 6654 items = item.compile_time_value(denv).iteritems() 6655 6656 try: 6657 for key, value in items: 6658 if reject_duplicates and key in result: 6659 raise ValueError("duplicate keyword argument found: %s" % key) 6660 result[key] = value 6661 except Exception as e: 6662 self.compile_time_value_error(e) 6663 return result 6664 6665 def type_dependencies(self, env): 6666 return () 6667 6668 def infer_type(self, env): 6669 return dict_type 6670 6671 def analyse_types(self, env): 6672 self.keyword_args = [ 6673 arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node( 6674 # FIXME: CPython's error message starts with the runtime function name 6675 'argument after ** must be a mapping, not NoneType') 6676 for arg in self.keyword_args 6677 ] 6678 6679 return self 6680 6681 def may_be_none(self): 6682 return False 6683 6684 gil_message = "Constructing Python dict" 6685 6686 def generate_evaluation_code(self, code): 6687 code.mark_pos(self.pos) 6688 self.allocate_temp_result(code) 6689 6690 args = iter(self.keyword_args) 6691 item = next(args) 6692 item.generate_evaluation_code(code) 6693 if item.type is not dict_type: 6694 # CPython supports calling functions with non-dicts, so do we 6695 code.putln('if (likely(PyDict_CheckExact(%s))) {' % 6696 item.py_result()) 6697 6698 if item.is_dict_literal: 6699 item.make_owned_reference(code) 6700 code.putln("%s = %s;" % (self.result(), item.py_result())) 6701 item.generate_post_assignment_code(code) 6702 else: 6703 code.putln("%s = PyDict_Copy(%s); %s" % ( 6704 self.result(), 6705 item.py_result(), 6706 code.error_goto_if_null(self.result(), item.pos))) 6707 code.put_gotref(self.result()) 6708 item.generate_disposal_code(code) 6709 6710 if item.type is not dict_type: 6711 code.putln('} else {') 6712 code.putln("%s = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, %s, NULL); %s" % ( 6713 self.result(), 6714 item.py_result(), 6715 code.error_goto_if_null(self.result(), self.pos))) 6716 code.put_gotref(self.py_result()) 6717 item.generate_disposal_code(code) 6718 code.putln('}') 6719 item.free_temps(code) 6720 6721 helpers = set() 6722 for item in args: 6723 if item.is_dict_literal: 6724 # inline update instead of creating an intermediate dict 6725 for arg in item.key_value_pairs: 6726 arg.generate_evaluation_code(code) 6727 if self.reject_duplicates: 6728 code.putln("if (unlikely(PyDict_Contains(%s, %s))) {" % ( 6729 self.result(), 6730 arg.key.py_result())) 6731 helpers.add("RaiseDoubleKeywords") 6732 # FIXME: find out function name at runtime! 6733 code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( 6734 arg.key.py_result(), 6735 code.error_goto(self.pos))) 6736 code.putln("}") 6737 code.put_error_if_neg(arg.key.pos, "PyDict_SetItem(%s, %s, %s)" % ( 6738 self.result(), 6739 arg.key.py_result(), 6740 arg.value.py_result())) 6741 arg.generate_disposal_code(code) 6742 arg.free_temps(code) 6743 else: 6744 item.generate_evaluation_code(code) 6745 if self.reject_duplicates: 6746 # merge mapping into kwdict one by one as we need to check for duplicates 6747 helpers.add("MergeKeywords") 6748 code.put_error_if_neg(item.pos, "__Pyx_MergeKeywords(%s, %s)" % ( 6749 self.result(), item.py_result())) 6750 else: 6751 # simple case, just add all entries 6752 helpers.add("RaiseMappingExpected") 6753 code.putln("if (unlikely(PyDict_Update(%s, %s) < 0)) {" % ( 6754 self.result(), item.py_result())) 6755 code.putln("if (PyErr_ExceptionMatches(PyExc_AttributeError)) " 6756 "__Pyx_RaiseMappingExpectedError(%s);" % item.py_result()) 6757 code.putln(code.error_goto(item.pos)) 6758 code.putln("}") 6759 item.generate_disposal_code(code) 6760 item.free_temps(code) 6761 6762 for helper in sorted(helpers): 6763 code.globalstate.use_utility_code(UtilityCode.load_cached(helper, "FunctionArguments.c")) 6764 6765 def annotate(self, code): 6766 for item in self.keyword_args: 6767 item.annotate(code) 6768 6769 6770class AttributeNode(ExprNode): 6771 # obj.attribute 6772 # 6773 # obj ExprNode 6774 # attribute string 6775 # needs_none_check boolean Used if obj is an extension type. 6776 # If set to True, it is known that the type is not None. 6777 # 6778 # Used internally: 6779 # 6780 # is_py_attr boolean Is a Python getattr operation 6781 # member string C name of struct member 6782 # is_called boolean Function call is being done on result 6783 # entry Entry Symbol table entry of attribute 6784 6785 is_attribute = 1 6786 subexprs = ['obj'] 6787 6788 type = PyrexTypes.error_type 6789 entry = None 6790 is_called = 0 6791 needs_none_check = True 6792 is_memslice_transpose = False 6793 is_special_lookup = False 6794 is_py_attr = 0 6795 6796 def as_cython_attribute(self): 6797 if (isinstance(self.obj, NameNode) and 6798 self.obj.is_cython_module and not 6799 self.attribute == u"parallel"): 6800 return self.attribute 6801 6802 cy = self.obj.as_cython_attribute() 6803 if cy: 6804 return "%s.%s" % (cy, self.attribute) 6805 return None 6806 6807 def coerce_to(self, dst_type, env): 6808 # If coercing to a generic pyobject and this is a cpdef function 6809 # we can create the corresponding attribute 6810 if dst_type is py_object_type: 6811 entry = self.entry 6812 if entry and entry.is_cfunction and entry.as_variable: 6813 # must be a cpdef function 6814 self.is_temp = 1 6815 self.entry = entry.as_variable 6816 self.analyse_as_python_attribute(env) 6817 return self 6818 return ExprNode.coerce_to(self, dst_type, env) 6819 6820 def calculate_constant_result(self): 6821 attr = self.attribute 6822 if attr.startswith("__") and attr.endswith("__"): 6823 return 6824 self.constant_result = getattr(self.obj.constant_result, attr) 6825 6826 def compile_time_value(self, denv): 6827 attr = self.attribute 6828 if attr.startswith("__") and attr.endswith("__"): 6829 error(self.pos, 6830 "Invalid attribute name '%s' in compile-time expression" % attr) 6831 return None 6832 obj = self.obj.compile_time_value(denv) 6833 try: 6834 return getattr(obj, attr) 6835 except Exception as e: 6836 self.compile_time_value_error(e) 6837 6838 def type_dependencies(self, env): 6839 return self.obj.type_dependencies(env) 6840 6841 def infer_type(self, env): 6842 # FIXME: this is way too redundant with analyse_types() 6843 node = self.analyse_as_cimported_attribute_node(env, target=False) 6844 if node is not None: 6845 if node.entry.type and node.entry.type.is_cfunction: 6846 # special-case - function converted to pointer 6847 return PyrexTypes.CPtrType(node.entry.type) 6848 else: 6849 return node.entry.type 6850 node = self.analyse_as_type_attribute(env) 6851 if node is not None: 6852 return node.entry.type 6853 obj_type = self.obj.infer_type(env) 6854 self.analyse_attribute(env, obj_type=obj_type) 6855 if obj_type.is_builtin_type and self.type.is_cfunction: 6856 # special case: C-API replacements for C methods of 6857 # builtin types cannot be inferred as C functions as 6858 # that would prevent their use as bound methods 6859 return py_object_type 6860 elif self.entry and self.entry.is_cmethod: 6861 # special case: bound methods should not be inferred 6862 # as their unbound method types 6863 return py_object_type 6864 return self.type 6865 6866 def analyse_target_declaration(self, env): 6867 pass 6868 6869 def analyse_target_types(self, env): 6870 node = self.analyse_types(env, target = 1) 6871 if node.type.is_const: 6872 error(self.pos, "Assignment to const attribute '%s'" % self.attribute) 6873 if not node.is_lvalue(): 6874 error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type) 6875 return node 6876 6877 def analyse_types(self, env, target = 0): 6878 self.initialized_check = env.directives['initializedcheck'] 6879 node = self.analyse_as_cimported_attribute_node(env, target) 6880 if node is None and not target: 6881 node = self.analyse_as_type_attribute(env) 6882 if node is None: 6883 node = self.analyse_as_ordinary_attribute_node(env, target) 6884 assert node is not None 6885 if node.entry: 6886 node.entry.used = True 6887 if node.is_attribute: 6888 node.wrap_obj_in_nonecheck(env) 6889 return node 6890 6891 def analyse_as_cimported_attribute_node(self, env, target): 6892 # Try to interpret this as a reference to an imported 6893 # C const, type, var or function. If successful, mutates 6894 # this node into a NameNode and returns 1, otherwise 6895 # returns 0. 6896 module_scope = self.obj.analyse_as_module(env) 6897 if module_scope: 6898 entry = module_scope.lookup_here(self.attribute) 6899 if entry and ( 6900 entry.is_cglobal or entry.is_cfunction 6901 or entry.is_type or entry.is_const): 6902 return self.as_name_node(env, entry, target) 6903 if self.is_cimported_module_without_shadow(env): 6904 error(self.pos, "cimported module has no attribute '%s'" % self.attribute) 6905 return self 6906 return None 6907 6908 def analyse_as_type_attribute(self, env): 6909 # Try to interpret this as a reference to an unbound 6910 # C method of an extension type or builtin type. If successful, 6911 # creates a corresponding NameNode and returns it, otherwise 6912 # returns None. 6913 if self.obj.is_string_literal: 6914 return 6915 type = self.obj.analyse_as_type(env) 6916 if type: 6917 if type.is_extension_type or type.is_builtin_type or type.is_cpp_class: 6918 entry = type.scope.lookup_here(self.attribute) 6919 if entry and (entry.is_cmethod or type.is_cpp_class and entry.type.is_cfunction): 6920 if type.is_builtin_type: 6921 if not self.is_called: 6922 # must handle this as Python object 6923 return None 6924 ubcm_entry = entry 6925 else: 6926 # Create a temporary entry describing the C method 6927 # as an ordinary function. 6928 if entry.func_cname and not hasattr(entry.type, 'op_arg_struct'): 6929 cname = entry.func_cname 6930 if entry.type.is_static_method or ( 6931 env.parent_scope and env.parent_scope.is_cpp_class_scope): 6932 ctype = entry.type 6933 elif type.is_cpp_class: 6934 error(self.pos, "%s not a static member of %s" % (entry.name, type)) 6935 ctype = PyrexTypes.error_type 6936 else: 6937 # Fix self type. 6938 ctype = copy.copy(entry.type) 6939 ctype.args = ctype.args[:] 6940 ctype.args[0] = PyrexTypes.CFuncTypeArg('self', type, 'self', None) 6941 else: 6942 cname = "%s->%s" % (type.vtabptr_cname, entry.cname) 6943 ctype = entry.type 6944 ubcm_entry = Symtab.Entry(entry.name, cname, ctype) 6945 ubcm_entry.is_cfunction = 1 6946 ubcm_entry.func_cname = entry.func_cname 6947 ubcm_entry.is_unbound_cmethod = 1 6948 ubcm_entry.scope = entry.scope 6949 return self.as_name_node(env, ubcm_entry, target=False) 6950 elif type.is_enum: 6951 if self.attribute in type.values: 6952 for entry in type.entry.enum_values: 6953 if entry.name == self.attribute: 6954 return self.as_name_node(env, entry, target=False) 6955 else: 6956 error(self.pos, "%s not a known value of %s" % (self.attribute, type)) 6957 else: 6958 error(self.pos, "%s not a known value of %s" % (self.attribute, type)) 6959 return None 6960 6961 def analyse_as_type(self, env): 6962 module_scope = self.obj.analyse_as_module(env) 6963 if module_scope: 6964 return module_scope.lookup_type(self.attribute) 6965 if not self.obj.is_string_literal: 6966 base_type = self.obj.analyse_as_type(env) 6967 if base_type and hasattr(base_type, 'scope') and base_type.scope is not None: 6968 return base_type.scope.lookup_type(self.attribute) 6969 return None 6970 6971 def analyse_as_extension_type(self, env): 6972 # Try to interpret this as a reference to an extension type 6973 # in a cimported module. Returns the extension type, or None. 6974 module_scope = self.obj.analyse_as_module(env) 6975 if module_scope: 6976 entry = module_scope.lookup_here(self.attribute) 6977 if entry and entry.is_type: 6978 if entry.type.is_extension_type or entry.type.is_builtin_type: 6979 return entry.type 6980 return None 6981 6982 def analyse_as_module(self, env): 6983 # Try to interpret this as a reference to a cimported module 6984 # in another cimported module. Returns the module scope, or None. 6985 module_scope = self.obj.analyse_as_module(env) 6986 if module_scope: 6987 entry = module_scope.lookup_here(self.attribute) 6988 if entry and entry.as_module: 6989 return entry.as_module 6990 return None 6991 6992 def as_name_node(self, env, entry, target): 6993 # Create a corresponding NameNode from this node and complete the 6994 # analyse_types phase. 6995 node = NameNode.from_node(self, name=self.attribute, entry=entry) 6996 if target: 6997 node = node.analyse_target_types(env) 6998 else: 6999 node = node.analyse_rvalue_entry(env) 7000 node.entry.used = 1 7001 return node 7002 7003 def analyse_as_ordinary_attribute_node(self, env, target): 7004 self.obj = self.obj.analyse_types(env) 7005 self.analyse_attribute(env) 7006 if self.entry and self.entry.is_cmethod and not self.is_called: 7007# error(self.pos, "C method can only be called") 7008 pass 7009 ## Reference to C array turns into pointer to first element. 7010 #while self.type.is_array: 7011 # self.type = self.type.element_ptr_type() 7012 if self.is_py_attr: 7013 if not target: 7014 self.is_temp = 1 7015 self.result_ctype = py_object_type 7016 elif target and self.obj.type.is_builtin_type: 7017 error(self.pos, "Assignment to an immutable object field") 7018 #elif self.type.is_memoryviewslice and not target: 7019 # self.is_temp = True 7020 return self 7021 7022 def analyse_attribute(self, env, obj_type = None): 7023 # Look up attribute and set self.type and self.member. 7024 immutable_obj = obj_type is not None # used during type inference 7025 self.is_py_attr = 0 7026 self.member = self.attribute 7027 if obj_type is None: 7028 if self.obj.type.is_string or self.obj.type.is_pyunicode_ptr: 7029 self.obj = self.obj.coerce_to_pyobject(env) 7030 obj_type = self.obj.type 7031 else: 7032 if obj_type.is_string or obj_type.is_pyunicode_ptr: 7033 obj_type = py_object_type 7034 if obj_type.is_ptr or obj_type.is_array: 7035 obj_type = obj_type.base_type 7036 self.op = "->" 7037 elif obj_type.is_extension_type or obj_type.is_builtin_type: 7038 self.op = "->" 7039 elif obj_type.is_reference and obj_type.is_fake_reference: 7040 self.op = "->" 7041 else: 7042 self.op = "." 7043 if obj_type.has_attributes: 7044 if obj_type.attributes_known(): 7045 entry = obj_type.scope.lookup_here(self.attribute) 7046 if obj_type.is_memoryviewslice and not entry: 7047 if self.attribute == 'T': 7048 self.is_memslice_transpose = True 7049 self.is_temp = True 7050 self.use_managed_ref = True 7051 self.type = self.obj.type.transpose(self.pos) 7052 return 7053 else: 7054 obj_type.declare_attribute(self.attribute, env, self.pos) 7055 entry = obj_type.scope.lookup_here(self.attribute) 7056 if entry and entry.is_member: 7057 entry = None 7058 else: 7059 error(self.pos, 7060 "Cannot select attribute of incomplete type '%s'" 7061 % obj_type) 7062 self.type = PyrexTypes.error_type 7063 return 7064 self.entry = entry 7065 if entry: 7066 if obj_type.is_extension_type and entry.name == "__weakref__": 7067 error(self.pos, "Illegal use of special attribute __weakref__") 7068 7069 # def methods need the normal attribute lookup 7070 # because they do not have struct entries 7071 # fused function go through assignment synthesis 7072 # (foo = pycfunction(foo_func_obj)) and need to go through 7073 # regular Python lookup as well 7074 if (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod: 7075 self.type = entry.type 7076 self.member = entry.cname 7077 return 7078 else: 7079 # If it's not a variable or C method, it must be a Python 7080 # method of an extension type, so we treat it like a Python 7081 # attribute. 7082 pass 7083 # If we get here, the base object is not a struct/union/extension 7084 # type, or it is an extension type and the attribute is either not 7085 # declared or is declared as a Python method. Treat it as a Python 7086 # attribute reference. 7087 self.analyse_as_python_attribute(env, obj_type, immutable_obj) 7088 7089 def analyse_as_python_attribute(self, env, obj_type=None, immutable_obj=False): 7090 if obj_type is None: 7091 obj_type = self.obj.type 7092 # mangle private '__*' Python attributes used inside of a class 7093 self.attribute = env.mangle_class_private_name(self.attribute) 7094 self.member = self.attribute 7095 self.type = py_object_type 7096 self.is_py_attr = 1 7097 7098 if not obj_type.is_pyobject and not obj_type.is_error: 7099 # Expose python methods for immutable objects. 7100 if (obj_type.is_string or obj_type.is_cpp_string 7101 or obj_type.is_buffer or obj_type.is_memoryviewslice 7102 or obj_type.is_numeric 7103 or (obj_type.is_ctuple and obj_type.can_coerce_to_pyobject(env)) 7104 or (obj_type.is_struct and obj_type.can_coerce_to_pyobject(env))): 7105 if not immutable_obj: 7106 self.obj = self.obj.coerce_to_pyobject(env) 7107 elif (obj_type.is_cfunction and (self.obj.is_name or self.obj.is_attribute) 7108 and self.obj.entry.as_variable 7109 and self.obj.entry.as_variable.type.is_pyobject): 7110 # might be an optimised builtin function => unpack it 7111 if not immutable_obj: 7112 self.obj = self.obj.coerce_to_pyobject(env) 7113 else: 7114 error(self.pos, 7115 "Object of type '%s' has no attribute '%s'" % 7116 (obj_type, self.attribute)) 7117 7118 def wrap_obj_in_nonecheck(self, env): 7119 if not env.directives['nonecheck']: 7120 return 7121 7122 msg = None 7123 format_args = () 7124 if (self.obj.type.is_extension_type and self.needs_none_check and not 7125 self.is_py_attr): 7126 msg = "'NoneType' object has no attribute '%{0}s'".format('.30' if len(self.attribute) <= 30 else '') 7127 format_args = (self.attribute,) 7128 elif self.obj.type.is_memoryviewslice: 7129 if self.is_memslice_transpose: 7130 msg = "Cannot transpose None memoryview slice" 7131 else: 7132 entry = self.obj.type.scope.lookup_here(self.attribute) 7133 if entry: 7134 # copy/is_c_contig/shape/strides etc 7135 msg = "Cannot access '%s' attribute of None memoryview slice" 7136 format_args = (entry.name,) 7137 7138 if msg: 7139 self.obj = self.obj.as_none_safe_node(msg, 'PyExc_AttributeError', 7140 format_args=format_args) 7141 7142 def nogil_check(self, env): 7143 if self.is_py_attr: 7144 self.gil_error() 7145 7146 gil_message = "Accessing Python attribute" 7147 7148 def is_cimported_module_without_shadow(self, env): 7149 return self.obj.is_cimported_module_without_shadow(env) 7150 7151 def is_simple(self): 7152 if self.obj: 7153 return self.result_in_temp() or self.obj.is_simple() 7154 else: 7155 return NameNode.is_simple(self) 7156 7157 def is_lvalue(self): 7158 if self.obj: 7159 return True 7160 else: 7161 return NameNode.is_lvalue(self) 7162 7163 def is_ephemeral(self): 7164 if self.obj: 7165 return self.obj.is_ephemeral() 7166 else: 7167 return NameNode.is_ephemeral(self) 7168 7169 def calculate_result_code(self): 7170 #print "AttributeNode.calculate_result_code:", self.member ### 7171 #print "...obj node =", self.obj, "code", self.obj.result() ### 7172 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ### 7173 obj = self.obj 7174 obj_code = obj.result_as(obj.type) 7175 #print "...obj_code =", obj_code ### 7176 if self.entry and self.entry.is_cmethod: 7177 if obj.type.is_extension_type and not self.entry.is_builtin_cmethod: 7178 if self.entry.final_func_cname: 7179 return self.entry.final_func_cname 7180 7181 if self.type.from_fused: 7182 # If the attribute was specialized through indexing, make 7183 # sure to get the right fused name, as our entry was 7184 # replaced by our parent index node 7185 # (AnalyseExpressionsTransform) 7186 self.member = self.entry.cname 7187 7188 return "((struct %s *)%s%s%s)->%s" % ( 7189 obj.type.vtabstruct_cname, obj_code, self.op, 7190 obj.type.vtabslot_cname, self.member) 7191 elif self.result_is_used: 7192 return self.member 7193 # Generating no code at all for unused access to optimised builtin 7194 # methods fixes the problem that some optimisations only exist as 7195 # macros, i.e. there is no function pointer to them, so we would 7196 # generate invalid C code here. 7197 return 7198 elif obj.type.is_complex: 7199 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code) 7200 else: 7201 if obj.type.is_builtin_type and self.entry and self.entry.is_variable: 7202 # accessing a field of a builtin type, need to cast better than result_as() does 7203 obj_code = obj.type.cast_code(obj.result(), to_object_struct = True) 7204 return "%s%s%s" % (obj_code, self.op, self.member) 7205 7206 def generate_result_code(self, code): 7207 if self.is_py_attr: 7208 if self.is_special_lookup: 7209 code.globalstate.use_utility_code( 7210 UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHandling.c")) 7211 lookup_func_name = '__Pyx_PyObject_LookupSpecial' 7212 else: 7213 code.globalstate.use_utility_code( 7214 UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandling.c")) 7215 lookup_func_name = '__Pyx_PyObject_GetAttrStr' 7216 code.putln( 7217 '%s = %s(%s, %s); %s' % ( 7218 self.result(), 7219 lookup_func_name, 7220 self.obj.py_result(), 7221 code.intern_identifier(self.attribute), 7222 code.error_goto_if_null(self.result(), self.pos))) 7223 code.put_gotref(self.py_result()) 7224 elif self.type.is_memoryviewslice: 7225 if self.is_memslice_transpose: 7226 # transpose the slice 7227 for access, packing in self.type.axes: 7228 if access == 'ptr': 7229 error(self.pos, "Transposing not supported for slices " 7230 "with indirect dimensions") 7231 return 7232 7233 code.putln("%s = %s;" % (self.result(), self.obj.result())) 7234 code.put_incref_memoryviewslice(self.result(), have_gil=True) 7235 7236 T = "__pyx_memslice_transpose(&%s) == 0" 7237 code.putln(code.error_goto_if(T % self.result(), self.pos)) 7238 elif self.initialized_check: 7239 code.putln( 7240 'if (unlikely(!%s.memview)) {' 7241 'PyErr_SetString(PyExc_AttributeError,' 7242 '"Memoryview is not initialized");' 7243 '%s' 7244 '}' % (self.result(), code.error_goto(self.pos))) 7245 else: 7246 # result_code contains what is needed, but we may need to insert 7247 # a check and raise an exception 7248 if self.obj.type and self.obj.type.is_extension_type: 7249 pass 7250 elif self.entry and self.entry.is_cmethod: 7251 # C method implemented as function call with utility code 7252 code.globalstate.use_entry_utility_code(self.entry) 7253 7254 def generate_disposal_code(self, code): 7255 if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_transpose: 7256 # mirror condition for putting the memview incref here: 7257 code.put_xdecref_memoryviewslice( 7258 self.result(), have_gil=True) 7259 code.putln("%s.memview = NULL;" % self.result()) 7260 code.putln("%s.data = NULL;" % self.result()) 7261 else: 7262 ExprNode.generate_disposal_code(self, code) 7263 7264 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 7265 exception_check=None, exception_value=None): 7266 self.obj.generate_evaluation_code(code) 7267 if self.is_py_attr: 7268 code.globalstate.use_utility_code( 7269 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 7270 code.put_error_if_neg(self.pos, 7271 '__Pyx_PyObject_SetAttrStr(%s, %s, %s)' % ( 7272 self.obj.py_result(), 7273 code.intern_identifier(self.attribute), 7274 rhs.py_result())) 7275 rhs.generate_disposal_code(code) 7276 rhs.free_temps(code) 7277 elif self.obj.type.is_complex: 7278 code.putln("__Pyx_SET_C%s(%s, %s);" % ( 7279 self.member.upper(), 7280 self.obj.result_as(self.obj.type), 7281 rhs.result_as(self.ctype()))) 7282 rhs.generate_disposal_code(code) 7283 rhs.free_temps(code) 7284 else: 7285 select_code = self.result() 7286 if self.type.is_pyobject and self.use_managed_ref: 7287 rhs.make_owned_reference(code) 7288 code.put_giveref(rhs.py_result()) 7289 code.put_gotref(select_code) 7290 code.put_decref(select_code, self.ctype()) 7291 elif self.type.is_memoryviewslice: 7292 from . import MemoryView 7293 MemoryView.put_assign_to_memviewslice( 7294 select_code, rhs, rhs.result(), self.type, code) 7295 7296 if not self.type.is_memoryviewslice: 7297 code.putln( 7298 "%s = %s;" % ( 7299 select_code, 7300 rhs.result_as(self.ctype()))) 7301 #rhs.result())) 7302 rhs.generate_post_assignment_code(code) 7303 rhs.free_temps(code) 7304 self.obj.generate_disposal_code(code) 7305 self.obj.free_temps(code) 7306 7307 def generate_deletion_code(self, code, ignore_nonexisting=False): 7308 self.obj.generate_evaluation_code(code) 7309 if self.is_py_attr or (self.entry.scope.is_property_scope 7310 and u'__del__' in self.entry.scope.entries): 7311 code.globalstate.use_utility_code( 7312 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c")) 7313 code.put_error_if_neg(self.pos, 7314 '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( 7315 self.obj.py_result(), 7316 code.intern_identifier(self.attribute))) 7317 else: 7318 error(self.pos, "Cannot delete C attribute of extension type") 7319 self.obj.generate_disposal_code(code) 7320 self.obj.free_temps(code) 7321 7322 def annotate(self, code): 7323 if self.is_py_attr: 7324 style, text = 'py_attr', 'python attribute (%s)' 7325 else: 7326 style, text = 'c_attr', 'c attribute (%s)' 7327 code.annotate(self.pos, AnnotationItem(style, text % self.type, size=len(self.attribute))) 7328 7329 7330#------------------------------------------------------------------- 7331# 7332# Constructor nodes 7333# 7334#------------------------------------------------------------------- 7335 7336class StarredUnpackingNode(ExprNode): 7337 # A starred expression like "*a" 7338 # 7339 # This is only allowed in sequence assignment or construction such as 7340 # 7341 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4] 7342 # 7343 # and will be special cased during type analysis (or generate an error 7344 # if it's found at unexpected places). 7345 # 7346 # target ExprNode 7347 7348 subexprs = ['target'] 7349 is_starred = 1 7350 type = py_object_type 7351 is_temp = 1 7352 starred_expr_allowed_here = False 7353 7354 def __init__(self, pos, target): 7355 ExprNode.__init__(self, pos, target=target) 7356 7357 def analyse_declarations(self, env): 7358 if not self.starred_expr_allowed_here: 7359 error(self.pos, "starred expression is not allowed here") 7360 self.target.analyse_declarations(env) 7361 7362 def infer_type(self, env): 7363 return self.target.infer_type(env) 7364 7365 def analyse_types(self, env): 7366 if not self.starred_expr_allowed_here: 7367 error(self.pos, "starred expression is not allowed here") 7368 self.target = self.target.analyse_types(env) 7369 self.type = self.target.type 7370 return self 7371 7372 def analyse_target_declaration(self, env): 7373 self.target.analyse_target_declaration(env) 7374 7375 def analyse_target_types(self, env): 7376 self.target = self.target.analyse_target_types(env) 7377 self.type = self.target.type 7378 return self 7379 7380 def calculate_result_code(self): 7381 return "" 7382 7383 def generate_result_code(self, code): 7384 pass 7385 7386 7387class SequenceNode(ExprNode): 7388 # Base class for list and tuple constructor nodes. 7389 # Contains common code for performing sequence unpacking. 7390 # 7391 # args [ExprNode] 7392 # unpacked_items [ExprNode] or None 7393 # coerced_unpacked_items [ExprNode] or None 7394 # mult_factor ExprNode the integer number of content repetitions ([1,2]*3) 7395 7396 subexprs = ['args', 'mult_factor'] 7397 7398 is_sequence_constructor = 1 7399 unpacked_items = None 7400 mult_factor = None 7401 slow = False # trade speed for code size (e.g. use PyTuple_Pack()) 7402 7403 def compile_time_value_list(self, denv): 7404 return [arg.compile_time_value(denv) for arg in self.args] 7405 7406 def replace_starred_target_node(self): 7407 # replace a starred node in the targets by the contained expression 7408 self.starred_assignment = False 7409 args = [] 7410 for arg in self.args: 7411 if arg.is_starred: 7412 if self.starred_assignment: 7413 error(arg.pos, "more than 1 starred expression in assignment") 7414 self.starred_assignment = True 7415 arg = arg.target 7416 arg.is_starred = True 7417 args.append(arg) 7418 self.args = args 7419 7420 def analyse_target_declaration(self, env): 7421 self.replace_starred_target_node() 7422 for arg in self.args: 7423 arg.analyse_target_declaration(env) 7424 7425 def analyse_types(self, env, skip_children=False): 7426 for i, arg in enumerate(self.args): 7427 if not skip_children: 7428 arg = arg.analyse_types(env) 7429 self.args[i] = arg.coerce_to_pyobject(env) 7430 if self.mult_factor: 7431 self.mult_factor = self.mult_factor.analyse_types(env) 7432 if not self.mult_factor.type.is_int: 7433 self.mult_factor = self.mult_factor.coerce_to_pyobject(env) 7434 self.is_temp = 1 7435 # not setting self.type here, subtypes do this 7436 return self 7437 7438 def coerce_to_ctuple(self, dst_type, env): 7439 if self.type == dst_type: 7440 return self 7441 assert not self.mult_factor 7442 if len(self.args) != dst_type.size: 7443 error(self.pos, "trying to coerce sequence to ctuple of wrong length, expected %d, got %d" % ( 7444 dst_type.size, len(self.args))) 7445 coerced_args = [arg.coerce_to(type, env) for arg, type in zip(self.args, dst_type.components)] 7446 return TupleNode(self.pos, args=coerced_args, type=dst_type, is_temp=True) 7447 7448 def _create_merge_node_if_necessary(self, env): 7449 self._flatten_starred_args() 7450 if not any(arg.is_starred for arg in self.args): 7451 return self 7452 # convert into MergedSequenceNode by building partial sequences 7453 args = [] 7454 values = [] 7455 for arg in self.args: 7456 if arg.is_starred: 7457 if values: 7458 args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True)) 7459 values = [] 7460 args.append(arg.target) 7461 else: 7462 values.append(arg) 7463 if values: 7464 args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True)) 7465 node = MergedSequenceNode(self.pos, args, self.type) 7466 if self.mult_factor: 7467 node = binop_node( 7468 self.pos, '*', node, self.mult_factor.coerce_to_pyobject(env), 7469 inplace=True, type=self.type, is_temp=True) 7470 return node 7471 7472 def _flatten_starred_args(self): 7473 args = [] 7474 for arg in self.args: 7475 if arg.is_starred and arg.target.is_sequence_constructor and not arg.target.mult_factor: 7476 args.extend(arg.target.args) 7477 else: 7478 args.append(arg) 7479 self.args[:] = args 7480 7481 def may_be_none(self): 7482 return False 7483 7484 def analyse_target_types(self, env): 7485 if self.mult_factor: 7486 error(self.pos, "can't assign to multiplied sequence") 7487 self.unpacked_items = [] 7488 self.coerced_unpacked_items = [] 7489 self.any_coerced_items = False 7490 for i, arg in enumerate(self.args): 7491 arg = self.args[i] = arg.analyse_target_types(env) 7492 if arg.is_starred: 7493 if not arg.type.assignable_from(list_type): 7494 error(arg.pos, 7495 "starred target must have Python object (list) type") 7496 if arg.type is py_object_type: 7497 arg.type = list_type 7498 unpacked_item = PyTempNode(self.pos, env) 7499 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) 7500 if unpacked_item is not coerced_unpacked_item: 7501 self.any_coerced_items = True 7502 self.unpacked_items.append(unpacked_item) 7503 self.coerced_unpacked_items.append(coerced_unpacked_item) 7504 self.type = py_object_type 7505 return self 7506 7507 def generate_result_code(self, code): 7508 self.generate_operation_code(code) 7509 7510 def generate_sequence_packing_code(self, code, target=None, plain=False): 7511 if target is None: 7512 target = self.result() 7513 size_factor = c_mult = '' 7514 mult_factor = None 7515 7516 if self.mult_factor and not plain: 7517 mult_factor = self.mult_factor 7518 if mult_factor.type.is_int: 7519 c_mult = mult_factor.result() 7520 if (isinstance(mult_factor.constant_result, _py_int_types) and 7521 mult_factor.constant_result > 0): 7522 size_factor = ' * %s' % mult_factor.constant_result 7523 elif mult_factor.type.signed: 7524 size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult) 7525 else: 7526 size_factor = ' * (%s)' % (c_mult,) 7527 7528 if self.type is tuple_type and (self.is_literal or self.slow) and not c_mult: 7529 # use PyTuple_Pack() to avoid generating huge amounts of one-time code 7530 code.putln('%s = PyTuple_Pack(%d, %s); %s' % ( 7531 target, 7532 len(self.args), 7533 ', '.join(arg.py_result() for arg in self.args), 7534 code.error_goto_if_null(target, self.pos))) 7535 code.put_gotref(target) 7536 elif self.type.is_ctuple: 7537 for i, arg in enumerate(self.args): 7538 code.putln("%s.f%s = %s;" % ( 7539 target, i, arg.result())) 7540 else: 7541 # build the tuple/list step by step, potentially multiplying it as we go 7542 if self.type is list_type: 7543 create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM' 7544 elif self.type is tuple_type: 7545 create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM' 7546 else: 7547 raise InternalError("sequence packing for unexpected type %s" % self.type) 7548 arg_count = len(self.args) 7549 code.putln("%s = %s(%s%s); %s" % ( 7550 target, create_func, arg_count, size_factor, 7551 code.error_goto_if_null(target, self.pos))) 7552 code.put_gotref(target) 7553 7554 if c_mult: 7555 # FIXME: can't use a temp variable here as the code may 7556 # end up in the constant building function. Temps 7557 # currently don't work there. 7558 7559 #counter = code.funcstate.allocate_temp(mult_factor.type, manage_ref=False) 7560 counter = Naming.quick_temp_cname 7561 code.putln('{ Py_ssize_t %s;' % counter) 7562 if arg_count == 1: 7563 offset = counter 7564 else: 7565 offset = '%s * %s' % (counter, arg_count) 7566 code.putln('for (%s=0; %s < %s; %s++) {' % ( 7567 counter, counter, c_mult, counter 7568 )) 7569 else: 7570 offset = '' 7571 7572 for i in range(arg_count): 7573 arg = self.args[i] 7574 if c_mult or not arg.result_in_temp(): 7575 code.put_incref(arg.result(), arg.ctype()) 7576 code.put_giveref(arg.py_result()) 7577 code.putln("%s(%s, %s, %s);" % ( 7578 set_item_func, 7579 target, 7580 (offset and i) and ('%s + %s' % (offset, i)) or (offset or i), 7581 arg.py_result())) 7582 7583 if c_mult: 7584 code.putln('}') 7585 #code.funcstate.release_temp(counter) 7586 code.putln('}') 7587 7588 if mult_factor is not None and mult_factor.type.is_pyobject: 7589 code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' % ( 7590 Naming.quick_temp_cname, target, mult_factor.py_result(), 7591 code.error_goto_if_null(Naming.quick_temp_cname, self.pos) 7592 )) 7593 code.put_gotref(Naming.quick_temp_cname) 7594 code.put_decref(target, py_object_type) 7595 code.putln('%s = %s;' % (target, Naming.quick_temp_cname)) 7596 code.putln('}') 7597 7598 def generate_subexpr_disposal_code(self, code): 7599 if self.mult_factor and self.mult_factor.type.is_int: 7600 super(SequenceNode, self).generate_subexpr_disposal_code(code) 7601 elif self.type is tuple_type and (self.is_literal or self.slow): 7602 super(SequenceNode, self).generate_subexpr_disposal_code(code) 7603 else: 7604 # We call generate_post_assignment_code here instead 7605 # of generate_disposal_code, because values were stored 7606 # in the tuple using a reference-stealing operation. 7607 for arg in self.args: 7608 arg.generate_post_assignment_code(code) 7609 # Should NOT call free_temps -- this is invoked by the default 7610 # generate_evaluation_code which will do that. 7611 if self.mult_factor: 7612 self.mult_factor.generate_disposal_code(code) 7613 7614 def generate_assignment_code(self, rhs, code, overloaded_assignment=False, 7615 exception_check=None, exception_value=None): 7616 if self.starred_assignment: 7617 self.generate_starred_assignment_code(rhs, code) 7618 else: 7619 self.generate_parallel_assignment_code(rhs, code) 7620 7621 for item in self.unpacked_items: 7622 item.release(code) 7623 rhs.free_temps(code) 7624 7625 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( 7626 PyrexTypes.py_object_type, [ 7627 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), 7628 ])) 7629 7630 def generate_parallel_assignment_code(self, rhs, code): 7631 # Need to work around the fact that generate_evaluation_code 7632 # allocates the temps in a rather hacky way -- the assignment 7633 # is evaluated twice, within each if-block. 7634 for item in self.unpacked_items: 7635 item.allocate(code) 7636 special_unpack = (rhs.type is py_object_type 7637 or rhs.type in (tuple_type, list_type) 7638 or not rhs.type.is_builtin_type) 7639 long_enough_for_a_loop = len(self.unpacked_items) > 3 7640 7641 if special_unpack: 7642 self.generate_special_parallel_unpacking_code( 7643 code, rhs, use_loop=long_enough_for_a_loop) 7644 else: 7645 code.putln("{") 7646 self.generate_generic_parallel_unpacking_code( 7647 code, rhs, self.unpacked_items, use_loop=long_enough_for_a_loop) 7648 code.putln("}") 7649 7650 for value_node in self.coerced_unpacked_items: 7651 value_node.generate_evaluation_code(code) 7652 for i in range(len(self.args)): 7653 self.args[i].generate_assignment_code( 7654 self.coerced_unpacked_items[i], code) 7655 7656 def generate_special_parallel_unpacking_code(self, code, rhs, use_loop): 7657 sequence_type_test = '1' 7658 none_check = "likely(%s != Py_None)" % rhs.py_result() 7659 if rhs.type is list_type: 7660 sequence_types = ['List'] 7661 if rhs.may_be_none(): 7662 sequence_type_test = none_check 7663 elif rhs.type is tuple_type: 7664 sequence_types = ['Tuple'] 7665 if rhs.may_be_none(): 7666 sequence_type_test = none_check 7667 else: 7668 sequence_types = ['Tuple', 'List'] 7669 tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result() 7670 list_check = 'PyList_CheckExact(%s)' % rhs.py_result() 7671 sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check) 7672 7673 code.putln("if (%s) {" % sequence_type_test) 7674 code.putln("PyObject* sequence = %s;" % rhs.py_result()) 7675 7676 # list/tuple => check size 7677 code.putln("Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);") 7678 code.putln("if (unlikely(size != %d)) {" % len(self.args)) 7679 code.globalstate.use_utility_code(raise_too_many_values_to_unpack) 7680 code.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % ( 7681 len(self.args), len(self.args))) 7682 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 7683 code.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);") 7684 # < 0 => exception 7685 code.putln(code.error_goto(self.pos)) 7686 code.putln("}") 7687 7688 code.putln("#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS") 7689 # unpack items from list/tuple in unrolled loop (can't fail) 7690 if len(sequence_types) == 2: 7691 code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types[0]) 7692 for i, item in enumerate(self.unpacked_items): 7693 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( 7694 item.result(), sequence_types[0], i)) 7695 if len(sequence_types) == 2: 7696 code.putln("} else {") 7697 for i, item in enumerate(self.unpacked_items): 7698 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( 7699 item.result(), sequence_types[1], i)) 7700 code.putln("}") 7701 for item in self.unpacked_items: 7702 code.put_incref(item.result(), item.ctype()) 7703 7704 code.putln("#else") 7705 # in non-CPython, use the PySequence protocol (which can fail) 7706 if not use_loop: 7707 for i, item in enumerate(self.unpacked_items): 7708 code.putln("%s = PySequence_ITEM(sequence, %d); %s" % ( 7709 item.result(), i, 7710 code.error_goto_if_null(item.result(), self.pos))) 7711 code.put_gotref(item.result()) 7712 else: 7713 code.putln("{") 7714 code.putln("Py_ssize_t i;") 7715 code.putln("PyObject** temps[%s] = {%s};" % ( 7716 len(self.unpacked_items), 7717 ','.join(['&%s' % item.result() for item in self.unpacked_items]))) 7718 code.putln("for (i=0; i < %s; i++) {" % len(self.unpacked_items)) 7719 code.putln("PyObject* item = PySequence_ITEM(sequence, i); %s" % ( 7720 code.error_goto_if_null('item', self.pos))) 7721 code.put_gotref('item') 7722 code.putln("*(temps[i]) = item;") 7723 code.putln("}") 7724 code.putln("}") 7725 7726 code.putln("#endif") 7727 rhs.generate_disposal_code(code) 7728 7729 if sequence_type_test == '1': 7730 code.putln("}") # all done 7731 elif sequence_type_test == none_check: 7732 # either tuple/list or None => save some code by generating the error directly 7733 code.putln("} else {") 7734 code.globalstate.use_utility_code( 7735 UtilityCode.load_cached("RaiseNoneIterError", "ObjectHandling.c")) 7736 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code.error_goto(self.pos)) 7737 code.putln("}") # all done 7738 else: 7739 code.putln("} else {") # needs iteration fallback code 7740 self.generate_generic_parallel_unpacking_code( 7741 code, rhs, self.unpacked_items, use_loop=use_loop) 7742 code.putln("}") 7743 7744 def generate_generic_parallel_unpacking_code(self, code, rhs, unpacked_items, use_loop, terminate=True): 7745 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 7746 code.globalstate.use_utility_code(UtilityCode.load_cached("IterFinish", "ObjectHandling.c")) 7747 code.putln("Py_ssize_t index = -1;") # must be at the start of a C block! 7748 7749 if use_loop: 7750 code.putln("PyObject** temps[%s] = {%s};" % ( 7751 len(self.unpacked_items), 7752 ','.join(['&%s' % item.result() for item in unpacked_items]))) 7753 7754 iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 7755 code.putln( 7756 "%s = PyObject_GetIter(%s); %s" % ( 7757 iterator_temp, 7758 rhs.py_result(), 7759 code.error_goto_if_null(iterator_temp, self.pos))) 7760 code.put_gotref(iterator_temp) 7761 rhs.generate_disposal_code(code) 7762 7763 iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, manage_ref=False) 7764 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % ( 7765 iternext_func, iterator_temp)) 7766 7767 unpacking_error_label = code.new_label('unpacking_failed') 7768 unpack_code = "%s(%s)" % (iternext_func, iterator_temp) 7769 if use_loop: 7770 code.putln("for (index=0; index < %s; index++) {" % len(unpacked_items)) 7771 code.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code) 7772 code.put_goto(unpacking_error_label) 7773 code.put_gotref("item") 7774 code.putln("*(temps[index]) = item;") 7775 code.putln("}") 7776 else: 7777 for i, item in enumerate(unpacked_items): 7778 code.put( 7779 "index = %d; %s = %s; if (unlikely(!%s)) " % ( 7780 i, 7781 item.result(), 7782 unpack_code, 7783 item.result())) 7784 code.put_goto(unpacking_error_label) 7785 code.put_gotref(item.py_result()) 7786 7787 if terminate: 7788 code.globalstate.use_utility_code( 7789 UtilityCode.load_cached("UnpackItemEndCheck", "ObjectHandling.c")) 7790 code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s, %d)" % ( 7791 unpack_code, 7792 len(unpacked_items))) 7793 code.putln("%s = NULL;" % iternext_func) 7794 code.put_decref_clear(iterator_temp, py_object_type) 7795 7796 unpacking_done_label = code.new_label('unpacking_done') 7797 code.put_goto(unpacking_done_label) 7798 7799 code.put_label(unpacking_error_label) 7800 code.put_decref_clear(iterator_temp, py_object_type) 7801 code.putln("%s = NULL;" % iternext_func) 7802 code.putln("if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);") 7803 code.putln(code.error_goto(self.pos)) 7804 code.put_label(unpacking_done_label) 7805 7806 code.funcstate.release_temp(iternext_func) 7807 if terminate: 7808 code.funcstate.release_temp(iterator_temp) 7809 iterator_temp = None 7810 7811 return iterator_temp 7812 7813 def generate_starred_assignment_code(self, rhs, code): 7814 for i, arg in enumerate(self.args): 7815 if arg.is_starred: 7816 starred_target = self.unpacked_items[i] 7817 unpacked_fixed_items_left = self.unpacked_items[:i] 7818 unpacked_fixed_items_right = self.unpacked_items[i+1:] 7819 break 7820 else: 7821 assert False 7822 7823 iterator_temp = None 7824 if unpacked_fixed_items_left: 7825 for item in unpacked_fixed_items_left: 7826 item.allocate(code) 7827 code.putln('{') 7828 iterator_temp = self.generate_generic_parallel_unpacking_code( 7829 code, rhs, unpacked_fixed_items_left, 7830 use_loop=True, terminate=False) 7831 for i, item in enumerate(unpacked_fixed_items_left): 7832 value_node = self.coerced_unpacked_items[i] 7833 value_node.generate_evaluation_code(code) 7834 code.putln('}') 7835 7836 starred_target.allocate(code) 7837 target_list = starred_target.result() 7838 code.putln("%s = PySequence_List(%s); %s" % ( 7839 target_list, 7840 iterator_temp or rhs.py_result(), 7841 code.error_goto_if_null(target_list, self.pos))) 7842 code.put_gotref(target_list) 7843 7844 if iterator_temp: 7845 code.put_decref_clear(iterator_temp, py_object_type) 7846 code.funcstate.release_temp(iterator_temp) 7847 else: 7848 rhs.generate_disposal_code(code) 7849 7850 if unpacked_fixed_items_right: 7851 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) 7852 length_temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_type, manage_ref=False) 7853 code.putln('%s = PyList_GET_SIZE(%s);' % (length_temp, target_list)) 7854 code.putln("if (unlikely(%s < %d)) {" % (length_temp, len(unpacked_fixed_items_right))) 7855 code.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % ( 7856 len(unpacked_fixed_items_left), length_temp, 7857 code.error_goto(self.pos))) 7858 code.putln('}') 7859 7860 for item in unpacked_fixed_items_right[::-1]: 7861 item.allocate(code) 7862 for i, (item, coerced_arg) in enumerate(zip(unpacked_fixed_items_right[::-1], 7863 self.coerced_unpacked_items[::-1])): 7864 code.putln('#if CYTHON_COMPILING_IN_CPYTHON') 7865 code.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % ( 7866 item.py_result(), target_list, length_temp, i+1)) 7867 # resize the list the hard way 7868 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list) 7869 code.putln('#else') 7870 code.putln("%s = PySequence_ITEM(%s, %s-%d); " % ( 7871 item.py_result(), target_list, length_temp, i+1)) 7872 code.putln('#endif') 7873 code.put_gotref(item.py_result()) 7874 coerced_arg.generate_evaluation_code(code) 7875 7876 code.putln('#if !CYTHON_COMPILING_IN_CPYTHON') 7877 sublist_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) 7878 code.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % ( 7879 sublist_temp, target_list, length_temp, len(unpacked_fixed_items_right), 7880 code.error_goto_if_null(sublist_temp, self.pos))) 7881 code.put_gotref(sublist_temp) 7882 code.funcstate.release_temp(length_temp) 7883 code.put_decref(target_list, py_object_type) 7884 code.putln('%s = %s; %s = NULL;' % (target_list, sublist_temp, sublist_temp)) 7885 code.putln('#else') 7886 code.putln('(void)%s;' % sublist_temp) # avoid warning about unused variable 7887 code.funcstate.release_temp(sublist_temp) 7888 code.putln('#endif') 7889 7890 for i, arg in enumerate(self.args): 7891 arg.generate_assignment_code(self.coerced_unpacked_items[i], code) 7892 7893 def annotate(self, code): 7894 for arg in self.args: 7895 arg.annotate(code) 7896 if self.unpacked_items: 7897 for arg in self.unpacked_items: 7898 arg.annotate(code) 7899 for arg in self.coerced_unpacked_items: 7900 arg.annotate(code) 7901 7902 7903class TupleNode(SequenceNode): 7904 # Tuple constructor. 7905 7906 type = tuple_type 7907 is_partly_literal = False 7908 7909 gil_message = "Constructing Python tuple" 7910 7911 def infer_type(self, env): 7912 if self.mult_factor or not self.args: 7913 return tuple_type 7914 arg_types = [arg.infer_type(env) for arg in self.args] 7915 if any(type.is_pyobject or type.is_memoryviewslice or type.is_unspecified or type.is_fused 7916 for type in arg_types): 7917 return tuple_type 7918 return env.declare_tuple_type(self.pos, arg_types).type 7919 7920 def analyse_types(self, env, skip_children=False): 7921 if len(self.args) == 0: 7922 self.is_temp = False 7923 self.is_literal = True 7924 return self 7925 7926 if not skip_children: 7927 for i, arg in enumerate(self.args): 7928 if arg.is_starred: 7929 arg.starred_expr_allowed_here = True 7930 self.args[i] = arg.analyse_types(env) 7931 if (not self.mult_factor and 7932 not any((arg.is_starred or arg.type.is_pyobject or arg.type.is_memoryviewslice or arg.type.is_fused) 7933 for arg in self.args)): 7934 self.type = env.declare_tuple_type(self.pos, (arg.type for arg in self.args)).type 7935 self.is_temp = 1 7936 return self 7937 7938 node = SequenceNode.analyse_types(self, env, skip_children=True) 7939 node = node._create_merge_node_if_necessary(env) 7940 if not node.is_sequence_constructor: 7941 return node 7942 7943 if not all(child.is_literal for child in node.args): 7944 return node 7945 if not node.mult_factor or ( 7946 node.mult_factor.is_literal and 7947 isinstance(node.mult_factor.constant_result, _py_int_types)): 7948 node.is_temp = False 7949 node.is_literal = True 7950 else: 7951 if not node.mult_factor.type.is_pyobject: 7952 node.mult_factor = node.mult_factor.coerce_to_pyobject(env) 7953 node.is_temp = True 7954 node.is_partly_literal = True 7955 return node 7956 7957 def analyse_as_type(self, env): 7958 # ctuple type 7959 if not self.args: 7960 return None 7961 item_types = [arg.analyse_as_type(env) for arg in self.args] 7962 if any(t is None for t in item_types): 7963 return None 7964 entry = env.declare_tuple_type(self.pos, item_types) 7965 return entry.type 7966 7967 def coerce_to(self, dst_type, env): 7968 if self.type.is_ctuple: 7969 if dst_type.is_ctuple and self.type.size == dst_type.size: 7970 return self.coerce_to_ctuple(dst_type, env) 7971 elif dst_type is tuple_type or dst_type is py_object_type: 7972 coerced_args = [arg.coerce_to_pyobject(env) for arg in self.args] 7973 return TupleNode(self.pos, args=coerced_args, type=tuple_type, is_temp=1).analyse_types(env, skip_children=True) 7974 else: 7975 return self.coerce_to_pyobject(env).coerce_to(dst_type, env) 7976 elif dst_type.is_ctuple and not self.mult_factor: 7977 return self.coerce_to_ctuple(dst_type, env) 7978 else: 7979 return SequenceNode.coerce_to(self, dst_type, env) 7980 7981 def as_list(self): 7982 t = ListNode(self.pos, args=self.args, mult_factor=self.mult_factor) 7983 if isinstance(self.constant_result, tuple): 7984 t.constant_result = list(self.constant_result) 7985 return t 7986 7987 def is_simple(self): 7988 # either temp or constant => always simple 7989 return True 7990 7991 def nonlocally_immutable(self): 7992 # either temp or constant => always safe 7993 return True 7994 7995 def calculate_result_code(self): 7996 if len(self.args) > 0: 7997 return self.result_code 7998 else: 7999 return Naming.empty_tuple 8000 8001 def calculate_constant_result(self): 8002 self.constant_result = tuple([ 8003 arg.constant_result for arg in self.args]) 8004 8005 def compile_time_value(self, denv): 8006 values = self.compile_time_value_list(denv) 8007 try: 8008 return tuple(values) 8009 except Exception as e: 8010 self.compile_time_value_error(e) 8011 8012 def generate_operation_code(self, code): 8013 if len(self.args) == 0: 8014 # result_code is Naming.empty_tuple 8015 return 8016 8017 if self.is_literal or self.is_partly_literal: 8018 # The "mult_factor" is part of the deduplication if it is also constant, i.e. when 8019 # we deduplicate the multiplied result. Otherwise, only deduplicate the constant part. 8020 dedup_key = make_dedup_key(self.type, [self.mult_factor if self.is_literal else None] + self.args) 8021 tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_level=2, dedup_key=dedup_key) 8022 const_code = code.get_cached_constants_writer(tuple_target) 8023 if const_code is not None: 8024 # constant is not yet initialised 8025 const_code.mark_pos(self.pos) 8026 self.generate_sequence_packing_code(const_code, tuple_target, plain=not self.is_literal) 8027 const_code.put_giveref(tuple_target) 8028 if self.is_literal: 8029 self.result_code = tuple_target 8030 else: 8031 code.putln('%s = PyNumber_Multiply(%s, %s); %s' % ( 8032 self.result(), tuple_target, self.mult_factor.py_result(), 8033 code.error_goto_if_null(self.result(), self.pos) 8034 )) 8035 code.put_gotref(self.py_result()) 8036 else: 8037 self.type.entry.used = True 8038 self.generate_sequence_packing_code(code) 8039 8040 8041class ListNode(SequenceNode): 8042 # List constructor. 8043 8044 # obj_conversion_errors [PyrexError] used internally 8045 # orignial_args [ExprNode] used internally 8046 8047 obj_conversion_errors = [] 8048 type = list_type 8049 in_module_scope = False 8050 8051 gil_message = "Constructing Python list" 8052 8053 def type_dependencies(self, env): 8054 return () 8055 8056 def infer_type(self, env): 8057 # TODO: Infer non-object list arrays. 8058 return list_type 8059 8060 def analyse_expressions(self, env): 8061 for arg in self.args: 8062 if arg.is_starred: 8063 arg.starred_expr_allowed_here = True 8064 node = SequenceNode.analyse_expressions(self, env) 8065 return node.coerce_to_pyobject(env) 8066 8067 def analyse_types(self, env): 8068 with local_errors(ignore=True) as errors: 8069 self.original_args = list(self.args) 8070 node = SequenceNode.analyse_types(self, env) 8071 node.obj_conversion_errors = errors 8072 if env.is_module_scope: 8073 self.in_module_scope = True 8074 node = node._create_merge_node_if_necessary(env) 8075 return node 8076 8077 def coerce_to(self, dst_type, env): 8078 if dst_type.is_pyobject: 8079 for err in self.obj_conversion_errors: 8080 report_error(err) 8081 self.obj_conversion_errors = [] 8082 if not self.type.subtype_of(dst_type): 8083 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) 8084 elif (dst_type.is_array or dst_type.is_ptr) and dst_type.base_type is not PyrexTypes.c_void_type: 8085 array_length = len(self.args) 8086 if self.mult_factor: 8087 if isinstance(self.mult_factor.constant_result, _py_int_types): 8088 if self.mult_factor.constant_result <= 0: 8089 error(self.pos, "Cannot coerce non-positively multiplied list to '%s'" % dst_type) 8090 else: 8091 array_length *= self.mult_factor.constant_result 8092 else: 8093 error(self.pos, "Cannot coerce dynamically multiplied list to '%s'" % dst_type) 8094 base_type = dst_type.base_type 8095 self.type = PyrexTypes.CArrayType(base_type, array_length) 8096 for i in range(len(self.original_args)): 8097 arg = self.args[i] 8098 if isinstance(arg, CoerceToPyTypeNode): 8099 arg = arg.arg 8100 self.args[i] = arg.coerce_to(base_type, env) 8101 elif dst_type.is_cpp_class: 8102 # TODO(robertwb): Avoid object conversion for vector/list/set. 8103 return TypecastNode(self.pos, operand=self, type=PyrexTypes.py_object_type).coerce_to(dst_type, env) 8104 elif self.mult_factor: 8105 error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type) 8106 elif dst_type.is_struct: 8107 if len(self.args) > len(dst_type.scope.var_entries): 8108 error(self.pos, "Too many members for '%s'" % dst_type) 8109 else: 8110 if len(self.args) < len(dst_type.scope.var_entries): 8111 warning(self.pos, "Too few members for '%s'" % dst_type, 1) 8112 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)): 8113 if isinstance(arg, CoerceToPyTypeNode): 8114 arg = arg.arg 8115 self.args[i] = arg.coerce_to(member.type, env) 8116 self.type = dst_type 8117 elif dst_type.is_ctuple: 8118 return self.coerce_to_ctuple(dst_type, env) 8119 else: 8120 self.type = error_type 8121 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) 8122 return self 8123 8124 def as_list(self): # dummy for compatibility with TupleNode 8125 return self 8126 8127 def as_tuple(self): 8128 t = TupleNode(self.pos, args=self.args, mult_factor=self.mult_factor) 8129 if isinstance(self.constant_result, list): 8130 t.constant_result = tuple(self.constant_result) 8131 return t 8132 8133 def allocate_temp_result(self, code): 8134 if self.type.is_array: 8135 if self.in_module_scope: 8136 self.temp_code = code.funcstate.allocate_temp( 8137 self.type, manage_ref=False, static=True, reusable=False) 8138 else: 8139 # To be valid C++, we must allocate the memory on the stack 8140 # manually and be sure not to reuse it for something else. 8141 # Yes, this means that we leak a temp array variable. 8142 self.temp_code = code.funcstate.allocate_temp( 8143 self.type, manage_ref=False, reusable=False) 8144 else: 8145 SequenceNode.allocate_temp_result(self, code) 8146 8147 def calculate_constant_result(self): 8148 if self.mult_factor: 8149 raise ValueError() # may exceed the compile time memory 8150 self.constant_result = [ 8151 arg.constant_result for arg in self.args] 8152 8153 def compile_time_value(self, denv): 8154 l = self.compile_time_value_list(denv) 8155 if self.mult_factor: 8156 l *= self.mult_factor.compile_time_value(denv) 8157 return l 8158 8159 def generate_operation_code(self, code): 8160 if self.type.is_pyobject: 8161 for err in self.obj_conversion_errors: 8162 report_error(err) 8163 self.generate_sequence_packing_code(code) 8164 elif self.type.is_array: 8165 if self.mult_factor: 8166 code.putln("{") 8167 code.putln("Py_ssize_t %s;" % Naming.quick_temp_cname) 8168 code.putln("for ({i} = 0; {i} < {count}; {i}++) {{".format( 8169 i=Naming.quick_temp_cname, count=self.mult_factor.result())) 8170 offset = '+ (%d * %s)' % (len(self.args), Naming.quick_temp_cname) 8171 else: 8172 offset = '' 8173 for i, arg in enumerate(self.args): 8174 if arg.type.is_array: 8175 code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStringH", "StringTools.c")) 8176 code.putln("memcpy(&(%s[%s%s]), %s, sizeof(%s[0]));" % ( 8177 self.result(), i, offset, 8178 arg.result(), self.result() 8179 )) 8180 else: 8181 code.putln("%s[%s%s] = %s;" % ( 8182 self.result(), 8183 i, 8184 offset, 8185 arg.result())) 8186 if self.mult_factor: 8187 code.putln("}") 8188 code.putln("}") 8189 elif self.type.is_struct: 8190 for arg, member in zip(self.args, self.type.scope.var_entries): 8191 code.putln("%s.%s = %s;" % ( 8192 self.result(), 8193 member.cname, 8194 arg.result())) 8195 else: 8196 raise InternalError("List type never specified") 8197 8198 8199class ScopedExprNode(ExprNode): 8200 # Abstract base class for ExprNodes that have their own local 8201 # scope, such as generator expressions. 8202 # 8203 # expr_scope Scope the inner scope of the expression 8204 8205 subexprs = [] 8206 expr_scope = None 8207 8208 # does this node really have a local scope, e.g. does it leak loop 8209 # variables or not? non-leaking Py3 behaviour is default, except 8210 # for list comprehensions where the behaviour differs in Py2 and 8211 # Py3 (set in Parsing.py based on parser context) 8212 has_local_scope = True 8213 8214 def init_scope(self, outer_scope, expr_scope=None): 8215 if expr_scope is not None: 8216 self.expr_scope = expr_scope 8217 elif self.has_local_scope: 8218 self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope) 8219 else: 8220 self.expr_scope = None 8221 8222 def analyse_declarations(self, env): 8223 self.init_scope(env) 8224 8225 def analyse_scoped_declarations(self, env): 8226 # this is called with the expr_scope as env 8227 pass 8228 8229 def analyse_types(self, env): 8230 # no recursion here, the children will be analysed separately below 8231 return self 8232 8233 def analyse_scoped_expressions(self, env): 8234 # this is called with the expr_scope as env 8235 return self 8236 8237 def generate_evaluation_code(self, code): 8238 # set up local variables and free their references on exit 8239 generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code 8240 if not self.has_local_scope or not self.expr_scope.var_entries: 8241 # no local variables => delegate, done 8242 generate_inner_evaluation_code(code) 8243 return 8244 8245 code.putln('{ /* enter inner scope */') 8246 py_entries = [] 8247 for _, entry in sorted(item for item in self.expr_scope.entries.items() if item[0]): 8248 if not entry.in_closure: 8249 if entry.type.is_pyobject and entry.used: 8250 py_entries.append(entry) 8251 if not py_entries: 8252 # no local Python references => no cleanup required 8253 generate_inner_evaluation_code(code) 8254 code.putln('} /* exit inner scope */') 8255 return 8256 8257 # must free all local Python references at each exit point 8258 old_loop_labels = code.new_loop_labels() 8259 old_error_label = code.new_error_label() 8260 8261 generate_inner_evaluation_code(code) 8262 8263 # normal (non-error) exit 8264 self._generate_vars_cleanup(code, py_entries) 8265 8266 # error/loop body exit points 8267 exit_scope = code.new_label('exit_scope') 8268 code.put_goto(exit_scope) 8269 for label, old_label in ([(code.error_label, old_error_label)] + 8270 list(zip(code.get_loop_labels(), old_loop_labels))): 8271 if code.label_used(label): 8272 code.put_label(label) 8273 self._generate_vars_cleanup(code, py_entries) 8274 code.put_goto(old_label) 8275 code.put_label(exit_scope) 8276 code.putln('} /* exit inner scope */') 8277 8278 code.set_loop_labels(old_loop_labels) 8279 code.error_label = old_error_label 8280 8281 def _generate_vars_cleanup(self, code, py_entries): 8282 for entry in py_entries: 8283 if entry.is_cglobal: 8284 code.put_var_gotref(entry) 8285 code.put_decref_set(entry.cname, "Py_None") 8286 else: 8287 code.put_var_xdecref_clear(entry) 8288 8289 8290class ComprehensionNode(ScopedExprNode): 8291 # A list/set/dict comprehension 8292 8293 child_attrs = ["loop"] 8294 8295 is_temp = True 8296 constant_result = not_a_constant 8297 8298 def infer_type(self, env): 8299 return self.type 8300 8301 def analyse_declarations(self, env): 8302 self.append.target = self # this is used in the PyList_Append of the inner loop 8303 self.init_scope(env) 8304 8305 def analyse_scoped_declarations(self, env): 8306 self.loop.analyse_declarations(env) 8307 8308 def analyse_types(self, env): 8309 if not self.has_local_scope: 8310 self.loop = self.loop.analyse_expressions(env) 8311 return self 8312 8313 def analyse_scoped_expressions(self, env): 8314 if self.has_local_scope: 8315 self.loop = self.loop.analyse_expressions(env) 8316 return self 8317 8318 def may_be_none(self): 8319 return False 8320 8321 def generate_result_code(self, code): 8322 self.generate_operation_code(code) 8323 8324 def generate_operation_code(self, code): 8325 if self.type is Builtin.list_type: 8326 create_code = 'PyList_New(0)' 8327 elif self.type is Builtin.set_type: 8328 create_code = 'PySet_New(NULL)' 8329 elif self.type is Builtin.dict_type: 8330 create_code = 'PyDict_New()' 8331 else: 8332 raise InternalError("illegal type for comprehension: %s" % self.type) 8333 code.putln('%s = %s; %s' % ( 8334 self.result(), create_code, 8335 code.error_goto_if_null(self.result(), self.pos))) 8336 8337 code.put_gotref(self.result()) 8338 self.loop.generate_execution_code(code) 8339 8340 def annotate(self, code): 8341 self.loop.annotate(code) 8342 8343 8344class ComprehensionAppendNode(Node): 8345 # Need to be careful to avoid infinite recursion: 8346 # target must not be in child_attrs/subexprs 8347 8348 child_attrs = ['expr'] 8349 target = None 8350 8351 type = PyrexTypes.c_int_type 8352 8353 def analyse_expressions(self, env): 8354 self.expr = self.expr.analyse_expressions(env) 8355 if not self.expr.type.is_pyobject: 8356 self.expr = self.expr.coerce_to_pyobject(env) 8357 return self 8358 8359 def generate_execution_code(self, code): 8360 if self.target.type is list_type: 8361 code.globalstate.use_utility_code( 8362 UtilityCode.load_cached("ListCompAppend", "Optimize.c")) 8363 function = "__Pyx_ListComp_Append" 8364 elif self.target.type is set_type: 8365 function = "PySet_Add" 8366 else: 8367 raise InternalError( 8368 "Invalid type for comprehension node: %s" % self.target.type) 8369 8370 self.expr.generate_evaluation_code(code) 8371 code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % ( 8372 function, 8373 self.target.result(), 8374 self.expr.result() 8375 ), self.pos)) 8376 self.expr.generate_disposal_code(code) 8377 self.expr.free_temps(code) 8378 8379 def generate_function_definitions(self, env, code): 8380 self.expr.generate_function_definitions(env, code) 8381 8382 def annotate(self, code): 8383 self.expr.annotate(code) 8384 8385class DictComprehensionAppendNode(ComprehensionAppendNode): 8386 child_attrs = ['key_expr', 'value_expr'] 8387 8388 def analyse_expressions(self, env): 8389 self.key_expr = self.key_expr.analyse_expressions(env) 8390 if not self.key_expr.type.is_pyobject: 8391 self.key_expr = self.key_expr.coerce_to_pyobject(env) 8392 self.value_expr = self.value_expr.analyse_expressions(env) 8393 if not self.value_expr.type.is_pyobject: 8394 self.value_expr = self.value_expr.coerce_to_pyobject(env) 8395 return self 8396 8397 def generate_execution_code(self, code): 8398 self.key_expr.generate_evaluation_code(code) 8399 self.value_expr.generate_evaluation_code(code) 8400 code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % ( 8401 self.target.result(), 8402 self.key_expr.result(), 8403 self.value_expr.result() 8404 ), self.pos)) 8405 self.key_expr.generate_disposal_code(code) 8406 self.key_expr.free_temps(code) 8407 self.value_expr.generate_disposal_code(code) 8408 self.value_expr.free_temps(code) 8409 8410 def generate_function_definitions(self, env, code): 8411 self.key_expr.generate_function_definitions(env, code) 8412 self.value_expr.generate_function_definitions(env, code) 8413 8414 def annotate(self, code): 8415 self.key_expr.annotate(code) 8416 self.value_expr.annotate(code) 8417 8418 8419class InlinedGeneratorExpressionNode(ExprNode): 8420 # An inlined generator expression for which the result is calculated 8421 # inside of the loop and returned as a single, first and only Generator 8422 # return value. 8423 # This will only be created by transforms when replacing safe builtin 8424 # calls on generator expressions. 8425 # 8426 # gen GeneratorExpressionNode the generator, not containing any YieldExprNodes 8427 # orig_func String the name of the builtin function this node replaces 8428 # target ExprNode or None a 'target' for a ComprehensionAppend node 8429 8430 subexprs = ["gen"] 8431 orig_func = None 8432 target = None 8433 is_temp = True 8434 type = py_object_type 8435 8436 def __init__(self, pos, gen, comprehension_type=None, **kwargs): 8437 gbody = gen.def_node.gbody 8438 gbody.is_inlined = True 8439 if comprehension_type is not None: 8440 assert comprehension_type in (list_type, set_type, dict_type), comprehension_type 8441 gbody.inlined_comprehension_type = comprehension_type 8442 kwargs.update( 8443 target=RawCNameExprNode(pos, comprehension_type, Naming.retval_cname), 8444 type=comprehension_type, 8445 ) 8446 super(InlinedGeneratorExpressionNode, self).__init__(pos, gen=gen, **kwargs) 8447 8448 def may_be_none(self): 8449 return self.orig_func not in ('any', 'all', 'sorted') 8450 8451 def infer_type(self, env): 8452 return self.type 8453 8454 def analyse_types(self, env): 8455 self.gen = self.gen.analyse_expressions(env) 8456 return self 8457 8458 def generate_result_code(self, code): 8459 code.putln("%s = __Pyx_Generator_Next(%s); %s" % ( 8460 self.result(), self.gen.result(), 8461 code.error_goto_if_null(self.result(), self.pos))) 8462 code.put_gotref(self.result()) 8463 8464 8465class MergedSequenceNode(ExprNode): 8466 """ 8467 Merge a sequence of iterables into a set/list/tuple. 8468 8469 The target collection is determined by self.type, which must be set externally. 8470 8471 args [ExprNode] 8472 """ 8473 subexprs = ['args'] 8474 is_temp = True 8475 gil_message = "Constructing Python collection" 8476 8477 def __init__(self, pos, args, type): 8478 if type in (list_type, tuple_type) and args and args[0].is_sequence_constructor: 8479 # construct a list directly from the first argument that we can then extend 8480 if args[0].type is not list_type: 8481 args[0] = ListNode(args[0].pos, args=args[0].args, is_temp=True) 8482 ExprNode.__init__(self, pos, args=args, type=type) 8483 8484 def calculate_constant_result(self): 8485 result = [] 8486 for item in self.args: 8487 if item.is_sequence_constructor and item.mult_factor: 8488 if item.mult_factor.constant_result <= 0: 8489 continue 8490 # otherwise, adding each item once should be enough 8491 if item.is_set_literal or item.is_sequence_constructor: 8492 # process items in order 8493 items = (arg.constant_result for arg in item.args) 8494 else: 8495 items = item.constant_result 8496 result.extend(items) 8497 if self.type is set_type: 8498 result = set(result) 8499 elif self.type is tuple_type: 8500 result = tuple(result) 8501 else: 8502 assert self.type is list_type 8503 self.constant_result = result 8504 8505 def compile_time_value(self, denv): 8506 result = [] 8507 for item in self.args: 8508 if item.is_sequence_constructor and item.mult_factor: 8509 if item.mult_factor.compile_time_value(denv) <= 0: 8510 continue 8511 if item.is_set_literal or item.is_sequence_constructor: 8512 # process items in order 8513 items = (arg.compile_time_value(denv) for arg in item.args) 8514 else: 8515 items = item.compile_time_value(denv) 8516 result.extend(items) 8517 if self.type is set_type: 8518 try: 8519 result = set(result) 8520 except Exception as e: 8521 self.compile_time_value_error(e) 8522 elif self.type is tuple_type: 8523 result = tuple(result) 8524 else: 8525 assert self.type is list_type 8526 return result 8527 8528 def type_dependencies(self, env): 8529 return () 8530 8531 def infer_type(self, env): 8532 return self.type 8533 8534 def analyse_types(self, env): 8535 args = [ 8536 arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node( 8537 # FIXME: CPython's error message starts with the runtime function name 8538 'argument after * must be an iterable, not NoneType') 8539 for arg in self.args 8540 ] 8541 8542 if len(args) == 1 and args[0].type is self.type: 8543 # strip this intermediate node and use the bare collection 8544 return args[0] 8545 8546 assert self.type in (set_type, list_type, tuple_type) 8547 8548 self.args = args 8549 return self 8550 8551 def may_be_none(self): 8552 return False 8553 8554 def generate_evaluation_code(self, code): 8555 code.mark_pos(self.pos) 8556 self.allocate_temp_result(code) 8557 8558 is_set = self.type is set_type 8559 8560 args = iter(self.args) 8561 item = next(args) 8562 item.generate_evaluation_code(code) 8563 if (is_set and item.is_set_literal or 8564 not is_set and item.is_sequence_constructor and item.type is list_type): 8565 code.putln("%s = %s;" % (self.result(), item.py_result())) 8566 item.generate_post_assignment_code(code) 8567 else: 8568 code.putln("%s = %s(%s); %s" % ( 8569 self.result(), 8570 'PySet_New' if is_set else 'PySequence_List', 8571 item.py_result(), 8572 code.error_goto_if_null(self.result(), self.pos))) 8573 code.put_gotref(self.py_result()) 8574 item.generate_disposal_code(code) 8575 item.free_temps(code) 8576 8577 helpers = set() 8578 if is_set: 8579 add_func = "PySet_Add" 8580 extend_func = "__Pyx_PySet_Update" 8581 else: 8582 add_func = "__Pyx_ListComp_Append" 8583 extend_func = "__Pyx_PyList_Extend" 8584 8585 for item in args: 8586 if (is_set and (item.is_set_literal or item.is_sequence_constructor) or 8587 (item.is_sequence_constructor and not item.mult_factor)): 8588 if not is_set and item.args: 8589 helpers.add(("ListCompAppend", "Optimize.c")) 8590 for arg in item.args: 8591 arg.generate_evaluation_code(code) 8592 code.put_error_if_neg(arg.pos, "%s(%s, %s)" % ( 8593 add_func, 8594 self.result(), 8595 arg.py_result())) 8596 arg.generate_disposal_code(code) 8597 arg.free_temps(code) 8598 continue 8599 8600 if is_set: 8601 helpers.add(("PySet_Update", "Builtins.c")) 8602 else: 8603 helpers.add(("ListExtend", "Optimize.c")) 8604 8605 item.generate_evaluation_code(code) 8606 code.put_error_if_neg(item.pos, "%s(%s, %s)" % ( 8607 extend_func, 8608 self.result(), 8609 item.py_result())) 8610 item.generate_disposal_code(code) 8611 item.free_temps(code) 8612 8613 if self.type is tuple_type: 8614 code.putln("{") 8615 code.putln("PyObject *%s = PyList_AsTuple(%s);" % ( 8616 Naming.quick_temp_cname, 8617 self.result())) 8618 code.put_decref(self.result(), py_object_type) 8619 code.putln("%s = %s; %s" % ( 8620 self.result(), 8621 Naming.quick_temp_cname, 8622 code.error_goto_if_null(self.result(), self.pos))) 8623 code.put_gotref(self.result()) 8624 code.putln("}") 8625 8626 for helper in sorted(helpers): 8627 code.globalstate.use_utility_code(UtilityCode.load_cached(*helper)) 8628 8629 def annotate(self, code): 8630 for item in self.args: 8631 item.annotate(code) 8632 8633 8634class SetNode(ExprNode): 8635 """ 8636 Set constructor. 8637 """ 8638 subexprs = ['args'] 8639 type = set_type 8640 is_set_literal = True 8641 gil_message = "Constructing Python set" 8642 8643 def analyse_types(self, env): 8644 for i in range(len(self.args)): 8645 arg = self.args[i] 8646 arg = arg.analyse_types(env) 8647 self.args[i] = arg.coerce_to_pyobject(env) 8648 self.type = set_type 8649 self.is_temp = 1 8650 return self 8651 8652 def may_be_none(self): 8653 return False 8654 8655 def calculate_constant_result(self): 8656 self.constant_result = set([arg.constant_result for arg in self.args]) 8657 8658 def compile_time_value(self, denv): 8659 values = [arg.compile_time_value(denv) for arg in self.args] 8660 try: 8661 return set(values) 8662 except Exception as e: 8663 self.compile_time_value_error(e) 8664 8665 def generate_evaluation_code(self, code): 8666 for arg in self.args: 8667 arg.generate_evaluation_code(code) 8668 self.allocate_temp_result(code) 8669 code.putln( 8670 "%s = PySet_New(0); %s" % ( 8671 self.result(), 8672 code.error_goto_if_null(self.result(), self.pos))) 8673 code.put_gotref(self.py_result()) 8674 for arg in self.args: 8675 code.put_error_if_neg( 8676 self.pos, 8677 "PySet_Add(%s, %s)" % (self.result(), arg.py_result())) 8678 arg.generate_disposal_code(code) 8679 arg.free_temps(code) 8680 8681 8682class DictNode(ExprNode): 8683 # Dictionary constructor. 8684 # 8685 # key_value_pairs [DictItemNode] 8686 # exclude_null_values [boolean] Do not add NULL values to dict 8687 # 8688 # obj_conversion_errors [PyrexError] used internally 8689 8690 subexprs = ['key_value_pairs'] 8691 is_temp = 1 8692 exclude_null_values = False 8693 type = dict_type 8694 is_dict_literal = True 8695 reject_duplicates = False 8696 8697 obj_conversion_errors = [] 8698 8699 @classmethod 8700 def from_pairs(cls, pos, pairs): 8701 return cls(pos, key_value_pairs=[ 8702 DictItemNode(pos, key=k, value=v) for k, v in pairs]) 8703 8704 def calculate_constant_result(self): 8705 self.constant_result = dict([ 8706 item.constant_result for item in self.key_value_pairs]) 8707 8708 def compile_time_value(self, denv): 8709 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv)) 8710 for item in self.key_value_pairs] 8711 try: 8712 return dict(pairs) 8713 except Exception as e: 8714 self.compile_time_value_error(e) 8715 8716 def type_dependencies(self, env): 8717 return () 8718 8719 def infer_type(self, env): 8720 # TODO: Infer struct constructors. 8721 return dict_type 8722 8723 def analyse_types(self, env): 8724 with local_errors(ignore=True) as errors: 8725 self.key_value_pairs = [ 8726 item.analyse_types(env) 8727 for item in self.key_value_pairs 8728 ] 8729 self.obj_conversion_errors = errors 8730 return self 8731 8732 def may_be_none(self): 8733 return False 8734 8735 def coerce_to(self, dst_type, env): 8736 if dst_type.is_pyobject: 8737 self.release_errors() 8738 if self.type.is_struct_or_union: 8739 if not dict_type.subtype_of(dst_type): 8740 error(self.pos, "Cannot interpret struct as non-dict type '%s'" % dst_type) 8741 return DictNode(self.pos, key_value_pairs=[ 8742 DictItemNode(item.pos, key=item.key.coerce_to_pyobject(env), 8743 value=item.value.coerce_to_pyobject(env)) 8744 for item in self.key_value_pairs]) 8745 if not self.type.subtype_of(dst_type): 8746 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 8747 elif dst_type.is_struct_or_union: 8748 self.type = dst_type 8749 if not dst_type.is_struct and len(self.key_value_pairs) != 1: 8750 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type) 8751 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries): 8752 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1) 8753 for item in self.key_value_pairs: 8754 if isinstance(item.key, CoerceToPyTypeNode): 8755 item.key = item.key.arg 8756 if not item.key.is_string_literal: 8757 error(item.key.pos, "Invalid struct field identifier") 8758 item.key = StringNode(item.key.pos, value="<error>") 8759 else: 8760 key = str(item.key.value) # converts string literals to unicode in Py3 8761 member = dst_type.scope.lookup_here(key) 8762 if not member: 8763 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, key)) 8764 else: 8765 value = item.value 8766 if isinstance(value, CoerceToPyTypeNode): 8767 value = value.arg 8768 item.value = value.coerce_to(member.type, env) 8769 else: 8770 self.type = error_type 8771 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 8772 return self 8773 8774 def release_errors(self): 8775 for err in self.obj_conversion_errors: 8776 report_error(err) 8777 self.obj_conversion_errors = [] 8778 8779 gil_message = "Constructing Python dict" 8780 8781 def generate_evaluation_code(self, code): 8782 # Custom method used here because key-value 8783 # pairs are evaluated and used one at a time. 8784 code.mark_pos(self.pos) 8785 self.allocate_temp_result(code) 8786 8787 is_dict = self.type.is_pyobject 8788 if is_dict: 8789 self.release_errors() 8790 code.putln( 8791 "%s = __Pyx_PyDict_NewPresized(%d); %s" % ( 8792 self.result(), 8793 len(self.key_value_pairs), 8794 code.error_goto_if_null(self.result(), self.pos))) 8795 code.put_gotref(self.py_result()) 8796 8797 keys_seen = set() 8798 key_type = None 8799 needs_error_helper = False 8800 8801 for item in self.key_value_pairs: 8802 item.generate_evaluation_code(code) 8803 if is_dict: 8804 if self.exclude_null_values: 8805 code.putln('if (%s) {' % item.value.py_result()) 8806 key = item.key 8807 if self.reject_duplicates: 8808 if keys_seen is not None: 8809 # avoid runtime 'in' checks for literals that we can do at compile time 8810 if not key.is_string_literal: 8811 keys_seen = None 8812 elif key.value in keys_seen: 8813 # FIXME: this could be a compile time error, at least in Cython code 8814 keys_seen = None 8815 elif key_type is not type(key.value): 8816 if key_type is None: 8817 key_type = type(key.value) 8818 keys_seen.add(key.value) 8819 else: 8820 # different types => may not be able to compare at compile time 8821 keys_seen = None 8822 else: 8823 keys_seen.add(key.value) 8824 8825 if keys_seen is None: 8826 code.putln('if (unlikely(PyDict_Contains(%s, %s))) {' % ( 8827 self.result(), key.py_result())) 8828 # currently only used in function calls 8829 needs_error_helper = True 8830 code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( 8831 key.py_result(), 8832 code.error_goto(item.pos))) 8833 code.putln("} else {") 8834 8835 code.put_error_if_neg(self.pos, "PyDict_SetItem(%s, %s, %s)" % ( 8836 self.result(), 8837 item.key.py_result(), 8838 item.value.py_result())) 8839 if self.reject_duplicates and keys_seen is None: 8840 code.putln('}') 8841 if self.exclude_null_values: 8842 code.putln('}') 8843 else: 8844 code.putln("%s.%s = %s;" % ( 8845 self.result(), 8846 item.key.value, 8847 item.value.result())) 8848 item.generate_disposal_code(code) 8849 item.free_temps(code) 8850 8851 if needs_error_helper: 8852 code.globalstate.use_utility_code( 8853 UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c")) 8854 8855 def annotate(self, code): 8856 for item in self.key_value_pairs: 8857 item.annotate(code) 8858 8859 8860class DictItemNode(ExprNode): 8861 # Represents a single item in a DictNode 8862 # 8863 # key ExprNode 8864 # value ExprNode 8865 subexprs = ['key', 'value'] 8866 8867 nogil_check = None # Parent DictNode takes care of it 8868 8869 def calculate_constant_result(self): 8870 self.constant_result = ( 8871 self.key.constant_result, self.value.constant_result) 8872 8873 def analyse_types(self, env): 8874 self.key = self.key.analyse_types(env) 8875 self.value = self.value.analyse_types(env) 8876 self.key = self.key.coerce_to_pyobject(env) 8877 self.value = self.value.coerce_to_pyobject(env) 8878 return self 8879 8880 def generate_evaluation_code(self, code): 8881 self.key.generate_evaluation_code(code) 8882 self.value.generate_evaluation_code(code) 8883 8884 def generate_disposal_code(self, code): 8885 self.key.generate_disposal_code(code) 8886 self.value.generate_disposal_code(code) 8887 8888 def free_temps(self, code): 8889 self.key.free_temps(code) 8890 self.value.free_temps(code) 8891 8892 def __iter__(self): 8893 return iter([self.key, self.value]) 8894 8895 8896class SortedDictKeysNode(ExprNode): 8897 # build sorted list of dict keys, e.g. for dir() 8898 subexprs = ['arg'] 8899 8900 is_temp = True 8901 8902 def __init__(self, arg): 8903 ExprNode.__init__(self, arg.pos, arg=arg) 8904 self.type = Builtin.list_type 8905 8906 def analyse_types(self, env): 8907 arg = self.arg.analyse_types(env) 8908 if arg.type is Builtin.dict_type: 8909 arg = arg.as_none_safe_node( 8910 "'NoneType' object is not iterable") 8911 self.arg = arg 8912 return self 8913 8914 def may_be_none(self): 8915 return False 8916 8917 def generate_result_code(self, code): 8918 dict_result = self.arg.py_result() 8919 if self.arg.type is Builtin.dict_type: 8920 code.putln('%s = PyDict_Keys(%s); %s' % ( 8921 self.result(), dict_result, 8922 code.error_goto_if_null(self.result(), self.pos))) 8923 code.put_gotref(self.py_result()) 8924 else: 8925 # originally used PyMapping_Keys() here, but that may return a tuple 8926 code.globalstate.use_utility_code(UtilityCode.load_cached( 8927 'PyObjectCallMethod0', 'ObjectHandling.c')) 8928 keys_cname = code.intern_identifier(StringEncoding.EncodedString("keys")) 8929 code.putln('%s = __Pyx_PyObject_CallMethod0(%s, %s); %s' % ( 8930 self.result(), dict_result, keys_cname, 8931 code.error_goto_if_null(self.result(), self.pos))) 8932 code.put_gotref(self.py_result()) 8933 code.putln("if (unlikely(!PyList_Check(%s))) {" % self.result()) 8934 code.put_decref_set(self.result(), "PySequence_List(%s)" % self.result()) 8935 code.putln(code.error_goto_if_null(self.result(), self.pos)) 8936 code.put_gotref(self.py_result()) 8937 code.putln("}") 8938 code.put_error_if_neg( 8939 self.pos, 'PyList_Sort(%s)' % self.py_result()) 8940 8941 8942class ModuleNameMixin(object): 8943 def get_py_mod_name(self, code): 8944 return code.get_py_string_const( 8945 self.module_name, identifier=True) 8946 8947 def get_py_qualified_name(self, code): 8948 return code.get_py_string_const( 8949 self.qualname, identifier=True) 8950 8951 8952class ClassNode(ExprNode, ModuleNameMixin): 8953 # Helper class used in the implementation of Python 8954 # class definitions. Constructs a class object given 8955 # a name, tuple of bases and class dictionary. 8956 # 8957 # name EncodedString Name of the class 8958 # class_def_node PyClassDefNode PyClassDefNode defining this class 8959 # doc ExprNode or None Doc string 8960 # module_name EncodedString Name of defining module 8961 8962 subexprs = ['doc'] 8963 type = py_object_type 8964 is_temp = True 8965 8966 def infer_type(self, env): 8967 # TODO: could return 'type' in some cases 8968 return py_object_type 8969 8970 def analyse_types(self, env): 8971 if self.doc: 8972 self.doc = self.doc.analyse_types(env) 8973 self.doc = self.doc.coerce_to_pyobject(env) 8974 env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandling.c")) 8975 return self 8976 8977 def may_be_none(self): 8978 return True 8979 8980 gil_message = "Constructing Python class" 8981 8982 def generate_result_code(self, code): 8983 class_def_node = self.class_def_node 8984 cname = code.intern_identifier(self.name) 8985 8986 if self.doc: 8987 code.put_error_if_neg(self.pos, 8988 'PyDict_SetItem(%s, %s, %s)' % ( 8989 class_def_node.dict.py_result(), 8990 code.intern_identifier( 8991 StringEncoding.EncodedString("__doc__")), 8992 self.doc.py_result())) 8993 py_mod_name = self.get_py_mod_name(code) 8994 qualname = self.get_py_qualified_name(code) 8995 code.putln( 8996 '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % ( 8997 self.result(), 8998 class_def_node.bases.py_result(), 8999 class_def_node.dict.py_result(), 9000 cname, 9001 qualname, 9002 py_mod_name, 9003 code.error_goto_if_null(self.result(), self.pos))) 9004 code.put_gotref(self.py_result()) 9005 9006 9007class Py3ClassNode(ExprNode): 9008 # Helper class used in the implementation of Python3+ 9009 # class definitions. Constructs a class object given 9010 # a name, tuple of bases and class dictionary. 9011 # 9012 # name EncodedString Name of the class 9013 # module_name EncodedString Name of defining module 9014 # class_def_node PyClassDefNode PyClassDefNode defining this class 9015 # calculate_metaclass bool should call CalculateMetaclass() 9016 # allow_py2_metaclass bool should look for Py2 metaclass 9017 9018 subexprs = [] 9019 type = py_object_type 9020 is_temp = True 9021 9022 def infer_type(self, env): 9023 # TODO: could return 'type' in some cases 9024 return py_object_type 9025 9026 def analyse_types(self, env): 9027 return self 9028 9029 def may_be_none(self): 9030 return True 9031 9032 gil_message = "Constructing Python class" 9033 9034 def generate_result_code(self, code): 9035 code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreate", "ObjectHandling.c")) 9036 cname = code.intern_identifier(self.name) 9037 class_def_node = self.class_def_node 9038 mkw = class_def_node.mkw.py_result() if class_def_node.mkw else 'NULL' 9039 if class_def_node.metaclass: 9040 metaclass = class_def_node.metaclass.py_result() 9041 else: 9042 metaclass = "((PyObject*)&__Pyx_DefaultClassType)" 9043 code.putln( 9044 '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % ( 9045 self.result(), 9046 metaclass, 9047 cname, 9048 class_def_node.bases.py_result(), 9049 class_def_node.dict.py_result(), 9050 mkw, 9051 self.calculate_metaclass, 9052 self.allow_py2_metaclass, 9053 code.error_goto_if_null(self.result(), self.pos))) 9054 code.put_gotref(self.py_result()) 9055 9056 9057class PyClassMetaclassNode(ExprNode): 9058 # Helper class holds Python3 metaclass object 9059 # 9060 # class_def_node PyClassDefNode PyClassDefNode defining this class 9061 9062 subexprs = [] 9063 9064 def analyse_types(self, env): 9065 self.type = py_object_type 9066 self.is_temp = True 9067 return self 9068 9069 def may_be_none(self): 9070 return True 9071 9072 def generate_result_code(self, code): 9073 bases = self.class_def_node.bases 9074 mkw = self.class_def_node.mkw 9075 if mkw: 9076 code.globalstate.use_utility_code( 9077 UtilityCode.load_cached("Py3MetaclassGet", "ObjectHandling.c")) 9078 call = "__Pyx_Py3MetaclassGet(%s, %s)" % ( 9079 bases.result(), 9080 mkw.result()) 9081 else: 9082 code.globalstate.use_utility_code( 9083 UtilityCode.load_cached("CalculateMetaclass", "ObjectHandling.c")) 9084 call = "__Pyx_CalculateMetaclass(NULL, %s)" % ( 9085 bases.result()) 9086 code.putln( 9087 "%s = %s; %s" % ( 9088 self.result(), call, 9089 code.error_goto_if_null(self.result(), self.pos))) 9090 code.put_gotref(self.py_result()) 9091 9092 9093class PyClassNamespaceNode(ExprNode, ModuleNameMixin): 9094 # Helper class holds Python3 namespace object 9095 # 9096 # All this are not owned by this node 9097 # class_def_node PyClassDefNode PyClassDefNode defining this class 9098 # doc ExprNode or None Doc string (owned) 9099 9100 subexprs = ['doc'] 9101 9102 def analyse_types(self, env): 9103 if self.doc: 9104 self.doc = self.doc.analyse_types(env).coerce_to_pyobject(env) 9105 self.type = py_object_type 9106 self.is_temp = 1 9107 return self 9108 9109 def may_be_none(self): 9110 return True 9111 9112 def generate_result_code(self, code): 9113 cname = code.intern_identifier(self.name) 9114 py_mod_name = self.get_py_mod_name(code) 9115 qualname = self.get_py_qualified_name(code) 9116 class_def_node = self.class_def_node 9117 null = "(PyObject *) NULL" 9118 doc_code = self.doc.result() if self.doc else null 9119 mkw = class_def_node.mkw.py_result() if class_def_node.mkw else null 9120 metaclass = class_def_node.metaclass.py_result() if class_def_node.metaclass else null 9121 code.putln( 9122 "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % ( 9123 self.result(), 9124 metaclass, 9125 class_def_node.bases.result(), 9126 cname, 9127 qualname, 9128 mkw, 9129 py_mod_name, 9130 doc_code, 9131 code.error_goto_if_null(self.result(), self.pos))) 9132 code.put_gotref(self.py_result()) 9133 9134 9135class ClassCellInjectorNode(ExprNode): 9136 # Initialize CyFunction.func_classobj 9137 is_temp = True 9138 type = py_object_type 9139 subexprs = [] 9140 is_active = False 9141 9142 def analyse_expressions(self, env): 9143 return self 9144 9145 def generate_result_code(self, code): 9146 assert self.is_active 9147 code.putln( 9148 '%s = PyList_New(0); %s' % ( 9149 self.result(), 9150 code.error_goto_if_null(self.result(), self.pos))) 9151 code.put_gotref(self.result()) 9152 9153 def generate_injection_code(self, code, classobj_cname): 9154 assert self.is_active 9155 code.globalstate.use_utility_code( 9156 UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c")) 9157 code.put_error_if_neg(self.pos, '__Pyx_CyFunction_InitClassCell(%s, %s)' % ( 9158 self.result(), classobj_cname)) 9159 9160 9161class ClassCellNode(ExprNode): 9162 # Class Cell for noargs super() 9163 subexprs = [] 9164 is_temp = True 9165 is_generator = False 9166 type = py_object_type 9167 9168 def analyse_types(self, env): 9169 return self 9170 9171 def generate_result_code(self, code): 9172 if not self.is_generator: 9173 code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % ( 9174 self.result(), 9175 Naming.self_cname)) 9176 else: 9177 code.putln('%s = %s->classobj;' % ( 9178 self.result(), Naming.generator_cname)) 9179 code.putln( 9180 'if (!%s) { PyErr_SetString(PyExc_SystemError, ' 9181 '"super(): empty __class__ cell"); %s }' % ( 9182 self.result(), 9183 code.error_goto(self.pos))) 9184 code.put_incref(self.result(), py_object_type) 9185 9186 9187class PyCFunctionNode(ExprNode, ModuleNameMixin): 9188 # Helper class used in the implementation of Python 9189 # functions. Constructs a PyCFunction object 9190 # from a PyMethodDef struct. 9191 # 9192 # pymethdef_cname string PyMethodDef structure 9193 # self_object ExprNode or None 9194 # binding bool 9195 # def_node DefNode the Python function node 9196 # module_name EncodedString Name of defining module 9197 # code_object CodeObjectNode the PyCodeObject creator node 9198 9199 subexprs = ['code_object', 'defaults_tuple', 'defaults_kwdict', 9200 'annotations_dict'] 9201 9202 self_object = None 9203 code_object = None 9204 binding = False 9205 def_node = None 9206 defaults = None 9207 defaults_struct = None 9208 defaults_pyobjects = 0 9209 defaults_tuple = None 9210 defaults_kwdict = None 9211 annotations_dict = None 9212 9213 type = py_object_type 9214 is_temp = 1 9215 9216 specialized_cpdefs = None 9217 is_specialization = False 9218 9219 @classmethod 9220 def from_defnode(cls, node, binding): 9221 return cls(node.pos, 9222 def_node=node, 9223 pymethdef_cname=node.entry.pymethdef_cname, 9224 binding=binding or node.specialized_cpdefs, 9225 specialized_cpdefs=node.specialized_cpdefs, 9226 code_object=CodeObjectNode(node)) 9227 9228 def analyse_types(self, env): 9229 if self.binding: 9230 self.analyse_default_args(env) 9231 return self 9232 9233 def analyse_default_args(self, env): 9234 """ 9235 Handle non-literal function's default arguments. 9236 """ 9237 nonliteral_objects = [] 9238 nonliteral_other = [] 9239 default_args = [] 9240 default_kwargs = [] 9241 annotations = [] 9242 9243 # For global cpdef functions and def/cpdef methods in cdef classes, we must use global constants 9244 # for default arguments to avoid the dependency on the CyFunction object as 'self' argument 9245 # in the underlying C function. Basically, cpdef functions/methods are static C functions, 9246 # so their optional arguments must be static, too. 9247 # TODO: change CyFunction implementation to pass both function object and owning object for method calls 9248 must_use_constants = env.is_c_class_scope or (self.def_node.is_wrapper and env.is_module_scope) 9249 9250 for arg in self.def_node.args: 9251 if arg.default and not must_use_constants: 9252 if not arg.default.is_literal: 9253 arg.is_dynamic = True 9254 if arg.type.is_pyobject: 9255 nonliteral_objects.append(arg) 9256 else: 9257 nonliteral_other.append(arg) 9258 else: 9259 arg.default = DefaultLiteralArgNode(arg.pos, arg.default) 9260 if arg.kw_only: 9261 default_kwargs.append(arg) 9262 else: 9263 default_args.append(arg) 9264 if arg.annotation: 9265 arg.annotation = self.analyse_annotation(env, arg.annotation) 9266 annotations.append((arg.pos, arg.name, arg.annotation)) 9267 9268 for arg in (self.def_node.star_arg, self.def_node.starstar_arg): 9269 if arg and arg.annotation: 9270 arg.annotation = self.analyse_annotation(env, arg.annotation) 9271 annotations.append((arg.pos, arg.name, arg.annotation)) 9272 9273 annotation = self.def_node.return_type_annotation 9274 if annotation: 9275 annotation = self.analyse_annotation(env, annotation) 9276 self.def_node.return_type_annotation = annotation 9277 annotations.append((annotation.pos, StringEncoding.EncodedString("return"), annotation)) 9278 9279 if nonliteral_objects or nonliteral_other: 9280 module_scope = env.global_scope() 9281 cname = module_scope.next_id(Naming.defaults_struct_prefix) 9282 scope = Symtab.StructOrUnionScope(cname) 9283 self.defaults = [] 9284 for arg in nonliteral_objects: 9285 entry = scope.declare_var(arg.name, arg.type, None, 9286 Naming.arg_prefix + arg.name, 9287 allow_pyobject=True) 9288 self.defaults.append((arg, entry)) 9289 for arg in nonliteral_other: 9290 entry = scope.declare_var(arg.name, arg.type, None, 9291 Naming.arg_prefix + arg.name, 9292 allow_pyobject=False, allow_memoryview=True) 9293 self.defaults.append((arg, entry)) 9294 entry = module_scope.declare_struct_or_union( 9295 None, 'struct', scope, 1, None, cname=cname) 9296 self.defaults_struct = scope 9297 self.defaults_pyobjects = len(nonliteral_objects) 9298 for arg, entry in self.defaults: 9299 arg.default_value = '%s->%s' % ( 9300 Naming.dynamic_args_cname, entry.cname) 9301 self.def_node.defaults_struct = self.defaults_struct.name 9302 9303 if default_args or default_kwargs: 9304 if self.defaults_struct is None: 9305 if default_args: 9306 defaults_tuple = TupleNode(self.pos, args=[ 9307 arg.default for arg in default_args]) 9308 self.defaults_tuple = defaults_tuple.analyse_types(env).coerce_to_pyobject(env) 9309 if default_kwargs: 9310 defaults_kwdict = DictNode(self.pos, key_value_pairs=[ 9311 DictItemNode( 9312 arg.pos, 9313 key=IdentifierStringNode(arg.pos, value=arg.name), 9314 value=arg.default) 9315 for arg in default_kwargs]) 9316 self.defaults_kwdict = defaults_kwdict.analyse_types(env) 9317 else: 9318 if default_args: 9319 defaults_tuple = DefaultsTupleNode( 9320 self.pos, default_args, self.defaults_struct) 9321 else: 9322 defaults_tuple = NoneNode(self.pos) 9323 if default_kwargs: 9324 defaults_kwdict = DefaultsKwDictNode( 9325 self.pos, default_kwargs, self.defaults_struct) 9326 else: 9327 defaults_kwdict = NoneNode(self.pos) 9328 9329 defaults_getter = Nodes.DefNode( 9330 self.pos, args=[], star_arg=None, starstar_arg=None, 9331 body=Nodes.ReturnStatNode( 9332 self.pos, return_type=py_object_type, 9333 value=TupleNode( 9334 self.pos, args=[defaults_tuple, defaults_kwdict])), 9335 decorators=None, 9336 name=StringEncoding.EncodedString("__defaults__")) 9337 # defaults getter must never live in class scopes, it's always a module function 9338 module_scope = env.global_scope() 9339 defaults_getter.analyse_declarations(module_scope) 9340 defaults_getter = defaults_getter.analyse_expressions(module_scope) 9341 defaults_getter.body = defaults_getter.body.analyse_expressions( 9342 defaults_getter.local_scope) 9343 defaults_getter.py_wrapper_required = False 9344 defaults_getter.pymethdef_required = False 9345 self.def_node.defaults_getter = defaults_getter 9346 if annotations: 9347 annotations_dict = DictNode(self.pos, key_value_pairs=[ 9348 DictItemNode( 9349 pos, key=IdentifierStringNode(pos, value=name), 9350 value=value) 9351 for pos, name, value in annotations]) 9352 self.annotations_dict = annotations_dict.analyse_types(env) 9353 9354 def analyse_annotation(self, env, annotation): 9355 if annotation is None: 9356 return None 9357 atype = annotation.analyse_as_type(env) 9358 if atype is not None: 9359 # Keep parsed types as strings as they might not be Python representable. 9360 annotation = UnicodeNode( 9361 annotation.pos, 9362 value=StringEncoding.EncodedString(atype.declaration_code('', for_display=True))) 9363 annotation = annotation.analyse_types(env) 9364 if not annotation.type.is_pyobject: 9365 annotation = annotation.coerce_to_pyobject(env) 9366 return annotation 9367 9368 def may_be_none(self): 9369 return False 9370 9371 gil_message = "Constructing Python function" 9372 9373 def self_result_code(self): 9374 if self.self_object is None: 9375 self_result = "NULL" 9376 else: 9377 self_result = self.self_object.py_result() 9378 return self_result 9379 9380 def generate_result_code(self, code): 9381 if self.binding: 9382 self.generate_cyfunction_code(code) 9383 else: 9384 self.generate_pycfunction_code(code) 9385 9386 def generate_pycfunction_code(self, code): 9387 py_mod_name = self.get_py_mod_name(code) 9388 code.putln( 9389 '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % ( 9390 self.result(), 9391 self.pymethdef_cname, 9392 self.self_result_code(), 9393 py_mod_name, 9394 code.error_goto_if_null(self.result(), self.pos))) 9395 9396 code.put_gotref(self.py_result()) 9397 9398 def generate_cyfunction_code(self, code): 9399 if self.specialized_cpdefs: 9400 def_node = self.specialized_cpdefs[0] 9401 else: 9402 def_node = self.def_node 9403 9404 if self.specialized_cpdefs or self.is_specialization: 9405 code.globalstate.use_utility_code( 9406 UtilityCode.load_cached("FusedFunction", "CythonFunction.c")) 9407 constructor = "__pyx_FusedFunction_New" 9408 else: 9409 code.globalstate.use_utility_code( 9410 UtilityCode.load_cached("CythonFunction", "CythonFunction.c")) 9411 constructor = "__Pyx_CyFunction_New" 9412 9413 if self.code_object: 9414 code_object_result = self.code_object.py_result() 9415 else: 9416 code_object_result = 'NULL' 9417 9418 flags = [] 9419 if def_node.is_staticmethod: 9420 flags.append('__Pyx_CYFUNCTION_STATICMETHOD') 9421 elif def_node.is_classmethod: 9422 flags.append('__Pyx_CYFUNCTION_CLASSMETHOD') 9423 9424 if def_node.local_scope.parent_scope.is_c_class_scope and not def_node.entry.is_anonymous: 9425 flags.append('__Pyx_CYFUNCTION_CCLASS') 9426 9427 if flags: 9428 flags = ' | '.join(flags) 9429 else: 9430 flags = '0' 9431 9432 code.putln( 9433 '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % ( 9434 self.result(), 9435 constructor, 9436 self.pymethdef_cname, 9437 flags, 9438 self.get_py_qualified_name(code), 9439 self.self_result_code(), 9440 self.get_py_mod_name(code), 9441 Naming.moddict_cname, 9442 code_object_result, 9443 code.error_goto_if_null(self.result(), self.pos))) 9444 9445 code.put_gotref(self.py_result()) 9446 9447 if def_node.requires_classobj: 9448 assert code.pyclass_stack, "pyclass_stack is empty" 9449 class_node = code.pyclass_stack[-1] 9450 code.put_incref(self.py_result(), py_object_type) 9451 code.putln( 9452 'PyList_Append(%s, %s);' % ( 9453 class_node.class_cell.result(), 9454 self.result())) 9455 code.put_giveref(self.py_result()) 9456 9457 if self.defaults: 9458 code.putln( 9459 'if (!__Pyx_CyFunction_InitDefaults(%s, sizeof(%s), %d)) %s' % ( 9460 self.result(), self.defaults_struct.name, 9461 self.defaults_pyobjects, code.error_goto(self.pos))) 9462 defaults = '__Pyx_CyFunction_Defaults(%s, %s)' % ( 9463 self.defaults_struct.name, self.result()) 9464 for arg, entry in self.defaults: 9465 arg.generate_assignment_code(code, target='%s->%s' % ( 9466 defaults, entry.cname)) 9467 9468 if self.defaults_tuple: 9469 code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % ( 9470 self.result(), self.defaults_tuple.py_result())) 9471 if self.defaults_kwdict: 9472 code.putln('__Pyx_CyFunction_SetDefaultsKwDict(%s, %s);' % ( 9473 self.result(), self.defaults_kwdict.py_result())) 9474 if def_node.defaults_getter and not self.specialized_cpdefs: 9475 # Fused functions do not support dynamic defaults, only their specialisations can have them for now. 9476 code.putln('__Pyx_CyFunction_SetDefaultsGetter(%s, %s);' % ( 9477 self.result(), def_node.defaults_getter.entry.pyfunc_cname)) 9478 if self.annotations_dict: 9479 code.putln('__Pyx_CyFunction_SetAnnotationsDict(%s, %s);' % ( 9480 self.result(), self.annotations_dict.py_result())) 9481 9482 9483class InnerFunctionNode(PyCFunctionNode): 9484 # Special PyCFunctionNode that depends on a closure class 9485 # 9486 9487 binding = True 9488 needs_self_code = True 9489 9490 def self_result_code(self): 9491 if self.needs_self_code: 9492 return "((PyObject*)%s)" % Naming.cur_scope_cname 9493 return "NULL" 9494 9495 9496class CodeObjectNode(ExprNode): 9497 # Create a PyCodeObject for a CyFunction instance. 9498 # 9499 # def_node DefNode the Python function node 9500 # varnames TupleNode a tuple with all local variable names 9501 9502 subexprs = ['varnames'] 9503 is_temp = False 9504 result_code = None 9505 9506 def __init__(self, def_node): 9507 ExprNode.__init__(self, def_node.pos, def_node=def_node) 9508 args = list(def_node.args) 9509 # if we have args/kwargs, then the first two in var_entries are those 9510 local_vars = [arg for arg in def_node.local_scope.var_entries if arg.name] 9511 self.varnames = TupleNode( 9512 def_node.pos, 9513 args=[IdentifierStringNode(arg.pos, value=arg.name) 9514 for arg in args + local_vars], 9515 is_temp=0, 9516 is_literal=1) 9517 9518 def may_be_none(self): 9519 return False 9520 9521 def calculate_result_code(self, code=None): 9522 if self.result_code is None: 9523 self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) 9524 return self.result_code 9525 9526 def generate_result_code(self, code): 9527 if self.result_code is None: 9528 self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_level=2) 9529 9530 code = code.get_cached_constants_writer(self.result_code) 9531 if code is None: 9532 return # already initialised 9533 code.mark_pos(self.pos) 9534 func = self.def_node 9535 func_name = code.get_py_string_const( 9536 func.name, identifier=True, is_str=False, unicode_value=func.name) 9537 # FIXME: better way to get the module file path at module init time? Encoding to use? 9538 file_path = StringEncoding.bytes_literal(func.pos[0].get_filenametable_entry().encode('utf8'), 'utf8') 9539 file_path_const = code.get_py_string_const(file_path, identifier=False, is_str=True) 9540 9541 # This combination makes CPython create a new dict for "frame.f_locals" (see GH #1836). 9542 flags = ['CO_OPTIMIZED', 'CO_NEWLOCALS'] 9543 9544 if self.def_node.star_arg: 9545 flags.append('CO_VARARGS') 9546 if self.def_node.starstar_arg: 9547 flags.append('CO_VARKEYWORDS') 9548 9549 code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % ( 9550 self.result_code, 9551 len(func.args) - func.num_kwonly_args, # argcount 9552 func.num_kwonly_args, # kwonlyargcount (Py3 only) 9553 len(self.varnames.args), # nlocals 9554 '|'.join(flags) or '0', # flags 9555 Naming.empty_bytes, # code 9556 Naming.empty_tuple, # consts 9557 Naming.empty_tuple, # names (FIXME) 9558 self.varnames.result(), # varnames 9559 Naming.empty_tuple, # freevars (FIXME) 9560 Naming.empty_tuple, # cellvars (FIXME) 9561 file_path_const, # filename 9562 func_name, # name 9563 self.pos[1], # firstlineno 9564 Naming.empty_bytes, # lnotab 9565 code.error_goto_if_null(self.result_code, self.pos), 9566 )) 9567 9568 9569class DefaultLiteralArgNode(ExprNode): 9570 # CyFunction's literal argument default value 9571 # 9572 # Evaluate literal only once. 9573 9574 subexprs = [] 9575 is_literal = True 9576 is_temp = False 9577 9578 def __init__(self, pos, arg): 9579 super(DefaultLiteralArgNode, self).__init__(pos) 9580 self.arg = arg 9581 self.type = self.arg.type 9582 self.evaluated = False 9583 9584 def analyse_types(self, env): 9585 return self 9586 9587 def generate_result_code(self, code): 9588 pass 9589 9590 def generate_evaluation_code(self, code): 9591 if not self.evaluated: 9592 self.arg.generate_evaluation_code(code) 9593 self.evaluated = True 9594 9595 def result(self): 9596 return self.type.cast_code(self.arg.result()) 9597 9598 9599class DefaultNonLiteralArgNode(ExprNode): 9600 # CyFunction's non-literal argument default value 9601 9602 subexprs = [] 9603 9604 def __init__(self, pos, arg, defaults_struct): 9605 super(DefaultNonLiteralArgNode, self).__init__(pos) 9606 self.arg = arg 9607 self.defaults_struct = defaults_struct 9608 9609 def analyse_types(self, env): 9610 self.type = self.arg.type 9611 self.is_temp = False 9612 return self 9613 9614 def generate_result_code(self, code): 9615 pass 9616 9617 def result(self): 9618 return '__Pyx_CyFunction_Defaults(%s, %s)->%s' % ( 9619 self.defaults_struct.name, Naming.self_cname, 9620 self.defaults_struct.lookup(self.arg.name).cname) 9621 9622 9623class DefaultsTupleNode(TupleNode): 9624 # CyFunction's __defaults__ tuple 9625 9626 def __init__(self, pos, defaults, defaults_struct): 9627 args = [] 9628 for arg in defaults: 9629 if not arg.default.is_literal: 9630 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) 9631 else: 9632 arg = arg.default 9633 args.append(arg) 9634 super(DefaultsTupleNode, self).__init__(pos, args=args) 9635 9636 def analyse_types(self, env, skip_children=False): 9637 return super(DefaultsTupleNode, self).analyse_types(env, skip_children).coerce_to_pyobject(env) 9638 9639 9640class DefaultsKwDictNode(DictNode): 9641 # CyFunction's __kwdefaults__ dict 9642 9643 def __init__(self, pos, defaults, defaults_struct): 9644 items = [] 9645 for arg in defaults: 9646 name = IdentifierStringNode(arg.pos, value=arg.name) 9647 if not arg.default.is_literal: 9648 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) 9649 else: 9650 arg = arg.default 9651 items.append(DictItemNode(arg.pos, key=name, value=arg)) 9652 super(DefaultsKwDictNode, self).__init__(pos, key_value_pairs=items) 9653 9654 9655class LambdaNode(InnerFunctionNode): 9656 # Lambda expression node (only used as a function reference) 9657 # 9658 # args [CArgDeclNode] formal arguments 9659 # star_arg PyArgDeclNode or None * argument 9660 # starstar_arg PyArgDeclNode or None ** argument 9661 # lambda_name string a module-globally unique lambda name 9662 # result_expr ExprNode 9663 # def_node DefNode the underlying function 'def' node 9664 9665 child_attrs = ['def_node'] 9666 9667 name = StringEncoding.EncodedString('<lambda>') 9668 9669 def analyse_declarations(self, env): 9670 self.lambda_name = self.def_node.lambda_name = env.next_id('lambda') 9671 self.def_node.no_assignment_synthesis = True 9672 self.def_node.pymethdef_required = True 9673 self.def_node.analyse_declarations(env) 9674 self.def_node.is_cyfunction = True 9675 self.pymethdef_cname = self.def_node.entry.pymethdef_cname 9676 env.add_lambda_def(self.def_node) 9677 9678 def analyse_types(self, env): 9679 self.def_node = self.def_node.analyse_expressions(env) 9680 return super(LambdaNode, self).analyse_types(env) 9681 9682 def generate_result_code(self, code): 9683 self.def_node.generate_execution_code(code) 9684 super(LambdaNode, self).generate_result_code(code) 9685 9686 9687class GeneratorExpressionNode(LambdaNode): 9688 # A generator expression, e.g. (i for i in range(10)) 9689 # 9690 # Result is a generator. 9691 # 9692 # loop ForStatNode the for-loop, containing a YieldExprNode 9693 # def_node DefNode the underlying generator 'def' node 9694 9695 name = StringEncoding.EncodedString('genexpr') 9696 binding = False 9697 9698 def analyse_declarations(self, env): 9699 self.genexpr_name = env.next_id('genexpr') 9700 super(GeneratorExpressionNode, self).analyse_declarations(env) 9701 # No pymethdef required 9702 self.def_node.pymethdef_required = False 9703 self.def_node.py_wrapper_required = False 9704 self.def_node.is_cyfunction = False 9705 # Force genexpr signature 9706 self.def_node.entry.signature = TypeSlots.pyfunction_noargs 9707 9708 def generate_result_code(self, code): 9709 code.putln( 9710 '%s = %s(%s); %s' % ( 9711 self.result(), 9712 self.def_node.entry.pyfunc_cname, 9713 self.self_result_code(), 9714 code.error_goto_if_null(self.result(), self.pos))) 9715 code.put_gotref(self.py_result()) 9716 9717 9718class YieldExprNode(ExprNode): 9719 # Yield expression node 9720 # 9721 # arg ExprNode the value to return from the generator 9722 # label_num integer yield label number 9723 # is_yield_from boolean is a YieldFromExprNode to delegate to another generator 9724 9725 subexprs = ['arg'] 9726 type = py_object_type 9727 label_num = 0 9728 is_yield_from = False 9729 is_await = False 9730 in_async_gen = False 9731 expr_keyword = 'yield' 9732 9733 def analyse_types(self, env): 9734 if not self.label_num or (self.is_yield_from and self.in_async_gen): 9735 error(self.pos, "'%s' not supported here" % self.expr_keyword) 9736 self.is_temp = 1 9737 if self.arg is not None: 9738 self.arg = self.arg.analyse_types(env) 9739 if not self.arg.type.is_pyobject: 9740 self.coerce_yield_argument(env) 9741 return self 9742 9743 def coerce_yield_argument(self, env): 9744 self.arg = self.arg.coerce_to_pyobject(env) 9745 9746 def generate_evaluation_code(self, code): 9747 if self.arg: 9748 self.arg.generate_evaluation_code(code) 9749 self.arg.make_owned_reference(code) 9750 code.putln( 9751 "%s = %s;" % ( 9752 Naming.retval_cname, 9753 self.arg.result_as(py_object_type))) 9754 self.arg.generate_post_assignment_code(code) 9755 self.arg.free_temps(code) 9756 else: 9757 code.put_init_to_py_none(Naming.retval_cname, py_object_type) 9758 self.generate_yield_code(code) 9759 9760 def generate_yield_code(self, code): 9761 """ 9762 Generate the code to return the argument in 'Naming.retval_cname' 9763 and to continue at the yield label. 9764 """ 9765 label_num, label_name = code.new_yield_label( 9766 self.expr_keyword.replace(' ', '_')) 9767 code.use_label(label_name) 9768 9769 saved = [] 9770 code.funcstate.closure_temps.reset() 9771 for cname, type, manage_ref in code.funcstate.temps_in_use(): 9772 save_cname = code.funcstate.closure_temps.allocate_temp(type) 9773 saved.append((cname, save_cname, type)) 9774 if type.is_pyobject: 9775 code.put_xgiveref(cname) 9776 code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cname)) 9777 9778 code.put_xgiveref(Naming.retval_cname) 9779 profile = code.globalstate.directives['profile'] 9780 linetrace = code.globalstate.directives['linetrace'] 9781 if profile or linetrace: 9782 code.put_trace_return(Naming.retval_cname, 9783 nogil=not code.funcstate.gil_owned) 9784 code.put_finish_refcount_context() 9785 9786 if code.funcstate.current_except is not None: 9787 # inside of an except block => save away currently handled exception 9788 code.putln("__Pyx_Coroutine_SwapException(%s);" % Naming.generator_cname) 9789 else: 9790 # no exceptions being handled => restore exception state of caller 9791 code.putln("__Pyx_Coroutine_ResetAndClearException(%s);" % Naming.generator_cname) 9792 9793 code.putln("/* return from %sgenerator, %sing value */" % ( 9794 'async ' if self.in_async_gen else '', 9795 'await' if self.is_await else 'yield')) 9796 code.putln("%s->resume_label = %d;" % ( 9797 Naming.generator_cname, label_num)) 9798 if self.in_async_gen and not self.is_await: 9799 # __Pyx__PyAsyncGenValueWrapperNew() steals a reference to the return value 9800 code.putln("return __Pyx__PyAsyncGenValueWrapperNew(%s);" % Naming.retval_cname) 9801 else: 9802 code.putln("return %s;" % Naming.retval_cname) 9803 9804 code.put_label(label_name) 9805 for cname, save_cname, type in saved: 9806 code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname)) 9807 if type.is_pyobject: 9808 code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname)) 9809 code.put_xgotref(cname) 9810 self.generate_sent_value_handling_code(code, Naming.sent_value_cname) 9811 if self.result_is_used: 9812 self.allocate_temp_result(code) 9813 code.put('%s = %s; ' % (self.result(), Naming.sent_value_cname)) 9814 code.put_incref(self.result(), py_object_type) 9815 9816 def generate_sent_value_handling_code(self, code, value_cname): 9817 code.putln(code.error_goto_if_null(value_cname, self.pos)) 9818 9819 9820class _YieldDelegationExprNode(YieldExprNode): 9821 def yield_from_func(self, code): 9822 raise NotImplementedError() 9823 9824 def generate_evaluation_code(self, code, source_cname=None, decref_source=False): 9825 if source_cname is None: 9826 self.arg.generate_evaluation_code(code) 9827 code.putln("%s = %s(%s, %s);" % ( 9828 Naming.retval_cname, 9829 self.yield_from_func(code), 9830 Naming.generator_cname, 9831 self.arg.py_result() if source_cname is None else source_cname)) 9832 if source_cname is None: 9833 self.arg.generate_disposal_code(code) 9834 self.arg.free_temps(code) 9835 elif decref_source: 9836 code.put_decref_clear(source_cname, py_object_type) 9837 code.put_xgotref(Naming.retval_cname) 9838 9839 code.putln("if (likely(%s)) {" % Naming.retval_cname) 9840 self.generate_yield_code(code) 9841 code.putln("} else {") 9842 # either error or sub-generator has normally terminated: return value => node result 9843 if self.result_is_used: 9844 self.fetch_iteration_result(code) 9845 else: 9846 self.handle_iteration_exception(code) 9847 code.putln("}") 9848 9849 def fetch_iteration_result(self, code): 9850 # YieldExprNode has allocated the result temp for us 9851 code.putln("%s = NULL;" % self.result()) 9852 code.put_error_if_neg(self.pos, "__Pyx_PyGen_FetchStopIterationValue(&%s)" % self.result()) 9853 code.put_gotref(self.result()) 9854 9855 def handle_iteration_exception(self, code): 9856 code.putln("PyObject* exc_type = __Pyx_PyErr_Occurred();") 9857 code.putln("if (exc_type) {") 9858 code.putln("if (likely(exc_type == PyExc_StopIteration || (exc_type != PyExc_GeneratorExit &&" 9859 " __Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration)))) PyErr_Clear();") 9860 code.putln("else %s" % code.error_goto(self.pos)) 9861 code.putln("}") 9862 9863 9864class YieldFromExprNode(_YieldDelegationExprNode): 9865 # "yield from GEN" expression 9866 is_yield_from = True 9867 expr_keyword = 'yield from' 9868 9869 def coerce_yield_argument(self, env): 9870 if not self.arg.type.is_string: 9871 # FIXME: support C arrays and C++ iterators? 9872 error(self.pos, "yielding from non-Python object not supported") 9873 self.arg = self.arg.coerce_to_pyobject(env) 9874 9875 def yield_from_func(self, code): 9876 code.globalstate.use_utility_code(UtilityCode.load_cached("GeneratorYieldFrom", "Coroutine.c")) 9877 return "__Pyx_Generator_Yield_From" 9878 9879 9880class AwaitExprNode(_YieldDelegationExprNode): 9881 # 'await' expression node 9882 # 9883 # arg ExprNode the Awaitable value to await 9884 # label_num integer yield label number 9885 9886 is_await = True 9887 expr_keyword = 'await' 9888 9889 def coerce_yield_argument(self, env): 9890 if self.arg is not None: 9891 # FIXME: use same check as in YieldFromExprNode.coerce_yield_argument() ? 9892 self.arg = self.arg.coerce_to_pyobject(env) 9893 9894 def yield_from_func(self, code): 9895 code.globalstate.use_utility_code(UtilityCode.load_cached("CoroutineYieldFrom", "Coroutine.c")) 9896 return "__Pyx_Coroutine_Yield_From" 9897 9898 9899class AwaitIterNextExprNode(AwaitExprNode): 9900 # 'await' expression node as part of 'async for' iteration 9901 # 9902 # Breaks out of loop on StopAsyncIteration exception. 9903 9904 def _generate_break(self, code): 9905 code.globalstate.use_utility_code(UtilityCode.load_cached("StopAsyncIteration", "Coroutine.c")) 9906 code.putln("PyObject* exc_type = __Pyx_PyErr_Occurred();") 9907 code.putln("if (unlikely(exc_type && (exc_type == __Pyx_PyExc_StopAsyncIteration || (" 9908 " exc_type != PyExc_StopIteration && exc_type != PyExc_GeneratorExit &&" 9909 " __Pyx_PyErr_GivenExceptionMatches(exc_type, __Pyx_PyExc_StopAsyncIteration))))) {") 9910 code.putln("PyErr_Clear();") 9911 code.putln("break;") 9912 code.putln("}") 9913 9914 def fetch_iteration_result(self, code): 9915 assert code.break_label, "AwaitIterNextExprNode outside of 'async for' loop" 9916 self._generate_break(code) 9917 super(AwaitIterNextExprNode, self).fetch_iteration_result(code) 9918 9919 def generate_sent_value_handling_code(self, code, value_cname): 9920 assert code.break_label, "AwaitIterNextExprNode outside of 'async for' loop" 9921 code.putln("if (unlikely(!%s)) {" % value_cname) 9922 self._generate_break(code) 9923 # all non-break exceptions are errors, as in parent class 9924 code.putln(code.error_goto(self.pos)) 9925 code.putln("}") 9926 9927 9928class GlobalsExprNode(AtomicExprNode): 9929 type = dict_type 9930 is_temp = 1 9931 9932 def analyse_types(self, env): 9933 env.use_utility_code(Builtin.globals_utility_code) 9934 return self 9935 9936 gil_message = "Constructing globals dict" 9937 9938 def may_be_none(self): 9939 return False 9940 9941 def generate_result_code(self, code): 9942 code.putln('%s = __Pyx_Globals(); %s' % ( 9943 self.result(), 9944 code.error_goto_if_null(self.result(), self.pos))) 9945 code.put_gotref(self.result()) 9946 9947 9948class LocalsDictItemNode(DictItemNode): 9949 def analyse_types(self, env): 9950 self.key = self.key.analyse_types(env) 9951 self.value = self.value.analyse_types(env) 9952 self.key = self.key.coerce_to_pyobject(env) 9953 if self.value.type.can_coerce_to_pyobject(env): 9954 self.value = self.value.coerce_to_pyobject(env) 9955 else: 9956 self.value = None 9957 return self 9958 9959 9960class FuncLocalsExprNode(DictNode): 9961 def __init__(self, pos, env): 9962 local_vars = sorted([ 9963 entry.name for entry in env.entries.values() if entry.name]) 9964 items = [LocalsDictItemNode( 9965 pos, key=IdentifierStringNode(pos, value=var), 9966 value=NameNode(pos, name=var, allow_null=True)) 9967 for var in local_vars] 9968 DictNode.__init__(self, pos, key_value_pairs=items, 9969 exclude_null_values=True) 9970 9971 def analyse_types(self, env): 9972 node = super(FuncLocalsExprNode, self).analyse_types(env) 9973 node.key_value_pairs = [ i for i in node.key_value_pairs 9974 if i.value is not None ] 9975 return node 9976 9977 9978class PyClassLocalsExprNode(AtomicExprNode): 9979 def __init__(self, pos, pyclass_dict): 9980 AtomicExprNode.__init__(self, pos) 9981 self.pyclass_dict = pyclass_dict 9982 9983 def analyse_types(self, env): 9984 self.type = self.pyclass_dict.type 9985 self.is_temp = False 9986 return self 9987 9988 def may_be_none(self): 9989 return False 9990 9991 def result(self): 9992 return self.pyclass_dict.result() 9993 9994 def generate_result_code(self, code): 9995 pass 9996 9997 9998def LocalsExprNode(pos, scope_node, env): 9999 if env.is_module_scope: 10000 return GlobalsExprNode(pos) 10001 if env.is_py_class_scope: 10002 return PyClassLocalsExprNode(pos, scope_node.dict) 10003 return FuncLocalsExprNode(pos, env) 10004 10005 10006#------------------------------------------------------------------- 10007# 10008# Unary operator nodes 10009# 10010#------------------------------------------------------------------- 10011 10012compile_time_unary_operators = { 10013 'not': operator.not_, 10014 '~': operator.inv, 10015 '-': operator.neg, 10016 '+': operator.pos, 10017} 10018 10019class UnopNode(ExprNode): 10020 # operator string 10021 # operand ExprNode 10022 # 10023 # Processing during analyse_expressions phase: 10024 # 10025 # analyse_c_operation 10026 # Called when the operand is not a pyobject. 10027 # - Check operand type and coerce if needed. 10028 # - Determine result type and result code fragment. 10029 # - Allocate temporary for result if needed. 10030 10031 subexprs = ['operand'] 10032 infix = True 10033 10034 def calculate_constant_result(self): 10035 func = compile_time_unary_operators[self.operator] 10036 self.constant_result = func(self.operand.constant_result) 10037 10038 def compile_time_value(self, denv): 10039 func = compile_time_unary_operators.get(self.operator) 10040 if not func: 10041 error(self.pos, 10042 "Unary '%s' not supported in compile-time expression" 10043 % self.operator) 10044 operand = self.operand.compile_time_value(denv) 10045 try: 10046 return func(operand) 10047 except Exception as e: 10048 self.compile_time_value_error(e) 10049 10050 def infer_type(self, env): 10051 operand_type = self.operand.infer_type(env) 10052 if operand_type.is_cpp_class or operand_type.is_ptr: 10053 cpp_type = operand_type.find_cpp_operation_type(self.operator) 10054 if cpp_type is not None: 10055 return cpp_type 10056 return self.infer_unop_type(env, operand_type) 10057 10058 def infer_unop_type(self, env, operand_type): 10059 if operand_type.is_pyobject: 10060 return py_object_type 10061 else: 10062 return operand_type 10063 10064 def may_be_none(self): 10065 if self.operand.type and self.operand.type.is_builtin_type: 10066 if self.operand.type is not type_type: 10067 return False 10068 return ExprNode.may_be_none(self) 10069 10070 def analyse_types(self, env): 10071 self.operand = self.operand.analyse_types(env) 10072 if self.is_pythran_operation(env): 10073 self.type = PythranExpr(pythran_unaryop_type(self.operator, self.operand.type)) 10074 self.is_temp = 1 10075 elif self.is_py_operation(): 10076 self.coerce_operand_to_pyobject(env) 10077 self.type = py_object_type 10078 self.is_temp = 1 10079 elif self.is_cpp_operation(): 10080 self.analyse_cpp_operation(env) 10081 else: 10082 self.analyse_c_operation(env) 10083 return self 10084 10085 def check_const(self): 10086 return self.operand.check_const() 10087 10088 def is_py_operation(self): 10089 return self.operand.type.is_pyobject or self.operand.type.is_ctuple 10090 10091 def is_pythran_operation(self, env): 10092 np_pythran = has_np_pythran(env) 10093 op_type = self.operand.type 10094 return np_pythran and (op_type.is_buffer or op_type.is_pythran_expr) 10095 10096 def nogil_check(self, env): 10097 if self.is_py_operation(): 10098 self.gil_error() 10099 10100 def is_cpp_operation(self): 10101 type = self.operand.type 10102 return type.is_cpp_class 10103 10104 def coerce_operand_to_pyobject(self, env): 10105 self.operand = self.operand.coerce_to_pyobject(env) 10106 10107 def generate_result_code(self, code): 10108 if self.type.is_pythran_expr: 10109 code.putln("// Pythran unaryop") 10110 code.putln("__Pyx_call_destructor(%s);" % self.result()) 10111 code.putln("new (&%s) decltype(%s){%s%s};" % ( 10112 self.result(), 10113 self.result(), 10114 self.operator, 10115 self.operand.pythran_result())) 10116 elif self.operand.type.is_pyobject: 10117 self.generate_py_operation_code(code) 10118 elif self.is_temp: 10119 if self.is_cpp_operation() and self.exception_check == '+': 10120 translate_cpp_exception(code, self.pos, 10121 "%s = %s %s;" % (self.result(), self.operator, self.operand.result()), 10122 self.result() if self.type.is_pyobject else None, 10123 self.exception_value, self.in_nogil_context) 10124 else: 10125 code.putln("%s = %s %s;" % (self.result(), self.operator, self.operand.result())) 10126 10127 def generate_py_operation_code(self, code): 10128 function = self.py_operation_function(code) 10129 code.putln( 10130 "%s = %s(%s); %s" % ( 10131 self.result(), 10132 function, 10133 self.operand.py_result(), 10134 code.error_goto_if_null(self.result(), self.pos))) 10135 code.put_gotref(self.py_result()) 10136 10137 def type_error(self): 10138 if not self.operand.type.is_error: 10139 error(self.pos, "Invalid operand type for '%s' (%s)" % 10140 (self.operator, self.operand.type)) 10141 self.type = PyrexTypes.error_type 10142 10143 def analyse_cpp_operation(self, env, overload_check=True): 10144 entry = env.lookup_operator(self.operator, [self.operand]) 10145 if overload_check and not entry: 10146 self.type_error() 10147 return 10148 if entry: 10149 self.exception_check = entry.type.exception_check 10150 self.exception_value = entry.type.exception_value 10151 if self.exception_check == '+': 10152 self.is_temp = True 10153 if self.exception_value is None: 10154 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 10155 else: 10156 self.exception_check = '' 10157 self.exception_value = '' 10158 cpp_type = self.operand.type.find_cpp_operation_type(self.operator) 10159 if overload_check and cpp_type is None: 10160 error(self.pos, "'%s' operator not defined for %s" % ( 10161 self.operator, type)) 10162 self.type_error() 10163 return 10164 self.type = cpp_type 10165 10166 10167class NotNode(UnopNode): 10168 # 'not' operator 10169 # 10170 # operand ExprNode 10171 operator = '!' 10172 10173 type = PyrexTypes.c_bint_type 10174 10175 def calculate_constant_result(self): 10176 self.constant_result = not self.operand.constant_result 10177 10178 def compile_time_value(self, denv): 10179 operand = self.operand.compile_time_value(denv) 10180 try: 10181 return not operand 10182 except Exception as e: 10183 self.compile_time_value_error(e) 10184 10185 def infer_unop_type(self, env, operand_type): 10186 return PyrexTypes.c_bint_type 10187 10188 def analyse_types(self, env): 10189 self.operand = self.operand.analyse_types(env) 10190 operand_type = self.operand.type 10191 if operand_type.is_cpp_class: 10192 self.analyse_cpp_operation(env) 10193 else: 10194 self.operand = self.operand.coerce_to_boolean(env) 10195 return self 10196 10197 def calculate_result_code(self): 10198 return "(!%s)" % self.operand.result() 10199 10200 10201class UnaryPlusNode(UnopNode): 10202 # unary '+' operator 10203 10204 operator = '+' 10205 10206 def analyse_c_operation(self, env): 10207 self.type = PyrexTypes.widest_numeric_type( 10208 self.operand.type, PyrexTypes.c_int_type) 10209 10210 def py_operation_function(self, code): 10211 return "PyNumber_Positive" 10212 10213 def calculate_result_code(self): 10214 if self.is_cpp_operation(): 10215 return "(+%s)" % self.operand.result() 10216 else: 10217 return self.operand.result() 10218 10219 10220class UnaryMinusNode(UnopNode): 10221 # unary '-' operator 10222 10223 operator = '-' 10224 10225 def analyse_c_operation(self, env): 10226 if self.operand.type.is_numeric: 10227 self.type = PyrexTypes.widest_numeric_type( 10228 self.operand.type, PyrexTypes.c_int_type) 10229 elif self.operand.type.is_enum: 10230 self.type = PyrexTypes.c_int_type 10231 else: 10232 self.type_error() 10233 if self.type.is_complex: 10234 self.infix = False 10235 10236 def py_operation_function(self, code): 10237 return "PyNumber_Negative" 10238 10239 def calculate_result_code(self): 10240 if self.infix: 10241 return "(-%s)" % self.operand.result() 10242 else: 10243 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result()) 10244 10245 def get_constant_c_result_code(self): 10246 value = self.operand.get_constant_c_result_code() 10247 if value: 10248 return "(-%s)" % value 10249 10250class TildeNode(UnopNode): 10251 # unary '~' operator 10252 10253 def analyse_c_operation(self, env): 10254 if self.operand.type.is_int: 10255 self.type = PyrexTypes.widest_numeric_type( 10256 self.operand.type, PyrexTypes.c_int_type) 10257 elif self.operand.type.is_enum: 10258 self.type = PyrexTypes.c_int_type 10259 else: 10260 self.type_error() 10261 10262 def py_operation_function(self, code): 10263 return "PyNumber_Invert" 10264 10265 def calculate_result_code(self): 10266 return "(~%s)" % self.operand.result() 10267 10268 10269class CUnopNode(UnopNode): 10270 10271 def is_py_operation(self): 10272 return False 10273 10274class DereferenceNode(CUnopNode): 10275 # unary * operator 10276 10277 operator = '*' 10278 10279 def infer_unop_type(self, env, operand_type): 10280 if operand_type.is_ptr: 10281 return operand_type.base_type 10282 else: 10283 return PyrexTypes.error_type 10284 10285 def analyse_c_operation(self, env): 10286 if self.operand.type.is_ptr: 10287 self.type = self.operand.type.base_type 10288 else: 10289 self.type_error() 10290 10291 def calculate_result_code(self): 10292 return "(*%s)" % self.operand.result() 10293 10294 10295class DecrementIncrementNode(CUnopNode): 10296 # unary ++/-- operator 10297 10298 def analyse_c_operation(self, env): 10299 if self.operand.type.is_numeric: 10300 self.type = PyrexTypes.widest_numeric_type( 10301 self.operand.type, PyrexTypes.c_int_type) 10302 elif self.operand.type.is_ptr: 10303 self.type = self.operand.type 10304 else: 10305 self.type_error() 10306 10307 def calculate_result_code(self): 10308 if self.is_prefix: 10309 return "(%s%s)" % (self.operator, self.operand.result()) 10310 else: 10311 return "(%s%s)" % (self.operand.result(), self.operator) 10312 10313def inc_dec_constructor(is_prefix, operator): 10314 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix, operator=operator, **kwds) 10315 10316 10317class AmpersandNode(CUnopNode): 10318 # The C address-of operator. 10319 # 10320 # operand ExprNode 10321 operator = '&' 10322 10323 def infer_unop_type(self, env, operand_type): 10324 return PyrexTypes.c_ptr_type(operand_type) 10325 10326 def analyse_types(self, env): 10327 self.operand = self.operand.analyse_types(env) 10328 argtype = self.operand.type 10329 if argtype.is_cpp_class: 10330 self.analyse_cpp_operation(env, overload_check=False) 10331 if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_addressable()): 10332 if argtype.is_memoryviewslice: 10333 self.error("Cannot take address of memoryview slice") 10334 else: 10335 self.error("Taking address of non-lvalue (type %s)" % argtype) 10336 return self 10337 if argtype.is_pyobject: 10338 self.error("Cannot take address of Python %s" % ( 10339 "variable '%s'" % self.operand.name if self.operand.is_name else 10340 "object attribute '%s'" % self.operand.attribute if self.operand.is_attribute else 10341 "object")) 10342 return self 10343 if not argtype.is_cpp_class or not self.type: 10344 self.type = PyrexTypes.c_ptr_type(argtype) 10345 return self 10346 10347 def check_const(self): 10348 return self.operand.check_const_addr() 10349 10350 def error(self, mess): 10351 error(self.pos, mess) 10352 self.type = PyrexTypes.error_type 10353 self.result_code = "<error>" 10354 10355 def calculate_result_code(self): 10356 return "(&%s)" % self.operand.result() 10357 10358 def generate_result_code(self, code): 10359 if (self.operand.type.is_cpp_class and self.exception_check == '+'): 10360 translate_cpp_exception(code, self.pos, 10361 "%s = %s %s;" % (self.result(), self.operator, self.operand.result()), 10362 self.result() if self.type.is_pyobject else None, 10363 self.exception_value, self.in_nogil_context) 10364 10365 10366unop_node_classes = { 10367 "+": UnaryPlusNode, 10368 "-": UnaryMinusNode, 10369 "~": TildeNode, 10370} 10371 10372def unop_node(pos, operator, operand): 10373 # Construct unnop node of appropriate class for 10374 # given operator. 10375 if isinstance(operand, IntNode) and operator == '-': 10376 return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)), 10377 longness=operand.longness, unsigned=operand.unsigned) 10378 elif isinstance(operand, UnopNode) and operand.operator == operator in '+-': 10379 warning(pos, "Python has no increment/decrement operator: %s%sx == %s(%sx) == x" % ((operator,)*4), 5) 10380 return unop_node_classes[operator](pos, 10381 operator = operator, 10382 operand = operand) 10383 10384 10385class TypecastNode(ExprNode): 10386 # C type cast 10387 # 10388 # operand ExprNode 10389 # base_type CBaseTypeNode 10390 # declarator CDeclaratorNode 10391 # typecheck boolean 10392 # 10393 # If used from a transform, one can if wanted specify the attribute 10394 # "type" directly and leave base_type and declarator to None 10395 10396 subexprs = ['operand'] 10397 base_type = declarator = type = None 10398 10399 def type_dependencies(self, env): 10400 return () 10401 10402 def infer_type(self, env): 10403 if self.type is None: 10404 base_type = self.base_type.analyse(env) 10405 _, self.type = self.declarator.analyse(base_type, env) 10406 return self.type 10407 10408 def analyse_types(self, env): 10409 if self.type is None: 10410 base_type = self.base_type.analyse(env) 10411 _, self.type = self.declarator.analyse(base_type, env) 10412 if self.operand.has_constant_result(): 10413 # Must be done after self.type is resolved. 10414 self.calculate_constant_result() 10415 if self.type.is_cfunction: 10416 error(self.pos, 10417 "Cannot cast to a function type") 10418 self.type = PyrexTypes.error_type 10419 self.operand = self.operand.analyse_types(env) 10420 if self.type is PyrexTypes.c_bint_type: 10421 # short circuit this to a coercion 10422 return self.operand.coerce_to_boolean(env) 10423 to_py = self.type.is_pyobject 10424 from_py = self.operand.type.is_pyobject 10425 if from_py and not to_py and self.operand.is_ephemeral(): 10426 if not self.type.is_numeric and not self.type.is_cpp_class: 10427 error(self.pos, "Casting temporary Python object to non-numeric non-Python type") 10428 if to_py and not from_py: 10429 if self.type is bytes_type and self.operand.type.is_int: 10430 return CoerceIntToBytesNode(self.operand, env) 10431 elif self.operand.type.can_coerce_to_pyobject(env): 10432 self.result_ctype = py_object_type 10433 self.operand = self.operand.coerce_to(self.type, env) 10434 else: 10435 if self.operand.type.is_ptr: 10436 if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct): 10437 error(self.pos, "Python objects cannot be cast from pointers of primitive types") 10438 else: 10439 # Should this be an error? 10440 warning(self.pos, "No conversion from %s to %s, python object pointer used." % ( 10441 self.operand.type, self.type)) 10442 self.operand = self.operand.coerce_to_simple(env) 10443 elif from_py and not to_py: 10444 if self.type.create_from_py_utility_code(env): 10445 self.operand = self.operand.coerce_to(self.type, env) 10446 elif self.type.is_ptr: 10447 if not (self.type.base_type.is_void or self.type.base_type.is_struct): 10448 error(self.pos, "Python objects cannot be cast to pointers of primitive types") 10449 else: 10450 warning(self.pos, "No conversion from %s to %s, python object pointer used." % ( 10451 self.type, self.operand.type)) 10452 elif from_py and to_py: 10453 if self.typecheck: 10454 self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True) 10455 elif isinstance(self.operand, SliceIndexNode): 10456 # This cast can influence the created type of string slices. 10457 self.operand = self.operand.coerce_to(self.type, env) 10458 elif self.type.is_complex and self.operand.type.is_complex: 10459 self.operand = self.operand.coerce_to_simple(env) 10460 elif self.operand.type.is_fused: 10461 self.operand = self.operand.coerce_to(self.type, env) 10462 #self.type = self.operand.type 10463 if self.type.is_ptr and self.type.base_type.is_cfunction and self.type.base_type.nogil: 10464 op_type = self.operand.type 10465 if op_type.is_ptr: 10466 op_type = op_type.base_type 10467 if op_type.is_cfunction and not op_type.nogil: 10468 warning(self.pos, 10469 "Casting a GIL-requiring function into a nogil function circumvents GIL validation", 1) 10470 return self 10471 10472 def is_simple(self): 10473 # either temp or a C cast => no side effects other than the operand's 10474 return self.operand.is_simple() 10475 10476 def is_ephemeral(self): 10477 # either temp or a C cast => no side effects other than the operand's 10478 return self.operand.is_ephemeral() 10479 10480 def nonlocally_immutable(self): 10481 return self.is_temp or self.operand.nonlocally_immutable() 10482 10483 def nogil_check(self, env): 10484 if self.type and self.type.is_pyobject and self.is_temp: 10485 self.gil_error() 10486 10487 def check_const(self): 10488 return self.operand.check_const() 10489 10490 def calculate_constant_result(self): 10491 self.constant_result = self.calculate_result_code(self.operand.constant_result) 10492 10493 def calculate_result_code(self, operand_result = None): 10494 if operand_result is None: 10495 operand_result = self.operand.result() 10496 if self.type.is_complex: 10497 operand_result = self.operand.result() 10498 if self.operand.type.is_complex: 10499 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % operand_result) 10500 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % operand_result) 10501 else: 10502 real_part = self.type.real_type.cast_code(operand_result) 10503 imag_part = "0" 10504 return "%s(%s, %s)" % ( 10505 self.type.from_parts, 10506 real_part, 10507 imag_part) 10508 else: 10509 return self.type.cast_code(operand_result) 10510 10511 def get_constant_c_result_code(self): 10512 operand_result = self.operand.get_constant_c_result_code() 10513 if operand_result: 10514 return self.type.cast_code(operand_result) 10515 10516 def result_as(self, type): 10517 if self.type.is_pyobject and not self.is_temp: 10518 # Optimise away some unnecessary casting 10519 return self.operand.result_as(type) 10520 else: 10521 return ExprNode.result_as(self, type) 10522 10523 def generate_result_code(self, code): 10524 if self.is_temp: 10525 code.putln( 10526 "%s = (PyObject *)%s;" % ( 10527 self.result(), 10528 self.operand.result())) 10529 code.put_incref(self.result(), self.ctype()) 10530 10531 10532ERR_START = "Start may not be given" 10533ERR_NOT_STOP = "Stop must be provided to indicate shape" 10534ERR_STEPS = ("Strides may only be given to indicate contiguity. " 10535 "Consider slicing it after conversion") 10536ERR_NOT_POINTER = "Can only create cython.array from pointer or array" 10537ERR_BASE_TYPE = "Pointer base type does not match cython.array base type" 10538 10539 10540class CythonArrayNode(ExprNode): 10541 """ 10542 Used when a pointer of base_type is cast to a memoryviewslice with that 10543 base type. i.e. 10544 10545 <int[:M:1, :N]> p 10546 10547 creates a fortran-contiguous cython.array. 10548 10549 We leave the type set to object so coercions to object are more efficient 10550 and less work. Acquiring a memoryviewslice from this will be just as 10551 efficient. ExprNode.coerce_to() will do the additional typecheck on 10552 self.compile_time_type 10553 10554 This also handles <int[:, :]> my_c_array 10555 10556 10557 operand ExprNode the thing we're casting 10558 base_type_node MemoryViewSliceTypeNode the cast expression node 10559 """ 10560 10561 subexprs = ['operand', 'shapes'] 10562 10563 shapes = None 10564 is_temp = True 10565 mode = "c" 10566 array_dtype = None 10567 10568 shape_type = PyrexTypes.c_py_ssize_t_type 10569 10570 def analyse_types(self, env): 10571 from . import MemoryView 10572 10573 self.operand = self.operand.analyse_types(env) 10574 if self.array_dtype: 10575 array_dtype = self.array_dtype 10576 else: 10577 array_dtype = self.base_type_node.base_type_node.analyse(env) 10578 axes = self.base_type_node.axes 10579 10580 self.type = error_type 10581 self.shapes = [] 10582 ndim = len(axes) 10583 10584 # Base type of the pointer or C array we are converting 10585 base_type = self.operand.type 10586 10587 if not self.operand.type.is_ptr and not self.operand.type.is_array: 10588 error(self.operand.pos, ERR_NOT_POINTER) 10589 return self 10590 10591 # Dimension sizes of C array 10592 array_dimension_sizes = [] 10593 if base_type.is_array: 10594 while base_type.is_array: 10595 array_dimension_sizes.append(base_type.size) 10596 base_type = base_type.base_type 10597 elif base_type.is_ptr: 10598 base_type = base_type.base_type 10599 else: 10600 error(self.pos, "unexpected base type %s found" % base_type) 10601 return self 10602 10603 if not (base_type.same_as(array_dtype) or base_type.is_void): 10604 error(self.operand.pos, ERR_BASE_TYPE) 10605 return self 10606 elif self.operand.type.is_array and len(array_dimension_sizes) != ndim: 10607 error(self.operand.pos, 10608 "Expected %d dimensions, array has %d dimensions" % 10609 (ndim, len(array_dimension_sizes))) 10610 return self 10611 10612 # Verify the start, stop and step values 10613 # In case of a C array, use the size of C array in each dimension to 10614 # get an automatic cast 10615 for axis_no, axis in enumerate(axes): 10616 if not axis.start.is_none: 10617 error(axis.start.pos, ERR_START) 10618 return self 10619 10620 if axis.stop.is_none: 10621 if array_dimension_sizes: 10622 dimsize = array_dimension_sizes[axis_no] 10623 axis.stop = IntNode(self.pos, value=str(dimsize), 10624 constant_result=dimsize, 10625 type=PyrexTypes.c_int_type) 10626 else: 10627 error(axis.pos, ERR_NOT_STOP) 10628 return self 10629 10630 axis.stop = axis.stop.analyse_types(env) 10631 shape = axis.stop.coerce_to(self.shape_type, env) 10632 if not shape.is_literal: 10633 shape.coerce_to_temp(env) 10634 10635 self.shapes.append(shape) 10636 10637 first_or_last = axis_no in (0, ndim - 1) 10638 if not axis.step.is_none and first_or_last: 10639 # '1' in the first or last dimension denotes F or C contiguity 10640 axis.step = axis.step.analyse_types(env) 10641 if (not axis.step.type.is_int and axis.step.is_literal and not 10642 axis.step.type.is_error): 10643 error(axis.step.pos, "Expected an integer literal") 10644 return self 10645 10646 if axis.step.compile_time_value(env) != 1: 10647 error(axis.step.pos, ERR_STEPS) 10648 return self 10649 10650 if axis_no == 0: 10651 self.mode = "fortran" 10652 10653 elif not axis.step.is_none and not first_or_last: 10654 # step provided in some other dimension 10655 error(axis.step.pos, ERR_STEPS) 10656 return self 10657 10658 if not self.operand.is_name: 10659 self.operand = self.operand.coerce_to_temp(env) 10660 10661 axes = [('direct', 'follow')] * len(axes) 10662 if self.mode == "fortran": 10663 axes[0] = ('direct', 'contig') 10664 else: 10665 axes[-1] = ('direct', 'contig') 10666 10667 self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes) 10668 self.coercion_type.validate_memslice_dtype(self.pos) 10669 self.type = self.get_cython_array_type(env) 10670 MemoryView.use_cython_array_utility_code(env) 10671 env.use_utility_code(MemoryView.typeinfo_to_format_code) 10672 return self 10673 10674 def allocate_temp_result(self, code): 10675 if self.temp_code: 10676 raise RuntimeError("temp allocated multiple times") 10677 10678 self.temp_code = code.funcstate.allocate_temp(self.type, True) 10679 10680 def infer_type(self, env): 10681 return self.get_cython_array_type(env) 10682 10683 def get_cython_array_type(self, env): 10684 cython_scope = env.global_scope().context.cython_scope 10685 cython_scope.load_cythonscope() 10686 return cython_scope.viewscope.lookup("array").type 10687 10688 def generate_result_code(self, code): 10689 from . import Buffer 10690 10691 shapes = [self.shape_type.cast_code(shape.result()) 10692 for shape in self.shapes] 10693 dtype = self.coercion_type.dtype 10694 10695 shapes_temp = code.funcstate.allocate_temp(py_object_type, True) 10696 format_temp = code.funcstate.allocate_temp(py_object_type, True) 10697 10698 itemsize = "sizeof(%s)" % dtype.empty_declaration_code() 10699 type_info = Buffer.get_type_information_cname(code, dtype) 10700 10701 if self.operand.type.is_ptr: 10702 code.putln("if (!%s) {" % self.operand.result()) 10703 code.putln( 'PyErr_SetString(PyExc_ValueError,' 10704 '"Cannot create cython.array from NULL pointer");') 10705 code.putln(code.error_goto(self.operand.pos)) 10706 code.putln("}") 10707 10708 code.putln("%s = __pyx_format_from_typeinfo(&%s); %s" % ( 10709 format_temp, 10710 type_info, 10711 code.error_goto_if_null(format_temp, self.pos), 10712 )) 10713 code.put_gotref(format_temp) 10714 10715 buildvalue_fmt = " __PYX_BUILD_PY_SSIZE_T " * len(shapes) 10716 code.putln('%s = Py_BuildValue((char*) "(" %s ")", %s); %s' % ( 10717 shapes_temp, 10718 buildvalue_fmt, 10719 ", ".join(shapes), 10720 code.error_goto_if_null(shapes_temp, self.pos), 10721 )) 10722 code.put_gotref(shapes_temp) 10723 10724 tup = (self.result(), shapes_temp, itemsize, format_temp, 10725 self.mode, self.operand.result()) 10726 code.putln('%s = __pyx_array_new(' 10727 '%s, %s, PyBytes_AS_STRING(%s), ' 10728 '(char *) "%s", (char *) %s);' % tup) 10729 code.putln(code.error_goto_if_null(self.result(), self.pos)) 10730 code.put_gotref(self.result()) 10731 10732 def dispose(temp): 10733 code.put_decref_clear(temp, py_object_type) 10734 code.funcstate.release_temp(temp) 10735 10736 dispose(shapes_temp) 10737 dispose(format_temp) 10738 10739 @classmethod 10740 def from_carray(cls, src_node, env): 10741 """ 10742 Given a C array type, return a CythonArrayNode 10743 """ 10744 pos = src_node.pos 10745 base_type = src_node.type 10746 10747 none_node = NoneNode(pos) 10748 axes = [] 10749 10750 while base_type.is_array: 10751 axes.append(SliceNode(pos, start=none_node, stop=none_node, 10752 step=none_node)) 10753 base_type = base_type.base_type 10754 axes[-1].step = IntNode(pos, value="1", is_c_literal=True) 10755 10756 memslicenode = Nodes.MemoryViewSliceTypeNode(pos, axes=axes, 10757 base_type_node=base_type) 10758 result = CythonArrayNode(pos, base_type_node=memslicenode, 10759 operand=src_node, array_dtype=base_type) 10760 result = result.analyse_types(env) 10761 return result 10762 10763class SizeofNode(ExprNode): 10764 # Abstract base class for sizeof(x) expression nodes. 10765 10766 type = PyrexTypes.c_size_t_type 10767 10768 def check_const(self): 10769 return True 10770 10771 def generate_result_code(self, code): 10772 pass 10773 10774 10775class SizeofTypeNode(SizeofNode): 10776 # C sizeof function applied to a type 10777 # 10778 # base_type CBaseTypeNode 10779 # declarator CDeclaratorNode 10780 10781 subexprs = [] 10782 arg_type = None 10783 10784 def analyse_types(self, env): 10785 # we may have incorrectly interpreted a dotted name as a type rather than an attribute 10786 # this could be better handled by more uniformly treating types as runtime-available objects 10787 if 0 and self.base_type.module_path: 10788 path = self.base_type.module_path 10789 obj = env.lookup(path[0]) 10790 if obj.as_module is None: 10791 operand = NameNode(pos=self.pos, name=path[0]) 10792 for attr in path[1:]: 10793 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr) 10794 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name) 10795 node = SizeofVarNode(self.pos, operand=operand).analyse_types(env) 10796 return node 10797 if self.arg_type is None: 10798 base_type = self.base_type.analyse(env) 10799 _, arg_type = self.declarator.analyse(base_type, env) 10800 self.arg_type = arg_type 10801 self.check_type() 10802 return self 10803 10804 def check_type(self): 10805 arg_type = self.arg_type 10806 if not arg_type: 10807 return 10808 if arg_type.is_pyobject and not arg_type.is_extension_type: 10809 error(self.pos, "Cannot take sizeof Python object") 10810 elif arg_type.is_void: 10811 error(self.pos, "Cannot take sizeof void") 10812 elif not arg_type.is_complete(): 10813 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type) 10814 10815 def calculate_result_code(self): 10816 if self.arg_type.is_extension_type: 10817 # the size of the pointer is boring 10818 # we want the size of the actual struct 10819 arg_code = self.arg_type.declaration_code("", deref=1) 10820 else: 10821 arg_code = self.arg_type.empty_declaration_code() 10822 return "(sizeof(%s))" % arg_code 10823 10824 10825class SizeofVarNode(SizeofNode): 10826 # C sizeof function applied to a variable 10827 # 10828 # operand ExprNode 10829 10830 subexprs = ['operand'] 10831 10832 def analyse_types(self, env): 10833 # We may actually be looking at a type rather than a variable... 10834 # If we are, traditional analysis would fail... 10835 operand_as_type = self.operand.analyse_as_type(env) 10836 if operand_as_type: 10837 self.arg_type = operand_as_type 10838 if self.arg_type.is_fused: 10839 self.arg_type = self.arg_type.specialize(env.fused_to_specific) 10840 self.__class__ = SizeofTypeNode 10841 self.check_type() 10842 else: 10843 self.operand = self.operand.analyse_types(env) 10844 return self 10845 10846 def calculate_result_code(self): 10847 return "(sizeof(%s))" % self.operand.result() 10848 10849 def generate_result_code(self, code): 10850 pass 10851 10852 10853class TypeidNode(ExprNode): 10854 # C++ typeid operator applied to a type or variable 10855 # 10856 # operand ExprNode 10857 # arg_type ExprNode 10858 # is_variable boolean 10859 10860 type = PyrexTypes.error_type 10861 10862 subexprs = ['operand'] 10863 10864 arg_type = None 10865 is_variable = None 10866 is_temp = 1 10867 10868 def get_type_info_type(self, env): 10869 env_module = env 10870 while not env_module.is_module_scope: 10871 env_module = env_module.outer_scope 10872 typeinfo_module = env_module.find_module('libcpp.typeinfo', self.pos) 10873 typeinfo_entry = typeinfo_module.lookup('type_info') 10874 return PyrexTypes.CFakeReferenceType(PyrexTypes.c_const_type(typeinfo_entry.type)) 10875 10876 cpp_message = 'typeid operator' 10877 10878 def analyse_types(self, env): 10879 self.cpp_check(env) 10880 type_info = self.get_type_info_type(env) 10881 if not type_info: 10882 self.error("The 'libcpp.typeinfo' module must be cimported to use the typeid() operator") 10883 return self 10884 self.type = type_info 10885 as_type = self.operand.analyse_as_type(env) 10886 if as_type: 10887 self.arg_type = as_type 10888 self.is_type = True 10889 else: 10890 self.arg_type = self.operand.analyse_types(env) 10891 self.is_type = False 10892 if self.arg_type.type.is_pyobject: 10893 self.error("Cannot use typeid on a Python object") 10894 return self 10895 elif self.arg_type.type.is_void: 10896 self.error("Cannot use typeid on void") 10897 return self 10898 elif not self.arg_type.type.is_complete(): 10899 self.error("Cannot use typeid on incomplete type '%s'" % self.arg_type.type) 10900 return self 10901 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 10902 return self 10903 10904 def error(self, mess): 10905 error(self.pos, mess) 10906 self.type = PyrexTypes.error_type 10907 self.result_code = "<error>" 10908 10909 def check_const(self): 10910 return True 10911 10912 def calculate_result_code(self): 10913 return self.temp_code 10914 10915 def generate_result_code(self, code): 10916 if self.is_type: 10917 arg_code = self.arg_type.empty_declaration_code() 10918 else: 10919 arg_code = self.arg_type.result() 10920 translate_cpp_exception(code, self.pos, 10921 "%s = typeid(%s);" % (self.temp_code, arg_code), 10922 None, None, self.in_nogil_context) 10923 10924class TypeofNode(ExprNode): 10925 # Compile-time type of an expression, as a string. 10926 # 10927 # operand ExprNode 10928 # literal StringNode # internal 10929 10930 literal = None 10931 type = py_object_type 10932 10933 subexprs = ['literal'] # 'operand' will be ignored after type analysis! 10934 10935 def analyse_types(self, env): 10936 self.operand = self.operand.analyse_types(env) 10937 value = StringEncoding.EncodedString(str(self.operand.type)) #self.operand.type.typeof_name()) 10938 literal = StringNode(self.pos, value=value) 10939 literal = literal.analyse_types(env) 10940 self.literal = literal.coerce_to_pyobject(env) 10941 return self 10942 10943 def analyse_as_type(self, env): 10944 self.operand = self.operand.analyse_types(env) 10945 return self.operand.type 10946 10947 def may_be_none(self): 10948 return False 10949 10950 def generate_evaluation_code(self, code): 10951 self.literal.generate_evaluation_code(code) 10952 10953 def calculate_result_code(self): 10954 return self.literal.calculate_result_code() 10955 10956#------------------------------------------------------------------- 10957# 10958# Binary operator nodes 10959# 10960#------------------------------------------------------------------- 10961 10962try: 10963 matmul_operator = operator.matmul 10964except AttributeError: 10965 def matmul_operator(a, b): 10966 try: 10967 func = a.__matmul__ 10968 except AttributeError: 10969 func = b.__rmatmul__ 10970 return func(a, b) 10971 10972compile_time_binary_operators = { 10973 '<': operator.lt, 10974 '<=': operator.le, 10975 '==': operator.eq, 10976 '!=': operator.ne, 10977 '>=': operator.ge, 10978 '>': operator.gt, 10979 'is': operator.is_, 10980 'is_not': operator.is_not, 10981 '+': operator.add, 10982 '&': operator.and_, 10983 '/': operator.truediv, 10984 '//': operator.floordiv, 10985 '<<': operator.lshift, 10986 '%': operator.mod, 10987 '*': operator.mul, 10988 '|': operator.or_, 10989 '**': operator.pow, 10990 '>>': operator.rshift, 10991 '-': operator.sub, 10992 '^': operator.xor, 10993 '@': matmul_operator, 10994 'in': lambda x, seq: x in seq, 10995 'not_in': lambda x, seq: x not in seq, 10996} 10997 10998def get_compile_time_binop(node): 10999 func = compile_time_binary_operators.get(node.operator) 11000 if not func: 11001 error(node.pos, 11002 "Binary '%s' not supported in compile-time expression" 11003 % node.operator) 11004 return func 11005 11006 11007class BinopNode(ExprNode): 11008 # operator string 11009 # operand1 ExprNode 11010 # operand2 ExprNode 11011 # 11012 # Processing during analyse_expressions phase: 11013 # 11014 # analyse_c_operation 11015 # Called when neither operand is a pyobject. 11016 # - Check operand types and coerce if needed. 11017 # - Determine result type and result code fragment. 11018 # - Allocate temporary for result if needed. 11019 11020 subexprs = ['operand1', 'operand2'] 11021 inplace = False 11022 11023 def calculate_constant_result(self): 11024 func = compile_time_binary_operators[self.operator] 11025 self.constant_result = func( 11026 self.operand1.constant_result, 11027 self.operand2.constant_result) 11028 11029 def compile_time_value(self, denv): 11030 func = get_compile_time_binop(self) 11031 operand1 = self.operand1.compile_time_value(denv) 11032 operand2 = self.operand2.compile_time_value(denv) 11033 try: 11034 return func(operand1, operand2) 11035 except Exception as e: 11036 self.compile_time_value_error(e) 11037 11038 def infer_type(self, env): 11039 return self.result_type(self.operand1.infer_type(env), 11040 self.operand2.infer_type(env), env) 11041 11042 def analyse_types(self, env): 11043 self.operand1 = self.operand1.analyse_types(env) 11044 self.operand2 = self.operand2.analyse_types(env) 11045 self.analyse_operation(env) 11046 return self 11047 11048 def analyse_operation(self, env): 11049 if self.is_pythran_operation(env): 11050 self.type = self.result_type(self.operand1.type, 11051 self.operand2.type, env) 11052 assert self.type.is_pythran_expr 11053 self.is_temp = 1 11054 elif self.is_py_operation(): 11055 self.coerce_operands_to_pyobjects(env) 11056 self.type = self.result_type(self.operand1.type, 11057 self.operand2.type, env) 11058 assert self.type.is_pyobject 11059 self.is_temp = 1 11060 elif self.is_cpp_operation(): 11061 self.analyse_cpp_operation(env) 11062 else: 11063 self.analyse_c_operation(env) 11064 11065 def is_py_operation(self): 11066 return self.is_py_operation_types(self.operand1.type, self.operand2.type) 11067 11068 def is_py_operation_types(self, type1, type2): 11069 return type1.is_pyobject or type2.is_pyobject or type1.is_ctuple or type2.is_ctuple 11070 11071 def is_pythran_operation(self, env): 11072 return self.is_pythran_operation_types(self.operand1.type, self.operand2.type, env) 11073 11074 def is_pythran_operation_types(self, type1, type2, env): 11075 # Support only expr op supported_type, or supported_type op expr 11076 return has_np_pythran(env) and \ 11077 (is_pythran_supported_operation_type(type1) and is_pythran_supported_operation_type(type2)) and \ 11078 (is_pythran_expr(type1) or is_pythran_expr(type2)) 11079 11080 def is_cpp_operation(self): 11081 return (self.operand1.type.is_cpp_class 11082 or self.operand2.type.is_cpp_class) 11083 11084 def analyse_cpp_operation(self, env): 11085 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) 11086 if not entry: 11087 self.type_error() 11088 return 11089 func_type = entry.type 11090 self.exception_check = func_type.exception_check 11091 self.exception_value = func_type.exception_value 11092 if self.exception_check == '+': 11093 # Used by NumBinopNodes to break up expressions involving multiple 11094 # operators so that exceptions can be handled properly. 11095 self.is_temp = 1 11096 if self.exception_value is None: 11097 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 11098 if func_type.is_ptr: 11099 func_type = func_type.base_type 11100 if len(func_type.args) == 1: 11101 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) 11102 else: 11103 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) 11104 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) 11105 self.type = func_type.return_type 11106 11107 def result_type(self, type1, type2, env): 11108 if self.is_pythran_operation_types(type1, type2, env): 11109 return PythranExpr(pythran_binop_type(self.operator, type1, type2)) 11110 if self.is_py_operation_types(type1, type2): 11111 if type2.is_string: 11112 type2 = Builtin.bytes_type 11113 elif type2.is_pyunicode_ptr: 11114 type2 = Builtin.unicode_type 11115 if type1.is_string: 11116 type1 = Builtin.bytes_type 11117 elif type1.is_pyunicode_ptr: 11118 type1 = Builtin.unicode_type 11119 if type1.is_builtin_type or type2.is_builtin_type: 11120 if type1 is type2 and self.operator in '**%+|&^': 11121 # FIXME: at least these operators should be safe - others? 11122 return type1 11123 result_type = self.infer_builtin_types_operation(type1, type2) 11124 if result_type is not None: 11125 return result_type 11126 return py_object_type 11127 elif type1.is_error or type2.is_error: 11128 return PyrexTypes.error_type 11129 else: 11130 return self.compute_c_result_type(type1, type2) 11131 11132 def infer_builtin_types_operation(self, type1, type2): 11133 return None 11134 11135 def nogil_check(self, env): 11136 if self.is_py_operation(): 11137 self.gil_error() 11138 11139 def coerce_operands_to_pyobjects(self, env): 11140 self.operand1 = self.operand1.coerce_to_pyobject(env) 11141 self.operand2 = self.operand2.coerce_to_pyobject(env) 11142 11143 def check_const(self): 11144 return self.operand1.check_const() and self.operand2.check_const() 11145 11146 def is_ephemeral(self): 11147 return (super(BinopNode, self).is_ephemeral() or 11148 self.operand1.is_ephemeral() or self.operand2.is_ephemeral()) 11149 11150 def generate_result_code(self, code): 11151 if self.type.is_pythran_expr: 11152 code.putln("// Pythran binop") 11153 code.putln("__Pyx_call_destructor(%s);" % self.result()) 11154 if self.operator == '**': 11155 code.putln("new (&%s) decltype(%s){pythonic::numpy::functor::power{}(%s, %s)};" % ( 11156 self.result(), 11157 self.result(), 11158 self.operand1.pythran_result(), 11159 self.operand2.pythran_result())) 11160 else: 11161 code.putln("new (&%s) decltype(%s){%s %s %s};" % ( 11162 self.result(), 11163 self.result(), 11164 self.operand1.pythran_result(), 11165 self.operator, 11166 self.operand2.pythran_result())) 11167 elif self.operand1.type.is_pyobject: 11168 function = self.py_operation_function(code) 11169 if self.operator == '**': 11170 extra_args = ", Py_None" 11171 else: 11172 extra_args = "" 11173 code.putln( 11174 "%s = %s(%s, %s%s); %s" % ( 11175 self.result(), 11176 function, 11177 self.operand1.py_result(), 11178 self.operand2.py_result(), 11179 extra_args, 11180 code.error_goto_if_null(self.result(), self.pos))) 11181 code.put_gotref(self.py_result()) 11182 elif self.is_temp: 11183 # C++ overloaded operators with exception values are currently all 11184 # handled through temporaries. 11185 if self.is_cpp_operation() and self.exception_check == '+': 11186 translate_cpp_exception(code, self.pos, 11187 "%s = %s;" % (self.result(), self.calculate_result_code()), 11188 self.result() if self.type.is_pyobject else None, 11189 self.exception_value, self.in_nogil_context) 11190 else: 11191 code.putln("%s = %s;" % (self.result(), self.calculate_result_code())) 11192 11193 def type_error(self): 11194 if not (self.operand1.type.is_error 11195 or self.operand2.type.is_error): 11196 error(self.pos, "Invalid operand types for '%s' (%s; %s)" % 11197 (self.operator, self.operand1.type, 11198 self.operand2.type)) 11199 self.type = PyrexTypes.error_type 11200 11201 11202class CBinopNode(BinopNode): 11203 11204 def analyse_types(self, env): 11205 node = BinopNode.analyse_types(self, env) 11206 if node.is_py_operation(): 11207 node.type = PyrexTypes.error_type 11208 return node 11209 11210 def py_operation_function(self, code): 11211 return "" 11212 11213 def calculate_result_code(self): 11214 return "(%s %s %s)" % ( 11215 self.operand1.result(), 11216 self.operator, 11217 self.operand2.result()) 11218 11219 def compute_c_result_type(self, type1, type2): 11220 cpp_type = None 11221 if type1.is_cpp_class or type1.is_ptr: 11222 cpp_type = type1.find_cpp_operation_type(self.operator, type2) 11223 if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): 11224 cpp_type = type2.find_cpp_operation_type(self.operator, type1) 11225 # FIXME: do we need to handle other cases here? 11226 return cpp_type 11227 11228 11229def c_binop_constructor(operator): 11230 def make_binop_node(pos, **operands): 11231 return CBinopNode(pos, operator=operator, **operands) 11232 return make_binop_node 11233 11234class NumBinopNode(BinopNode): 11235 # Binary operation taking numeric arguments. 11236 11237 infix = True 11238 overflow_check = False 11239 overflow_bit_node = None 11240 11241 def analyse_c_operation(self, env): 11242 type1 = self.operand1.type 11243 type2 = self.operand2.type 11244 self.type = self.compute_c_result_type(type1, type2) 11245 if not self.type: 11246 self.type_error() 11247 return 11248 if self.type.is_complex: 11249 self.infix = False 11250 if (self.type.is_int 11251 and env.directives['overflowcheck'] 11252 and self.operator in self.overflow_op_names): 11253 if (self.operator in ('+', '*') 11254 and self.operand1.has_constant_result() 11255 and not self.operand2.has_constant_result()): 11256 self.operand1, self.operand2 = self.operand2, self.operand1 11257 self.overflow_check = True 11258 self.overflow_fold = env.directives['overflowcheck.fold'] 11259 self.func = self.type.overflow_check_binop( 11260 self.overflow_op_names[self.operator], 11261 env, 11262 const_rhs = self.operand2.has_constant_result()) 11263 self.is_temp = True 11264 if not self.infix or (type1.is_numeric and type2.is_numeric): 11265 self.operand1 = self.operand1.coerce_to(self.type, env) 11266 self.operand2 = self.operand2.coerce_to(self.type, env) 11267 11268 def compute_c_result_type(self, type1, type2): 11269 if self.c_types_okay(type1, type2): 11270 widest_type = PyrexTypes.widest_numeric_type(type1, type2) 11271 if widest_type is PyrexTypes.c_bint_type: 11272 if self.operator not in '|^&': 11273 # False + False == 0 # not False! 11274 widest_type = PyrexTypes.c_int_type 11275 else: 11276 widest_type = PyrexTypes.widest_numeric_type( 11277 widest_type, PyrexTypes.c_int_type) 11278 return widest_type 11279 else: 11280 return None 11281 11282 def may_be_none(self): 11283 if self.type and self.type.is_builtin_type: 11284 # if we know the result type, we know the operation, so it can't be None 11285 return False 11286 type1 = self.operand1.type 11287 type2 = self.operand2.type 11288 if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type: 11289 # XXX: I can't think of any case where a binary operation 11290 # on builtin types evaluates to None - add a special case 11291 # here if there is one. 11292 return False 11293 return super(NumBinopNode, self).may_be_none() 11294 11295 def get_constant_c_result_code(self): 11296 value1 = self.operand1.get_constant_c_result_code() 11297 value2 = self.operand2.get_constant_c_result_code() 11298 if value1 and value2: 11299 return "(%s %s %s)" % (value1, self.operator, value2) 11300 else: 11301 return None 11302 11303 def c_types_okay(self, type1, type2): 11304 #print "NumBinopNode.c_types_okay:", type1, type2 ### 11305 return (type1.is_numeric or type1.is_enum) \ 11306 and (type2.is_numeric or type2.is_enum) 11307 11308 def generate_evaluation_code(self, code): 11309 if self.overflow_check: 11310 self.overflow_bit_node = self 11311 self.overflow_bit = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False) 11312 code.putln("%s = 0;" % self.overflow_bit) 11313 super(NumBinopNode, self).generate_evaluation_code(code) 11314 if self.overflow_check: 11315 code.putln("if (unlikely(%s)) {" % self.overflow_bit) 11316 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large");') 11317 code.putln(code.error_goto(self.pos)) 11318 code.putln("}") 11319 code.funcstate.release_temp(self.overflow_bit) 11320 11321 def calculate_result_code(self): 11322 if self.overflow_bit_node is not None: 11323 return "%s(%s, %s, &%s)" % ( 11324 self.func, 11325 self.operand1.result(), 11326 self.operand2.result(), 11327 self.overflow_bit_node.overflow_bit) 11328 elif self.type.is_cpp_class or self.infix: 11329 if is_pythran_expr(self.type): 11330 result1, result2 = self.operand1.pythran_result(), self.operand2.pythran_result() 11331 else: 11332 result1, result2 = self.operand1.result(), self.operand2.result() 11333 return "(%s %s %s)" % (result1, self.operator, result2) 11334 else: 11335 func = self.type.binary_op(self.operator) 11336 if func is None: 11337 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type)) 11338 return "%s(%s, %s)" % ( 11339 func, 11340 self.operand1.result(), 11341 self.operand2.result()) 11342 11343 def is_py_operation_types(self, type1, type2): 11344 return (type1.is_unicode_char or 11345 type2.is_unicode_char or 11346 BinopNode.is_py_operation_types(self, type1, type2)) 11347 11348 def py_operation_function(self, code): 11349 function_name = self.py_functions[self.operator] 11350 if self.inplace: 11351 function_name = function_name.replace('PyNumber_', 'PyNumber_InPlace') 11352 return function_name 11353 11354 py_functions = { 11355 "|": "PyNumber_Or", 11356 "^": "PyNumber_Xor", 11357 "&": "PyNumber_And", 11358 "<<": "PyNumber_Lshift", 11359 ">>": "PyNumber_Rshift", 11360 "+": "PyNumber_Add", 11361 "-": "PyNumber_Subtract", 11362 "*": "PyNumber_Multiply", 11363 "@": "__Pyx_PyNumber_MatrixMultiply", 11364 "/": "__Pyx_PyNumber_Divide", 11365 "//": "PyNumber_FloorDivide", 11366 "%": "PyNumber_Remainder", 11367 "**": "PyNumber_Power", 11368 } 11369 11370 overflow_op_names = { 11371 "+": "add", 11372 "-": "sub", 11373 "*": "mul", 11374 "<<": "lshift", 11375 } 11376 11377 11378class IntBinopNode(NumBinopNode): 11379 # Binary operation taking integer arguments. 11380 11381 def c_types_okay(self, type1, type2): 11382 #print "IntBinopNode.c_types_okay:", type1, type2 ### 11383 return (type1.is_int or type1.is_enum) \ 11384 and (type2.is_int or type2.is_enum) 11385 11386 11387class AddNode(NumBinopNode): 11388 # '+' operator. 11389 11390 def is_py_operation_types(self, type1, type2): 11391 if type1.is_string and type2.is_string or type1.is_pyunicode_ptr and type2.is_pyunicode_ptr: 11392 return 1 11393 else: 11394 return NumBinopNode.is_py_operation_types(self, type1, type2) 11395 11396 def infer_builtin_types_operation(self, type1, type2): 11397 # b'abc' + 'abc' raises an exception in Py3, 11398 # so we can safely infer the Py2 type for bytes here 11399 string_types = (bytes_type, bytearray_type, str_type, basestring_type, unicode_type) 11400 if type1 in string_types and type2 in string_types: 11401 return string_types[max(string_types.index(type1), 11402 string_types.index(type2))] 11403 return None 11404 11405 def compute_c_result_type(self, type1, type2): 11406 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ### 11407 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): 11408 return type1 11409 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum): 11410 return type2 11411 else: 11412 return NumBinopNode.compute_c_result_type( 11413 self, type1, type2) 11414 11415 def py_operation_function(self, code): 11416 type1, type2 = self.operand1.type, self.operand2.type 11417 11418 if type1 is unicode_type or type2 is unicode_type: 11419 if type1 in (unicode_type, str_type) and type2 in (unicode_type, str_type): 11420 is_unicode_concat = True 11421 elif isinstance(self.operand1, FormattedValueNode) or isinstance(self.operand2, FormattedValueNode): 11422 # Assume that even if we don't know the second type, it's going to be a string. 11423 is_unicode_concat = True 11424 else: 11425 # Operation depends on the second type. 11426 is_unicode_concat = False 11427 11428 if is_unicode_concat: 11429 if self.operand1.may_be_none() or self.operand2.may_be_none(): 11430 return '__Pyx_PyUnicode_ConcatSafe' 11431 else: 11432 return '__Pyx_PyUnicode_Concat' 11433 11434 return super(AddNode, self).py_operation_function(code) 11435 11436 11437class SubNode(NumBinopNode): 11438 # '-' operator. 11439 11440 def compute_c_result_type(self, type1, type2): 11441 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): 11442 return type1 11443 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array): 11444 return PyrexTypes.c_ptrdiff_t_type 11445 else: 11446 return NumBinopNode.compute_c_result_type( 11447 self, type1, type2) 11448 11449 11450class MulNode(NumBinopNode): 11451 # '*' operator. 11452 11453 def is_py_operation_types(self, type1, type2): 11454 if ((type1.is_string and type2.is_int) or 11455 (type2.is_string and type1.is_int)): 11456 return 1 11457 else: 11458 return NumBinopNode.is_py_operation_types(self, type1, type2) 11459 11460 def infer_builtin_types_operation(self, type1, type2): 11461 # let's assume that whatever builtin type you multiply a string with 11462 # will either return a string of the same type or fail with an exception 11463 string_types = (bytes_type, bytearray_type, str_type, basestring_type, unicode_type) 11464 if type1 in string_types and type2.is_builtin_type: 11465 return type1 11466 if type2 in string_types and type1.is_builtin_type: 11467 return type2 11468 # multiplication of containers/numbers with an integer value 11469 # always (?) returns the same type 11470 if type1.is_int: 11471 return type2 11472 if type2.is_int: 11473 return type1 11474 return None 11475 11476 11477class MatMultNode(NumBinopNode): 11478 # '@' operator. 11479 11480 def is_py_operation_types(self, type1, type2): 11481 return True 11482 11483 def generate_evaluation_code(self, code): 11484 code.globalstate.use_utility_code(UtilityCode.load_cached("MatrixMultiply", "ObjectHandling.c")) 11485 super(MatMultNode, self).generate_evaluation_code(code) 11486 11487 11488class DivNode(NumBinopNode): 11489 # '/' or '//' operator. 11490 11491 cdivision = None 11492 truedivision = None # == "unknown" if operator == '/' 11493 ctruedivision = False 11494 cdivision_warnings = False 11495 zerodivision_check = None 11496 11497 def find_compile_time_binary_operator(self, op1, op2): 11498 func = compile_time_binary_operators[self.operator] 11499 if self.operator == '/' and self.truedivision is None: 11500 # => true div for floats, floor div for integers 11501 if isinstance(op1, _py_int_types) and isinstance(op2, _py_int_types): 11502 func = compile_time_binary_operators['//'] 11503 return func 11504 11505 def calculate_constant_result(self): 11506 op1 = self.operand1.constant_result 11507 op2 = self.operand2.constant_result 11508 func = self.find_compile_time_binary_operator(op1, op2) 11509 self.constant_result = func( 11510 self.operand1.constant_result, 11511 self.operand2.constant_result) 11512 11513 def compile_time_value(self, denv): 11514 operand1 = self.operand1.compile_time_value(denv) 11515 operand2 = self.operand2.compile_time_value(denv) 11516 try: 11517 func = self.find_compile_time_binary_operator( 11518 operand1, operand2) 11519 return func(operand1, operand2) 11520 except Exception as e: 11521 self.compile_time_value_error(e) 11522 11523 def _check_truedivision(self, env): 11524 if self.cdivision or env.directives['cdivision']: 11525 self.ctruedivision = False 11526 else: 11527 self.ctruedivision = self.truedivision 11528 11529 def infer_type(self, env): 11530 self._check_truedivision(env) 11531 return self.result_type( 11532 self.operand1.infer_type(env), 11533 self.operand2.infer_type(env), env) 11534 11535 def analyse_operation(self, env): 11536 self._check_truedivision(env) 11537 NumBinopNode.analyse_operation(self, env) 11538 if self.is_cpp_operation(): 11539 self.cdivision = True 11540 if not self.type.is_pyobject: 11541 self.zerodivision_check = ( 11542 self.cdivision is None and not env.directives['cdivision'] 11543 and (not self.operand2.has_constant_result() or 11544 self.operand2.constant_result == 0)) 11545 if self.zerodivision_check or env.directives['cdivision_warnings']: 11546 # Need to check ahead of time to warn or raise zero division error 11547 self.operand1 = self.operand1.coerce_to_simple(env) 11548 self.operand2 = self.operand2.coerce_to_simple(env) 11549 11550 def compute_c_result_type(self, type1, type2): 11551 if self.operator == '/' and self.ctruedivision and not type1.is_cpp_class and not type2.is_cpp_class: 11552 if not type1.is_float and not type2.is_float: 11553 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c_double_type) 11554 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type) 11555 return widest_type 11556 return NumBinopNode.compute_c_result_type(self, type1, type2) 11557 11558 def zero_division_message(self): 11559 if self.type.is_int: 11560 return "integer division or modulo by zero" 11561 else: 11562 return "float division" 11563 11564 def generate_evaluation_code(self, code): 11565 if not self.type.is_pyobject and not self.type.is_complex: 11566 if self.cdivision is None: 11567 self.cdivision = ( 11568 code.globalstate.directives['cdivision'] 11569 or self.type.is_float 11570 or ((self.type.is_numeric or self.type.is_enum) and not self.type.signed) 11571 ) 11572 if not self.cdivision: 11573 code.globalstate.use_utility_code( 11574 UtilityCode.load_cached("DivInt", "CMath.c").specialize(self.type)) 11575 NumBinopNode.generate_evaluation_code(self, code) 11576 self.generate_div_warning_code(code) 11577 11578 def generate_div_warning_code(self, code): 11579 in_nogil = self.in_nogil_context 11580 if not self.type.is_pyobject: 11581 if self.zerodivision_check: 11582 if not self.infix: 11583 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result()) 11584 else: 11585 zero_test = "%s == 0" % self.operand2.result() 11586 code.putln("if (unlikely(%s)) {" % zero_test) 11587 if in_nogil: 11588 code.put_ensure_gil() 11589 code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message()) 11590 if in_nogil: 11591 code.put_release_ensured_gil() 11592 code.putln(code.error_goto(self.pos)) 11593 code.putln("}") 11594 if self.type.is_int and self.type.signed and self.operator != '%': 11595 code.globalstate.use_utility_code(UtilityCode.load_cached("UnaryNegOverflows", "Overflow.c")) 11596 if self.operand2.type.signed == 2: 11597 # explicitly signed, no runtime check needed 11598 minus1_check = 'unlikely(%s == -1)' % self.operand2.result() 11599 else: 11600 type_of_op2 = self.operand2.type.empty_declaration_code() 11601 minus1_check = '(!(((%s)-1) > 0)) && unlikely(%s == (%s)-1)' % ( 11602 type_of_op2, self.operand2.result(), type_of_op2) 11603 code.putln("else if (sizeof(%s) == sizeof(long) && %s " 11604 " && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % ( 11605 self.type.empty_declaration_code(), 11606 minus1_check, 11607 self.operand1.result())) 11608 if in_nogil: 11609 code.put_ensure_gil() 11610 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large to perform division");') 11611 if in_nogil: 11612 code.put_release_ensured_gil() 11613 code.putln(code.error_goto(self.pos)) 11614 code.putln("}") 11615 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/': 11616 code.globalstate.use_utility_code( 11617 UtilityCode.load_cached("CDivisionWarning", "CMath.c")) 11618 code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % ( 11619 self.operand1.result(), 11620 self.operand2.result())) 11621 warning_code = "__Pyx_cdivision_warning(%(FILENAME)s, %(LINENO)s)" % { 11622 'FILENAME': Naming.filename_cname, 11623 'LINENO': Naming.lineno_cname, 11624 } 11625 11626 if in_nogil: 11627 result_code = 'result' 11628 code.putln("int %s;" % result_code) 11629 code.put_ensure_gil() 11630 code.putln(code.set_error_info(self.pos, used=True)) 11631 code.putln("%s = %s;" % (result_code, warning_code)) 11632 code.put_release_ensured_gil() 11633 else: 11634 result_code = warning_code 11635 code.putln(code.set_error_info(self.pos, used=True)) 11636 11637 code.put("if (unlikely(%s)) " % result_code) 11638 code.put_goto(code.error_label) 11639 code.putln("}") 11640 11641 def calculate_result_code(self): 11642 if self.type.is_complex or self.is_cpp_operation(): 11643 return NumBinopNode.calculate_result_code(self) 11644 elif self.type.is_float and self.operator == '//': 11645 return "floor(%s / %s)" % ( 11646 self.operand1.result(), 11647 self.operand2.result()) 11648 elif self.truedivision or self.cdivision: 11649 op1 = self.operand1.result() 11650 op2 = self.operand2.result() 11651 if self.truedivision: 11652 if self.type != self.operand1.type: 11653 op1 = self.type.cast_code(op1) 11654 if self.type != self.operand2.type: 11655 op2 = self.type.cast_code(op2) 11656 return "(%s / %s)" % (op1, op2) 11657 else: 11658 return "__Pyx_div_%s(%s, %s)" % ( 11659 self.type.specialization_name(), 11660 self.operand1.result(), 11661 self.operand2.result()) 11662 11663 11664_find_formatting_types = re.compile( 11665 br"%" 11666 br"(?:%|" # %% 11667 br"(?:\([^)]+\))?" # %(name) 11668 br"[-+#,0-9 ]*([a-z])" # %.2f etc. 11669 br")").findall 11670 11671# These format conversion types can never trigger a Unicode string conversion in Py2. 11672_safe_bytes_formats = set([ 11673 # Excludes 's' and 'r', which can generate non-bytes strings. 11674 b'd', b'i', b'o', b'u', b'x', b'X', b'e', b'E', b'f', b'F', b'g', b'G', b'c', b'b', b'a', 11675]) 11676 11677 11678class ModNode(DivNode): 11679 # '%' operator. 11680 11681 def is_py_operation_types(self, type1, type2): 11682 return (type1.is_string 11683 or type2.is_string 11684 or NumBinopNode.is_py_operation_types(self, type1, type2)) 11685 11686 def infer_builtin_types_operation(self, type1, type2): 11687 # b'%s' % xyz raises an exception in Py3<3.5, so it's safe to infer the type for Py2 and later Py3's. 11688 if type1 is unicode_type: 11689 # None + xyz may be implemented by RHS 11690 if type2.is_builtin_type or not self.operand1.may_be_none(): 11691 return type1 11692 elif type1 in (bytes_type, str_type, basestring_type): 11693 if type2 is unicode_type: 11694 return type2 11695 elif type2.is_numeric: 11696 return type1 11697 elif self.operand1.is_string_literal: 11698 if type1 is str_type or type1 is bytes_type: 11699 if set(_find_formatting_types(self.operand1.value)) <= _safe_bytes_formats: 11700 return type1 11701 return basestring_type 11702 elif type1 is bytes_type and not type2.is_builtin_type: 11703 return None # RHS might implement '% operator differently in Py3 11704 else: 11705 return basestring_type # either str or unicode, can't tell 11706 return None 11707 11708 def zero_division_message(self): 11709 if self.type.is_int: 11710 return "integer division or modulo by zero" 11711 else: 11712 return "float divmod()" 11713 11714 def analyse_operation(self, env): 11715 DivNode.analyse_operation(self, env) 11716 if not self.type.is_pyobject: 11717 if self.cdivision is None: 11718 self.cdivision = env.directives['cdivision'] or not self.type.signed 11719 if not self.cdivision and not self.type.is_int and not self.type.is_float: 11720 error(self.pos, "mod operator not supported for type '%s'" % self.type) 11721 11722 def generate_evaluation_code(self, code): 11723 if not self.type.is_pyobject and not self.cdivision: 11724 if self.type.is_int: 11725 code.globalstate.use_utility_code( 11726 UtilityCode.load_cached("ModInt", "CMath.c").specialize(self.type)) 11727 else: # float 11728 code.globalstate.use_utility_code( 11729 UtilityCode.load_cached("ModFloat", "CMath.c").specialize( 11730 self.type, math_h_modifier=self.type.math_h_modifier)) 11731 # NOTE: skipping over DivNode here 11732 NumBinopNode.generate_evaluation_code(self, code) 11733 self.generate_div_warning_code(code) 11734 11735 def calculate_result_code(self): 11736 if self.cdivision: 11737 if self.type.is_float: 11738 return "fmod%s(%s, %s)" % ( 11739 self.type.math_h_modifier, 11740 self.operand1.result(), 11741 self.operand2.result()) 11742 else: 11743 return "(%s %% %s)" % ( 11744 self.operand1.result(), 11745 self.operand2.result()) 11746 else: 11747 return "__Pyx_mod_%s(%s, %s)" % ( 11748 self.type.specialization_name(), 11749 self.operand1.result(), 11750 self.operand2.result()) 11751 11752 def py_operation_function(self, code): 11753 type1, type2 = self.operand1.type, self.operand2.type 11754 # ("..." % x) must call "x.__rmod__()" for string subtypes. 11755 if type1 is unicode_type: 11756 if self.operand1.may_be_none() or ( 11757 type2.is_extension_type and type2.subtype_of(type1) or 11758 type2 is py_object_type and not isinstance(self.operand2, CoerceToPyTypeNode)): 11759 return '__Pyx_PyUnicode_FormatSafe' 11760 else: 11761 return 'PyUnicode_Format' 11762 elif type1 is str_type: 11763 if self.operand1.may_be_none() or ( 11764 type2.is_extension_type and type2.subtype_of(type1) or 11765 type2 is py_object_type and not isinstance(self.operand2, CoerceToPyTypeNode)): 11766 return '__Pyx_PyString_FormatSafe' 11767 else: 11768 return '__Pyx_PyString_Format' 11769 return super(ModNode, self).py_operation_function(code) 11770 11771 11772class PowNode(NumBinopNode): 11773 # '**' operator. 11774 11775 def analyse_c_operation(self, env): 11776 NumBinopNode.analyse_c_operation(self, env) 11777 if self.type.is_complex: 11778 if self.type.real_type.is_float: 11779 self.operand1 = self.operand1.coerce_to(self.type, env) 11780 self.operand2 = self.operand2.coerce_to(self.type, env) 11781 self.pow_func = self.type.binary_op('**') 11782 else: 11783 error(self.pos, "complex int powers not supported") 11784 self.pow_func = "<error>" 11785 elif self.type.is_float: 11786 self.pow_func = "pow" + self.type.math_h_modifier 11787 elif self.type.is_int: 11788 self.pow_func = "__Pyx_pow_%s" % self.type.empty_declaration_code().replace(' ', '_') 11789 env.use_utility_code( 11790 UtilityCode.load_cached("IntPow", "CMath.c").specialize( 11791 func_name=self.pow_func, 11792 type=self.type.empty_declaration_code(), 11793 signed=self.type.signed and 1 or 0)) 11794 elif not self.type.is_error: 11795 error(self.pos, "got unexpected types for C power operator: %s, %s" % 11796 (self.operand1.type, self.operand2.type)) 11797 11798 def calculate_result_code(self): 11799 # Work around MSVC overloading ambiguity. 11800 def typecast(operand): 11801 if self.type == operand.type: 11802 return operand.result() 11803 else: 11804 return self.type.cast_code(operand.result()) 11805 return "%s(%s, %s)" % ( 11806 self.pow_func, 11807 typecast(self.operand1), 11808 typecast(self.operand2)) 11809 11810 def py_operation_function(self, code): 11811 if (self.type.is_pyobject and 11812 self.operand1.constant_result == 2 and 11813 isinstance(self.operand1.constant_result, _py_int_types) and 11814 self.operand2.type is py_object_type): 11815 code.globalstate.use_utility_code(UtilityCode.load_cached('PyNumberPow2', 'Optimize.c')) 11816 if self.inplace: 11817 return '__Pyx_PyNumber_InPlacePowerOf2' 11818 else: 11819 return '__Pyx_PyNumber_PowerOf2' 11820 return super(PowNode, self).py_operation_function(code) 11821 11822 11823class BoolBinopNode(ExprNode): 11824 """ 11825 Short-circuiting boolean operation. 11826 11827 Note that this node provides the same code generation method as 11828 BoolBinopResultNode to simplify expression nesting. 11829 11830 operator string "and"/"or" 11831 operand1 BoolBinopNode/BoolBinopResultNode left operand 11832 operand2 BoolBinopNode/BoolBinopResultNode right operand 11833 """ 11834 subexprs = ['operand1', 'operand2'] 11835 is_temp = True 11836 operator = None 11837 operand1 = None 11838 operand2 = None 11839 11840 def infer_type(self, env): 11841 type1 = self.operand1.infer_type(env) 11842 type2 = self.operand2.infer_type(env) 11843 return PyrexTypes.independent_spanning_type(type1, type2) 11844 11845 def may_be_none(self): 11846 if self.operator == 'or': 11847 return self.operand2.may_be_none() 11848 else: 11849 return self.operand1.may_be_none() or self.operand2.may_be_none() 11850 11851 def calculate_constant_result(self): 11852 operand1 = self.operand1.constant_result 11853 operand2 = self.operand2.constant_result 11854 if self.operator == 'and': 11855 self.constant_result = operand1 and operand2 11856 else: 11857 self.constant_result = operand1 or operand2 11858 11859 def compile_time_value(self, denv): 11860 operand1 = self.operand1.compile_time_value(denv) 11861 operand2 = self.operand2.compile_time_value(denv) 11862 if self.operator == 'and': 11863 return operand1 and operand2 11864 else: 11865 return operand1 or operand2 11866 11867 def is_ephemeral(self): 11868 return self.operand1.is_ephemeral() or self.operand2.is_ephemeral() 11869 11870 def analyse_types(self, env): 11871 # Note: we do not do any coercion here as we most likely do not know the final type anyway. 11872 # We even accept to set self.type to ErrorType if both operands do not have a spanning type. 11873 # The coercion to the final type and to a "simple" value is left to coerce_to(). 11874 operand1 = self.operand1.analyse_types(env) 11875 operand2 = self.operand2.analyse_types(env) 11876 self.type = PyrexTypes.independent_spanning_type( 11877 operand1.type, operand2.type) 11878 self.operand1 = self._wrap_operand(operand1, env) 11879 self.operand2 = self._wrap_operand(operand2, env) 11880 return self 11881 11882 def _wrap_operand(self, operand, env): 11883 if not isinstance(operand, (BoolBinopNode, BoolBinopResultNode)): 11884 operand = BoolBinopResultNode(operand, self.type, env) 11885 return operand 11886 11887 def wrap_operands(self, env): 11888 """ 11889 Must get called by transforms that want to create a correct BoolBinopNode 11890 after the type analysis phase. 11891 """ 11892 self.operand1 = self._wrap_operand(self.operand1, env) 11893 self.operand2 = self._wrap_operand(self.operand2, env) 11894 11895 def coerce_to_boolean(self, env): 11896 return self.coerce_to(PyrexTypes.c_bint_type, env) 11897 11898 def coerce_to(self, dst_type, env): 11899 operand1 = self.operand1.coerce_to(dst_type, env) 11900 operand2 = self.operand2.coerce_to(dst_type, env) 11901 return BoolBinopNode.from_node( 11902 self, type=dst_type, 11903 operator=self.operator, 11904 operand1=operand1, operand2=operand2) 11905 11906 def generate_bool_evaluation_code(self, code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through): 11907 code.mark_pos(self.pos) 11908 11909 outer_labels = (and_label, or_label) 11910 if self.operator == 'and': 11911 my_label = and_label = code.new_label('next_and') 11912 else: 11913 my_label = or_label = code.new_label('next_or') 11914 self.operand1.generate_bool_evaluation_code( 11915 code, final_result_temp, final_result_type, and_label, or_label, end_label, my_label) 11916 11917 and_label, or_label = outer_labels 11918 11919 code.put_label(my_label) 11920 self.operand2.generate_bool_evaluation_code( 11921 code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through) 11922 11923 def generate_evaluation_code(self, code): 11924 self.allocate_temp_result(code) 11925 result_type = PyrexTypes.py_object_type if self.type.is_pyobject else self.type 11926 or_label = and_label = None 11927 end_label = code.new_label('bool_binop_done') 11928 self.generate_bool_evaluation_code(code, self.result(), result_type, and_label, or_label, end_label, end_label) 11929 code.put_label(end_label) 11930 11931 gil_message = "Truth-testing Python object" 11932 11933 def check_const(self): 11934 return self.operand1.check_const() and self.operand2.check_const() 11935 11936 def generate_subexpr_disposal_code(self, code): 11937 pass # nothing to do here, all done in generate_evaluation_code() 11938 11939 def free_subexpr_temps(self, code): 11940 pass # nothing to do here, all done in generate_evaluation_code() 11941 11942 def generate_operand1_test(self, code): 11943 # Generate code to test the truth of the first operand. 11944 if self.type.is_pyobject: 11945 test_result = code.funcstate.allocate_temp( 11946 PyrexTypes.c_bint_type, manage_ref=False) 11947 code.putln( 11948 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( 11949 test_result, 11950 self.operand1.py_result(), 11951 code.error_goto_if_neg(test_result, self.pos))) 11952 else: 11953 test_result = self.operand1.result() 11954 return (test_result, self.type.is_pyobject) 11955 11956 11957class BoolBinopResultNode(ExprNode): 11958 """ 11959 Intermediate result of a short-circuiting and/or expression. 11960 Tests the result for 'truthiness' and takes care of coercing the final result 11961 of the overall expression to the target type. 11962 11963 Note that this node provides the same code generation method as 11964 BoolBinopNode to simplify expression nesting. 11965 11966 arg ExprNode the argument to test 11967 value ExprNode the coerced result value node 11968 """ 11969 11970 subexprs = ['arg', 'value'] 11971 is_temp = True 11972 arg = None 11973 value = None 11974 11975 def __init__(self, arg, result_type, env): 11976 # using 'arg' multiple times, so it must be a simple/temp value 11977 arg = arg.coerce_to_simple(env) 11978 # wrap in ProxyNode, in case a transform wants to replace self.arg later 11979 arg = ProxyNode(arg) 11980 super(BoolBinopResultNode, self).__init__( 11981 arg.pos, arg=arg, type=result_type, 11982 value=CloneNode(arg).coerce_to(result_type, env)) 11983 11984 def coerce_to_boolean(self, env): 11985 return self.coerce_to(PyrexTypes.c_bint_type, env) 11986 11987 def coerce_to(self, dst_type, env): 11988 # unwrap, coerce, rewrap 11989 arg = self.arg.arg 11990 if dst_type is PyrexTypes.c_bint_type: 11991 arg = arg.coerce_to_boolean(env) 11992 # TODO: unwrap more coercion nodes? 11993 return BoolBinopResultNode(arg, dst_type, env) 11994 11995 def nogil_check(self, env): 11996 # let's leave all errors to BoolBinopNode 11997 pass 11998 11999 def generate_operand_test(self, code): 12000 # Generate code to test the truth of the first operand. 12001 if self.arg.type.is_pyobject: 12002 test_result = code.funcstate.allocate_temp( 12003 PyrexTypes.c_bint_type, manage_ref=False) 12004 code.putln( 12005 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( 12006 test_result, 12007 self.arg.py_result(), 12008 code.error_goto_if_neg(test_result, self.pos))) 12009 else: 12010 test_result = self.arg.result() 12011 return (test_result, self.arg.type.is_pyobject) 12012 12013 def generate_bool_evaluation_code(self, code, final_result_temp, final_result_type, and_label, or_label, end_label, fall_through): 12014 code.mark_pos(self.pos) 12015 12016 # x => x 12017 # x and ... or ... => next 'and' / 'or' 12018 # False ... or x => next 'or' 12019 # True and x => next 'and' 12020 # True or x => True (operand) 12021 12022 self.arg.generate_evaluation_code(code) 12023 if and_label or or_label: 12024 test_result, uses_temp = self.generate_operand_test(code) 12025 if uses_temp and (and_label and or_label): 12026 # cannot become final result => free early 12027 # disposal: uses_temp and (and_label and or_label) 12028 self.arg.generate_disposal_code(code) 12029 sense = '!' if or_label else '' 12030 code.putln("if (%s%s) {" % (sense, test_result)) 12031 if uses_temp: 12032 code.funcstate.release_temp(test_result) 12033 if not uses_temp or not (and_label and or_label): 12034 # disposal: (not uses_temp) or {not (and_label and or_label) [if]} 12035 self.arg.generate_disposal_code(code) 12036 12037 if or_label and or_label != fall_through: 12038 # value is false => short-circuit to next 'or' 12039 code.put_goto(or_label) 12040 if and_label: 12041 # value is true => go to next 'and' 12042 if or_label: 12043 code.putln("} else {") 12044 if not uses_temp: 12045 # disposal: (not uses_temp) and {(and_label and or_label) [else]} 12046 self.arg.generate_disposal_code(code) 12047 if and_label != fall_through: 12048 code.put_goto(and_label) 12049 12050 if not and_label or not or_label: 12051 # if no next 'and' or 'or', we provide the result 12052 if and_label or or_label: 12053 code.putln("} else {") 12054 self.value.generate_evaluation_code(code) 12055 self.value.make_owned_reference(code) 12056 code.putln("%s = %s;" % (final_result_temp, self.value.result_as(final_result_type))) 12057 self.value.generate_post_assignment_code(code) 12058 # disposal: {not (and_label and or_label) [else]} 12059 self.arg.generate_disposal_code(code) 12060 self.value.free_temps(code) 12061 if end_label != fall_through: 12062 code.put_goto(end_label) 12063 12064 if and_label or or_label: 12065 code.putln("}") 12066 self.arg.free_temps(code) 12067 12068 12069class CondExprNode(ExprNode): 12070 # Short-circuiting conditional expression. 12071 # 12072 # test ExprNode 12073 # true_val ExprNode 12074 # false_val ExprNode 12075 12076 true_val = None 12077 false_val = None 12078 is_temp = True 12079 12080 subexprs = ['test', 'true_val', 'false_val'] 12081 12082 def type_dependencies(self, env): 12083 return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env) 12084 12085 def infer_type(self, env): 12086 return PyrexTypes.independent_spanning_type( 12087 self.true_val.infer_type(env), 12088 self.false_val.infer_type(env)) 12089 12090 def calculate_constant_result(self): 12091 if self.test.constant_result: 12092 self.constant_result = self.true_val.constant_result 12093 else: 12094 self.constant_result = self.false_val.constant_result 12095 12096 def is_ephemeral(self): 12097 return self.true_val.is_ephemeral() or self.false_val.is_ephemeral() 12098 12099 def analyse_types(self, env): 12100 self.test = self.test.analyse_types(env).coerce_to_boolean(env) 12101 self.true_val = self.true_val.analyse_types(env) 12102 self.false_val = self.false_val.analyse_types(env) 12103 return self.analyse_result_type(env) 12104 12105 def analyse_result_type(self, env): 12106 self.type = PyrexTypes.independent_spanning_type( 12107 self.true_val.type, self.false_val.type) 12108 if self.type.is_reference: 12109 self.type = PyrexTypes.CFakeReferenceType(self.type.ref_base_type) 12110 if self.type.is_pyobject: 12111 self.result_ctype = py_object_type 12112 elif self.true_val.is_ephemeral() or self.false_val.is_ephemeral(): 12113 error(self.pos, "Unsafe C derivative of temporary Python reference used in conditional expression") 12114 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: 12115 self.true_val = self.true_val.coerce_to(self.type, env) 12116 self.false_val = self.false_val.coerce_to(self.type, env) 12117 if self.type.is_error: 12118 self.type_error() 12119 return self 12120 12121 def coerce_to_integer(self, env): 12122 self.true_val = self.true_val.coerce_to_integer(env) 12123 self.false_val = self.false_val.coerce_to_integer(env) 12124 self.result_ctype = None 12125 return self.analyse_result_type(env) 12126 12127 def coerce_to(self, dst_type, env): 12128 self.true_val = self.true_val.coerce_to(dst_type, env) 12129 self.false_val = self.false_val.coerce_to(dst_type, env) 12130 self.result_ctype = None 12131 return self.analyse_result_type(env) 12132 12133 def type_error(self): 12134 if not (self.true_val.type.is_error or self.false_val.type.is_error): 12135 error(self.pos, "Incompatible types in conditional expression (%s; %s)" % 12136 (self.true_val.type, self.false_val.type)) 12137 self.type = PyrexTypes.error_type 12138 12139 def check_const(self): 12140 return (self.test.check_const() 12141 and self.true_val.check_const() 12142 and self.false_val.check_const()) 12143 12144 def generate_evaluation_code(self, code): 12145 # Because subexprs may not be evaluated we can use a more optimal 12146 # subexpr allocation strategy than the default, so override evaluation_code. 12147 12148 code.mark_pos(self.pos) 12149 self.allocate_temp_result(code) 12150 self.test.generate_evaluation_code(code) 12151 code.putln("if (%s) {" % self.test.result()) 12152 self.eval_and_get(code, self.true_val) 12153 code.putln("} else {") 12154 self.eval_and_get(code, self.false_val) 12155 code.putln("}") 12156 self.test.generate_disposal_code(code) 12157 self.test.free_temps(code) 12158 12159 def eval_and_get(self, code, expr): 12160 expr.generate_evaluation_code(code) 12161 if self.type.is_memoryviewslice: 12162 expr.make_owned_memoryviewslice(code) 12163 else: 12164 expr.make_owned_reference(code) 12165 code.putln('%s = %s;' % (self.result(), expr.result_as(self.ctype()))) 12166 expr.generate_post_assignment_code(code) 12167 expr.free_temps(code) 12168 12169 def generate_subexpr_disposal_code(self, code): 12170 pass # done explicitly above (cleanup must separately happen within the if/else blocks) 12171 12172 def free_subexpr_temps(self, code): 12173 pass # done explicitly above (cleanup must separately happen within the if/else blocks) 12174 12175 12176richcmp_constants = { 12177 "<" : "Py_LT", 12178 "<=": "Py_LE", 12179 "==": "Py_EQ", 12180 "!=": "Py_NE", 12181 "<>": "Py_NE", 12182 ">" : "Py_GT", 12183 ">=": "Py_GE", 12184 # the following are faked by special compare functions 12185 "in" : "Py_EQ", 12186 "not_in": "Py_NE", 12187} 12188 12189class CmpNode(object): 12190 # Mixin class containing code common to PrimaryCmpNodes 12191 # and CascadedCmpNodes. 12192 12193 special_bool_cmp_function = None 12194 special_bool_cmp_utility_code = None 12195 12196 def infer_type(self, env): 12197 # TODO: Actually implement this (after merging with -unstable). 12198 return py_object_type 12199 12200 def calculate_cascaded_constant_result(self, operand1_result): 12201 func = compile_time_binary_operators[self.operator] 12202 operand2_result = self.operand2.constant_result 12203 if (isinstance(operand1_result, any_string_type) and 12204 isinstance(operand2_result, any_string_type) and 12205 type(operand1_result) != type(operand2_result)): 12206 # string comparison of different types isn't portable 12207 return 12208 12209 if self.operator in ('in', 'not_in'): 12210 if isinstance(self.operand2, (ListNode, TupleNode, SetNode)): 12211 if not self.operand2.args: 12212 self.constant_result = self.operator == 'not_in' 12213 return 12214 elif isinstance(self.operand2, ListNode) and not self.cascade: 12215 # tuples are more efficient to store than lists 12216 self.operand2 = self.operand2.as_tuple() 12217 elif isinstance(self.operand2, DictNode): 12218 if not self.operand2.key_value_pairs: 12219 self.constant_result = self.operator == 'not_in' 12220 return 12221 12222 self.constant_result = func(operand1_result, operand2_result) 12223 12224 def cascaded_compile_time_value(self, operand1, denv): 12225 func = get_compile_time_binop(self) 12226 operand2 = self.operand2.compile_time_value(denv) 12227 try: 12228 result = func(operand1, operand2) 12229 except Exception as e: 12230 self.compile_time_value_error(e) 12231 result = None 12232 if result: 12233 cascade = self.cascade 12234 if cascade: 12235 result = result and cascade.cascaded_compile_time_value(operand2, denv) 12236 return result 12237 12238 def is_cpp_comparison(self): 12239 return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_class 12240 12241 def find_common_int_type(self, env, op, operand1, operand2): 12242 # type1 != type2 and at least one of the types is not a C int 12243 type1 = operand1.type 12244 type2 = operand2.type 12245 type1_can_be_int = False 12246 type2_can_be_int = False 12247 12248 if operand1.is_string_literal and operand1.can_coerce_to_char_literal(): 12249 type1_can_be_int = True 12250 if operand2.is_string_literal and operand2.can_coerce_to_char_literal(): 12251 type2_can_be_int = True 12252 12253 if type1.is_int: 12254 if type2_can_be_int: 12255 return type1 12256 elif type2.is_int: 12257 if type1_can_be_int: 12258 return type2 12259 elif type1_can_be_int: 12260 if type2_can_be_int: 12261 if Builtin.unicode_type in (type1, type2): 12262 return PyrexTypes.c_py_ucs4_type 12263 else: 12264 return PyrexTypes.c_uchar_type 12265 12266 return None 12267 12268 def find_common_type(self, env, op, operand1, common_type=None): 12269 operand2 = self.operand2 12270 type1 = operand1.type 12271 type2 = operand2.type 12272 12273 new_common_type = None 12274 12275 # catch general errors 12276 if (type1 == str_type and (type2.is_string or type2 in (bytes_type, unicode_type)) or 12277 type2 == str_type and (type1.is_string or type1 in (bytes_type, unicode_type))): 12278 error(self.pos, "Comparisons between bytes/unicode and str are not portable to Python 3") 12279 new_common_type = error_type 12280 12281 # try to use numeric comparisons where possible 12282 elif type1.is_complex or type2.is_complex: 12283 if (op not in ('==', '!=') 12284 and (type1.is_complex or type1.is_numeric) 12285 and (type2.is_complex or type2.is_numeric)): 12286 error(self.pos, "complex types are unordered") 12287 new_common_type = error_type 12288 elif type1.is_pyobject: 12289 new_common_type = Builtin.complex_type if type1.subtype_of(Builtin.complex_type) else py_object_type 12290 elif type2.is_pyobject: 12291 new_common_type = Builtin.complex_type if type2.subtype_of(Builtin.complex_type) else py_object_type 12292 else: 12293 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) 12294 elif type1.is_numeric and type2.is_numeric: 12295 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) 12296 elif common_type is None or not common_type.is_pyobject: 12297 new_common_type = self.find_common_int_type(env, op, operand1, operand2) 12298 12299 if new_common_type is None: 12300 # fall back to generic type compatibility tests 12301 if type1.is_ctuple or type2.is_ctuple: 12302 new_common_type = py_object_type 12303 elif type1 == type2: 12304 new_common_type = type1 12305 elif type1.is_pyobject or type2.is_pyobject: 12306 if type2.is_numeric or type2.is_string: 12307 if operand2.check_for_coercion_error(type1, env): 12308 new_common_type = error_type 12309 else: 12310 new_common_type = py_object_type 12311 elif type1.is_numeric or type1.is_string: 12312 if operand1.check_for_coercion_error(type2, env): 12313 new_common_type = error_type 12314 else: 12315 new_common_type = py_object_type 12316 elif py_object_type.assignable_from(type1) and py_object_type.assignable_from(type2): 12317 new_common_type = py_object_type 12318 else: 12319 # one Python type and one non-Python type, not assignable 12320 self.invalid_types_error(operand1, op, operand2) 12321 new_common_type = error_type 12322 elif type1.assignable_from(type2): 12323 new_common_type = type1 12324 elif type2.assignable_from(type1): 12325 new_common_type = type2 12326 else: 12327 # C types that we couldn't handle up to here are an error 12328 self.invalid_types_error(operand1, op, operand2) 12329 new_common_type = error_type 12330 12331 if new_common_type.is_string and (isinstance(operand1, BytesNode) or 12332 isinstance(operand2, BytesNode)): 12333 # special case when comparing char* to bytes literal: must 12334 # compare string values! 12335 new_common_type = bytes_type 12336 12337 # recursively merge types 12338 if common_type is None or new_common_type.is_error: 12339 common_type = new_common_type 12340 else: 12341 # we could do a lot better by splitting the comparison 12342 # into a non-Python part and a Python part, but this is 12343 # safer for now 12344 common_type = PyrexTypes.spanning_type(common_type, new_common_type) 12345 12346 if self.cascade: 12347 common_type = self.cascade.find_common_type(env, self.operator, operand2, common_type) 12348 12349 return common_type 12350 12351 def invalid_types_error(self, operand1, op, operand2): 12352 error(self.pos, "Invalid types for '%s' (%s, %s)" % 12353 (op, operand1.type, operand2.type)) 12354 12355 def is_python_comparison(self): 12356 return (not self.is_ptr_contains() 12357 and not self.is_c_string_contains() 12358 and (self.has_python_operands() 12359 or (self.cascade and self.cascade.is_python_comparison()) 12360 or self.operator in ('in', 'not_in'))) 12361 12362 def coerce_operands_to(self, dst_type, env): 12363 operand2 = self.operand2 12364 if operand2.type != dst_type: 12365 self.operand2 = operand2.coerce_to(dst_type, env) 12366 if self.cascade: 12367 self.cascade.coerce_operands_to(dst_type, env) 12368 12369 def is_python_result(self): 12370 return ((self.has_python_operands() and 12371 self.special_bool_cmp_function is None and 12372 self.operator not in ('is', 'is_not', 'in', 'not_in') and 12373 not self.is_c_string_contains() and 12374 not self.is_ptr_contains()) 12375 or (self.cascade and self.cascade.is_python_result())) 12376 12377 def is_c_string_contains(self): 12378 return self.operator in ('in', 'not_in') and \ 12379 ((self.operand1.type.is_int 12380 and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or 12381 (self.operand1.type.is_unicode_char 12382 and self.operand2.type is unicode_type)) 12383 12384 def is_ptr_contains(self): 12385 if self.operator in ('in', 'not_in'): 12386 container_type = self.operand2.type 12387 return (container_type.is_ptr or container_type.is_array) \ 12388 and not container_type.is_string 12389 12390 def find_special_bool_compare_function(self, env, operand1, result_is_bool=False): 12391 # note: currently operand1 must get coerced to a Python object if we succeed here! 12392 if self.operator in ('==', '!='): 12393 type1, type2 = operand1.type, self.operand2.type 12394 if result_is_bool or (type1.is_builtin_type and type2.is_builtin_type): 12395 if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type: 12396 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") 12397 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" 12398 return True 12399 elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type: 12400 self.special_bool_cmp_utility_code = UtilityCode.load_cached("BytesEquals", "StringTools.c") 12401 self.special_bool_cmp_function = "__Pyx_PyBytes_Equals" 12402 return True 12403 elif type1 is Builtin.basestring_type or type2 is Builtin.basestring_type: 12404 self.special_bool_cmp_utility_code = UtilityCode.load_cached("UnicodeEquals", "StringTools.c") 12405 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" 12406 return True 12407 elif type1 is Builtin.str_type or type2 is Builtin.str_type: 12408 self.special_bool_cmp_utility_code = UtilityCode.load_cached("StrEquals", "StringTools.c") 12409 self.special_bool_cmp_function = "__Pyx_PyString_Equals" 12410 return True 12411 elif self.operator in ('in', 'not_in'): 12412 if self.operand2.type is Builtin.dict_type: 12413 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 12414 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c") 12415 self.special_bool_cmp_function = "__Pyx_PyDict_ContainsTF" 12416 return True 12417 elif self.operand2.type is Builtin.set_type: 12418 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 12419 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySetContains", "ObjectHandling.c") 12420 self.special_bool_cmp_function = "__Pyx_PySet_ContainsTF" 12421 return True 12422 elif self.operand2.type is Builtin.unicode_type: 12423 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 12424 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c") 12425 self.special_bool_cmp_function = "__Pyx_PyUnicode_ContainsTF" 12426 return True 12427 else: 12428 if not self.operand2.type.is_pyobject: 12429 self.operand2 = self.operand2.coerce_to_pyobject(env) 12430 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySequenceContains", "ObjectHandling.c") 12431 self.special_bool_cmp_function = "__Pyx_PySequence_ContainsTF" 12432 return True 12433 return False 12434 12435 def generate_operation_code(self, code, result_code, 12436 operand1, op , operand2): 12437 if self.type.is_pyobject: 12438 error_clause = code.error_goto_if_null 12439 got_ref = "__Pyx_XGOTREF(%s); " % result_code 12440 if self.special_bool_cmp_function: 12441 code.globalstate.use_utility_code( 12442 UtilityCode.load_cached("PyBoolOrNullFromLong", "ObjectHandling.c")) 12443 coerce_result = "__Pyx_PyBoolOrNull_FromLong" 12444 else: 12445 coerce_result = "__Pyx_PyBool_FromLong" 12446 else: 12447 error_clause = code.error_goto_if_neg 12448 got_ref = "" 12449 coerce_result = "" 12450 12451 if self.special_bool_cmp_function: 12452 if operand1.type.is_pyobject: 12453 result1 = operand1.py_result() 12454 else: 12455 result1 = operand1.result() 12456 if operand2.type.is_pyobject: 12457 result2 = operand2.py_result() 12458 else: 12459 result2 = operand2.result() 12460 if self.special_bool_cmp_utility_code: 12461 code.globalstate.use_utility_code(self.special_bool_cmp_utility_code) 12462 code.putln( 12463 "%s = %s(%s(%s, %s, %s)); %s%s" % ( 12464 result_code, 12465 coerce_result, 12466 self.special_bool_cmp_function, 12467 result1, result2, richcmp_constants[op], 12468 got_ref, 12469 error_clause(result_code, self.pos))) 12470 12471 elif operand1.type.is_pyobject and op not in ('is', 'is_not'): 12472 assert op not in ('in', 'not_in'), op 12473 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s%s" % ( 12474 result_code, 12475 operand1.py_result(), 12476 operand2.py_result(), 12477 richcmp_constants[op], 12478 got_ref, 12479 error_clause(result_code, self.pos))) 12480 12481 elif operand1.type.is_complex: 12482 code.putln("%s = %s(%s%s(%s, %s));" % ( 12483 result_code, 12484 coerce_result, 12485 op == "!=" and "!" or "", 12486 operand1.type.unary_op('eq'), 12487 operand1.result(), 12488 operand2.result())) 12489 12490 else: 12491 type1 = operand1.type 12492 type2 = operand2.type 12493 if (type1.is_extension_type or type2.is_extension_type) \ 12494 and not type1.same_as(type2): 12495 common_type = py_object_type 12496 elif type1.is_numeric: 12497 common_type = PyrexTypes.widest_numeric_type(type1, type2) 12498 else: 12499 common_type = type1 12500 code1 = operand1.result_as(common_type) 12501 code2 = operand2.result_as(common_type) 12502 statement = "%s = %s(%s %s %s);" % ( 12503 result_code, 12504 coerce_result, 12505 code1, 12506 self.c_operator(op), 12507 code2) 12508 if self.is_cpp_comparison() and self.exception_check == '+': 12509 translate_cpp_exception( 12510 code, 12511 self.pos, 12512 statement, 12513 result_code if self.type.is_pyobject else None, 12514 self.exception_value, 12515 self.in_nogil_context) 12516 else: 12517 code.putln(statement) 12518 12519 def c_operator(self, op): 12520 if op == 'is': 12521 return "==" 12522 elif op == 'is_not': 12523 return "!=" 12524 else: 12525 return op 12526 12527class PrimaryCmpNode(ExprNode, CmpNode): 12528 # Non-cascaded comparison or first comparison of 12529 # a cascaded sequence. 12530 # 12531 # operator string 12532 # operand1 ExprNode 12533 # operand2 ExprNode 12534 # cascade CascadedCmpNode 12535 12536 # We don't use the subexprs mechanism, because 12537 # things here are too complicated for it to handle. 12538 # Instead, we override all the framework methods 12539 # which use it. 12540 12541 child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade'] 12542 12543 cascade = None 12544 coerced_operand2 = None 12545 is_memslice_nonecheck = False 12546 12547 def infer_type(self, env): 12548 type1 = self.operand1.infer_type(env) 12549 type2 = self.operand2.infer_type(env) 12550 12551 if is_pythran_expr(type1) or is_pythran_expr(type2): 12552 if is_pythran_supported_type(type1) and is_pythran_supported_type(type2): 12553 return PythranExpr(pythran_binop_type(self.operator, type1, type2)) 12554 12555 # TODO: implement this for other types. 12556 return py_object_type 12557 12558 def type_dependencies(self, env): 12559 return () 12560 12561 def calculate_constant_result(self): 12562 assert not self.cascade 12563 self.calculate_cascaded_constant_result(self.operand1.constant_result) 12564 12565 def compile_time_value(self, denv): 12566 operand1 = self.operand1.compile_time_value(denv) 12567 return self.cascaded_compile_time_value(operand1, denv) 12568 12569 def analyse_types(self, env): 12570 self.operand1 = self.operand1.analyse_types(env) 12571 self.operand2 = self.operand2.analyse_types(env) 12572 if self.is_cpp_comparison(): 12573 self.analyse_cpp_comparison(env) 12574 if self.cascade: 12575 error(self.pos, "Cascading comparison not yet supported for cpp types.") 12576 return self 12577 12578 type1 = self.operand1.type 12579 type2 = self.operand2.type 12580 if is_pythran_expr(type1) or is_pythran_expr(type2): 12581 if is_pythran_supported_type(type1) and is_pythran_supported_type(type2): 12582 self.type = PythranExpr(pythran_binop_type(self.operator, type1, type2)) 12583 self.is_pycmp = False 12584 return self 12585 12586 if self.analyse_memoryviewslice_comparison(env): 12587 return self 12588 12589 if self.cascade: 12590 self.cascade = self.cascade.analyse_types(env) 12591 12592 if self.operator in ('in', 'not_in'): 12593 if self.is_c_string_contains(): 12594 self.is_pycmp = False 12595 common_type = None 12596 if self.cascade: 12597 error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.") 12598 return self 12599 if self.operand2.type is unicode_type: 12600 env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicode", "StringTools.c")) 12601 else: 12602 if self.operand1.type is PyrexTypes.c_uchar_type: 12603 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env) 12604 if self.operand2.type is not bytes_type: 12605 self.operand2 = self.operand2.coerce_to(bytes_type, env) 12606 env.use_utility_code(UtilityCode.load_cached("BytesContains", "StringTools.c")) 12607 self.operand2 = self.operand2.as_none_safe_node( 12608 "argument of type 'NoneType' is not iterable") 12609 elif self.is_ptr_contains(): 12610 if self.cascade: 12611 error(self.pos, "Cascading comparison not supported for 'val in sliced pointer'.") 12612 self.type = PyrexTypes.c_bint_type 12613 # Will be transformed by IterationTransform 12614 return self 12615 elif self.find_special_bool_compare_function(env, self.operand1): 12616 if not self.operand1.type.is_pyobject: 12617 self.operand1 = self.operand1.coerce_to_pyobject(env) 12618 common_type = None # if coercion needed, the method call above has already done it 12619 self.is_pycmp = False # result is bint 12620 else: 12621 common_type = py_object_type 12622 self.is_pycmp = True 12623 elif self.find_special_bool_compare_function(env, self.operand1): 12624 if not self.operand1.type.is_pyobject: 12625 self.operand1 = self.operand1.coerce_to_pyobject(env) 12626 common_type = None # if coercion needed, the method call above has already done it 12627 self.is_pycmp = False # result is bint 12628 else: 12629 common_type = self.find_common_type(env, self.operator, self.operand1) 12630 self.is_pycmp = common_type.is_pyobject 12631 12632 if common_type is not None and not common_type.is_error: 12633 if self.operand1.type != common_type: 12634 self.operand1 = self.operand1.coerce_to(common_type, env) 12635 self.coerce_operands_to(common_type, env) 12636 12637 if self.cascade: 12638 self.operand2 = self.operand2.coerce_to_simple(env) 12639 self.cascade.coerce_cascaded_operands_to_temp(env) 12640 operand2 = self.cascade.optimise_comparison(self.operand2, env) 12641 if operand2 is not self.operand2: 12642 self.coerced_operand2 = operand2 12643 if self.is_python_result(): 12644 self.type = PyrexTypes.py_object_type 12645 else: 12646 self.type = PyrexTypes.c_bint_type 12647 cdr = self.cascade 12648 while cdr: 12649 cdr.type = self.type 12650 cdr = cdr.cascade 12651 if self.is_pycmp or self.cascade or self.special_bool_cmp_function: 12652 # 1) owned reference, 2) reused value, 3) potential function error return value 12653 self.is_temp = 1 12654 return self 12655 12656 def analyse_cpp_comparison(self, env): 12657 type1 = self.operand1.type 12658 type2 = self.operand2.type 12659 self.is_pycmp = False 12660 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2]) 12661 if entry is None: 12662 error(self.pos, "Invalid types for '%s' (%s, %s)" % 12663 (self.operator, type1, type2)) 12664 self.type = PyrexTypes.error_type 12665 self.result_code = "<error>" 12666 return 12667 func_type = entry.type 12668 if func_type.is_ptr: 12669 func_type = func_type.base_type 12670 self.exception_check = func_type.exception_check 12671 self.exception_value = func_type.exception_value 12672 if self.exception_check == '+': 12673 self.is_temp = True 12674 if self.exception_value is None: 12675 env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) 12676 if len(func_type.args) == 1: 12677 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) 12678 else: 12679 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) 12680 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) 12681 self.type = func_type.return_type 12682 12683 def analyse_memoryviewslice_comparison(self, env): 12684 have_none = self.operand1.is_none or self.operand2.is_none 12685 have_slice = (self.operand1.type.is_memoryviewslice or 12686 self.operand2.type.is_memoryviewslice) 12687 ops = ('==', '!=', 'is', 'is_not') 12688 if have_slice and have_none and self.operator in ops: 12689 self.is_pycmp = False 12690 self.type = PyrexTypes.c_bint_type 12691 self.is_memslice_nonecheck = True 12692 return True 12693 12694 return False 12695 12696 def coerce_to_boolean(self, env): 12697 if self.is_pycmp: 12698 # coercing to bool => may allow for more efficient comparison code 12699 if self.find_special_bool_compare_function( 12700 env, self.operand1, result_is_bool=True): 12701 self.is_pycmp = False 12702 self.type = PyrexTypes.c_bint_type 12703 self.is_temp = 1 12704 if self.cascade: 12705 operand2 = self.cascade.optimise_comparison( 12706 self.operand2, env, result_is_bool=True) 12707 if operand2 is not self.operand2: 12708 self.coerced_operand2 = operand2 12709 return self 12710 # TODO: check if we can optimise parts of the cascade here 12711 return ExprNode.coerce_to_boolean(self, env) 12712 12713 def has_python_operands(self): 12714 return (self.operand1.type.is_pyobject 12715 or self.operand2.type.is_pyobject) 12716 12717 def check_const(self): 12718 if self.cascade: 12719 self.not_const() 12720 return False 12721 else: 12722 return self.operand1.check_const() and self.operand2.check_const() 12723 12724 def calculate_result_code(self): 12725 operand1, operand2 = self.operand1, self.operand2 12726 if operand1.type.is_complex: 12727 if self.operator == "!=": 12728 negation = "!" 12729 else: 12730 negation = "" 12731 return "(%s%s(%s, %s))" % ( 12732 negation, 12733 operand1.type.binary_op('=='), 12734 operand1.result(), 12735 operand2.result()) 12736 elif self.is_c_string_contains(): 12737 if operand2.type is unicode_type: 12738 method = "__Pyx_UnicodeContainsUCS4" 12739 else: 12740 method = "__Pyx_BytesContains" 12741 if self.operator == "not_in": 12742 negation = "!" 12743 else: 12744 negation = "" 12745 return "(%s%s(%s, %s))" % ( 12746 negation, 12747 method, 12748 operand2.result(), 12749 operand1.result()) 12750 else: 12751 if is_pythran_expr(self.type): 12752 result1, result2 = operand1.pythran_result(), operand2.pythran_result() 12753 else: 12754 result1, result2 = operand1.result(), operand2.result() 12755 if self.is_memslice_nonecheck: 12756 if operand1.type.is_memoryviewslice: 12757 result1 = "((PyObject *) %s.memview)" % result1 12758 else: 12759 result2 = "((PyObject *) %s.memview)" % result2 12760 12761 return "(%s %s %s)" % ( 12762 result1, 12763 self.c_operator(self.operator), 12764 result2) 12765 12766 def generate_evaluation_code(self, code): 12767 self.operand1.generate_evaluation_code(code) 12768 self.operand2.generate_evaluation_code(code) 12769 if self.is_temp: 12770 self.allocate_temp_result(code) 12771 self.generate_operation_code(code, self.result(), 12772 self.operand1, self.operator, self.operand2) 12773 if self.cascade: 12774 self.cascade.generate_evaluation_code( 12775 code, self.result(), self.coerced_operand2 or self.operand2, 12776 needs_evaluation=self.coerced_operand2 is not None) 12777 self.operand1.generate_disposal_code(code) 12778 self.operand1.free_temps(code) 12779 self.operand2.generate_disposal_code(code) 12780 self.operand2.free_temps(code) 12781 12782 def generate_subexpr_disposal_code(self, code): 12783 # If this is called, it is a non-cascaded cmp, 12784 # so only need to dispose of the two main operands. 12785 self.operand1.generate_disposal_code(code) 12786 self.operand2.generate_disposal_code(code) 12787 12788 def free_subexpr_temps(self, code): 12789 # If this is called, it is a non-cascaded cmp, 12790 # so only need to dispose of the two main operands. 12791 self.operand1.free_temps(code) 12792 self.operand2.free_temps(code) 12793 12794 def annotate(self, code): 12795 self.operand1.annotate(code) 12796 self.operand2.annotate(code) 12797 if self.cascade: 12798 self.cascade.annotate(code) 12799 12800 12801class CascadedCmpNode(Node, CmpNode): 12802 # A CascadedCmpNode is not a complete expression node. It 12803 # hangs off the side of another comparison node, shares 12804 # its left operand with that node, and shares its result 12805 # with the PrimaryCmpNode at the head of the chain. 12806 # 12807 # operator string 12808 # operand2 ExprNode 12809 # cascade CascadedCmpNode 12810 12811 child_attrs = ['operand2', 'coerced_operand2', 'cascade'] 12812 12813 cascade = None 12814 coerced_operand2 = None 12815 constant_result = constant_value_not_set # FIXME: where to calculate this? 12816 12817 def infer_type(self, env): 12818 # TODO: Actually implement this (after merging with -unstable). 12819 return py_object_type 12820 12821 def type_dependencies(self, env): 12822 return () 12823 12824 def has_constant_result(self): 12825 return self.constant_result is not constant_value_not_set and \ 12826 self.constant_result is not not_a_constant 12827 12828 def analyse_types(self, env): 12829 self.operand2 = self.operand2.analyse_types(env) 12830 if self.cascade: 12831 self.cascade = self.cascade.analyse_types(env) 12832 return self 12833 12834 def has_python_operands(self): 12835 return self.operand2.type.is_pyobject 12836 12837 def is_cpp_comparison(self): 12838 # cascaded comparisons aren't currently implemented for c++ classes. 12839 return False 12840 12841 def optimise_comparison(self, operand1, env, result_is_bool=False): 12842 if self.find_special_bool_compare_function(env, operand1, result_is_bool): 12843 self.is_pycmp = False 12844 self.type = PyrexTypes.c_bint_type 12845 if not operand1.type.is_pyobject: 12846 operand1 = operand1.coerce_to_pyobject(env) 12847 if self.cascade: 12848 operand2 = self.cascade.optimise_comparison(self.operand2, env, result_is_bool) 12849 if operand2 is not self.operand2: 12850 self.coerced_operand2 = operand2 12851 return operand1 12852 12853 def coerce_operands_to_pyobjects(self, env): 12854 self.operand2 = self.operand2.coerce_to_pyobject(env) 12855 if self.operand2.type is dict_type and self.operator in ('in', 'not_in'): 12856 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable") 12857 if self.cascade: 12858 self.cascade.coerce_operands_to_pyobjects(env) 12859 12860 def coerce_cascaded_operands_to_temp(self, env): 12861 if self.cascade: 12862 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT 12863 self.operand2 = self.operand2.coerce_to_simple(env) 12864 self.cascade.coerce_cascaded_operands_to_temp(env) 12865 12866 def generate_evaluation_code(self, code, result, operand1, needs_evaluation=False): 12867 if self.type.is_pyobject: 12868 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result) 12869 code.put_decref(result, self.type) 12870 else: 12871 code.putln("if (%s) {" % result) 12872 if needs_evaluation: 12873 operand1.generate_evaluation_code(code) 12874 self.operand2.generate_evaluation_code(code) 12875 self.generate_operation_code(code, result, 12876 operand1, self.operator, self.operand2) 12877 if self.cascade: 12878 self.cascade.generate_evaluation_code( 12879 code, result, self.coerced_operand2 or self.operand2, 12880 needs_evaluation=self.coerced_operand2 is not None) 12881 if needs_evaluation: 12882 operand1.generate_disposal_code(code) 12883 operand1.free_temps(code) 12884 # Cascaded cmp result is always temp 12885 self.operand2.generate_disposal_code(code) 12886 self.operand2.free_temps(code) 12887 code.putln("}") 12888 12889 def annotate(self, code): 12890 self.operand2.annotate(code) 12891 if self.cascade: 12892 self.cascade.annotate(code) 12893 12894 12895binop_node_classes = { 12896 "or": BoolBinopNode, 12897 "and": BoolBinopNode, 12898 "|": IntBinopNode, 12899 "^": IntBinopNode, 12900 "&": IntBinopNode, 12901 "<<": IntBinopNode, 12902 ">>": IntBinopNode, 12903 "+": AddNode, 12904 "-": SubNode, 12905 "*": MulNode, 12906 "@": MatMultNode, 12907 "/": DivNode, 12908 "//": DivNode, 12909 "%": ModNode, 12910 "**": PowNode, 12911} 12912 12913 12914def binop_node(pos, operator, operand1, operand2, inplace=False, **kwargs): 12915 # Construct binop node of appropriate class for 12916 # given operator. 12917 return binop_node_classes[operator]( 12918 pos, 12919 operator=operator, 12920 operand1=operand1, 12921 operand2=operand2, 12922 inplace=inplace, 12923 **kwargs) 12924 12925 12926#------------------------------------------------------------------- 12927# 12928# Coercion nodes 12929# 12930# Coercion nodes are special in that they are created during 12931# the analyse_types phase of parse tree processing. 12932# Their __init__ methods consequently incorporate some aspects 12933# of that phase. 12934# 12935#------------------------------------------------------------------- 12936 12937class CoercionNode(ExprNode): 12938 # Abstract base class for coercion nodes. 12939 # 12940 # arg ExprNode node being coerced 12941 12942 subexprs = ['arg'] 12943 constant_result = not_a_constant 12944 12945 def __init__(self, arg): 12946 super(CoercionNode, self).__init__(arg.pos) 12947 self.arg = arg 12948 if debug_coercion: 12949 print("%s Coercing %s" % (self, self.arg)) 12950 12951 def calculate_constant_result(self): 12952 # constant folding can break type coercion, so this is disabled 12953 pass 12954 12955 def annotate(self, code): 12956 self.arg.annotate(code) 12957 if self.arg.type != self.type: 12958 file, line, col = self.pos 12959 code.annotate((file, line, col-1), AnnotationItem( 12960 style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type))) 12961 12962 12963class CoerceToMemViewSliceNode(CoercionNode): 12964 """ 12965 Coerce an object to a memoryview slice. This holds a new reference in 12966 a managed temp. 12967 """ 12968 12969 def __init__(self, arg, dst_type, env): 12970 assert dst_type.is_memoryviewslice 12971 assert not arg.type.is_memoryviewslice 12972 CoercionNode.__init__(self, arg) 12973 self.type = dst_type 12974 self.is_temp = 1 12975 self.use_managed_ref = True 12976 self.arg = arg 12977 self.type.create_from_py_utility_code(env) 12978 12979 def generate_result_code(self, code): 12980 code.putln(self.type.from_py_call_code( 12981 self.arg.py_result(), 12982 self.result(), 12983 self.pos, 12984 code 12985 )) 12986 12987 12988class CastNode(CoercionNode): 12989 # Wrap a node in a C type cast. 12990 12991 def __init__(self, arg, new_type): 12992 CoercionNode.__init__(self, arg) 12993 self.type = new_type 12994 12995 def may_be_none(self): 12996 return self.arg.may_be_none() 12997 12998 def calculate_result_code(self): 12999 return self.arg.result_as(self.type) 13000 13001 def generate_result_code(self, code): 13002 self.arg.generate_result_code(code) 13003 13004 13005class PyTypeTestNode(CoercionNode): 13006 # This node is used to check that a generic Python 13007 # object is an instance of a particular extension type. 13008 # This node borrows the result of its argument node. 13009 13010 exact_builtin_type = True 13011 13012 def __init__(self, arg, dst_type, env, notnone=False): 13013 # The arg is know to be a Python object, and 13014 # the dst_type is known to be an extension type. 13015 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type" 13016 CoercionNode.__init__(self, arg) 13017 self.type = dst_type 13018 self.result_ctype = arg.ctype() 13019 self.notnone = notnone 13020 13021 nogil_check = Node.gil_error 13022 gil_message = "Python type test" 13023 13024 def analyse_types(self, env): 13025 return self 13026 13027 def may_be_none(self): 13028 if self.notnone: 13029 return False 13030 return self.arg.may_be_none() 13031 13032 def is_simple(self): 13033 return self.arg.is_simple() 13034 13035 def result_in_temp(self): 13036 return self.arg.result_in_temp() 13037 13038 def is_ephemeral(self): 13039 return self.arg.is_ephemeral() 13040 13041 def nonlocally_immutable(self): 13042 return self.arg.nonlocally_immutable() 13043 13044 def reanalyse(self): 13045 if self.type != self.arg.type or not self.arg.is_temp: 13046 return self 13047 if not self.type.typeobj_is_available(): 13048 return self 13049 if self.arg.may_be_none() and self.notnone: 13050 return self.arg.as_none_safe_node("Cannot convert NoneType to %.200s" % self.type.name) 13051 return self.arg 13052 13053 def calculate_constant_result(self): 13054 # FIXME 13055 pass 13056 13057 def calculate_result_code(self): 13058 return self.arg.result() 13059 13060 def generate_result_code(self, code): 13061 if self.type.typeobj_is_available(): 13062 if self.type.is_builtin_type: 13063 type_test = self.type.type_test_code( 13064 self.arg.py_result(), 13065 self.notnone, exact=self.exact_builtin_type) 13066 else: 13067 type_test = self.type.type_test_code( 13068 self.arg.py_result(), self.notnone) 13069 code.globalstate.use_utility_code( 13070 UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c")) 13071 code.putln("if (!(%s)) %s" % ( 13072 type_test, code.error_goto(self.pos))) 13073 else: 13074 error(self.pos, "Cannot test type of extern C class " 13075 "without type object name specification") 13076 13077 def generate_post_assignment_code(self, code): 13078 self.arg.generate_post_assignment_code(code) 13079 13080 def allocate_temp_result(self, code): 13081 pass 13082 13083 def release_temp_result(self, code): 13084 pass 13085 13086 def free_temps(self, code): 13087 self.arg.free_temps(code) 13088 13089 def free_subexpr_temps(self, code): 13090 self.arg.free_subexpr_temps(code) 13091 13092 13093class NoneCheckNode(CoercionNode): 13094 # This node is used to check that a Python object is not None and 13095 # raises an appropriate exception (as specified by the creating 13096 # transform). 13097 13098 is_nonecheck = True 13099 13100 def __init__(self, arg, exception_type_cname, exception_message, 13101 exception_format_args=()): 13102 CoercionNode.__init__(self, arg) 13103 self.type = arg.type 13104 self.result_ctype = arg.ctype() 13105 self.exception_type_cname = exception_type_cname 13106 self.exception_message = exception_message 13107 self.exception_format_args = tuple(exception_format_args or ()) 13108 13109 nogil_check = None # this node only guards an operation that would fail already 13110 13111 def analyse_types(self, env): 13112 return self 13113 13114 def may_be_none(self): 13115 return False 13116 13117 def is_simple(self): 13118 return self.arg.is_simple() 13119 13120 def result_in_temp(self): 13121 return self.arg.result_in_temp() 13122 13123 def nonlocally_immutable(self): 13124 return self.arg.nonlocally_immutable() 13125 13126 def calculate_result_code(self): 13127 return self.arg.result() 13128 13129 def condition(self): 13130 if self.type.is_pyobject: 13131 return self.arg.py_result() 13132 elif self.type.is_memoryviewslice: 13133 return "((PyObject *) %s.memview)" % self.arg.result() 13134 else: 13135 raise Exception("unsupported type") 13136 13137 @classmethod 13138 def generate(cls, arg, code, exception_message, 13139 exception_type_cname="PyExc_TypeError", exception_format_args=(), in_nogil_context=False): 13140 node = cls(arg, exception_type_cname, exception_message, exception_format_args) 13141 node.in_nogil_context = in_nogil_context 13142 node.put_nonecheck(code) 13143 13144 @classmethod 13145 def generate_if_needed(cls, arg, code, exception_message, 13146 exception_type_cname="PyExc_TypeError", exception_format_args=(), in_nogil_context=False): 13147 if arg.may_be_none(): 13148 cls.generate(arg, code, exception_message, exception_type_cname, exception_format_args, in_nogil_context) 13149 13150 def put_nonecheck(self, code): 13151 code.putln( 13152 "if (unlikely(%s == Py_None)) {" % self.condition()) 13153 13154 if self.in_nogil_context: 13155 code.put_ensure_gil() 13156 13157 escape = StringEncoding.escape_byte_string 13158 if self.exception_format_args: 13159 code.putln('PyErr_Format(%s, "%s", %s);' % ( 13160 self.exception_type_cname, 13161 StringEncoding.escape_byte_string( 13162 self.exception_message.encode('UTF-8')), 13163 ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8')) 13164 for arg in self.exception_format_args ]))) 13165 else: 13166 code.putln('PyErr_SetString(%s, "%s");' % ( 13167 self.exception_type_cname, 13168 escape(self.exception_message.encode('UTF-8')))) 13169 13170 if self.in_nogil_context: 13171 code.put_release_ensured_gil() 13172 13173 code.putln(code.error_goto(self.pos)) 13174 code.putln("}") 13175 13176 def generate_result_code(self, code): 13177 self.put_nonecheck(code) 13178 13179 def generate_post_assignment_code(self, code): 13180 self.arg.generate_post_assignment_code(code) 13181 13182 def free_temps(self, code): 13183 self.arg.free_temps(code) 13184 13185 13186class CoerceToPyTypeNode(CoercionNode): 13187 # This node is used to convert a C data type 13188 # to a Python object. 13189 13190 type = py_object_type 13191 target_type = py_object_type 13192 is_temp = 1 13193 13194 def __init__(self, arg, env, type=py_object_type): 13195 if not arg.type.create_to_py_utility_code(env): 13196 error(arg.pos, "Cannot convert '%s' to Python object" % arg.type) 13197 elif arg.type.is_complex: 13198 # special case: complex coercion is so complex that it 13199 # uses a macro ("__pyx_PyComplex_FromComplex()"), for 13200 # which the argument must be simple 13201 arg = arg.coerce_to_simple(env) 13202 CoercionNode.__init__(self, arg) 13203 if type is py_object_type: 13204 # be specific about some known types 13205 if arg.type.is_string or arg.type.is_cpp_string: 13206 self.type = default_str_type(env) 13207 elif arg.type.is_pyunicode_ptr or arg.type.is_unicode_char: 13208 self.type = unicode_type 13209 elif arg.type.is_complex: 13210 self.type = Builtin.complex_type 13211 self.target_type = self.type 13212 elif arg.type.is_string or arg.type.is_cpp_string: 13213 if (type not in (bytes_type, bytearray_type) 13214 and not env.directives['c_string_encoding']): 13215 error(arg.pos, 13216 "default encoding required for conversion from '%s' to '%s'" % 13217 (arg.type, type)) 13218 self.type = self.target_type = type 13219 else: 13220 # FIXME: check that the target type and the resulting type are compatible 13221 self.target_type = type 13222 13223 gil_message = "Converting to Python object" 13224 13225 def may_be_none(self): 13226 # FIXME: is this always safe? 13227 return False 13228 13229 def coerce_to_boolean(self, env): 13230 arg_type = self.arg.type 13231 if (arg_type == PyrexTypes.c_bint_type or 13232 (arg_type.is_pyobject and arg_type.name == 'bool')): 13233 return self.arg.coerce_to_temp(env) 13234 else: 13235 return CoerceToBooleanNode(self, env) 13236 13237 def coerce_to_integer(self, env): 13238 # If not already some C integer type, coerce to longint. 13239 if self.arg.type.is_int: 13240 return self.arg 13241 else: 13242 return self.arg.coerce_to(PyrexTypes.c_long_type, env) 13243 13244 def analyse_types(self, env): 13245 # The arg is always already analysed 13246 return self 13247 13248 def generate_result_code(self, code): 13249 code.putln('%s; %s' % ( 13250 self.arg.type.to_py_call_code( 13251 self.arg.result(), 13252 self.result(), 13253 self.target_type), 13254 code.error_goto_if_null(self.result(), self.pos))) 13255 13256 code.put_gotref(self.py_result()) 13257 13258 13259class CoerceIntToBytesNode(CoerceToPyTypeNode): 13260 # This node is used to convert a C int type to a Python bytes 13261 # object. 13262 13263 is_temp = 1 13264 13265 def __init__(self, arg, env): 13266 arg = arg.coerce_to_simple(env) 13267 CoercionNode.__init__(self, arg) 13268 self.type = Builtin.bytes_type 13269 13270 def generate_result_code(self, code): 13271 arg = self.arg 13272 arg_result = arg.result() 13273 if arg.type not in (PyrexTypes.c_char_type, 13274 PyrexTypes.c_uchar_type, 13275 PyrexTypes.c_schar_type): 13276 if arg.type.signed: 13277 code.putln("if ((%s < 0) || (%s > 255)) {" % ( 13278 arg_result, arg_result)) 13279 else: 13280 code.putln("if (%s > 255) {" % arg_result) 13281 code.putln('PyErr_SetString(PyExc_OverflowError, ' 13282 '"value too large to pack into a byte"); %s' % ( 13283 code.error_goto(self.pos))) 13284 code.putln('}') 13285 temp = None 13286 if arg.type is not PyrexTypes.c_char_type: 13287 temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_ref=False) 13288 code.putln("%s = (char)%s;" % (temp, arg_result)) 13289 arg_result = temp 13290 code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % ( 13291 self.result(), 13292 arg_result, 13293 code.error_goto_if_null(self.result(), self.pos))) 13294 if temp is not None: 13295 code.funcstate.release_temp(temp) 13296 code.put_gotref(self.py_result()) 13297 13298 13299class CoerceFromPyTypeNode(CoercionNode): 13300 # This node is used to convert a Python object 13301 # to a C data type. 13302 13303 def __init__(self, result_type, arg, env): 13304 CoercionNode.__init__(self, arg) 13305 self.type = result_type 13306 self.is_temp = 1 13307 if not result_type.create_from_py_utility_code(env): 13308 error(arg.pos, 13309 "Cannot convert Python object to '%s'" % result_type) 13310 if self.type.is_string or self.type.is_pyunicode_ptr: 13311 if self.arg.is_name and self.arg.entry and self.arg.entry.is_pyglobal: 13312 warning(arg.pos, 13313 "Obtaining '%s' from externally modifiable global Python value" % result_type, 13314 level=1) 13315 13316 def analyse_types(self, env): 13317 # The arg is always already analysed 13318 return self 13319 13320 def is_ephemeral(self): 13321 return (self.type.is_ptr and not self.type.is_array) and self.arg.is_ephemeral() 13322 13323 def generate_result_code(self, code): 13324 from_py_function = None 13325 # for certain source types, we can do better than the generic coercion 13326 if self.type.is_string and self.arg.type is bytes_type: 13327 if self.type.from_py_function.startswith('__Pyx_PyObject_As'): 13328 from_py_function = '__Pyx_PyBytes' + self.type.from_py_function[len('__Pyx_PyObject'):] 13329 NoneCheckNode.generate_if_needed(self.arg, code, "expected bytes, NoneType found") 13330 13331 code.putln(self.type.from_py_call_code( 13332 self.arg.py_result(), self.result(), self.pos, code, from_py_function=from_py_function)) 13333 if self.type.is_pyobject: 13334 code.put_gotref(self.py_result()) 13335 13336 def nogil_check(self, env): 13337 error(self.pos, "Coercion from Python not allowed without the GIL") 13338 13339 13340class CoerceToBooleanNode(CoercionNode): 13341 # This node is used when a result needs to be used 13342 # in a boolean context. 13343 13344 type = PyrexTypes.c_bint_type 13345 13346 _special_builtins = { 13347 Builtin.list_type: 'PyList_GET_SIZE', 13348 Builtin.tuple_type: 'PyTuple_GET_SIZE', 13349 Builtin.set_type: 'PySet_GET_SIZE', 13350 Builtin.frozenset_type: 'PySet_GET_SIZE', 13351 Builtin.bytes_type: 'PyBytes_GET_SIZE', 13352 Builtin.bytearray_type: 'PyByteArray_GET_SIZE', 13353 Builtin.unicode_type: '__Pyx_PyUnicode_IS_TRUE', 13354 } 13355 13356 def __init__(self, arg, env): 13357 CoercionNode.__init__(self, arg) 13358 if arg.type.is_pyobject: 13359 self.is_temp = 1 13360 13361 def nogil_check(self, env): 13362 if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.type) is None: 13363 self.gil_error() 13364 13365 gil_message = "Truth-testing Python object" 13366 13367 def check_const(self): 13368 if self.is_temp: 13369 self.not_const() 13370 return False 13371 return self.arg.check_const() 13372 13373 def calculate_result_code(self): 13374 return "(%s != 0)" % self.arg.result() 13375 13376 def generate_result_code(self, code): 13377 if not self.is_temp: 13378 return 13379 test_func = self._special_builtins.get(self.arg.type) 13380 if test_func is not None: 13381 checks = ["(%s != Py_None)" % self.arg.py_result()] if self.arg.may_be_none() else [] 13382 checks.append("(%s(%s) != 0)" % (test_func, self.arg.py_result())) 13383 code.putln("%s = %s;" % (self.result(), '&&'.join(checks))) 13384 else: 13385 code.putln( 13386 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( 13387 self.result(), 13388 self.arg.py_result(), 13389 code.error_goto_if_neg(self.result(), self.pos))) 13390 13391 13392class CoerceToComplexNode(CoercionNode): 13393 13394 def __init__(self, arg, dst_type, env): 13395 if arg.type.is_complex: 13396 arg = arg.coerce_to_simple(env) 13397 self.type = dst_type 13398 CoercionNode.__init__(self, arg) 13399 dst_type.create_declaration_utility_code(env) 13400 13401 def calculate_result_code(self): 13402 if self.arg.type.is_complex: 13403 real_part = "__Pyx_CREAL(%s)" % self.arg.result() 13404 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result() 13405 else: 13406 real_part = self.arg.result() 13407 imag_part = "0" 13408 return "%s(%s, %s)" % ( 13409 self.type.from_parts, 13410 real_part, 13411 imag_part) 13412 13413 def generate_result_code(self, code): 13414 pass 13415 13416class CoerceToTempNode(CoercionNode): 13417 # This node is used to force the result of another node 13418 # to be stored in a temporary. It is only used if the 13419 # argument node's result is not already in a temporary. 13420 13421 def __init__(self, arg, env): 13422 CoercionNode.__init__(self, arg) 13423 self.type = self.arg.type.as_argument_type() 13424 self.constant_result = self.arg.constant_result 13425 self.is_temp = 1 13426 if self.type.is_pyobject: 13427 self.result_ctype = py_object_type 13428 13429 gil_message = "Creating temporary Python reference" 13430 13431 def analyse_types(self, env): 13432 # The arg is always already analysed 13433 return self 13434 13435 def coerce_to_boolean(self, env): 13436 self.arg = self.arg.coerce_to_boolean(env) 13437 if self.arg.is_simple(): 13438 return self.arg 13439 self.type = self.arg.type 13440 self.result_ctype = self.type 13441 return self 13442 13443 def generate_result_code(self, code): 13444 #self.arg.generate_evaluation_code(code) # Already done 13445 # by generic generate_subexpr_evaluation_code! 13446 code.putln("%s = %s;" % ( 13447 self.result(), self.arg.result_as(self.ctype()))) 13448 if self.use_managed_ref: 13449 if self.type.is_pyobject: 13450 code.put_incref(self.result(), self.ctype()) 13451 elif self.type.is_memoryviewslice: 13452 code.put_incref_memoryviewslice(self.result(), 13453 not self.in_nogil_context) 13454 13455class ProxyNode(CoercionNode): 13456 """ 13457 A node that should not be replaced by transforms or other means, 13458 and hence can be useful to wrap the argument to a clone node 13459 13460 MyNode -> ProxyNode -> ArgNode 13461 CloneNode -^ 13462 """ 13463 13464 nogil_check = None 13465 13466 def __init__(self, arg): 13467 super(ProxyNode, self).__init__(arg) 13468 self.constant_result = arg.constant_result 13469 self._proxy_type() 13470 13471 def analyse_types(self, env): 13472 self.arg = self.arg.analyse_expressions(env) 13473 self._proxy_type() 13474 return self 13475 13476 def infer_type(self, env): 13477 return self.arg.infer_type(env) 13478 13479 def _proxy_type(self): 13480 if hasattr(self.arg, 'type'): 13481 self.type = self.arg.type 13482 self.result_ctype = self.arg.result_ctype 13483 if hasattr(self.arg, 'entry'): 13484 self.entry = self.arg.entry 13485 13486 def generate_result_code(self, code): 13487 self.arg.generate_result_code(code) 13488 13489 def result(self): 13490 return self.arg.result() 13491 13492 def is_simple(self): 13493 return self.arg.is_simple() 13494 13495 def may_be_none(self): 13496 return self.arg.may_be_none() 13497 13498 def generate_evaluation_code(self, code): 13499 self.arg.generate_evaluation_code(code) 13500 13501 def generate_disposal_code(self, code): 13502 self.arg.generate_disposal_code(code) 13503 13504 def free_temps(self, code): 13505 self.arg.free_temps(code) 13506 13507class CloneNode(CoercionNode): 13508 # This node is employed when the result of another node needs 13509 # to be used multiple times. The argument node's result must 13510 # be in a temporary. This node "borrows" the result from the 13511 # argument node, and does not generate any evaluation or 13512 # disposal code for it. The original owner of the argument 13513 # node is responsible for doing those things. 13514 13515 subexprs = [] # Arg is not considered a subexpr 13516 nogil_check = None 13517 13518 def __init__(self, arg): 13519 CoercionNode.__init__(self, arg) 13520 self.constant_result = arg.constant_result 13521 if hasattr(arg, 'type'): 13522 self.type = arg.type 13523 self.result_ctype = arg.result_ctype 13524 if hasattr(arg, 'entry'): 13525 self.entry = arg.entry 13526 13527 def result(self): 13528 return self.arg.result() 13529 13530 def may_be_none(self): 13531 return self.arg.may_be_none() 13532 13533 def type_dependencies(self, env): 13534 return self.arg.type_dependencies(env) 13535 13536 def infer_type(self, env): 13537 return self.arg.infer_type(env) 13538 13539 def analyse_types(self, env): 13540 self.type = self.arg.type 13541 self.result_ctype = self.arg.result_ctype 13542 self.is_temp = 1 13543 if hasattr(self.arg, 'entry'): 13544 self.entry = self.arg.entry 13545 return self 13546 13547 def coerce_to(self, dest_type, env): 13548 if self.arg.is_literal: 13549 return self.arg.coerce_to(dest_type, env) 13550 return super(CloneNode, self).coerce_to(dest_type, env) 13551 13552 def is_simple(self): 13553 return True # result is always in a temp (or a name) 13554 13555 def generate_evaluation_code(self, code): 13556 pass 13557 13558 def generate_result_code(self, code): 13559 pass 13560 13561 def generate_disposal_code(self, code): 13562 pass 13563 13564 def free_temps(self, code): 13565 pass 13566 13567 13568class CMethodSelfCloneNode(CloneNode): 13569 # Special CloneNode for the self argument of builtin C methods 13570 # that accepts subtypes of the builtin type. This is safe only 13571 # for 'final' subtypes, as subtypes of the declared type may 13572 # override the C method. 13573 13574 def coerce_to(self, dst_type, env): 13575 if dst_type.is_builtin_type and self.type.subtype_of(dst_type): 13576 return self 13577 return CloneNode.coerce_to(self, dst_type, env) 13578 13579 13580class ModuleRefNode(ExprNode): 13581 # Simple returns the module object 13582 13583 type = py_object_type 13584 is_temp = False 13585 subexprs = [] 13586 13587 def analyse_types(self, env): 13588 return self 13589 13590 def may_be_none(self): 13591 return False 13592 13593 def calculate_result_code(self): 13594 return Naming.module_cname 13595 13596 def generate_result_code(self, code): 13597 pass 13598 13599class DocstringRefNode(ExprNode): 13600 # Extracts the docstring of the body element 13601 13602 subexprs = ['body'] 13603 type = py_object_type 13604 is_temp = True 13605 13606 def __init__(self, pos, body): 13607 ExprNode.__init__(self, pos) 13608 assert body.type.is_pyobject 13609 self.body = body 13610 13611 def analyse_types(self, env): 13612 return self 13613 13614 def generate_result_code(self, code): 13615 code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % ( 13616 self.result(), self.body.result(), 13617 code.intern_identifier(StringEncoding.EncodedString("__doc__")), 13618 code.error_goto_if_null(self.result(), self.pos))) 13619 code.put_gotref(self.result()) 13620 13621 13622 13623#------------------------------------------------------------------------------------ 13624# 13625# Runtime support code 13626# 13627#------------------------------------------------------------------------------------ 13628 13629pyerr_occurred_withgil_utility_code= UtilityCode( 13630proto = """ 13631static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */ 13632""", 13633impl = """ 13634static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { 13635 int err; 13636 #ifdef WITH_THREAD 13637 PyGILState_STATE _save = PyGILState_Ensure(); 13638 #endif 13639 err = !!PyErr_Occurred(); 13640 #ifdef WITH_THREAD 13641 PyGILState_Release(_save); 13642 #endif 13643 return err; 13644} 13645""" 13646) 13647 13648#------------------------------------------------------------------------------------ 13649 13650raise_unbound_local_error_utility_code = UtilityCode( 13651proto = """ 13652static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); 13653""", 13654impl = """ 13655static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { 13656 PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); 13657} 13658""") 13659 13660raise_closure_name_error_utility_code = UtilityCode( 13661proto = """ 13662static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname); 13663""", 13664impl = """ 13665static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) { 13666 PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname); 13667} 13668""") 13669 13670# Don't inline the function, it should really never be called in production 13671raise_unbound_memoryview_utility_code_nogil = UtilityCode( 13672proto = """ 13673static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname); 13674""", 13675impl = """ 13676static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) { 13677 #ifdef WITH_THREAD 13678 PyGILState_STATE gilstate = PyGILState_Ensure(); 13679 #endif 13680 __Pyx_RaiseUnboundLocalError(varname); 13681 #ifdef WITH_THREAD 13682 PyGILState_Release(gilstate); 13683 #endif 13684} 13685""", 13686requires = [raise_unbound_local_error_utility_code]) 13687 13688#------------------------------------------------------------------------------------ 13689 13690raise_too_many_values_to_unpack = UtilityCode.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c") 13691raise_need_more_values_to_unpack = UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c") 13692tuple_unpacking_error_code = UtilityCode.load_cached("UnpackTupleError", "ObjectHandling.c") 13693