OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Parse tree nodes for expressions |
| 3 # |
| 4 |
| 5 import cython |
| 6 cython.declare(error=object, warning=object, warn_once=object, InternalError=obj
ect, |
| 7 CompileError=object, UtilityCode=object, TempitaUtilityCode=objec
t, |
| 8 StringEncoding=object, operator=object, |
| 9 Naming=object, Nodes=object, PyrexTypes=object, py_object_type=ob
ject, |
| 10 list_type=object, tuple_type=object, set_type=object, dict_type=o
bject, |
| 11 unicode_type=object, str_type=object, bytes_type=object, type_typ
e=object, |
| 12 Builtin=object, Symtab=object, Utils=object, find_coercion_error=
object, |
| 13 debug_disposal_code=object, debug_temp_alloc=object, debug_coerci
on=object, |
| 14 bytearray_type=object, slice_type=object) |
| 15 |
| 16 import sys |
| 17 import copy |
| 18 import operator |
| 19 |
| 20 from Errors import error, warning, warn_once, InternalError, CompileError |
| 21 from Errors import hold_errors, release_errors, held_errors, report_error |
| 22 from Code import UtilityCode, TempitaUtilityCode |
| 23 import StringEncoding |
| 24 import Naming |
| 25 import Nodes |
| 26 from Nodes import Node |
| 27 import PyrexTypes |
| 28 from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \ |
| 29 unspecified_type |
| 30 import TypeSlots |
| 31 from Builtin import list_type, tuple_type, set_type, dict_type, type_type, \ |
| 32 unicode_type, str_type, bytes_type, bytearray_type, basestring_type, slice_
type |
| 33 import Builtin |
| 34 import Symtab |
| 35 from Cython import Utils |
| 36 from Annotate import AnnotationItem |
| 37 from Cython.Compiler import Future |
| 38 from Cython.Debugging import print_call_chain |
| 39 from DebugFlags import debug_disposal_code, debug_temp_alloc, \ |
| 40 debug_coercion |
| 41 |
| 42 try: |
| 43 from __builtin__ import basestring |
| 44 except ImportError: |
| 45 basestring = str # Python 3 |
| 46 |
| 47 try: |
| 48 from builtins import bytes |
| 49 except ImportError: |
| 50 bytes = str # Python 2 |
| 51 |
| 52 |
| 53 class NotConstant(object): |
| 54 _obj = None |
| 55 |
| 56 def __new__(cls): |
| 57 if NotConstant._obj is None: |
| 58 NotConstant._obj = super(NotConstant, cls).__new__(cls) |
| 59 |
| 60 return NotConstant._obj |
| 61 |
| 62 def __repr__(self): |
| 63 return "<NOT CONSTANT>" |
| 64 |
| 65 not_a_constant = NotConstant() |
| 66 constant_value_not_set = object() |
| 67 |
| 68 # error messages when coercing from key[0] to key[1] |
| 69 coercion_error_dict = { |
| 70 # string related errors |
| 71 (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string
to 'bytes' implicitly, encoding required.", |
| 72 (Builtin.unicode_type, Builtin.str_type) : "Cannot convert Unicode string
to 'str' implicitly. This is not portable and requires explicit encoding.", |
| 73 (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects only s
upport coercion to Py_UNICODE*.", |
| 74 (Builtin.unicode_type, PyrexTypes.c_uchar_ptr_type) : "Unicode objects only
support coercion to Py_UNICODE*.", |
| 75 (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object
to unicode implicitly, decoding required", |
| 76 (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to s
tr implicitly. This is not portable to Py3.", |
| 77 (Builtin.bytes_type, Builtin.basestring_type) : "Cannot convert 'bytes' obje
ct to basestring implicitly. This is not portable to Py3.", |
| 78 (Builtin.bytes_type, PyrexTypes.c_py_unicode_ptr_type) : "Cannot convert 'by
tes' object to Py_UNICODE*, use 'unicode'.", |
| 79 (Builtin.basestring_type, Builtin.bytes_type) : "Cannot convert 'basestring'
object to bytes implicitly. This is not portable.", |
| 80 (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coerc
ion to unicode, use a unicode string literal instead (u'')", |
| 81 (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' im
plicitly. This is not portable.", |
| 82 (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not suppo
rt coercion to C types (use 'bytes'?).", |
| 83 (Builtin.str_type, PyrexTypes.c_uchar_ptr_type) : "'str' objects do not supp
ort coercion to C types (use 'bytes'?).", |
| 84 (Builtin.str_type, PyrexTypes.c_py_unicode_ptr_type) : "'str' objects do not
support coercion to C types (use 'unicode'?).", |
| 85 (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*'
to unicode implicitly, decoding required", |
| 86 (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*
' to unicode implicitly, decoding required", |
| 87 } |
| 88 |
| 89 def find_coercion_error(type_tuple, default, env): |
| 90 err = coercion_error_dict.get(type_tuple) |
| 91 if err is None: |
| 92 return default |
| 93 elif ((PyrexTypes.c_char_ptr_type in type_tuple or PyrexTypes.c_uchar_ptr_ty
pe in type_tuple) |
| 94 and env.directives['c_string_encoding']): |
| 95 if type_tuple[1].is_pyobject: |
| 96 return default |
| 97 elif env.directives['c_string_encoding'] in ('ascii', 'default'): |
| 98 return default |
| 99 else: |
| 100 return "'%s' objects do not support coercion to C types with non-asc
ii or non-default c_string_encoding" % type_tuple[0].name |
| 101 else: |
| 102 return err |
| 103 |
| 104 |
| 105 def default_str_type(env): |
| 106 return { |
| 107 'bytes': bytes_type, |
| 108 'bytearray': bytearray_type, |
| 109 'str': str_type, |
| 110 'unicode': unicode_type |
| 111 }.get(env.directives['c_string_type']) |
| 112 |
| 113 |
| 114 def check_negative_indices(*nodes): |
| 115 """ |
| 116 Raise a warning on nodes that are known to have negative numeric values. |
| 117 Used to find (potential) bugs inside of "wraparound=False" sections. |
| 118 """ |
| 119 for node in nodes: |
| 120 if (node is None |
| 121 or not isinstance(node.constant_result, (int, float, long))): |
| 122 continue |
| 123 if node.constant_result < 0: |
| 124 warning(node.pos, |
| 125 "the result of using negative indices inside of " |
| 126 "code sections marked as 'wraparound=False' is " |
| 127 "undefined", level=1) |
| 128 |
| 129 |
| 130 def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None): |
| 131 if not seq_node.is_sequence_constructor: |
| 132 if seq_type is None: |
| 133 seq_type = seq_node.infer_type(env) |
| 134 if seq_type is tuple_type: |
| 135 # tuples are immutable => we can safely follow assignments |
| 136 if seq_node.cf_state and len(seq_node.cf_state) == 1: |
| 137 try: |
| 138 seq_node = seq_node.cf_state[0].rhs |
| 139 except AttributeError: |
| 140 pass |
| 141 if seq_node is not None and seq_node.is_sequence_constructor: |
| 142 if index_node is not None and index_node.has_constant_result(): |
| 143 try: |
| 144 item = seq_node.args[index_node.constant_result] |
| 145 except (ValueError, TypeError, IndexError): |
| 146 pass |
| 147 else: |
| 148 return item.infer_type(env) |
| 149 # if we're lucky, all items have the same type |
| 150 item_types = set([item.infer_type(env) for item in seq_node.args]) |
| 151 if len(item_types) == 1: |
| 152 return item_types.pop() |
| 153 return None |
| 154 |
| 155 |
| 156 class ExprNode(Node): |
| 157 # subexprs [string] Class var holding names of subexpr node attrs |
| 158 # type PyrexType Type of the result |
| 159 # result_code string Code fragment |
| 160 # result_ctype string C type of result_code if different from type |
| 161 # is_temp boolean Result is in a temporary variable |
| 162 # is_sequence_constructor |
| 163 # boolean Is a list or tuple constructor expression |
| 164 # is_starred boolean Is a starred expression (e.g. '*a') |
| 165 # saved_subexpr_nodes |
| 166 # [ExprNode or [ExprNode or None] or None] |
| 167 # Cached result of subexpr_nodes() |
| 168 # use_managed_ref boolean use ref-counted temps/assignments/etc. |
| 169 # result_is_used boolean indicates that the result will be dropped and t
he |
| 170 # result_code/temp_result can safely be set to No
ne |
| 171 |
| 172 result_ctype = None |
| 173 type = None |
| 174 temp_code = None |
| 175 old_temp = None # error checker for multiple frees etc. |
| 176 use_managed_ref = True # can be set by optimisation transforms |
| 177 result_is_used = True |
| 178 |
| 179 # The Analyse Expressions phase for expressions is split |
| 180 # into two sub-phases: |
| 181 # |
| 182 # Analyse Types |
| 183 # Determines the result type of the expression based |
| 184 # on the types of its sub-expressions, and inserts |
| 185 # coercion nodes into the expression tree where needed. |
| 186 # Marks nodes which will need to have temporary variables |
| 187 # allocated. |
| 188 # |
| 189 # Allocate Temps |
| 190 # Allocates temporary variables where needed, and fills |
| 191 # in the result_code field of each node. |
| 192 # |
| 193 # ExprNode provides some convenience routines which |
| 194 # perform both of the above phases. These should only |
| 195 # be called from statement nodes, and only when no |
| 196 # coercion nodes need to be added around the expression |
| 197 # being analysed. In that case, the above two phases |
| 198 # should be invoked separately. |
| 199 # |
| 200 # Framework code in ExprNode provides much of the common |
| 201 # processing for the various phases. It makes use of the |
| 202 # 'subexprs' class attribute of ExprNodes, which should |
| 203 # contain a list of the names of attributes which can |
| 204 # hold sub-nodes or sequences of sub-nodes. |
| 205 # |
| 206 # The framework makes use of a number of abstract methods. |
| 207 # Their responsibilities are as follows. |
| 208 # |
| 209 # Declaration Analysis phase |
| 210 # |
| 211 # analyse_target_declaration |
| 212 # Called during the Analyse Declarations phase to analyse |
| 213 # the LHS of an assignment or argument of a del statement. |
| 214 # Nodes which cannot be the LHS of an assignment need not |
| 215 # implement it. |
| 216 # |
| 217 # Expression Analysis phase |
| 218 # |
| 219 # analyse_types |
| 220 # - Call analyse_types on all sub-expressions. |
| 221 # - Check operand types, and wrap coercion nodes around |
| 222 # sub-expressions where needed. |
| 223 # - Set the type of this node. |
| 224 # - If a temporary variable will be required for the |
| 225 # result, set the is_temp flag of this node. |
| 226 # |
| 227 # analyse_target_types |
| 228 # Called during the Analyse Types phase to analyse |
| 229 # the LHS of an assignment or argument of a del |
| 230 # statement. Similar responsibilities to analyse_types. |
| 231 # |
| 232 # target_code |
| 233 # Called by the default implementation of allocate_target_temps. |
| 234 # Should return a C lvalue for assigning to the node. The default |
| 235 # implementation calls calculate_result_code. |
| 236 # |
| 237 # check_const |
| 238 # - Check that this node and its subnodes form a |
| 239 # legal constant expression. If so, do nothing, |
| 240 # otherwise call not_const. |
| 241 # |
| 242 # The default implementation of check_const |
| 243 # assumes that the expression is not constant. |
| 244 # |
| 245 # check_const_addr |
| 246 # - Same as check_const, except check that the |
| 247 # expression is a C lvalue whose address is |
| 248 # constant. Otherwise, call addr_not_const. |
| 249 # |
| 250 # The default implementation of calc_const_addr |
| 251 # assumes that the expression is not a constant |
| 252 # lvalue. |
| 253 # |
| 254 # Code Generation phase |
| 255 # |
| 256 # generate_evaluation_code |
| 257 # - Call generate_evaluation_code for sub-expressions. |
| 258 # - Perform the functions of generate_result_code |
| 259 # (see below). |
| 260 # - If result is temporary, call generate_disposal_code |
| 261 # on all sub-expressions. |
| 262 # |
| 263 # A default implementation of generate_evaluation_code |
| 264 # is provided which uses the following abstract methods: |
| 265 # |
| 266 # generate_result_code |
| 267 # - Generate any C statements necessary to calculate |
| 268 # the result of this node from the results of its |
| 269 # sub-expressions. |
| 270 # |
| 271 # calculate_result_code |
| 272 # - Should return a C code fragment evaluating to the |
| 273 # result. This is only called when the result is not |
| 274 # a temporary. |
| 275 # |
| 276 # generate_assignment_code |
| 277 # Called on the LHS of an assignment. |
| 278 # - Call generate_evaluation_code for sub-expressions. |
| 279 # - Generate code to perform the assignment. |
| 280 # - If the assignment absorbed a reference, call |
| 281 # generate_post_assignment_code on the RHS, |
| 282 # otherwise call generate_disposal_code on it. |
| 283 # |
| 284 # generate_deletion_code |
| 285 # Called on an argument of a del statement. |
| 286 # - Call generate_evaluation_code for sub-expressions. |
| 287 # - Generate code to perform the deletion. |
| 288 # - Call generate_disposal_code on all sub-expressions. |
| 289 # |
| 290 # |
| 291 |
| 292 is_sequence_constructor = 0 |
| 293 is_string_literal = 0 |
| 294 is_attribute = 0 |
| 295 is_subscript = 0 |
| 296 |
| 297 saved_subexpr_nodes = None |
| 298 is_temp = 0 |
| 299 is_target = 0 |
| 300 is_starred = 0 |
| 301 |
| 302 constant_result = constant_value_not_set |
| 303 |
| 304 # whether this node with a memoryview type should be broadcast |
| 305 memslice_broadcast = False |
| 306 |
| 307 child_attrs = property(fget=operator.attrgetter('subexprs')) |
| 308 |
| 309 def not_implemented(self, method_name): |
| 310 print_call_chain(method_name, "not implemented") ### |
| 311 raise InternalError( |
| 312 "%s.%s not implemented" % |
| 313 (self.__class__.__name__, method_name)) |
| 314 |
| 315 def is_lvalue(self): |
| 316 return 0 |
| 317 |
| 318 def is_addressable(self): |
| 319 return self.is_lvalue() and not self.type.is_memoryviewslice |
| 320 |
| 321 def is_ephemeral(self): |
| 322 # An ephemeral node is one whose result is in |
| 323 # a Python temporary and we suspect there are no |
| 324 # other references to it. Certain operations are |
| 325 # disallowed on such values, since they are |
| 326 # likely to result in a dangling pointer. |
| 327 return self.type.is_pyobject and self.is_temp |
| 328 |
| 329 def subexpr_nodes(self): |
| 330 # Extract a list of subexpression nodes based |
| 331 # on the contents of the subexprs class attribute. |
| 332 nodes = [] |
| 333 for name in self.subexprs: |
| 334 item = getattr(self, name) |
| 335 if item is not None: |
| 336 if type(item) is list: |
| 337 nodes.extend(item) |
| 338 else: |
| 339 nodes.append(item) |
| 340 return nodes |
| 341 |
| 342 def result(self): |
| 343 if self.is_temp: |
| 344 return self.temp_code |
| 345 else: |
| 346 return self.calculate_result_code() |
| 347 |
| 348 def result_as(self, type = None): |
| 349 # Return the result code cast to the specified C type. |
| 350 if (self.is_temp and self.type.is_pyobject and |
| 351 type != py_object_type): |
| 352 # Allocated temporaries are always PyObject *, which may not |
| 353 # reflect the actual type (e.g. an extension type) |
| 354 return typecast(type, py_object_type, self.result()) |
| 355 return typecast(type, self.ctype(), self.result()) |
| 356 |
| 357 def py_result(self): |
| 358 # Return the result code cast to PyObject *. |
| 359 return self.result_as(py_object_type) |
| 360 |
| 361 def ctype(self): |
| 362 # Return the native C type of the result (i.e. the |
| 363 # C type of the result_code expression). |
| 364 return self.result_ctype or self.type |
| 365 |
| 366 def get_constant_c_result_code(self): |
| 367 # Return the constant value of this node as a result code |
| 368 # string, or None if the node is not constant. This method |
| 369 # can be called when the constant result code is required |
| 370 # before the code generation phase. |
| 371 # |
| 372 # The return value is a string that can represent a simple C |
| 373 # value, a constant C name or a constant C expression. If the |
| 374 # node type depends on Python code, this must return None. |
| 375 return None |
| 376 |
| 377 def calculate_constant_result(self): |
| 378 # Calculate the constant compile time result value of this |
| 379 # expression and store it in ``self.constant_result``. Does |
| 380 # nothing by default, thus leaving ``self.constant_result`` |
| 381 # unknown. If valid, the result can be an arbitrary Python |
| 382 # value. |
| 383 # |
| 384 # This must only be called when it is assured that all |
| 385 # sub-expressions have a valid constant_result value. The |
| 386 # ConstantFolding transform will do this. |
| 387 pass |
| 388 |
| 389 def has_constant_result(self): |
| 390 return self.constant_result is not constant_value_not_set and \ |
| 391 self.constant_result is not not_a_constant |
| 392 |
| 393 def compile_time_value(self, denv): |
| 394 # Return value of compile-time expression, or report error. |
| 395 error(self.pos, "Invalid compile-time expression") |
| 396 |
| 397 def compile_time_value_error(self, e): |
| 398 error(self.pos, "Error in compile-time expression: %s: %s" % ( |
| 399 e.__class__.__name__, e)) |
| 400 |
| 401 # ------------- Declaration Analysis ---------------- |
| 402 |
| 403 def analyse_target_declaration(self, env): |
| 404 error(self.pos, "Cannot assign to or delete this") |
| 405 |
| 406 # ------------- Expression Analysis ---------------- |
| 407 |
| 408 def analyse_const_expression(self, env): |
| 409 # Called during the analyse_declarations phase of a |
| 410 # constant expression. Analyses the expression's type, |
| 411 # checks whether it is a legal const expression, |
| 412 # and determines its value. |
| 413 node = self.analyse_types(env) |
| 414 node.check_const() |
| 415 return node |
| 416 |
| 417 def analyse_expressions(self, env): |
| 418 # Convenience routine performing both the Type |
| 419 # Analysis and Temp Allocation phases for a whole |
| 420 # expression. |
| 421 return self.analyse_types(env) |
| 422 |
| 423 def analyse_target_expression(self, env, rhs): |
| 424 # Convenience routine performing both the Type |
| 425 # Analysis and Temp Allocation phases for the LHS of |
| 426 # an assignment. |
| 427 return self.analyse_target_types(env) |
| 428 |
| 429 def analyse_boolean_expression(self, env): |
| 430 # Analyse expression and coerce to a boolean. |
| 431 node = self.analyse_types(env) |
| 432 bool = node.coerce_to_boolean(env) |
| 433 return bool |
| 434 |
| 435 def analyse_temp_boolean_expression(self, env): |
| 436 # Analyse boolean expression and coerce result into |
| 437 # a temporary. This is used when a branch is to be |
| 438 # performed on the result and we won't have an |
| 439 # opportunity to ensure disposal code is executed |
| 440 # afterwards. By forcing the result into a temporary, |
| 441 # we ensure that all disposal has been done by the |
| 442 # time we get the result. |
| 443 node = self.analyse_types(env) |
| 444 return node.coerce_to_boolean(env).coerce_to_simple(env) |
| 445 |
| 446 # --------------- Type Inference ----------------- |
| 447 |
| 448 def type_dependencies(self, env): |
| 449 # Returns the list of entries whose types must be determined |
| 450 # before the type of self can be inferred. |
| 451 if hasattr(self, 'type') and self.type is not None: |
| 452 return () |
| 453 return sum([node.type_dependencies(env) for node in self.subexpr_nodes()
], ()) |
| 454 |
| 455 def infer_type(self, env): |
| 456 # Attempt to deduce the type of self. |
| 457 # Differs from analyse_types as it avoids unnecessary |
| 458 # analysis of subexpressions, but can assume everything |
| 459 # in self.type_dependencies() has been resolved. |
| 460 if hasattr(self, 'type') and self.type is not None: |
| 461 return self.type |
| 462 elif hasattr(self, 'entry') and self.entry is not None: |
| 463 return self.entry.type |
| 464 else: |
| 465 self.not_implemented("infer_type") |
| 466 |
| 467 def nonlocally_immutable(self): |
| 468 # Returns whether this variable is a safe reference, i.e. |
| 469 # can't be modified as part of globals or closures. |
| 470 return self.is_literal or self.is_temp or self.type.is_array or self.typ
e.is_cfunction |
| 471 |
| 472 # --------------- Type Analysis ------------------ |
| 473 |
| 474 def analyse_as_module(self, env): |
| 475 # If this node can be interpreted as a reference to a |
| 476 # cimported module, return its scope, else None. |
| 477 return None |
| 478 |
| 479 def analyse_as_type(self, env): |
| 480 # If this node can be interpreted as a reference to a |
| 481 # type, return that type, else None. |
| 482 return None |
| 483 |
| 484 def analyse_as_extension_type(self, env): |
| 485 # If this node can be interpreted as a reference to an |
| 486 # extension type or builtin type, return its type, else None. |
| 487 return None |
| 488 |
| 489 def analyse_types(self, env): |
| 490 self.not_implemented("analyse_types") |
| 491 |
| 492 def analyse_target_types(self, env): |
| 493 return self.analyse_types(env) |
| 494 |
| 495 def nogil_check(self, env): |
| 496 # By default, any expression based on Python objects is |
| 497 # prevented in nogil environments. Subtypes must override |
| 498 # this if they can work without the GIL. |
| 499 if self.type and self.type.is_pyobject: |
| 500 self.gil_error() |
| 501 |
| 502 def gil_assignment_check(self, env): |
| 503 if env.nogil and self.type.is_pyobject: |
| 504 error(self.pos, "Assignment of Python object not allowed without gil
") |
| 505 |
| 506 def check_const(self): |
| 507 self.not_const() |
| 508 return False |
| 509 |
| 510 def not_const(self): |
| 511 error(self.pos, "Not allowed in a constant expression") |
| 512 |
| 513 def check_const_addr(self): |
| 514 self.addr_not_const() |
| 515 return False |
| 516 |
| 517 def addr_not_const(self): |
| 518 error(self.pos, "Address is not constant") |
| 519 |
| 520 # ----------------- Result Allocation ----------------- |
| 521 |
| 522 def result_in_temp(self): |
| 523 # Return true if result is in a temporary owned by |
| 524 # this node or one of its subexpressions. Overridden |
| 525 # by certain nodes which can share the result of |
| 526 # a subnode. |
| 527 return self.is_temp |
| 528 |
| 529 def target_code(self): |
| 530 # Return code fragment for use as LHS of a C assignment. |
| 531 return self.calculate_result_code() |
| 532 |
| 533 def calculate_result_code(self): |
| 534 self.not_implemented("calculate_result_code") |
| 535 |
| 536 # def release_target_temp(self, env): |
| 537 # # Release temporaries used by LHS of an assignment. |
| 538 # self.release_subexpr_temps(env) |
| 539 |
| 540 def allocate_temp_result(self, code): |
| 541 if self.temp_code: |
| 542 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self
.__class__.__name__, self.pos)) |
| 543 type = self.type |
| 544 if not type.is_void: |
| 545 if type.is_pyobject: |
| 546 type = PyrexTypes.py_object_type |
| 547 self.temp_code = code.funcstate.allocate_temp( |
| 548 type, manage_ref=self.use_managed_ref) |
| 549 else: |
| 550 self.temp_code = None |
| 551 |
| 552 def release_temp_result(self, code): |
| 553 if not self.temp_code: |
| 554 if not self.result_is_used: |
| 555 # not used anyway, so ignore if not set up |
| 556 return |
| 557 if self.old_temp: |
| 558 raise RuntimeError("temp %s released multiple times in %s" % ( |
| 559 self.old_temp, self.__class__.__name__)) |
| 560 else: |
| 561 raise RuntimeError("no temp, but release requested in %s" % ( |
| 562 self.__class__.__name__)) |
| 563 code.funcstate.release_temp(self.temp_code) |
| 564 self.old_temp = self.temp_code |
| 565 self.temp_code = None |
| 566 |
| 567 # ---------------- Code Generation ----------------- |
| 568 |
| 569 def make_owned_reference(self, code): |
| 570 """ |
| 571 If result is a pyobject, make sure we own a reference to it. |
| 572 If the result is in a temp, it is already a new reference. |
| 573 """ |
| 574 if self.type.is_pyobject and not self.result_in_temp(): |
| 575 code.put_incref(self.result(), self.ctype()) |
| 576 |
| 577 def make_owned_memoryviewslice(self, code): |
| 578 """ |
| 579 Make sure we own the reference to this memoryview slice. |
| 580 """ |
| 581 if not self.result_in_temp(): |
| 582 code.put_incref_memoryviewslice(self.result(), |
| 583 have_gil=self.in_nogil_context) |
| 584 |
| 585 def generate_evaluation_code(self, code): |
| 586 # Generate code to evaluate this node and |
| 587 # its sub-expressions, and dispose of any |
| 588 # temporary results of its sub-expressions. |
| 589 self.generate_subexpr_evaluation_code(code) |
| 590 |
| 591 code.mark_pos(self.pos) |
| 592 if self.is_temp: |
| 593 self.allocate_temp_result(code) |
| 594 |
| 595 self.generate_result_code(code) |
| 596 if self.is_temp: |
| 597 # If we are temp we do not need to wait until this node is disposed |
| 598 # before disposing children. |
| 599 self.generate_subexpr_disposal_code(code) |
| 600 self.free_subexpr_temps(code) |
| 601 |
| 602 def generate_subexpr_evaluation_code(self, code): |
| 603 for node in self.subexpr_nodes(): |
| 604 node.generate_evaluation_code(code) |
| 605 |
| 606 def generate_result_code(self, code): |
| 607 self.not_implemented("generate_result_code") |
| 608 |
| 609 def generate_disposal_code(self, code): |
| 610 if self.is_temp: |
| 611 if self.result(): |
| 612 if self.type.is_pyobject: |
| 613 code.put_decref_clear(self.result(), self.ctype()) |
| 614 elif self.type.is_memoryviewslice: |
| 615 code.put_xdecref_memoryviewslice( |
| 616 self.result(), have_gil=not self.in_nogil_context) |
| 617 else: |
| 618 # Already done if self.is_temp |
| 619 self.generate_subexpr_disposal_code(code) |
| 620 |
| 621 def generate_subexpr_disposal_code(self, code): |
| 622 # Generate code to dispose of temporary results |
| 623 # of all sub-expressions. |
| 624 for node in self.subexpr_nodes(): |
| 625 node.generate_disposal_code(code) |
| 626 |
| 627 def generate_post_assignment_code(self, code): |
| 628 if self.is_temp: |
| 629 if self.type.is_pyobject: |
| 630 code.putln("%s = 0;" % self.result()) |
| 631 elif self.type.is_memoryviewslice: |
| 632 code.putln("%s.memview = NULL;" % self.result()) |
| 633 code.putln("%s.data = NULL;" % self.result()) |
| 634 else: |
| 635 self.generate_subexpr_disposal_code(code) |
| 636 |
| 637 def generate_assignment_code(self, rhs, code): |
| 638 # Stub method for nodes which are not legal as |
| 639 # the LHS of an assignment. An error will have |
| 640 # been reported earlier. |
| 641 pass |
| 642 |
| 643 def generate_deletion_code(self, code, ignore_nonexisting=False): |
| 644 # Stub method for nodes that are not legal as |
| 645 # the argument of a del statement. An error |
| 646 # will have been reported earlier. |
| 647 pass |
| 648 |
| 649 def free_temps(self, code): |
| 650 if self.is_temp: |
| 651 if not self.type.is_void: |
| 652 self.release_temp_result(code) |
| 653 else: |
| 654 self.free_subexpr_temps(code) |
| 655 |
| 656 def free_subexpr_temps(self, code): |
| 657 for sub in self.subexpr_nodes(): |
| 658 sub.free_temps(code) |
| 659 |
| 660 def generate_function_definitions(self, env, code): |
| 661 pass |
| 662 |
| 663 # ---------------- Annotation --------------------- |
| 664 |
| 665 def annotate(self, code): |
| 666 for node in self.subexpr_nodes(): |
| 667 node.annotate(code) |
| 668 |
| 669 # ----------------- Coercion ---------------------- |
| 670 |
| 671 def coerce_to(self, dst_type, env): |
| 672 # Coerce the result so that it can be assigned to |
| 673 # something of type dst_type. If processing is necessary, |
| 674 # wraps this node in a coercion node and returns that. |
| 675 # Otherwise, returns this node unchanged. |
| 676 # |
| 677 # This method is called during the analyse_expressions |
| 678 # phase of the src_node's processing. |
| 679 # |
| 680 # Note that subclasses that override this (especially |
| 681 # ConstNodes) must not (re-)set their own .type attribute |
| 682 # here. Since expression nodes may turn up in different |
| 683 # places in the tree (e.g. inside of CloneNodes in cascaded |
| 684 # assignments), this method must return a new node instance |
| 685 # if it changes the type. |
| 686 # |
| 687 src = self |
| 688 src_type = self.type |
| 689 |
| 690 if self.check_for_coercion_error(dst_type, env): |
| 691 return self |
| 692 |
| 693 if dst_type.is_reference and not src_type.is_reference: |
| 694 dst_type = dst_type.ref_base_type |
| 695 |
| 696 if src_type.is_const: |
| 697 src_type = src_type.const_base_type |
| 698 |
| 699 if src_type.is_fused or dst_type.is_fused: |
| 700 # See if we are coercing a fused function to a pointer to a |
| 701 # specialized function |
| 702 if (src_type.is_cfunction and not dst_type.is_fused and |
| 703 dst_type.is_ptr and dst_type.base_type.is_cfunction): |
| 704 |
| 705 dst_type = dst_type.base_type |
| 706 |
| 707 for signature in src_type.get_all_specialized_function_types(): |
| 708 if signature.same_as(dst_type): |
| 709 src.type = signature |
| 710 src.entry = src.type.entry |
| 711 src.entry.used = True |
| 712 return self |
| 713 |
| 714 if src_type.is_fused: |
| 715 error(self.pos, "Type is not specialized") |
| 716 else: |
| 717 error(self.pos, "Cannot coerce to a type that is not specialized
") |
| 718 |
| 719 self.type = error_type |
| 720 return self |
| 721 |
| 722 if self.coercion_type is not None: |
| 723 # This is purely for error checking purposes! |
| 724 node = NameNode(self.pos, name='', type=self.coercion_type) |
| 725 node.coerce_to(dst_type, env) |
| 726 |
| 727 if dst_type.is_memoryviewslice: |
| 728 import MemoryView |
| 729 if not src.type.is_memoryviewslice: |
| 730 if src.type.is_pyobject: |
| 731 src = CoerceToMemViewSliceNode(src, dst_type, env) |
| 732 elif src.type.is_array: |
| 733 src = CythonArrayNode.from_carray(src, env).coerce_to( |
| 734 dst_type, env) |
| 735 elif not src_type.is_error: |
| 736 error(self.pos, |
| 737 "Cannot convert '%s' to memoryviewslice" % |
| 738 (src_type,)) |
| 739 elif not MemoryView.src_conforms_to_dst( |
| 740 src.type, dst_type, broadcast=self.memslice_broadcast): |
| 741 if src.type.dtype.same_as(dst_type.dtype): |
| 742 msg = "Memoryview '%s' not conformable to memoryview '%s'." |
| 743 tup = src.type, dst_type |
| 744 else: |
| 745 msg = "Different base types for memoryviews (%s, %s)" |
| 746 tup = src.type.dtype, dst_type.dtype |
| 747 |
| 748 error(self.pos, msg % tup) |
| 749 |
| 750 elif dst_type.is_pyobject: |
| 751 if not src.type.is_pyobject: |
| 752 if dst_type is bytes_type and src.type.is_int: |
| 753 src = CoerceIntToBytesNode(src, env) |
| 754 else: |
| 755 src = CoerceToPyTypeNode(src, env, type=dst_type) |
| 756 if not src.type.subtype_of(dst_type): |
| 757 if src.constant_result is not None: |
| 758 src = PyTypeTestNode(src, dst_type, env) |
| 759 elif src.type.is_pyobject: |
| 760 src = CoerceFromPyTypeNode(dst_type, src, env) |
| 761 elif (dst_type.is_complex |
| 762 and src_type != dst_type |
| 763 and dst_type.assignable_from(src_type)): |
| 764 src = CoerceToComplexNode(src, dst_type, env) |
| 765 else: # neither src nor dst are py types |
| 766 # Added the string comparison, since for c types that |
| 767 # is enough, but Cython gets confused when the types are |
| 768 # in different pxi files. |
| 769 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(s
rc_type)): |
| 770 self.fail_assignment(dst_type) |
| 771 return src |
| 772 |
| 773 def fail_assignment(self, dst_type): |
| 774 error(self.pos, "Cannot assign type '%s' to '%s'" % (self.type, dst_type
)) |
| 775 |
| 776 def check_for_coercion_error(self, dst_type, env, fail=False, default=None): |
| 777 if fail and not default: |
| 778 default = "Cannot assign type '%(FROM)s' to '%(TO)s'" |
| 779 message = find_coercion_error((self.type, dst_type), default, env) |
| 780 if message is not None: |
| 781 error(self.pos, message % {'FROM': self.type, 'TO': dst_type}) |
| 782 return True |
| 783 if fail: |
| 784 self.fail_assignment(dst_type) |
| 785 return True |
| 786 return False |
| 787 |
| 788 def coerce_to_pyobject(self, env): |
| 789 return self.coerce_to(PyrexTypes.py_object_type, env) |
| 790 |
| 791 def coerce_to_boolean(self, env): |
| 792 # Coerce result to something acceptable as |
| 793 # a boolean value. |
| 794 |
| 795 # if it's constant, calculate the result now |
| 796 if self.has_constant_result(): |
| 797 bool_value = bool(self.constant_result) |
| 798 return BoolNode(self.pos, value=bool_value, |
| 799 constant_result=bool_value) |
| 800 |
| 801 type = self.type |
| 802 if type.is_enum or type.is_error: |
| 803 return self |
| 804 elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float: |
| 805 return CoerceToBooleanNode(self, env) |
| 806 else: |
| 807 error(self.pos, "Type '%s' not acceptable as a boolean" % type) |
| 808 return self |
| 809 |
| 810 def coerce_to_integer(self, env): |
| 811 # If not already some C integer type, coerce to longint. |
| 812 if self.type.is_int: |
| 813 return self |
| 814 else: |
| 815 return self.coerce_to(PyrexTypes.c_long_type, env) |
| 816 |
| 817 def coerce_to_temp(self, env): |
| 818 # Ensure that the result is in a temporary. |
| 819 if self.result_in_temp(): |
| 820 return self |
| 821 else: |
| 822 return CoerceToTempNode(self, env) |
| 823 |
| 824 def coerce_to_simple(self, env): |
| 825 # Ensure that the result is simple (see is_simple). |
| 826 if self.is_simple(): |
| 827 return self |
| 828 else: |
| 829 return self.coerce_to_temp(env) |
| 830 |
| 831 def is_simple(self): |
| 832 # A node is simple if its result is something that can |
| 833 # be referred to without performing any operations, e.g. |
| 834 # a constant, local var, C global var, struct member |
| 835 # reference, or temporary. |
| 836 return self.result_in_temp() |
| 837 |
| 838 def may_be_none(self): |
| 839 if self.type and not (self.type.is_pyobject or |
| 840 self.type.is_memoryviewslice): |
| 841 return False |
| 842 if self.has_constant_result(): |
| 843 return self.constant_result is not None |
| 844 return True |
| 845 |
| 846 def as_cython_attribute(self): |
| 847 return None |
| 848 |
| 849 def as_none_safe_node(self, message, error="PyExc_TypeError", format_args=()
): |
| 850 # Wraps the node in a NoneCheckNode if it is not known to be |
| 851 # not-None (e.g. because it is a Python literal). |
| 852 if self.may_be_none(): |
| 853 return NoneCheckNode(self, error, message, format_args) |
| 854 else: |
| 855 return self |
| 856 |
| 857 @classmethod |
| 858 def from_node(cls, node, **kwargs): |
| 859 """Instantiate this node class from another node, properly |
| 860 copying over all attributes that one would forget otherwise. |
| 861 """ |
| 862 attributes = "cf_state cf_maybe_null cf_is_null constant_result".split() |
| 863 for attr_name in attributes: |
| 864 if attr_name in kwargs: |
| 865 continue |
| 866 try: |
| 867 value = getattr(node, attr_name) |
| 868 except AttributeError: |
| 869 pass |
| 870 else: |
| 871 kwargs[attr_name] = value |
| 872 return cls(node.pos, **kwargs) |
| 873 |
| 874 |
| 875 class AtomicExprNode(ExprNode): |
| 876 # Abstract base class for expression nodes which have |
| 877 # no sub-expressions. |
| 878 |
| 879 subexprs = [] |
| 880 |
| 881 # Override to optimize -- we know we have no children |
| 882 def generate_subexpr_evaluation_code(self, code): |
| 883 pass |
| 884 def generate_subexpr_disposal_code(self, code): |
| 885 pass |
| 886 |
| 887 class PyConstNode(AtomicExprNode): |
| 888 # Abstract base class for constant Python values. |
| 889 |
| 890 is_literal = 1 |
| 891 type = py_object_type |
| 892 |
| 893 def is_simple(self): |
| 894 return 1 |
| 895 |
| 896 def may_be_none(self): |
| 897 return False |
| 898 |
| 899 def analyse_types(self, env): |
| 900 return self |
| 901 |
| 902 def calculate_result_code(self): |
| 903 return self.value |
| 904 |
| 905 def generate_result_code(self, code): |
| 906 pass |
| 907 |
| 908 |
| 909 class NoneNode(PyConstNode): |
| 910 # The constant value None |
| 911 |
| 912 is_none = 1 |
| 913 value = "Py_None" |
| 914 |
| 915 constant_result = None |
| 916 |
| 917 nogil_check = None |
| 918 |
| 919 def compile_time_value(self, denv): |
| 920 return None |
| 921 |
| 922 def may_be_none(self): |
| 923 return True |
| 924 |
| 925 |
| 926 class EllipsisNode(PyConstNode): |
| 927 # '...' in a subscript list. |
| 928 |
| 929 value = "Py_Ellipsis" |
| 930 |
| 931 constant_result = Ellipsis |
| 932 |
| 933 def compile_time_value(self, denv): |
| 934 return Ellipsis |
| 935 |
| 936 |
| 937 class ConstNode(AtomicExprNode): |
| 938 # Abstract base type for literal constant nodes. |
| 939 # |
| 940 # value string C code fragment |
| 941 |
| 942 is_literal = 1 |
| 943 nogil_check = None |
| 944 |
| 945 def is_simple(self): |
| 946 return 1 |
| 947 |
| 948 def nonlocally_immutable(self): |
| 949 return 1 |
| 950 |
| 951 def may_be_none(self): |
| 952 return False |
| 953 |
| 954 def analyse_types(self, env): |
| 955 return self # Types are held in class variables |
| 956 |
| 957 def check_const(self): |
| 958 return True |
| 959 |
| 960 def get_constant_c_result_code(self): |
| 961 return self.calculate_result_code() |
| 962 |
| 963 def calculate_result_code(self): |
| 964 return str(self.value) |
| 965 |
| 966 def generate_result_code(self, code): |
| 967 pass |
| 968 |
| 969 |
| 970 class BoolNode(ConstNode): |
| 971 type = PyrexTypes.c_bint_type |
| 972 # The constant value True or False |
| 973 |
| 974 def calculate_constant_result(self): |
| 975 self.constant_result = self.value |
| 976 |
| 977 def compile_time_value(self, denv): |
| 978 return self.value |
| 979 |
| 980 def calculate_result_code(self): |
| 981 if self.type.is_pyobject: |
| 982 return self.value and 'Py_True' or 'Py_False' |
| 983 else: |
| 984 return str(int(self.value)) |
| 985 |
| 986 def coerce_to(self, dst_type, env): |
| 987 if dst_type.is_pyobject and self.type.is_int: |
| 988 return BoolNode( |
| 989 self.pos, value=self.value, |
| 990 constant_result=self.constant_result, |
| 991 type=Builtin.bool_type) |
| 992 if dst_type.is_int and self.type.is_pyobject: |
| 993 return BoolNode( |
| 994 self.pos, value=self.value, |
| 995 constant_result=self.constant_result, |
| 996 type=PyrexTypes.c_bint_type) |
| 997 return ConstNode.coerce_to(self, dst_type, env) |
| 998 |
| 999 |
| 1000 class NullNode(ConstNode): |
| 1001 type = PyrexTypes.c_null_ptr_type |
| 1002 value = "NULL" |
| 1003 constant_result = 0 |
| 1004 |
| 1005 def get_constant_c_result_code(self): |
| 1006 return self.value |
| 1007 |
| 1008 |
| 1009 class CharNode(ConstNode): |
| 1010 type = PyrexTypes.c_char_type |
| 1011 |
| 1012 def calculate_constant_result(self): |
| 1013 self.constant_result = ord(self.value) |
| 1014 |
| 1015 def compile_time_value(self, denv): |
| 1016 return ord(self.value) |
| 1017 |
| 1018 def calculate_result_code(self): |
| 1019 return "'%s'" % StringEncoding.escape_char(self.value) |
| 1020 |
| 1021 |
| 1022 class IntNode(ConstNode): |
| 1023 |
| 1024 # unsigned "" or "U" |
| 1025 # longness "" or "L" or "LL" |
| 1026 # is_c_literal True/False/None creator considers this a C integer litera
l |
| 1027 |
| 1028 unsigned = "" |
| 1029 longness = "" |
| 1030 is_c_literal = None # unknown |
| 1031 |
| 1032 def __init__(self, pos, **kwds): |
| 1033 ExprNode.__init__(self, pos, **kwds) |
| 1034 if 'type' not in kwds: |
| 1035 self.type = self.find_suitable_type_for_value() |
| 1036 |
| 1037 def find_suitable_type_for_value(self): |
| 1038 if self.constant_result is constant_value_not_set: |
| 1039 try: |
| 1040 self.calculate_constant_result() |
| 1041 except ValueError: |
| 1042 pass |
| 1043 # we ignore 'is_c_literal = True' and instead map signed 32bit |
| 1044 # integers as C long values |
| 1045 if self.is_c_literal or \ |
| 1046 self.constant_result in (constant_value_not_set, not_a_constant)
or \ |
| 1047 self.unsigned or self.longness == 'LL': |
| 1048 # clearly a C literal |
| 1049 rank = (self.longness == 'LL') and 2 or 1 |
| 1050 suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsig
ned, rank, "int"] |
| 1051 if self.type: |
| 1052 suitable_type = PyrexTypes.widest_numeric_type(suitable_type, se
lf.type) |
| 1053 else: |
| 1054 # C literal or Python literal - split at 32bit boundary |
| 1055 if -2**31 <= self.constant_result < 2**31: |
| 1056 if self.type and self.type.is_int: |
| 1057 suitable_type = self.type |
| 1058 else: |
| 1059 suitable_type = PyrexTypes.c_long_type |
| 1060 else: |
| 1061 suitable_type = PyrexTypes.py_object_type |
| 1062 return suitable_type |
| 1063 |
| 1064 def coerce_to(self, dst_type, env): |
| 1065 if self.type is dst_type: |
| 1066 return self |
| 1067 elif dst_type.is_float: |
| 1068 if self.has_constant_result(): |
| 1069 return FloatNode(self.pos, value='%d.0' % int(self.constant_resu
lt), type=dst_type, |
| 1070 constant_result=float(self.constant_result)) |
| 1071 else: |
| 1072 return FloatNode(self.pos, value=self.value, type=dst_type, |
| 1073 constant_result=not_a_constant) |
| 1074 if dst_type.is_numeric and not dst_type.is_complex: |
| 1075 node = IntNode(self.pos, value=self.value, constant_result=self.cons
tant_result, |
| 1076 type = dst_type, is_c_literal = True, |
| 1077 unsigned=self.unsigned, longness=self.longness) |
| 1078 return node |
| 1079 elif dst_type.is_pyobject: |
| 1080 node = IntNode(self.pos, value=self.value, constant_result=self.cons
tant_result, |
| 1081 type = PyrexTypes.py_object_type, is_c_literal = Fals
e, |
| 1082 unsigned=self.unsigned, longness=self.longness) |
| 1083 else: |
| 1084 # FIXME: not setting the type here to keep it working with |
| 1085 # complex numbers. Should they be special cased? |
| 1086 node = IntNode(self.pos, value=self.value, constant_result=self.cons
tant_result, |
| 1087 unsigned=self.unsigned, longness=self.longness) |
| 1088 # We still need to perform normal coerce_to processing on the |
| 1089 # result, because we might be coercing to an extension type, |
| 1090 # in which case a type test node will be needed. |
| 1091 return ConstNode.coerce_to(node, dst_type, env) |
| 1092 |
| 1093 def coerce_to_boolean(self, env): |
| 1094 return IntNode( |
| 1095 self.pos, value=self.value, |
| 1096 constant_result=self.constant_result, |
| 1097 type=PyrexTypes.c_bint_type, |
| 1098 unsigned=self.unsigned, longness=self.longness) |
| 1099 |
| 1100 def generate_evaluation_code(self, code): |
| 1101 if self.type.is_pyobject: |
| 1102 # pre-allocate a Python version of the number |
| 1103 plain_integer_string = str(Utils.str_to_number(self.value)) |
| 1104 self.result_code = code.get_py_int(plain_integer_string, self.longne
ss) |
| 1105 else: |
| 1106 self.result_code = self.get_constant_c_result_code() |
| 1107 |
| 1108 def get_constant_c_result_code(self): |
| 1109 return self.value_as_c_integer_string() + self.unsigned + self.longness |
| 1110 |
| 1111 def value_as_c_integer_string(self): |
| 1112 value = self.value |
| 1113 if len(value) > 2: |
| 1114 # convert C-incompatible Py3 oct/bin notations |
| 1115 if value[1] in 'oO': |
| 1116 value = value[0] + value[2:] # '0o123' => '0123' |
| 1117 elif value[1] in 'bB': |
| 1118 value = int(value[2:], 2) |
| 1119 return str(value) |
| 1120 |
| 1121 def calculate_result_code(self): |
| 1122 return self.result_code |
| 1123 |
| 1124 def calculate_constant_result(self): |
| 1125 self.constant_result = Utils.str_to_number(self.value) |
| 1126 |
| 1127 def compile_time_value(self, denv): |
| 1128 return Utils.str_to_number(self.value) |
| 1129 |
| 1130 |
| 1131 class FloatNode(ConstNode): |
| 1132 type = PyrexTypes.c_double_type |
| 1133 |
| 1134 def calculate_constant_result(self): |
| 1135 self.constant_result = float(self.value) |
| 1136 |
| 1137 def compile_time_value(self, denv): |
| 1138 return float(self.value) |
| 1139 |
| 1140 def coerce_to(self, dst_type, env): |
| 1141 if dst_type.is_pyobject and self.type.is_float: |
| 1142 return FloatNode( |
| 1143 self.pos, value=self.value, |
| 1144 constant_result=self.constant_result, |
| 1145 type=Builtin.float_type) |
| 1146 if dst_type.is_float and self.type.is_pyobject: |
| 1147 return FloatNode( |
| 1148 self.pos, value=self.value, |
| 1149 constant_result=self.constant_result, |
| 1150 type=dst_type) |
| 1151 return ConstNode.coerce_to(self, dst_type, env) |
| 1152 |
| 1153 def calculate_result_code(self): |
| 1154 return self.result_code |
| 1155 |
| 1156 def get_constant_c_result_code(self): |
| 1157 strval = self.value |
| 1158 assert isinstance(strval, (str, unicode)) |
| 1159 cmpval = repr(float(strval)) |
| 1160 if cmpval == 'nan': |
| 1161 return "(Py_HUGE_VAL * 0)" |
| 1162 elif cmpval == 'inf': |
| 1163 return "Py_HUGE_VAL" |
| 1164 elif cmpval == '-inf': |
| 1165 return "(-Py_HUGE_VAL)" |
| 1166 else: |
| 1167 return strval |
| 1168 |
| 1169 def generate_evaluation_code(self, code): |
| 1170 c_value = self.get_constant_c_result_code() |
| 1171 if self.type.is_pyobject: |
| 1172 self.result_code = code.get_py_float(self.value, c_value) |
| 1173 else: |
| 1174 self.result_code = c_value |
| 1175 |
| 1176 |
| 1177 class BytesNode(ConstNode): |
| 1178 # A char* or bytes literal |
| 1179 # |
| 1180 # value BytesLiteral |
| 1181 |
| 1182 is_string_literal = True |
| 1183 # start off as Python 'bytes' to support len() in O(1) |
| 1184 type = bytes_type |
| 1185 |
| 1186 def calculate_constant_result(self): |
| 1187 self.constant_result = self.value |
| 1188 |
| 1189 def as_sliced_node(self, start, stop, step=None): |
| 1190 value = StringEncoding.BytesLiteral(self.value[start:stop:step]) |
| 1191 value.encoding = self.value.encoding |
| 1192 return BytesNode( |
| 1193 self.pos, value=value, constant_result=value) |
| 1194 |
| 1195 def compile_time_value(self, denv): |
| 1196 return self.value |
| 1197 |
| 1198 def analyse_as_type(self, env): |
| 1199 type = PyrexTypes.parse_basic_type(self.value) |
| 1200 if type is not None: |
| 1201 return type |
| 1202 from TreeFragment import TreeFragment |
| 1203 pos = (self.pos[0], self.pos[1], self.pos[2]-7) |
| 1204 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filen
ame, initial_pos=pos) |
| 1205 sizeof_node = declaration.root.stats[0].expr |
| 1206 sizeof_node = sizeof_node.analyse_types(env) |
| 1207 if isinstance(sizeof_node, SizeofTypeNode): |
| 1208 return sizeof_node.arg_type |
| 1209 |
| 1210 def can_coerce_to_char_literal(self): |
| 1211 return len(self.value) == 1 |
| 1212 |
| 1213 def coerce_to_boolean(self, env): |
| 1214 # This is special because testing a C char* for truth directly |
| 1215 # would yield the wrong result. |
| 1216 bool_value = bool(self.value) |
| 1217 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) |
| 1218 |
| 1219 def coerce_to(self, dst_type, env): |
| 1220 if self.type == dst_type: |
| 1221 return self |
| 1222 if dst_type.is_int: |
| 1223 if not self.can_coerce_to_char_literal(): |
| 1224 error(self.pos, "Only single-character string literals can be co
erced into ints.") |
| 1225 return self |
| 1226 if dst_type.is_unicode_char: |
| 1227 error(self.pos, "Bytes literals cannot coerce to Py_UNICODE/Py_U
CS4, use a unicode literal instead.") |
| 1228 return self |
| 1229 return CharNode(self.pos, value=self.value, |
| 1230 constant_result=ord(self.value)) |
| 1231 |
| 1232 node = BytesNode(self.pos, value=self.value, |
| 1233 constant_result=self.constant_result) |
| 1234 if dst_type.is_pyobject: |
| 1235 if dst_type in (py_object_type, Builtin.bytes_type): |
| 1236 node.type = Builtin.bytes_type |
| 1237 else: |
| 1238 self.check_for_coercion_error(dst_type, env, fail=True) |
| 1239 return node |
| 1240 elif dst_type == PyrexTypes.c_char_ptr_type: |
| 1241 node.type = dst_type |
| 1242 return node |
| 1243 elif dst_type == PyrexTypes.c_uchar_ptr_type: |
| 1244 node.type = PyrexTypes.c_char_ptr_type |
| 1245 return CastNode(node, PyrexTypes.c_uchar_ptr_type) |
| 1246 elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type): |
| 1247 node.type = dst_type |
| 1248 return node |
| 1249 |
| 1250 # We still need to perform normal coerce_to processing on the |
| 1251 # result, because we might be coercing to an extension type, |
| 1252 # in which case a type test node will be needed. |
| 1253 return ConstNode.coerce_to(node, dst_type, env) |
| 1254 |
| 1255 def generate_evaluation_code(self, code): |
| 1256 if self.type.is_pyobject: |
| 1257 self.result_code = code.get_py_string_const(self.value) |
| 1258 else: |
| 1259 self.result_code = code.get_string_const(self.value) |
| 1260 |
| 1261 def get_constant_c_result_code(self): |
| 1262 return None # FIXME |
| 1263 |
| 1264 def calculate_result_code(self): |
| 1265 return self.result_code |
| 1266 |
| 1267 |
| 1268 class UnicodeNode(ConstNode): |
| 1269 # A Py_UNICODE* or unicode literal |
| 1270 # |
| 1271 # value EncodedString |
| 1272 # bytes_value BytesLiteral the literal parsed as bytes string |
| 1273 # ('-3' unicode literals only) |
| 1274 |
| 1275 is_string_literal = True |
| 1276 bytes_value = None |
| 1277 type = unicode_type |
| 1278 |
| 1279 def calculate_constant_result(self): |
| 1280 self.constant_result = self.value |
| 1281 |
| 1282 def as_sliced_node(self, start, stop, step=None): |
| 1283 if StringEncoding.string_contains_surrogates(self.value[:stop]): |
| 1284 # this is unsafe as it may give different results |
| 1285 # in different runtimes |
| 1286 return None |
| 1287 value = StringEncoding.EncodedString(self.value[start:stop:step]) |
| 1288 value.encoding = self.value.encoding |
| 1289 if self.bytes_value is not None: |
| 1290 bytes_value = StringEncoding.BytesLiteral( |
| 1291 self.bytes_value[start:stop:step]) |
| 1292 bytes_value.encoding = self.bytes_value.encoding |
| 1293 else: |
| 1294 bytes_value = None |
| 1295 return UnicodeNode( |
| 1296 self.pos, value=value, bytes_value=bytes_value, |
| 1297 constant_result=value) |
| 1298 |
| 1299 def coerce_to(self, dst_type, env): |
| 1300 if dst_type is self.type: |
| 1301 pass |
| 1302 elif dst_type.is_unicode_char: |
| 1303 if not self.can_coerce_to_char_literal(): |
| 1304 error(self.pos, |
| 1305 "Only single-character Unicode string literals or " |
| 1306 "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.") |
| 1307 return self |
| 1308 int_value = ord(self.value) |
| 1309 return IntNode(self.pos, type=dst_type, value=str(int_value), |
| 1310 constant_result=int_value) |
| 1311 elif not dst_type.is_pyobject: |
| 1312 if dst_type.is_string and self.bytes_value is not None: |
| 1313 # special case: '-3' enforced unicode literal used in a |
| 1314 # C char* context |
| 1315 return BytesNode(self.pos, value=self.bytes_value |
| 1316 ).coerce_to(dst_type, env) |
| 1317 if dst_type.is_pyunicode_ptr: |
| 1318 node = UnicodeNode(self.pos, value=self.value) |
| 1319 node.type = dst_type |
| 1320 return node |
| 1321 error(self.pos, |
| 1322 "Unicode literals do not support coercion to C types other " |
| 1323 "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* " |
| 1324 "(for strings).") |
| 1325 elif dst_type not in (py_object_type, Builtin.basestring_type): |
| 1326 self.check_for_coercion_error(dst_type, env, fail=True) |
| 1327 return self |
| 1328 |
| 1329 def can_coerce_to_char_literal(self): |
| 1330 return len(self.value) == 1 |
| 1331 ## or (len(self.value) == 2 |
| 1332 ## and (0xD800 <= self.value[0] <= 0xDBFF) |
| 1333 ## and (0xDC00 <= self.value[1] <= 0xDFFF)) |
| 1334 |
| 1335 def coerce_to_boolean(self, env): |
| 1336 bool_value = bool(self.value) |
| 1337 return BoolNode(self.pos, value=bool_value, constant_result=bool_value) |
| 1338 |
| 1339 def contains_surrogates(self): |
| 1340 return StringEncoding.string_contains_surrogates(self.value) |
| 1341 |
| 1342 def generate_evaluation_code(self, code): |
| 1343 if self.type.is_pyobject: |
| 1344 if self.contains_surrogates(): |
| 1345 # surrogates are not really portable and cannot be |
| 1346 # decoded by the UTF-8 codec in Py3.3 |
| 1347 self.result_code = code.get_py_const(py_object_type, 'ustring') |
| 1348 data_cname = code.get_pyunicode_ptr_const(self.value) |
| 1349 code = code.get_cached_constants_writer() |
| 1350 code.mark_pos(self.pos) |
| 1351 code.putln( |
| 1352 "%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNIC
ODE))-1); %s" % ( |
| 1353 self.result_code, |
| 1354 data_cname, |
| 1355 data_cname, |
| 1356 code.error_goto_if_null(self.result_code, self.pos))) |
| 1357 code.putln("#if CYTHON_PEP393_ENABLED") |
| 1358 code.put_error_if_neg( |
| 1359 self.pos, "PyUnicode_READY(%s)" % self.result_code) |
| 1360 code.putln("#endif") |
| 1361 else: |
| 1362 self.result_code = code.get_py_string_const(self.value) |
| 1363 else: |
| 1364 self.result_code = code.get_pyunicode_ptr_const(self.value) |
| 1365 |
| 1366 def calculate_result_code(self): |
| 1367 return self.result_code |
| 1368 |
| 1369 def compile_time_value(self, env): |
| 1370 return self.value |
| 1371 |
| 1372 |
| 1373 class StringNode(PyConstNode): |
| 1374 # A Python str object, i.e. a byte string in Python 2.x and a |
| 1375 # unicode string in Python 3.x |
| 1376 # |
| 1377 # value BytesLiteral (or EncodedString with ASCII content) |
| 1378 # unicode_value EncodedString or None |
| 1379 # is_identifier boolean |
| 1380 |
| 1381 type = str_type |
| 1382 is_string_literal = True |
| 1383 is_identifier = None |
| 1384 unicode_value = None |
| 1385 |
| 1386 def calculate_constant_result(self): |
| 1387 if self.unicode_value is not None: |
| 1388 # only the Unicode value is portable across Py2/3 |
| 1389 self.constant_result = self.unicode_value |
| 1390 |
| 1391 def as_sliced_node(self, start, stop, step=None): |
| 1392 value = type(self.value)(self.value[start:stop:step]) |
| 1393 value.encoding = self.value.encoding |
| 1394 if self.unicode_value is not None: |
| 1395 if StringEncoding.string_contains_surrogates(self.unicode_value[:sto
p]): |
| 1396 # this is unsafe as it may give different results in different r
untimes |
| 1397 return None |
| 1398 unicode_value = StringEncoding.EncodedString( |
| 1399 self.unicode_value[start:stop:step]) |
| 1400 else: |
| 1401 unicode_value = None |
| 1402 return StringNode( |
| 1403 self.pos, value=value, unicode_value=unicode_value, |
| 1404 constant_result=value, is_identifier=self.is_identifier) |
| 1405 |
| 1406 def coerce_to(self, dst_type, env): |
| 1407 if dst_type is not py_object_type and not str_type.subtype_of(dst_type): |
| 1408 # if dst_type is Builtin.bytes_type: |
| 1409 # # special case: bytes = 'str literal' |
| 1410 # return BytesNode(self.pos, value=self.value) |
| 1411 if not dst_type.is_pyobject: |
| 1412 return BytesNode(self.pos, value=self.value).coerce_to(dst_type,
env) |
| 1413 if dst_type is not Builtin.basestring_type: |
| 1414 self.check_for_coercion_error(dst_type, env, fail=True) |
| 1415 return self |
| 1416 |
| 1417 def can_coerce_to_char_literal(self): |
| 1418 return not self.is_identifier and len(self.value) == 1 |
| 1419 |
| 1420 def generate_evaluation_code(self, code): |
| 1421 self.result_code = code.get_py_string_const( |
| 1422 self.value, identifier=self.is_identifier, is_str=True, |
| 1423 unicode_value=self.unicode_value) |
| 1424 |
| 1425 def get_constant_c_result_code(self): |
| 1426 return None |
| 1427 |
| 1428 def calculate_result_code(self): |
| 1429 return self.result_code |
| 1430 |
| 1431 def compile_time_value(self, env): |
| 1432 return self.value |
| 1433 |
| 1434 |
| 1435 class IdentifierStringNode(StringNode): |
| 1436 # A special str value that represents an identifier (bytes in Py2, |
| 1437 # unicode in Py3). |
| 1438 is_identifier = True |
| 1439 |
| 1440 |
| 1441 class ImagNode(AtomicExprNode): |
| 1442 # Imaginary number literal |
| 1443 # |
| 1444 # value float imaginary part |
| 1445 |
| 1446 type = PyrexTypes.c_double_complex_type |
| 1447 |
| 1448 def calculate_constant_result(self): |
| 1449 self.constant_result = complex(0.0, self.value) |
| 1450 |
| 1451 def compile_time_value(self, denv): |
| 1452 return complex(0.0, self.value) |
| 1453 |
| 1454 def analyse_types(self, env): |
| 1455 self.type.create_declaration_utility_code(env) |
| 1456 return self |
| 1457 |
| 1458 def may_be_none(self): |
| 1459 return False |
| 1460 |
| 1461 def coerce_to(self, dst_type, env): |
| 1462 if self.type is dst_type: |
| 1463 return self |
| 1464 node = ImagNode(self.pos, value=self.value) |
| 1465 if dst_type.is_pyobject: |
| 1466 node.is_temp = 1 |
| 1467 node.type = PyrexTypes.py_object_type |
| 1468 # We still need to perform normal coerce_to processing on the |
| 1469 # result, because we might be coercing to an extension type, |
| 1470 # in which case a type test node will be needed. |
| 1471 return AtomicExprNode.coerce_to(node, dst_type, env) |
| 1472 |
| 1473 gil_message = "Constructing complex number" |
| 1474 |
| 1475 def calculate_result_code(self): |
| 1476 if self.type.is_pyobject: |
| 1477 return self.result() |
| 1478 else: |
| 1479 return "%s(0, %r)" % (self.type.from_parts, float(self.value)) |
| 1480 |
| 1481 def generate_result_code(self, code): |
| 1482 if self.type.is_pyobject: |
| 1483 code.putln( |
| 1484 "%s = PyComplex_FromDoubles(0.0, %r); %s" % ( |
| 1485 self.result(), |
| 1486 float(self.value), |
| 1487 code.error_goto_if_null(self.result(), self.pos))) |
| 1488 code.put_gotref(self.py_result()) |
| 1489 |
| 1490 |
| 1491 class NewExprNode(AtomicExprNode): |
| 1492 |
| 1493 # C++ new statement |
| 1494 # |
| 1495 # cppclass node c++ class to create |
| 1496 |
| 1497 type = None |
| 1498 |
| 1499 def infer_type(self, env): |
| 1500 type = self.cppclass.analyse_as_type(env) |
| 1501 if type is None or not type.is_cpp_class: |
| 1502 error(self.pos, "new operator can only be applied to a C++ class") |
| 1503 self.type = error_type |
| 1504 return |
| 1505 self.cpp_check(env) |
| 1506 constructor = type.scope.lookup(u'<init>') |
| 1507 if constructor is None: |
| 1508 func_type = PyrexTypes.CFuncType(type, [], exception_check='+') |
| 1509 type.scope.declare_cfunction(u'<init>', func_type, self.pos) |
| 1510 constructor = type.scope.lookup(u'<init>') |
| 1511 self.class_type = type |
| 1512 self.entry = constructor |
| 1513 self.type = constructor.type |
| 1514 return self.type |
| 1515 |
| 1516 def analyse_types(self, env): |
| 1517 if self.type is None: |
| 1518 self.infer_type(env) |
| 1519 return self |
| 1520 |
| 1521 def may_be_none(self): |
| 1522 return False |
| 1523 |
| 1524 def generate_result_code(self, code): |
| 1525 pass |
| 1526 |
| 1527 def calculate_result_code(self): |
| 1528 return "new " + self.class_type.declaration_code("") |
| 1529 |
| 1530 |
| 1531 class NameNode(AtomicExprNode): |
| 1532 # Reference to a local or global variable name. |
| 1533 # |
| 1534 # name string Python name of the variable |
| 1535 # entry Entry Symbol table entry |
| 1536 # type_entry Entry For extension type names, the original type ent
ry |
| 1537 # cf_is_null boolean Is uninitialized before this node |
| 1538 # cf_maybe_null boolean Maybe uninitialized before this node |
| 1539 # allow_null boolean Don't raise UnboundLocalError |
| 1540 # nogil boolean Whether it is used in a nogil context |
| 1541 |
| 1542 is_name = True |
| 1543 is_cython_module = False |
| 1544 cython_attribute = None |
| 1545 lhs_of_first_assignment = False # TODO: remove me |
| 1546 is_used_as_rvalue = 0 |
| 1547 entry = None |
| 1548 type_entry = None |
| 1549 cf_maybe_null = True |
| 1550 cf_is_null = False |
| 1551 allow_null = False |
| 1552 nogil = False |
| 1553 inferred_type = None |
| 1554 |
| 1555 def as_cython_attribute(self): |
| 1556 return self.cython_attribute |
| 1557 |
| 1558 def type_dependencies(self, env): |
| 1559 if self.entry is None: |
| 1560 self.entry = env.lookup(self.name) |
| 1561 if self.entry is not None and self.entry.type.is_unspecified: |
| 1562 return (self,) |
| 1563 else: |
| 1564 return () |
| 1565 |
| 1566 def infer_type(self, env): |
| 1567 if self.entry is None: |
| 1568 self.entry = env.lookup(self.name) |
| 1569 if self.entry is None or self.entry.type is unspecified_type: |
| 1570 if self.inferred_type is not None: |
| 1571 return self.inferred_type |
| 1572 return py_object_type |
| 1573 elif (self.entry.type.is_extension_type or self.entry.type.is_builtin_ty
pe) and \ |
| 1574 self.name == self.entry.type.name: |
| 1575 # Unfortunately the type attribute of type objects |
| 1576 # is used for the pointer to the type they represent. |
| 1577 return type_type |
| 1578 elif self.entry.type.is_cfunction: |
| 1579 if self.entry.scope.is_builtin_scope: |
| 1580 # special case: optimised builtin functions must be treated as P
ython objects |
| 1581 return py_object_type |
| 1582 else: |
| 1583 # special case: referring to a C function must return its pointe
r |
| 1584 return PyrexTypes.CPtrType(self.entry.type) |
| 1585 else: |
| 1586 # If entry is inferred as pyobject it's safe to use local |
| 1587 # NameNode's inferred_type. |
| 1588 if self.entry.type.is_pyobject and self.inferred_type: |
| 1589 # Overflow may happen if integer |
| 1590 if not (self.inferred_type.is_int and self.entry.might_overflow)
: |
| 1591 return self.inferred_type |
| 1592 return self.entry.type |
| 1593 |
| 1594 def compile_time_value(self, denv): |
| 1595 try: |
| 1596 return denv.lookup(self.name) |
| 1597 except KeyError: |
| 1598 error(self.pos, "Compile-time name '%s' not defined" % self.name) |
| 1599 |
| 1600 def get_constant_c_result_code(self): |
| 1601 if not self.entry or self.entry.type.is_pyobject: |
| 1602 return None |
| 1603 return self.entry.cname |
| 1604 |
| 1605 def coerce_to(self, dst_type, env): |
| 1606 # If coercing to a generic pyobject and this is a builtin |
| 1607 # C function with a Python equivalent, manufacture a NameNode |
| 1608 # referring to the Python builtin. |
| 1609 #print "NameNode.coerce_to:", self.name, dst_type ### |
| 1610 if dst_type is py_object_type: |
| 1611 entry = self.entry |
| 1612 if entry and entry.is_cfunction: |
| 1613 var_entry = entry.as_variable |
| 1614 if var_entry: |
| 1615 if var_entry.is_builtin and var_entry.is_const: |
| 1616 var_entry = env.declare_builtin(var_entry.name, self.pos
) |
| 1617 node = NameNode(self.pos, name = self.name) |
| 1618 node.entry = var_entry |
| 1619 node.analyse_rvalue_entry(env) |
| 1620 return node |
| 1621 |
| 1622 return super(NameNode, self).coerce_to(dst_type, env) |
| 1623 |
| 1624 def analyse_as_module(self, env): |
| 1625 # Try to interpret this as a reference to a cimported module. |
| 1626 # Returns the module scope, or None. |
| 1627 entry = self.entry |
| 1628 if not entry: |
| 1629 entry = env.lookup(self.name) |
| 1630 if entry and entry.as_module: |
| 1631 return entry.as_module |
| 1632 return None |
| 1633 |
| 1634 def analyse_as_type(self, env): |
| 1635 if self.cython_attribute: |
| 1636 type = PyrexTypes.parse_basic_type(self.cython_attribute) |
| 1637 else: |
| 1638 type = PyrexTypes.parse_basic_type(self.name) |
| 1639 if type: |
| 1640 return type |
| 1641 entry = self.entry |
| 1642 if not entry: |
| 1643 entry = env.lookup(self.name) |
| 1644 if entry and entry.is_type: |
| 1645 return entry.type |
| 1646 else: |
| 1647 return None |
| 1648 |
| 1649 def analyse_as_extension_type(self, env): |
| 1650 # Try to interpret this as a reference to an extension type. |
| 1651 # Returns the extension type, or None. |
| 1652 entry = self.entry |
| 1653 if not entry: |
| 1654 entry = env.lookup(self.name) |
| 1655 if entry and entry.is_type: |
| 1656 if entry.type.is_extension_type or entry.type.is_builtin_type: |
| 1657 return entry.type |
| 1658 return None |
| 1659 |
| 1660 def analyse_target_declaration(self, env): |
| 1661 if not self.entry: |
| 1662 self.entry = env.lookup_here(self.name) |
| 1663 if not self.entry: |
| 1664 if env.directives['warn.undeclared']: |
| 1665 warning(self.pos, "implicit declaration of '%s'" % self.name, 1) |
| 1666 if env.directives['infer_types'] != False: |
| 1667 type = unspecified_type |
| 1668 else: |
| 1669 type = py_object_type |
| 1670 self.entry = env.declare_var(self.name, type, self.pos) |
| 1671 if self.entry.is_declared_generic: |
| 1672 self.result_ctype = py_object_type |
| 1673 |
| 1674 def analyse_types(self, env): |
| 1675 self.initialized_check = env.directives['initializedcheck'] |
| 1676 if self.entry is None: |
| 1677 self.entry = env.lookup(self.name) |
| 1678 if not self.entry: |
| 1679 self.entry = env.declare_builtin(self.name, self.pos) |
| 1680 if not self.entry: |
| 1681 self.type = PyrexTypes.error_type |
| 1682 return self |
| 1683 entry = self.entry |
| 1684 if entry: |
| 1685 entry.used = 1 |
| 1686 if entry.type.is_buffer: |
| 1687 import Buffer |
| 1688 Buffer.used_buffer_aux_vars(entry) |
| 1689 self.analyse_rvalue_entry(env) |
| 1690 return self |
| 1691 |
| 1692 def analyse_target_types(self, env): |
| 1693 self.analyse_entry(env, is_target=True) |
| 1694 |
| 1695 if (not self.is_lvalue() and self.entry.is_cfunction and |
| 1696 self.entry.fused_cfunction and self.entry.as_variable): |
| 1697 # We need this for the fused 'def' TreeFragment |
| 1698 self.entry = self.entry.as_variable |
| 1699 self.type = self.entry.type |
| 1700 |
| 1701 if self.type.is_const: |
| 1702 error(self.pos, "Assignment to const '%s'" % self.name) |
| 1703 if self.type.is_reference: |
| 1704 error(self.pos, "Assignment to reference '%s'" % self.name) |
| 1705 if not self.is_lvalue(): |
| 1706 error(self.pos, "Assignment to non-lvalue '%s'" |
| 1707 % self.name) |
| 1708 self.type = PyrexTypes.error_type |
| 1709 self.entry.used = 1 |
| 1710 if self.entry.type.is_buffer: |
| 1711 import Buffer |
| 1712 Buffer.used_buffer_aux_vars(self.entry) |
| 1713 return self |
| 1714 |
| 1715 def analyse_rvalue_entry(self, env): |
| 1716 #print "NameNode.analyse_rvalue_entry:", self.name ### |
| 1717 #print "Entry:", self.entry.__dict__ ### |
| 1718 self.analyse_entry(env) |
| 1719 entry = self.entry |
| 1720 |
| 1721 if entry.is_declared_generic: |
| 1722 self.result_ctype = py_object_type |
| 1723 |
| 1724 if entry.is_pyglobal or entry.is_builtin: |
| 1725 if entry.is_builtin and entry.is_const: |
| 1726 self.is_temp = 0 |
| 1727 else: |
| 1728 self.is_temp = 1 |
| 1729 |
| 1730 self.is_used_as_rvalue = 1 |
| 1731 elif entry.type.is_memoryviewslice: |
| 1732 self.is_temp = False |
| 1733 self.is_used_as_rvalue = True |
| 1734 self.use_managed_ref = True |
| 1735 return self |
| 1736 |
| 1737 def nogil_check(self, env): |
| 1738 self.nogil = True |
| 1739 if self.is_used_as_rvalue: |
| 1740 entry = self.entry |
| 1741 if entry.is_builtin: |
| 1742 if not entry.is_const: # cached builtins are ok |
| 1743 self.gil_error() |
| 1744 elif entry.is_pyglobal: |
| 1745 self.gil_error() |
| 1746 elif self.entry.type.is_memoryviewslice: |
| 1747 if self.cf_is_null or self.cf_maybe_null: |
| 1748 import MemoryView |
| 1749 MemoryView.err_if_nogil_initialized_check(self.pos, env) |
| 1750 |
| 1751 gil_message = "Accessing Python global or builtin" |
| 1752 |
| 1753 def analyse_entry(self, env, is_target=False): |
| 1754 #print "NameNode.analyse_entry:", self.name ### |
| 1755 self.check_identifier_kind() |
| 1756 entry = self.entry |
| 1757 type = entry.type |
| 1758 if (not is_target and type.is_pyobject and self.inferred_type and |
| 1759 self.inferred_type.is_builtin_type): |
| 1760 # assume that type inference is smarter than the static entry |
| 1761 type = self.inferred_type |
| 1762 self.type = type |
| 1763 |
| 1764 def check_identifier_kind(self): |
| 1765 # Check that this is an appropriate kind of name for use in an |
| 1766 # expression. Also finds the variable entry associated with |
| 1767 # an extension type. |
| 1768 entry = self.entry |
| 1769 if entry.is_type and entry.type.is_extension_type: |
| 1770 self.type_entry = entry |
| 1771 if not (entry.is_const or entry.is_variable |
| 1772 or entry.is_builtin or entry.is_cfunction |
| 1773 or entry.is_cpp_class): |
| 1774 if self.entry.as_variable: |
| 1775 self.entry = self.entry.as_variable |
| 1776 else: |
| 1777 error(self.pos, |
| 1778 "'%s' is not a constant, variable or function identifi
er" % self.name) |
| 1779 |
| 1780 def is_simple(self): |
| 1781 # If it's not a C variable, it'll be in a temp. |
| 1782 return 1 |
| 1783 |
| 1784 def may_be_none(self): |
| 1785 if self.cf_state and self.type and (self.type.is_pyobject or |
| 1786 self.type.is_memoryviewslice): |
| 1787 # gard against infinite recursion on self-dependencies |
| 1788 if getattr(self, '_none_checking', False): |
| 1789 # self-dependency - either this node receives a None |
| 1790 # value from *another* node, or it can not reference |
| 1791 # None at this point => safe to assume "not None" |
| 1792 return False |
| 1793 self._none_checking = True |
| 1794 # evaluate control flow state to see if there were any |
| 1795 # potential None values assigned to the node so far |
| 1796 may_be_none = False |
| 1797 for assignment in self.cf_state: |
| 1798 if assignment.rhs.may_be_none(): |
| 1799 may_be_none = True |
| 1800 break |
| 1801 del self._none_checking |
| 1802 return may_be_none |
| 1803 return super(NameNode, self).may_be_none() |
| 1804 |
| 1805 def nonlocally_immutable(self): |
| 1806 if ExprNode.nonlocally_immutable(self): |
| 1807 return True |
| 1808 entry = self.entry |
| 1809 if not entry or entry.in_closure: |
| 1810 return False |
| 1811 return entry.is_local or entry.is_arg or entry.is_builtin or entry.is_re
adonly |
| 1812 |
| 1813 def calculate_target_results(self, env): |
| 1814 pass |
| 1815 |
| 1816 def check_const(self): |
| 1817 entry = self.entry |
| 1818 if entry is not None and not (entry.is_const or entry.is_cfunction or en
try.is_builtin): |
| 1819 self.not_const() |
| 1820 return False |
| 1821 return True |
| 1822 |
| 1823 def check_const_addr(self): |
| 1824 entry = self.entry |
| 1825 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin): |
| 1826 self.addr_not_const() |
| 1827 return False |
| 1828 return True |
| 1829 |
| 1830 def is_lvalue(self): |
| 1831 return self.entry.is_variable and \ |
| 1832 not self.entry.type.is_array and \ |
| 1833 not self.entry.is_readonly |
| 1834 |
| 1835 def is_addressable(self): |
| 1836 return self.entry.is_variable and not self.type.is_memoryviewslice |
| 1837 |
| 1838 def is_ephemeral(self): |
| 1839 # Name nodes are never ephemeral, even if the |
| 1840 # result is in a temporary. |
| 1841 return 0 |
| 1842 |
| 1843 def calculate_result_code(self): |
| 1844 entry = self.entry |
| 1845 if not entry: |
| 1846 return "<error>" # There was an error earlier |
| 1847 return entry.cname |
| 1848 |
| 1849 def generate_result_code(self, code): |
| 1850 assert hasattr(self, 'entry') |
| 1851 entry = self.entry |
| 1852 if entry is None: |
| 1853 return # There was an error earlier |
| 1854 if entry.is_builtin and entry.is_const: |
| 1855 return # Lookup already cached |
| 1856 elif entry.is_pyclass_attr: |
| 1857 assert entry.type.is_pyobject, "Python global or builtin not a Pytho
n object" |
| 1858 interned_cname = code.intern_identifier(self.entry.name) |
| 1859 if entry.is_builtin: |
| 1860 namespace = Naming.builtins_cname |
| 1861 else: # entry.is_pyglobal |
| 1862 namespace = entry.scope.namespace_cname |
| 1863 if not self.cf_is_null: |
| 1864 code.putln( |
| 1865 '%s = PyObject_GetItem(%s, %s);' % ( |
| 1866 self.result(), |
| 1867 namespace, |
| 1868 interned_cname)) |
| 1869 code.putln('if (unlikely(!%s)) {' % self.result()) |
| 1870 code.putln('PyErr_Clear();') |
| 1871 code.globalstate.use_utility_code( |
| 1872 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandling.c
")) |
| 1873 code.putln( |
| 1874 '%s = __Pyx_GetModuleGlobalName(%s);' % ( |
| 1875 self.result(), |
| 1876 interned_cname)) |
| 1877 if not self.cf_is_null: |
| 1878 code.putln("}") |
| 1879 code.putln(code.error_goto_if_null(self.result(), self.pos)) |
| 1880 code.put_gotref(self.py_result()) |
| 1881 |
| 1882 elif entry.is_builtin: |
| 1883 assert entry.type.is_pyobject, "Python global or builtin not a Pytho
n object" |
| 1884 interned_cname = code.intern_identifier(self.entry.name) |
| 1885 code.globalstate.use_utility_code( |
| 1886 UtilityCode.load_cached("GetBuiltinName", "ObjectHandling.c")) |
| 1887 code.putln( |
| 1888 '%s = __Pyx_GetBuiltinName(%s); %s' % ( |
| 1889 self.result(), |
| 1890 interned_cname, |
| 1891 code.error_goto_if_null(self.result(), self.pos))) |
| 1892 code.put_gotref(self.py_result()) |
| 1893 |
| 1894 elif entry.is_pyglobal: |
| 1895 assert entry.type.is_pyobject, "Python global or builtin not a Pytho
n object" |
| 1896 interned_cname = code.intern_identifier(self.entry.name) |
| 1897 if entry.scope.is_module_scope: |
| 1898 code.globalstate.use_utility_code( |
| 1899 UtilityCode.load_cached("GetModuleGlobalName", "ObjectHandli
ng.c")) |
| 1900 code.putln( |
| 1901 '%s = __Pyx_GetModuleGlobalName(%s); %s' % ( |
| 1902 self.result(), |
| 1903 interned_cname, |
| 1904 code.error_goto_if_null(self.result(), self.pos))) |
| 1905 else: |
| 1906 # FIXME: is_pyglobal is also used for class namespace |
| 1907 code.globalstate.use_utility_code( |
| 1908 UtilityCode.load_cached("GetNameInClass", "ObjectHandling.c"
)) |
| 1909 code.putln( |
| 1910 '%s = __Pyx_GetNameInClass(%s, %s); %s' % ( |
| 1911 self.result(), |
| 1912 entry.scope.namespace_cname, |
| 1913 interned_cname, |
| 1914 code.error_goto_if_null(self.result(), self.pos))) |
| 1915 code.put_gotref(self.py_result()) |
| 1916 |
| 1917 elif entry.is_local or entry.in_closure or entry.from_closure or entry.t
ype.is_memoryviewslice: |
| 1918 # Raise UnboundLocalError for objects and memoryviewslices |
| 1919 raise_unbound = ( |
| 1920 (self.cf_maybe_null or self.cf_is_null) and not self.allow_null) |
| 1921 null_code = entry.type.check_for_null_code(entry.cname) |
| 1922 |
| 1923 memslice_check = entry.type.is_memoryviewslice and self.initialized_
check |
| 1924 |
| 1925 if null_code and raise_unbound and (entry.type.is_pyobject or memsli
ce_check): |
| 1926 code.put_error_if_unbound(self.pos, entry, self.in_nogil_context
) |
| 1927 |
| 1928 def generate_assignment_code(self, rhs, code): |
| 1929 #print "NameNode.generate_assignment_code:", self.name ### |
| 1930 entry = self.entry |
| 1931 if entry is None: |
| 1932 return # There was an error earlier |
| 1933 |
| 1934 if (self.entry.type.is_ptr and isinstance(rhs, ListNode) |
| 1935 and not self.lhs_of_first_assignment and not rhs.in_module_scope): |
| 1936 error(self.pos, "Literal list must be assigned to pointer at time of
declaration") |
| 1937 |
| 1938 # is_pyglobal seems to be True for module level-globals only. |
| 1939 # We use this to access class->tp_dict if necessary. |
| 1940 if entry.is_pyglobal: |
| 1941 assert entry.type.is_pyobject, "Python global or builtin not a Pytho
n object" |
| 1942 interned_cname = code.intern_identifier(self.entry.name) |
| 1943 namespace = self.entry.scope.namespace_cname |
| 1944 if entry.is_member: |
| 1945 # if the entry is a member we have to cheat: SetAttr does not wo
rk |
| 1946 # on types, so we create a descriptor which is then added to tp_
dict |
| 1947 setter = 'PyDict_SetItem' |
| 1948 namespace = '%s->tp_dict' % namespace |
| 1949 elif entry.scope.is_module_scope: |
| 1950 setter = 'PyDict_SetItem' |
| 1951 namespace = Naming.moddict_cname |
| 1952 elif entry.is_pyclass_attr: |
| 1953 setter = 'PyObject_SetItem' |
| 1954 else: |
| 1955 assert False, repr(entry) |
| 1956 code.put_error_if_neg( |
| 1957 self.pos, |
| 1958 '%s(%s, %s, %s)' % ( |
| 1959 setter, |
| 1960 namespace, |
| 1961 interned_cname, |
| 1962 rhs.py_result())) |
| 1963 if debug_disposal_code: |
| 1964 print("NameNode.generate_assignment_code:") |
| 1965 print("...generating disposal code for %s" % rhs) |
| 1966 rhs.generate_disposal_code(code) |
| 1967 rhs.free_temps(code) |
| 1968 if entry.is_member: |
| 1969 # in Py2.6+, we need to invalidate the method cache |
| 1970 code.putln("PyType_Modified(%s);" % |
| 1971 entry.scope.parent_type.typeptr_cname) |
| 1972 else: |
| 1973 if self.type.is_memoryviewslice: |
| 1974 self.generate_acquire_memoryviewslice(rhs, code) |
| 1975 |
| 1976 elif self.type.is_buffer: |
| 1977 # Generate code for doing the buffer release/acquisition. |
| 1978 # This might raise an exception in which case the assignment (do
ne |
| 1979 # below) will not happen. |
| 1980 # |
| 1981 # The reason this is not in a typetest-like node is because the |
| 1982 # variables that the acquired buffer info is stored to is alloca
ted |
| 1983 # per entry and coupled with it. |
| 1984 self.generate_acquire_buffer(rhs, code) |
| 1985 assigned = False |
| 1986 if self.type.is_pyobject: |
| 1987 #print "NameNode.generate_assignment_code: to", self.name ### |
| 1988 #print "...from", rhs ### |
| 1989 #print "...LHS type", self.type, "ctype", self.ctype() ### |
| 1990 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ### |
| 1991 if self.use_managed_ref: |
| 1992 rhs.make_owned_reference(code) |
| 1993 is_external_ref = entry.is_cglobal or self.entry.in_closure
or self.entry.from_closure |
| 1994 if is_external_ref: |
| 1995 if not self.cf_is_null: |
| 1996 if self.cf_maybe_null: |
| 1997 code.put_xgotref(self.py_result()) |
| 1998 else: |
| 1999 code.put_gotref(self.py_result()) |
| 2000 assigned = True |
| 2001 if entry.is_cglobal: |
| 2002 code.put_decref_set( |
| 2003 self.result(), rhs.result_as(self.ctype())) |
| 2004 else: |
| 2005 if not self.cf_is_null: |
| 2006 if self.cf_maybe_null: |
| 2007 code.put_xdecref_set( |
| 2008 self.result(), rhs.result_as(self.ctype())) |
| 2009 else: |
| 2010 code.put_decref_set( |
| 2011 self.result(), rhs.result_as(self.ctype())) |
| 2012 else: |
| 2013 assigned = False |
| 2014 if is_external_ref: |
| 2015 code.put_giveref(rhs.py_result()) |
| 2016 if not self.type.is_memoryviewslice: |
| 2017 if not assigned: |
| 2018 code.putln('%s = %s;' % ( |
| 2019 self.result(), rhs.result_as(self.ctype()))) |
| 2020 if debug_disposal_code: |
| 2021 print("NameNode.generate_assignment_code:") |
| 2022 print("...generating post-assignment code for %s" % rhs) |
| 2023 rhs.generate_post_assignment_code(code) |
| 2024 elif rhs.result_in_temp(): |
| 2025 rhs.generate_post_assignment_code(code) |
| 2026 |
| 2027 rhs.free_temps(code) |
| 2028 |
| 2029 def generate_acquire_memoryviewslice(self, rhs, code): |
| 2030 """ |
| 2031 Slices, coercions from objects, return values etc are new references. |
| 2032 We have a borrowed reference in case of dst = src |
| 2033 """ |
| 2034 import MemoryView |
| 2035 |
| 2036 MemoryView.put_acquire_memoryviewslice( |
| 2037 lhs_cname=self.result(), |
| 2038 lhs_type=self.type, |
| 2039 lhs_pos=self.pos, |
| 2040 rhs=rhs, |
| 2041 code=code, |
| 2042 have_gil=not self.in_nogil_context, |
| 2043 first_assignment=self.cf_is_null) |
| 2044 |
| 2045 def generate_acquire_buffer(self, rhs, code): |
| 2046 # rhstmp is only used in case the rhs is a complicated expression leadin
g to |
| 2047 # the object, to avoid repeating the same C expression for every referen
ce |
| 2048 # to the rhs. It does NOT hold a reference. |
| 2049 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp |
| 2050 if pretty_rhs: |
| 2051 rhstmp = rhs.result_as(self.ctype()) |
| 2052 else: |
| 2053 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=Fa
lse) |
| 2054 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype()))) |
| 2055 |
| 2056 import Buffer |
| 2057 Buffer.put_assign_to_buffer(self.result(), rhstmp, self.entry, |
| 2058 is_initialized=not self.lhs_of_first_assignm
ent, |
| 2059 pos=self.pos, code=code) |
| 2060 |
| 2061 if not pretty_rhs: |
| 2062 code.putln("%s = 0;" % rhstmp) |
| 2063 code.funcstate.release_temp(rhstmp) |
| 2064 |
| 2065 def generate_deletion_code(self, code, ignore_nonexisting=False): |
| 2066 if self.entry is None: |
| 2067 return # There was an error earlier |
| 2068 elif self.entry.is_pyclass_attr: |
| 2069 namespace = self.entry.scope.namespace_cname |
| 2070 interned_cname = code.intern_identifier(self.entry.name) |
| 2071 if ignore_nonexisting: |
| 2072 key_error_code = 'PyErr_Clear(); else' |
| 2073 else: |
| 2074 # minor hack: fake a NameError on KeyError |
| 2075 key_error_code = ( |
| 2076 '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\
' is not defined", "%s"); }' % |
| 2077 self.entry.name) |
| 2078 code.putln( |
| 2079 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {' |
| 2080 ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s' |
| 2081 ' %s ' |
| 2082 '}' % (namespace, interned_cname, |
| 2083 key_error_code, |
| 2084 code.error_goto(self.pos))) |
| 2085 elif self.entry.is_pyglobal: |
| 2086 code.globalstate.use_utility_code( |
| 2087 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"
)) |
| 2088 interned_cname = code.intern_identifier(self.entry.name) |
| 2089 del_code = '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( |
| 2090 Naming.module_cname, interned_cname) |
| 2091 if ignore_nonexisting: |
| 2092 code.putln('if (unlikely(%s < 0)) { if (likely(PyErr_ExceptionMa
tches(PyExc_AttributeError))) PyErr_Clear(); else %s }' % ( |
| 2093 del_code, |
| 2094 code.error_goto(self.pos))) |
| 2095 else: |
| 2096 code.put_error_if_neg(self.pos, del_code) |
| 2097 elif self.entry.type.is_pyobject or self.entry.type.is_memoryviewslice: |
| 2098 if not self.cf_is_null: |
| 2099 if self.cf_maybe_null and not ignore_nonexisting: |
| 2100 code.put_error_if_unbound(self.pos, self.entry) |
| 2101 |
| 2102 if self.entry.type.is_pyobject: |
| 2103 if self.entry.in_closure: |
| 2104 # generator |
| 2105 if ignore_nonexisting and self.cf_maybe_null: |
| 2106 code.put_xgotref(self.result()) |
| 2107 else: |
| 2108 code.put_gotref(self.result()) |
| 2109 if ignore_nonexisting and self.cf_maybe_null: |
| 2110 code.put_xdecref(self.result(), self.ctype()) |
| 2111 else: |
| 2112 code.put_decref(self.result(), self.ctype()) |
| 2113 code.putln('%s = NULL;' % self.result()) |
| 2114 else: |
| 2115 code.put_xdecref_memoryviewslice(self.entry.cname, |
| 2116 have_gil=not self.nogil) |
| 2117 else: |
| 2118 error(self.pos, "Deletion of C names not supported") |
| 2119 |
| 2120 def annotate(self, code): |
| 2121 if hasattr(self, 'is_called') and self.is_called: |
| 2122 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1) |
| 2123 if self.type.is_pyobject: |
| 2124 style, text = 'py_call', 'python function (%s)' |
| 2125 else: |
| 2126 style, text = 'c_call', 'c function (%s)' |
| 2127 code.annotate(pos, AnnotationItem(style, text % self.type, size=len(
self.name))) |
| 2128 |
| 2129 class BackquoteNode(ExprNode): |
| 2130 # `expr` |
| 2131 # |
| 2132 # arg ExprNode |
| 2133 |
| 2134 type = py_object_type |
| 2135 |
| 2136 subexprs = ['arg'] |
| 2137 |
| 2138 def analyse_types(self, env): |
| 2139 self.arg = self.arg.analyse_types(env) |
| 2140 self.arg = self.arg.coerce_to_pyobject(env) |
| 2141 self.is_temp = 1 |
| 2142 return self |
| 2143 |
| 2144 gil_message = "Backquote expression" |
| 2145 |
| 2146 def calculate_constant_result(self): |
| 2147 self.constant_result = repr(self.arg.constant_result) |
| 2148 |
| 2149 def generate_result_code(self, code): |
| 2150 code.putln( |
| 2151 "%s = PyObject_Repr(%s); %s" % ( |
| 2152 self.result(), |
| 2153 self.arg.py_result(), |
| 2154 code.error_goto_if_null(self.result(), self.pos))) |
| 2155 code.put_gotref(self.py_result()) |
| 2156 |
| 2157 |
| 2158 class ImportNode(ExprNode): |
| 2159 # Used as part of import statement implementation. |
| 2160 # Implements result = |
| 2161 # __import__(module_name, globals(), None, name_list, level) |
| 2162 # |
| 2163 # module_name StringNode dotted name of module. Empty module |
| 2164 # name means importing the parent package according |
| 2165 # to level |
| 2166 # name_list ListNode or None list of names to be imported |
| 2167 # level int relative import level: |
| 2168 # -1: attempt both relative import and absolute import
; |
| 2169 # 0: absolute import; |
| 2170 # >0: the number of parent directories to search |
| 2171 # relative to the current module. |
| 2172 # None: decide the level according to language level and |
| 2173 # directives |
| 2174 |
| 2175 type = py_object_type |
| 2176 |
| 2177 subexprs = ['module_name', 'name_list'] |
| 2178 |
| 2179 def analyse_types(self, env): |
| 2180 if self.level is None: |
| 2181 if (env.directives['py2_import'] or |
| 2182 Future.absolute_import not in env.global_scope().context.future_
directives): |
| 2183 self.level = -1 |
| 2184 else: |
| 2185 self.level = 0 |
| 2186 module_name = self.module_name.analyse_types(env) |
| 2187 self.module_name = module_name.coerce_to_pyobject(env) |
| 2188 if self.name_list: |
| 2189 name_list = self.name_list.analyse_types(env) |
| 2190 self.name_list = name_list.coerce_to_pyobject(env) |
| 2191 self.is_temp = 1 |
| 2192 env.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c")
) |
| 2193 return self |
| 2194 |
| 2195 gil_message = "Python import" |
| 2196 |
| 2197 def generate_result_code(self, code): |
| 2198 if self.name_list: |
| 2199 name_list_code = self.name_list.py_result() |
| 2200 else: |
| 2201 name_list_code = "0" |
| 2202 code.putln( |
| 2203 "%s = __Pyx_Import(%s, %s, %d); %s" % ( |
| 2204 self.result(), |
| 2205 self.module_name.py_result(), |
| 2206 name_list_code, |
| 2207 self.level, |
| 2208 code.error_goto_if_null(self.result(), self.pos))) |
| 2209 code.put_gotref(self.py_result()) |
| 2210 |
| 2211 |
| 2212 class IteratorNode(ExprNode): |
| 2213 # Used as part of for statement implementation. |
| 2214 # |
| 2215 # Implements result = iter(sequence) |
| 2216 # |
| 2217 # sequence ExprNode |
| 2218 |
| 2219 type = py_object_type |
| 2220 iter_func_ptr = None |
| 2221 counter_cname = None |
| 2222 cpp_iterator_cname = None |
| 2223 reversed = False # currently only used for list/tuple types (see Optimi
ze.py) |
| 2224 |
| 2225 subexprs = ['sequence'] |
| 2226 |
| 2227 def analyse_types(self, env): |
| 2228 self.sequence = self.sequence.analyse_types(env) |
| 2229 if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \ |
| 2230 not self.sequence.type.is_string: |
| 2231 # C array iteration will be transformed later on |
| 2232 self.type = self.sequence.type |
| 2233 elif self.sequence.type.is_cpp_class: |
| 2234 self.analyse_cpp_types(env) |
| 2235 else: |
| 2236 self.sequence = self.sequence.coerce_to_pyobject(env) |
| 2237 if self.sequence.type is list_type or \ |
| 2238 self.sequence.type is tuple_type: |
| 2239 self.sequence = self.sequence.as_none_safe_node("'NoneType' obje
ct is not iterable") |
| 2240 self.is_temp = 1 |
| 2241 return self |
| 2242 |
| 2243 gil_message = "Iterating over Python object" |
| 2244 |
| 2245 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( |
| 2246 PyrexTypes.py_object_type, [ |
| 2247 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), |
| 2248 ])) |
| 2249 |
| 2250 def type_dependencies(self, env): |
| 2251 return self.sequence.type_dependencies(env) |
| 2252 |
| 2253 def infer_type(self, env): |
| 2254 sequence_type = self.sequence.infer_type(env) |
| 2255 if sequence_type.is_array or sequence_type.is_ptr: |
| 2256 return sequence_type |
| 2257 elif sequence_type.is_cpp_class: |
| 2258 begin = sequence_type.scope.lookup("begin") |
| 2259 if begin is not None: |
| 2260 return begin.type.return_type |
| 2261 elif sequence_type.is_pyobject: |
| 2262 return sequence_type |
| 2263 return py_object_type |
| 2264 |
| 2265 def analyse_cpp_types(self, env): |
| 2266 sequence_type = self.sequence.type |
| 2267 if sequence_type.is_ptr: |
| 2268 sequence_type = sequence_type.base_type |
| 2269 begin = sequence_type.scope.lookup("begin") |
| 2270 end = sequence_type.scope.lookup("end") |
| 2271 if (begin is None |
| 2272 or not begin.type.is_cfunction |
| 2273 or begin.type.args): |
| 2274 error(self.pos, "missing begin() on %s" % self.sequence.type) |
| 2275 self.type = error_type |
| 2276 return |
| 2277 if (end is None |
| 2278 or not end.type.is_cfunction |
| 2279 or end.type.args): |
| 2280 error(self.pos, "missing end() on %s" % self.sequence.type) |
| 2281 self.type = error_type |
| 2282 return |
| 2283 iter_type = begin.type.return_type |
| 2284 if iter_type.is_cpp_class: |
| 2285 if env.lookup_operator_for_types( |
| 2286 self.pos, |
| 2287 "!=", |
| 2288 [iter_type, end.type.return_type]) is None: |
| 2289 error(self.pos, "missing operator!= on result of begin() on %s"
% self.sequence.type) |
| 2290 self.type = error_type |
| 2291 return |
| 2292 if env.lookup_operator_for_types(self.pos, '++', [iter_type]) is Non
e: |
| 2293 error(self.pos, "missing operator++ on result of begin() on %s"
% self.sequence.type) |
| 2294 self.type = error_type |
| 2295 return |
| 2296 if env.lookup_operator_for_types(self.pos, '*', [iter_type]) is None
: |
| 2297 error(self.pos, "missing operator* on result of begin() on %s" %
self.sequence.type) |
| 2298 self.type = error_type |
| 2299 return |
| 2300 self.type = iter_type |
| 2301 elif iter_type.is_ptr: |
| 2302 if not (iter_type == end.type.return_type): |
| 2303 error(self.pos, "incompatible types for begin() and end()") |
| 2304 self.type = iter_type |
| 2305 else: |
| 2306 error(self.pos, "result type of begin() on %s must be a C++ class or
pointer" % self.sequence.type) |
| 2307 self.type = error_type |
| 2308 return |
| 2309 |
| 2310 def generate_result_code(self, code): |
| 2311 sequence_type = self.sequence.type |
| 2312 if sequence_type.is_cpp_class: |
| 2313 if self.sequence.is_name: |
| 2314 # safe: C++ won't allow you to reassign to class references |
| 2315 begin_func = "%s.begin" % self.sequence.result() |
| 2316 else: |
| 2317 sequence_type = PyrexTypes.c_ptr_type(sequence_type) |
| 2318 self.cpp_iterator_cname = code.funcstate.allocate_temp(sequence_
type, manage_ref=False) |
| 2319 code.putln("%s = &%s;" % (self.cpp_iterator_cname, self.sequence
.result())) |
| 2320 begin_func = "%s->begin" % self.cpp_iterator_cname |
| 2321 # TODO: Limit scope. |
| 2322 code.putln("%s = %s();" % (self.result(), begin_func)) |
| 2323 return |
| 2324 if sequence_type.is_array or sequence_type.is_ptr: |
| 2325 raise InternalError("for in carray slice not transformed") |
| 2326 is_builtin_sequence = sequence_type is list_type or \ |
| 2327 sequence_type is tuple_type |
| 2328 if not is_builtin_sequence: |
| 2329 # reversed() not currently optimised (see Optimize.py) |
| 2330 assert not self.reversed, "internal error: reversed() only implement
ed for list/tuple objects" |
| 2331 self.may_be_a_sequence = not sequence_type.is_builtin_type |
| 2332 if self.may_be_a_sequence: |
| 2333 code.putln( |
| 2334 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % ( |
| 2335 self.sequence.py_result(), |
| 2336 self.sequence.py_result())) |
| 2337 if is_builtin_sequence or self.may_be_a_sequence: |
| 2338 self.counter_cname = code.funcstate.allocate_temp( |
| 2339 PyrexTypes.c_py_ssize_t_type, manage_ref=False) |
| 2340 if self.reversed: |
| 2341 if sequence_type is list_type: |
| 2342 init_value = 'PyList_GET_SIZE(%s) - 1' % self.result() |
| 2343 else: |
| 2344 init_value = 'PyTuple_GET_SIZE(%s) - 1' % self.result() |
| 2345 else: |
| 2346 init_value = '0' |
| 2347 code.putln( |
| 2348 "%s = %s; __Pyx_INCREF(%s); %s = %s;" % ( |
| 2349 self.result(), |
| 2350 self.sequence.py_result(), |
| 2351 self.result(), |
| 2352 self.counter_cname, |
| 2353 init_value |
| 2354 )) |
| 2355 if not is_builtin_sequence: |
| 2356 self.iter_func_ptr = code.funcstate.allocate_temp(self._func_iternex
t_type, manage_ref=False) |
| 2357 if self.may_be_a_sequence: |
| 2358 code.putln("%s = NULL;" % self.iter_func_ptr) |
| 2359 code.putln("} else {") |
| 2360 code.put("%s = -1; " % self.counter_cname) |
| 2361 code.putln("%s = PyObject_GetIter(%s); %s" % ( |
| 2362 self.result(), |
| 2363 self.sequence.py_result(), |
| 2364 code.error_goto_if_null(self.result(), self.pos))) |
| 2365 code.put_gotref(self.py_result()) |
| 2366 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % (self.iter_func_ptr, s
elf.py_result())) |
| 2367 if self.may_be_a_sequence: |
| 2368 code.putln("}") |
| 2369 |
| 2370 def generate_next_sequence_item(self, test_name, result_name, code): |
| 2371 assert self.counter_cname, "internal error: counter_cname temp not prepa
red" |
| 2372 final_size = 'Py%s_GET_SIZE(%s)' % (test_name, self.py_result()) |
| 2373 if self.sequence.is_sequence_constructor: |
| 2374 item_count = len(self.sequence.args) |
| 2375 if self.sequence.mult_factor is None: |
| 2376 final_size = item_count |
| 2377 elif isinstance(self.sequence.mult_factor.constant_result, (int, lon
g)): |
| 2378 final_size = item_count * self.sequence.mult_factor.constant_res
ult |
| 2379 code.putln("if (%s >= %s) break;" % (self.counter_cname, final_size)) |
| 2380 if self.reversed: |
| 2381 inc_dec = '--' |
| 2382 else: |
| 2383 inc_dec = '++' |
| 2384 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") |
| 2385 code.putln( |
| 2386 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % ( |
| 2387 result_name, |
| 2388 test_name, |
| 2389 self.py_result(), |
| 2390 self.counter_cname, |
| 2391 result_name, |
| 2392 self.counter_cname, |
| 2393 inc_dec, |
| 2394 # use the error label to avoid C compiler warnings if we only us
e it below |
| 2395 code.error_goto_if_neg('0', self.pos) |
| 2396 )) |
| 2397 code.putln("#else") |
| 2398 code.putln( |
| 2399 "%s = PySequence_ITEM(%s, %s); %s%s; %s" % ( |
| 2400 result_name, |
| 2401 self.py_result(), |
| 2402 self.counter_cname, |
| 2403 self.counter_cname, |
| 2404 inc_dec, |
| 2405 code.error_goto_if_null(result_name, self.pos))) |
| 2406 code.putln("#endif") |
| 2407 |
| 2408 def generate_iter_next_result_code(self, result_name, code): |
| 2409 sequence_type = self.sequence.type |
| 2410 if self.reversed: |
| 2411 code.putln("if (%s < 0) break;" % self.counter_cname) |
| 2412 if sequence_type.is_cpp_class: |
| 2413 if self.cpp_iterator_cname: |
| 2414 end_func = "%s->end" % self.cpp_iterator_cname |
| 2415 else: |
| 2416 end_func = "%s.end" % self.sequence.result() |
| 2417 # TODO: Cache end() call? |
| 2418 code.putln("if (!(%s != %s())) break;" % ( |
| 2419 self.result(), |
| 2420 end_func)) |
| 2421 code.putln("%s = *%s;" % ( |
| 2422 result_name, |
| 2423 self.result())) |
| 2424 code.putln("++%s;" % self.result()) |
| 2425 return |
| 2426 elif sequence_type is list_type: |
| 2427 self.generate_next_sequence_item('List', result_name, code) |
| 2428 return |
| 2429 elif sequence_type is tuple_type: |
| 2430 self.generate_next_sequence_item('Tuple', result_name, code) |
| 2431 return |
| 2432 |
| 2433 if self.may_be_a_sequence: |
| 2434 for test_name in ('List', 'Tuple'): |
| 2435 code.putln("if (!%s && Py%s_CheckExact(%s)) {" % ( |
| 2436 self.iter_func_ptr, test_name, self.py_result())) |
| 2437 self.generate_next_sequence_item(test_name, result_name, code) |
| 2438 code.put("} else ") |
| 2439 |
| 2440 code.putln("{") |
| 2441 code.putln( |
| 2442 "%s = %s(%s);" % ( |
| 2443 result_name, |
| 2444 self.iter_func_ptr, |
| 2445 self.py_result())) |
| 2446 code.putln("if (unlikely(!%s)) {" % result_name) |
| 2447 code.putln("PyObject* exc_type = PyErr_Occurred();") |
| 2448 code.putln("if (exc_type) {") |
| 2449 code.putln("if (likely(exc_type == PyExc_StopIteration ||" |
| 2450 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))
) PyErr_Clear();") |
| 2451 code.putln("else %s" % code.error_goto(self.pos)) |
| 2452 code.putln("}") |
| 2453 code.putln("break;") |
| 2454 code.putln("}") |
| 2455 code.put_gotref(result_name) |
| 2456 code.putln("}") |
| 2457 |
| 2458 def free_temps(self, code): |
| 2459 if self.counter_cname: |
| 2460 code.funcstate.release_temp(self.counter_cname) |
| 2461 if self.iter_func_ptr: |
| 2462 code.funcstate.release_temp(self.iter_func_ptr) |
| 2463 self.iter_func_ptr = None |
| 2464 if self.cpp_iterator_cname: |
| 2465 code.funcstate.release_temp(self.cpp_iterator_cname) |
| 2466 ExprNode.free_temps(self, code) |
| 2467 |
| 2468 |
| 2469 class NextNode(AtomicExprNode): |
| 2470 # Used as part of for statement implementation. |
| 2471 # Implements result = iterator.next() |
| 2472 # Created during analyse_types phase. |
| 2473 # The iterator is not owned by this node. |
| 2474 # |
| 2475 # iterator IteratorNode |
| 2476 |
| 2477 def __init__(self, iterator): |
| 2478 AtomicExprNode.__init__(self, iterator.pos) |
| 2479 self.iterator = iterator |
| 2480 |
| 2481 def type_dependencies(self, env): |
| 2482 return self.iterator.type_dependencies(env) |
| 2483 |
| 2484 def infer_type(self, env, iterator_type = None): |
| 2485 if iterator_type is None: |
| 2486 iterator_type = self.iterator.infer_type(env) |
| 2487 if iterator_type.is_ptr or iterator_type.is_array: |
| 2488 return iterator_type.base_type |
| 2489 elif iterator_type.is_cpp_class: |
| 2490 item_type = env.lookup_operator_for_types(self.pos, "*", [iterator_t
ype]).type.return_type |
| 2491 if item_type.is_reference: |
| 2492 item_type = item_type.ref_base_type |
| 2493 if item_type.is_const: |
| 2494 item_type = item_type.const_base_type |
| 2495 return item_type |
| 2496 else: |
| 2497 # Avoid duplication of complicated logic. |
| 2498 fake_index_node = IndexNode( |
| 2499 self.pos, |
| 2500 base=self.iterator.sequence, |
| 2501 index=IntNode(self.pos, value='PY_SSIZE_T_MAX', |
| 2502 type=PyrexTypes.c_py_ssize_t_type)) |
| 2503 return fake_index_node.infer_type(env) |
| 2504 |
| 2505 def analyse_types(self, env): |
| 2506 self.type = self.infer_type(env, self.iterator.type) |
| 2507 self.is_temp = 1 |
| 2508 return self |
| 2509 |
| 2510 def generate_result_code(self, code): |
| 2511 self.iterator.generate_iter_next_result_code(self.result(), code) |
| 2512 |
| 2513 |
| 2514 class WithExitCallNode(ExprNode): |
| 2515 # The __exit__() call of a 'with' statement. Used in both the |
| 2516 # except and finally clauses. |
| 2517 |
| 2518 # with_stat WithStatNode the surrounding 'with' statement |
| 2519 # args TupleNode or ResultStatNode the exception info tuple |
| 2520 |
| 2521 subexprs = ['args'] |
| 2522 test_if_run = True |
| 2523 |
| 2524 def analyse_types(self, env): |
| 2525 self.args = self.args.analyse_types(env) |
| 2526 self.type = PyrexTypes.c_bint_type |
| 2527 self.is_temp = True |
| 2528 return self |
| 2529 |
| 2530 def generate_evaluation_code(self, code): |
| 2531 if self.test_if_run: |
| 2532 # call only if it was not already called (and decref-cleared) |
| 2533 code.putln("if (%s) {" % self.with_stat.exit_var) |
| 2534 |
| 2535 self.args.generate_evaluation_code(code) |
| 2536 result_var = code.funcstate.allocate_temp(py_object_type, manage_ref=Fal
se) |
| 2537 |
| 2538 code.mark_pos(self.pos) |
| 2539 code.globalstate.use_utility_code(UtilityCode.load_cached( |
| 2540 "PyObjectCall", "ObjectHandling.c")) |
| 2541 code.putln("%s = __Pyx_PyObject_Call(%s, %s, NULL);" % ( |
| 2542 result_var, |
| 2543 self.with_stat.exit_var, |
| 2544 self.args.result())) |
| 2545 code.put_decref_clear(self.with_stat.exit_var, type=py_object_type) |
| 2546 self.args.generate_disposal_code(code) |
| 2547 self.args.free_temps(code) |
| 2548 |
| 2549 code.putln(code.error_goto_if_null(result_var, self.pos)) |
| 2550 code.put_gotref(result_var) |
| 2551 if self.result_is_used: |
| 2552 self.allocate_temp_result(code) |
| 2553 code.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self.result(), resul
t_var)) |
| 2554 code.put_decref_clear(result_var, type=py_object_type) |
| 2555 if self.result_is_used: |
| 2556 code.put_error_if_neg(self.pos, self.result()) |
| 2557 code.funcstate.release_temp(result_var) |
| 2558 if self.test_if_run: |
| 2559 code.putln("}") |
| 2560 |
| 2561 |
| 2562 class ExcValueNode(AtomicExprNode): |
| 2563 # Node created during analyse_types phase |
| 2564 # of an ExceptClauseNode to fetch the current |
| 2565 # exception value. |
| 2566 |
| 2567 type = py_object_type |
| 2568 |
| 2569 def __init__(self, pos): |
| 2570 ExprNode.__init__(self, pos) |
| 2571 |
| 2572 def set_var(self, var): |
| 2573 self.var = var |
| 2574 |
| 2575 def calculate_result_code(self): |
| 2576 return self.var |
| 2577 |
| 2578 def generate_result_code(self, code): |
| 2579 pass |
| 2580 |
| 2581 def analyse_types(self, env): |
| 2582 return self |
| 2583 |
| 2584 |
| 2585 class TempNode(ExprNode): |
| 2586 # Node created during analyse_types phase |
| 2587 # of some nodes to hold a temporary value. |
| 2588 # |
| 2589 # Note: One must call "allocate" and "release" on |
| 2590 # the node during code generation to get/release the temp. |
| 2591 # This is because the temp result is often used outside of |
| 2592 # the regular cycle. |
| 2593 |
| 2594 subexprs = [] |
| 2595 |
| 2596 def __init__(self, pos, type, env=None): |
| 2597 ExprNode.__init__(self, pos) |
| 2598 self.type = type |
| 2599 if type.is_pyobject: |
| 2600 self.result_ctype = py_object_type |
| 2601 self.is_temp = 1 |
| 2602 |
| 2603 def analyse_types(self, env): |
| 2604 return self |
| 2605 |
| 2606 def analyse_target_declaration(self, env): |
| 2607 pass |
| 2608 |
| 2609 def generate_result_code(self, code): |
| 2610 pass |
| 2611 |
| 2612 def allocate(self, code): |
| 2613 self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=Tru
e) |
| 2614 |
| 2615 def release(self, code): |
| 2616 code.funcstate.release_temp(self.temp_cname) |
| 2617 self.temp_cname = None |
| 2618 |
| 2619 def result(self): |
| 2620 try: |
| 2621 return self.temp_cname |
| 2622 except: |
| 2623 assert False, "Remember to call allocate/release on TempNode" |
| 2624 raise |
| 2625 |
| 2626 # Do not participate in normal temp alloc/dealloc: |
| 2627 def allocate_temp_result(self, code): |
| 2628 pass |
| 2629 |
| 2630 def release_temp_result(self, code): |
| 2631 pass |
| 2632 |
| 2633 class PyTempNode(TempNode): |
| 2634 # TempNode holding a Python value. |
| 2635 |
| 2636 def __init__(self, pos, env): |
| 2637 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env) |
| 2638 |
| 2639 class RawCNameExprNode(ExprNode): |
| 2640 subexprs = [] |
| 2641 |
| 2642 def __init__(self, pos, type=None, cname=None): |
| 2643 ExprNode.__init__(self, pos, type=type) |
| 2644 if cname is not None: |
| 2645 self.cname = cname |
| 2646 |
| 2647 def analyse_types(self, env): |
| 2648 return self |
| 2649 |
| 2650 def set_cname(self, cname): |
| 2651 self.cname = cname |
| 2652 |
| 2653 def result(self): |
| 2654 return self.cname |
| 2655 |
| 2656 def generate_result_code(self, code): |
| 2657 pass |
| 2658 |
| 2659 |
| 2660 #------------------------------------------------------------------- |
| 2661 # |
| 2662 # Parallel nodes (cython.parallel.thread(savailable|id)) |
| 2663 # |
| 2664 #------------------------------------------------------------------- |
| 2665 |
| 2666 class ParallelThreadsAvailableNode(AtomicExprNode): |
| 2667 """ |
| 2668 Note: this is disabled and not a valid directive at this moment |
| 2669 |
| 2670 Implements cython.parallel.threadsavailable(). If we are called from the |
| 2671 sequential part of the application, we need to call omp_get_max_threads(), |
| 2672 and in the parallel part we can just call omp_get_num_threads() |
| 2673 """ |
| 2674 |
| 2675 type = PyrexTypes.c_int_type |
| 2676 |
| 2677 def analyse_types(self, env): |
| 2678 self.is_temp = True |
| 2679 # env.add_include_file("omp.h") |
| 2680 return self |
| 2681 |
| 2682 def generate_result_code(self, code): |
| 2683 code.putln("#ifdef _OPENMP") |
| 2684 code.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" % |
| 2685 self.temp_code) |
| 2686 code.putln("else %s = omp_get_num_threads();" % self.temp_code) |
| 2687 code.putln("#else") |
| 2688 code.putln("%s = 1;" % self.temp_code) |
| 2689 code.putln("#endif") |
| 2690 |
| 2691 def result(self): |
| 2692 return self.temp_code |
| 2693 |
| 2694 |
| 2695 class ParallelThreadIdNode(AtomicExprNode): #, Nodes.ParallelNode): |
| 2696 """ |
| 2697 Implements cython.parallel.threadid() |
| 2698 """ |
| 2699 |
| 2700 type = PyrexTypes.c_int_type |
| 2701 |
| 2702 def analyse_types(self, env): |
| 2703 self.is_temp = True |
| 2704 # env.add_include_file("omp.h") |
| 2705 return self |
| 2706 |
| 2707 def generate_result_code(self, code): |
| 2708 code.putln("#ifdef _OPENMP") |
| 2709 code.putln("%s = omp_get_thread_num();" % self.temp_code) |
| 2710 code.putln("#else") |
| 2711 code.putln("%s = 0;" % self.temp_code) |
| 2712 code.putln("#endif") |
| 2713 |
| 2714 def result(self): |
| 2715 return self.temp_code |
| 2716 |
| 2717 |
| 2718 #------------------------------------------------------------------- |
| 2719 # |
| 2720 # Trailer nodes |
| 2721 # |
| 2722 #------------------------------------------------------------------- |
| 2723 |
| 2724 class IndexNode(ExprNode): |
| 2725 # Sequence indexing. |
| 2726 # |
| 2727 # base ExprNode |
| 2728 # index ExprNode |
| 2729 # indices [ExprNode] |
| 2730 # type_indices [PyrexType] |
| 2731 # is_buffer_access boolean Whether this is a buffer access. |
| 2732 # |
| 2733 # indices is used on buffer access, index on non-buffer access. |
| 2734 # The former contains a clean list of index parameters, the |
| 2735 # latter whatever Python object is needed for index access. |
| 2736 # |
| 2737 # is_fused_index boolean Whether the index is used to specialize a |
| 2738 # c(p)def function |
| 2739 |
| 2740 subexprs = ['base', 'index', 'indices'] |
| 2741 indices = None |
| 2742 type_indices = None |
| 2743 |
| 2744 is_subscript = True |
| 2745 is_fused_index = False |
| 2746 |
| 2747 # Whether we're assigning to a buffer (in that case it needs to be |
| 2748 # writable) |
| 2749 writable_needed = False |
| 2750 |
| 2751 # Whether we are indexing or slicing a memoryviewslice |
| 2752 memslice_index = False |
| 2753 memslice_slice = False |
| 2754 is_memslice_copy = False |
| 2755 memslice_ellipsis_noop = False |
| 2756 warned_untyped_idx = False |
| 2757 # set by SingleAssignmentNode after analyse_types() |
| 2758 is_memslice_scalar_assignment = False |
| 2759 |
| 2760 def __init__(self, pos, index, **kw): |
| 2761 ExprNode.__init__(self, pos, index=index, **kw) |
| 2762 self._index = index |
| 2763 |
| 2764 def calculate_constant_result(self): |
| 2765 self.constant_result = \ |
| 2766 self.base.constant_result[self.index.constant_result] |
| 2767 |
| 2768 def compile_time_value(self, denv): |
| 2769 base = self.base.compile_time_value(denv) |
| 2770 index = self.index.compile_time_value(denv) |
| 2771 try: |
| 2772 return base[index] |
| 2773 except Exception, e: |
| 2774 self.compile_time_value_error(e) |
| 2775 |
| 2776 def is_ephemeral(self): |
| 2777 return self.base.is_ephemeral() |
| 2778 |
| 2779 def is_simple(self): |
| 2780 if self.is_buffer_access or self.memslice_index: |
| 2781 return False |
| 2782 elif self.memslice_slice: |
| 2783 return True |
| 2784 |
| 2785 base = self.base |
| 2786 return (base.is_simple() and self.index.is_simple() |
| 2787 and base.type and (base.type.is_ptr or base.type.is_array)) |
| 2788 |
| 2789 def may_be_none(self): |
| 2790 base_type = self.base.type |
| 2791 if base_type: |
| 2792 if base_type.is_string: |
| 2793 return False |
| 2794 if isinstance(self.index, SliceNode): |
| 2795 # slicing! |
| 2796 if base_type in (bytes_type, str_type, unicode_type, |
| 2797 basestring_type, list_type, tuple_type): |
| 2798 return False |
| 2799 return ExprNode.may_be_none(self) |
| 2800 |
| 2801 def analyse_target_declaration(self, env): |
| 2802 pass |
| 2803 |
| 2804 def analyse_as_type(self, env): |
| 2805 base_type = self.base.analyse_as_type(env) |
| 2806 if base_type and not base_type.is_pyobject: |
| 2807 if base_type.is_cpp_class: |
| 2808 if isinstance(self.index, TupleNode): |
| 2809 template_values = self.index.args |
| 2810 else: |
| 2811 template_values = [self.index] |
| 2812 import Nodes |
| 2813 type_node = Nodes.TemplatedTypeNode( |
| 2814 pos = self.pos, |
| 2815 positional_args = template_values, |
| 2816 keyword_args = None) |
| 2817 return type_node.analyse(env, base_type = base_type) |
| 2818 else: |
| 2819 index = self.index.compile_time_value(env) |
| 2820 if index is not None: |
| 2821 return PyrexTypes.CArrayType(base_type, int(index)) |
| 2822 error(self.pos, "Array size must be a compile time constant") |
| 2823 return None |
| 2824 |
| 2825 def type_dependencies(self, env): |
| 2826 return self.base.type_dependencies(env) + self.index.type_dependencies(e
nv) |
| 2827 |
| 2828 def infer_type(self, env): |
| 2829 base_type = self.base.infer_type(env) |
| 2830 if isinstance(self.index, SliceNode): |
| 2831 # slicing! |
| 2832 if base_type.is_string: |
| 2833 # sliced C strings must coerce to Python |
| 2834 return bytes_type |
| 2835 elif base_type.is_pyunicode_ptr: |
| 2836 # sliced Py_UNICODE* strings must coerce to Python |
| 2837 return unicode_type |
| 2838 elif base_type in (unicode_type, bytes_type, str_type, |
| 2839 bytearray_type, list_type, tuple_type): |
| 2840 # slicing these returns the same type |
| 2841 return base_type |
| 2842 else: |
| 2843 # TODO: Handle buffers (hopefully without too much redundancy). |
| 2844 return py_object_type |
| 2845 |
| 2846 index_type = self.index.infer_type(env) |
| 2847 if index_type and index_type.is_int or isinstance(self.index, IntNode): |
| 2848 # indexing! |
| 2849 if base_type is unicode_type: |
| 2850 # Py_UCS4 will automatically coerce to a unicode string |
| 2851 # if required, so this is safe. We only infer Py_UCS4 |
| 2852 # when the index is a C integer type. Otherwise, we may |
| 2853 # need to use normal Python item access, in which case |
| 2854 # it's faster to return the one-char unicode string than |
| 2855 # to receive it, throw it away, and potentially rebuild it |
| 2856 # on a subsequent PyObject coercion. |
| 2857 return PyrexTypes.c_py_ucs4_type |
| 2858 elif base_type is str_type: |
| 2859 # always returns str - Py2: bytes, Py3: unicode |
| 2860 return base_type |
| 2861 elif base_type is bytearray_type: |
| 2862 return PyrexTypes.c_uchar_type |
| 2863 elif isinstance(self.base, BytesNode): |
| 2864 #if env.global_scope().context.language_level >= 3: |
| 2865 # # inferring 'char' can be made to work in Python 3 mode |
| 2866 # return PyrexTypes.c_char_type |
| 2867 # Py2/3 return different types on indexing bytes objects |
| 2868 return py_object_type |
| 2869 elif base_type in (tuple_type, list_type): |
| 2870 # if base is a literal, take a look at its values |
| 2871 item_type = infer_sequence_item_type( |
| 2872 env, self.base, self.index, seq_type=base_type) |
| 2873 if item_type is not None: |
| 2874 return item_type |
| 2875 elif base_type.is_ptr or base_type.is_array: |
| 2876 return base_type.base_type |
| 2877 |
| 2878 if base_type.is_cpp_class: |
| 2879 class FakeOperand: |
| 2880 def __init__(self, **kwds): |
| 2881 self.__dict__.update(kwds) |
| 2882 operands = [ |
| 2883 FakeOperand(pos=self.pos, type=base_type), |
| 2884 FakeOperand(pos=self.pos, type=index_type), |
| 2885 ] |
| 2886 index_func = env.lookup_operator('[]', operands) |
| 2887 if index_func is not None: |
| 2888 return index_func.type.return_type |
| 2889 |
| 2890 # may be slicing or indexing, we don't know |
| 2891 if base_type in (unicode_type, str_type): |
| 2892 # these types always returns their own type on Python indexing/slici
ng |
| 2893 return base_type |
| 2894 else: |
| 2895 # TODO: Handle buffers (hopefully without too much redundancy). |
| 2896 return py_object_type |
| 2897 |
| 2898 def analyse_types(self, env): |
| 2899 return self.analyse_base_and_index_types(env, getting=True) |
| 2900 |
| 2901 def analyse_target_types(self, env): |
| 2902 node = self.analyse_base_and_index_types(env, setting=True) |
| 2903 if node.type.is_const: |
| 2904 error(self.pos, "Assignment to const dereference") |
| 2905 if not node.is_lvalue(): |
| 2906 error(self.pos, "Assignment to non-lvalue of type '%s'" % node.type) |
| 2907 return node |
| 2908 |
| 2909 def analyse_base_and_index_types(self, env, getting=False, setting=False, |
| 2910 analyse_base=True): |
| 2911 # Note: This might be cleaned up by having IndexNode |
| 2912 # parsed in a saner way and only construct the tuple if |
| 2913 # needed. |
| 2914 |
| 2915 # Note that this function must leave IndexNode in a cloneable state. |
| 2916 # For buffers, self.index is packed out on the initial analysis, and |
| 2917 # when cloning self.indices is copied. |
| 2918 self.is_buffer_access = False |
| 2919 |
| 2920 # a[...] = b |
| 2921 self.is_memslice_copy = False |
| 2922 # incomplete indexing, Ellipsis indexing or slicing |
| 2923 self.memslice_slice = False |
| 2924 # integer indexing |
| 2925 self.memslice_index = False |
| 2926 |
| 2927 if analyse_base: |
| 2928 self.base = self.base.analyse_types(env) |
| 2929 |
| 2930 if self.base.type.is_error: |
| 2931 # Do not visit child tree if base is undeclared to avoid confusing |
| 2932 # error messages |
| 2933 self.type = PyrexTypes.error_type |
| 2934 return self |
| 2935 |
| 2936 is_slice = isinstance(self.index, SliceNode) |
| 2937 |
| 2938 if not env.directives['wraparound']: |
| 2939 if is_slice: |
| 2940 check_negative_indices(self.index.start, self.index.stop) |
| 2941 else: |
| 2942 check_negative_indices(self.index) |
| 2943 |
| 2944 # Potentially overflowing index value. |
| 2945 if not is_slice and isinstance(self.index, IntNode) and Utils.long_liter
al(self.index.value): |
| 2946 self.index = self.index.coerce_to_pyobject(env) |
| 2947 |
| 2948 is_memslice = self.base.type.is_memoryviewslice |
| 2949 |
| 2950 # Handle the case where base is a literal char* (and we expect a string,
not an int) |
| 2951 if not is_memslice and (isinstance(self.base, BytesNode) or is_slice): |
| 2952 if self.base.type.is_string or not (self.base.type.is_ptr or self.ba
se.type.is_array): |
| 2953 self.base = self.base.coerce_to_pyobject(env) |
| 2954 |
| 2955 skip_child_analysis = False |
| 2956 buffer_access = False |
| 2957 |
| 2958 if self.indices: |
| 2959 indices = self.indices |
| 2960 elif isinstance(self.index, TupleNode): |
| 2961 indices = self.index.args |
| 2962 else: |
| 2963 indices = [self.index] |
| 2964 |
| 2965 if (is_memslice and not self.indices and |
| 2966 isinstance(self.index, EllipsisNode)): |
| 2967 # Memoryviewslice copying |
| 2968 self.is_memslice_copy = True |
| 2969 |
| 2970 elif is_memslice: |
| 2971 # memoryviewslice indexing or slicing |
| 2972 import MemoryView |
| 2973 |
| 2974 skip_child_analysis = True |
| 2975 newaxes = [newaxis for newaxis in indices if newaxis.is_none] |
| 2976 have_slices, indices = MemoryView.unellipsify(indices, |
| 2977 newaxes, |
| 2978 self.base.type.ndim) |
| 2979 |
| 2980 self.memslice_index = (not newaxes and |
| 2981 len(indices) == self.base.type.ndim) |
| 2982 axes = [] |
| 2983 |
| 2984 index_type = PyrexTypes.c_py_ssize_t_type |
| 2985 new_indices = [] |
| 2986 |
| 2987 if len(indices) - len(newaxes) > self.base.type.ndim: |
| 2988 self.type = error_type |
| 2989 error(indices[self.base.type.ndim].pos, |
| 2990 "Too many indices specified for type %s" % |
| 2991 self.base.type) |
| 2992 return self |
| 2993 |
| 2994 axis_idx = 0 |
| 2995 for i, index in enumerate(indices[:]): |
| 2996 index = index.analyse_types(env) |
| 2997 if not index.is_none: |
| 2998 access, packing = self.base.type.axes[axis_idx] |
| 2999 axis_idx += 1 |
| 3000 |
| 3001 if isinstance(index, SliceNode): |
| 3002 self.memslice_slice = True |
| 3003 if index.step.is_none: |
| 3004 axes.append((access, packing)) |
| 3005 else: |
| 3006 axes.append((access, 'strided')) |
| 3007 |
| 3008 # Coerce start, stop and step to temps of the right type |
| 3009 for attr in ('start', 'stop', 'step'): |
| 3010 value = getattr(index, attr) |
| 3011 if not value.is_none: |
| 3012 value = value.coerce_to(index_type, env) |
| 3013 #value = value.coerce_to_temp(env) |
| 3014 setattr(index, attr, value) |
| 3015 new_indices.append(value) |
| 3016 |
| 3017 elif index.is_none: |
| 3018 self.memslice_slice = True |
| 3019 new_indices.append(index) |
| 3020 axes.append(('direct', 'strided')) |
| 3021 |
| 3022 elif index.type.is_int or index.type.is_pyobject: |
| 3023 if index.type.is_pyobject and not self.warned_untyped_idx: |
| 3024 warning(index.pos, "Index should be typed for more " |
| 3025 "efficient access", level=2) |
| 3026 IndexNode.warned_untyped_idx = True |
| 3027 |
| 3028 self.memslice_index = True |
| 3029 index = index.coerce_to(index_type, env) |
| 3030 indices[i] = index |
| 3031 new_indices.append(index) |
| 3032 |
| 3033 else: |
| 3034 self.type = error_type |
| 3035 error(index.pos, "Invalid index for memoryview specified") |
| 3036 return self |
| 3037 |
| 3038 self.memslice_index = self.memslice_index and not self.memslice_slic
e |
| 3039 self.original_indices = indices |
| 3040 # All indices with all start/stop/step for slices. |
| 3041 # We need to keep this around |
| 3042 self.indices = new_indices |
| 3043 self.env = env |
| 3044 |
| 3045 elif self.base.type.is_buffer: |
| 3046 # Buffer indexing |
| 3047 if len(indices) == self.base.type.ndim: |
| 3048 buffer_access = True |
| 3049 skip_child_analysis = True |
| 3050 for x in indices: |
| 3051 x = x.analyse_types(env) |
| 3052 if not x.type.is_int: |
| 3053 buffer_access = False |
| 3054 |
| 3055 if buffer_access and not self.base.type.is_memoryviewslice: |
| 3056 assert hasattr(self.base, "entry") # Must be a NameNode-like nod
e |
| 3057 |
| 3058 # On cloning, indices is cloned. Otherwise, unpack index into indices |
| 3059 assert not (buffer_access and isinstance(self.index, CloneNode)) |
| 3060 |
| 3061 self.nogil = env.nogil |
| 3062 |
| 3063 if buffer_access or self.memslice_index: |
| 3064 #if self.base.type.is_memoryviewslice and not self.base.is_name: |
| 3065 # self.base = self.base.coerce_to_temp(env) |
| 3066 self.base = self.base.coerce_to_simple(env) |
| 3067 |
| 3068 self.indices = indices |
| 3069 self.index = None |
| 3070 self.type = self.base.type.dtype |
| 3071 self.is_buffer_access = True |
| 3072 self.buffer_type = self.base.type #self.base.entry.type |
| 3073 |
| 3074 if getting and self.type.is_pyobject: |
| 3075 self.is_temp = True |
| 3076 |
| 3077 if setting and self.base.type.is_memoryviewslice: |
| 3078 self.base.type.writable_needed = True |
| 3079 elif setting: |
| 3080 if not self.base.entry.type.writable: |
| 3081 error(self.pos, "Writing to readonly buffer") |
| 3082 else: |
| 3083 self.writable_needed = True |
| 3084 if self.base.type.is_buffer: |
| 3085 self.base.entry.buffer_aux.writable_needed = True |
| 3086 |
| 3087 elif self.is_memslice_copy: |
| 3088 self.type = self.base.type |
| 3089 if getting: |
| 3090 self.memslice_ellipsis_noop = True |
| 3091 else: |
| 3092 self.memslice_broadcast = True |
| 3093 |
| 3094 elif self.memslice_slice: |
| 3095 self.index = None |
| 3096 self.is_temp = True |
| 3097 self.use_managed_ref = True |
| 3098 |
| 3099 if not MemoryView.validate_axes(self.pos, axes): |
| 3100 self.type = error_type |
| 3101 return self |
| 3102 |
| 3103 self.type = PyrexTypes.MemoryViewSliceType( |
| 3104 self.base.type.dtype, axes) |
| 3105 |
| 3106 if (self.base.type.is_memoryviewslice and not |
| 3107 self.base.is_name and not |
| 3108 self.base.result_in_temp()): |
| 3109 self.base = self.base.coerce_to_temp(env) |
| 3110 |
| 3111 if setting: |
| 3112 self.memslice_broadcast = True |
| 3113 |
| 3114 else: |
| 3115 base_type = self.base.type |
| 3116 |
| 3117 if not base_type.is_cfunction: |
| 3118 if isinstance(self.index, TupleNode): |
| 3119 self.index = self.index.analyse_types( |
| 3120 env, skip_children=skip_child_analysis) |
| 3121 elif not skip_child_analysis: |
| 3122 self.index = self.index.analyse_types(env) |
| 3123 self.original_index_type = self.index.type |
| 3124 |
| 3125 if base_type.is_unicode_char: |
| 3126 # we infer Py_UNICODE/Py_UCS4 for unicode strings in some |
| 3127 # cases, but indexing must still work for them |
| 3128 if setting: |
| 3129 warning(self.pos, "cannot assign to Unicode string index", l
evel=1) |
| 3130 elif self.index.constant_result in (0, -1): |
| 3131 # uchar[0] => uchar |
| 3132 return self.base |
| 3133 self.base = self.base.coerce_to_pyobject(env) |
| 3134 base_type = self.base.type |
| 3135 if base_type.is_pyobject: |
| 3136 if self.index.type.is_int and base_type is not dict_type: |
| 3137 if (getting |
| 3138 and (base_type in (list_type, tuple_type, bytearray_type
)) |
| 3139 and (not self.index.type.signed |
| 3140 or not env.directives['wraparound'] |
| 3141 or (isinstance(self.index, IntNode) and |
| 3142 self.index.has_constant_result() and self.index
.constant_result >= 0)) |
| 3143 and not env.directives['boundscheck']): |
| 3144 self.is_temp = 0 |
| 3145 else: |
| 3146 self.is_temp = 1 |
| 3147 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_ty
pe, env).coerce_to_simple(env) |
| 3148 self.original_index_type.create_to_py_utility_code(env) |
| 3149 else: |
| 3150 self.index = self.index.coerce_to_pyobject(env) |
| 3151 self.is_temp = 1 |
| 3152 if self.index.type.is_int and base_type is unicode_type: |
| 3153 # Py_UNICODE/Py_UCS4 will automatically coerce to a unicode
string |
| 3154 # if required, so this is fast and safe |
| 3155 self.type = PyrexTypes.c_py_ucs4_type |
| 3156 elif self.index.type.is_int and base_type is bytearray_type: |
| 3157 if setting: |
| 3158 self.type = PyrexTypes.c_uchar_type |
| 3159 else: |
| 3160 # not using 'uchar' to enable fast and safe error report
ing as '-1' |
| 3161 self.type = PyrexTypes.c_int_type |
| 3162 elif is_slice and base_type in (bytes_type, str_type, unicode_ty
pe, list_type, tuple_type): |
| 3163 self.type = base_type |
| 3164 else: |
| 3165 item_type = None |
| 3166 if base_type in (list_type, tuple_type) and self.index.type.
is_int: |
| 3167 item_type = infer_sequence_item_type( |
| 3168 env, self.base, self.index, seq_type=base_type) |
| 3169 if item_type is None: |
| 3170 item_type = py_object_type |
| 3171 self.type = item_type |
| 3172 if base_type in (list_type, tuple_type, dict_type): |
| 3173 # do the None check explicitly (not in a helper) to allo
w optimising it away |
| 3174 self.base = self.base.as_none_safe_node("'NoneType' obje
ct is not subscriptable") |
| 3175 else: |
| 3176 if base_type.is_ptr or base_type.is_array: |
| 3177 self.type = base_type.base_type |
| 3178 if is_slice: |
| 3179 self.type = base_type |
| 3180 elif self.index.type.is_pyobject: |
| 3181 self.index = self.index.coerce_to( |
| 3182 PyrexTypes.c_py_ssize_t_type, env) |
| 3183 elif not self.index.type.is_int: |
| 3184 error(self.pos, |
| 3185 "Invalid index type '%s'" % |
| 3186 self.index.type) |
| 3187 elif base_type.is_cpp_class: |
| 3188 function = env.lookup_operator("[]", [self.base, self.index]
) |
| 3189 if function is None: |
| 3190 error(self.pos, "Indexing '%s' not supported for index t
ype '%s'" % (base_type, self.index.type)) |
| 3191 self.type = PyrexTypes.error_type |
| 3192 self.result_code = "<error>" |
| 3193 return self |
| 3194 func_type = function.type |
| 3195 if func_type.is_ptr: |
| 3196 func_type = func_type.base_type |
| 3197 self.index = self.index.coerce_to(func_type.args[0].type, en
v) |
| 3198 self.type = func_type.return_type |
| 3199 if setting and not func_type.return_type.is_reference: |
| 3200 error(self.pos, "Can't set non-reference result '%s'" %
self.type) |
| 3201 elif base_type.is_cfunction: |
| 3202 if base_type.is_fused: |
| 3203 self.parse_indexed_fused_cdef(env) |
| 3204 else: |
| 3205 self.type_indices = self.parse_index_as_types(env) |
| 3206 if base_type.templates is None: |
| 3207 error(self.pos, "Can only parameterize template func
tions.") |
| 3208 elif len(base_type.templates) != len(self.type_indices): |
| 3209 error(self.pos, "Wrong number of template arguments:
expected %s, got %s" % ( |
| 3210 (len(base_type.templates), len(self.type_ind
ices)))) |
| 3211 self.type = base_type.specialize(dict(zip(base_type.temp
lates, self.type_indices))) |
| 3212 else: |
| 3213 error(self.pos, |
| 3214 "Attempting to index non-array type '%s'" % |
| 3215 base_type) |
| 3216 self.type = PyrexTypes.error_type |
| 3217 |
| 3218 self.wrap_in_nonecheck_node(env, getting) |
| 3219 return self |
| 3220 |
| 3221 def wrap_in_nonecheck_node(self, env, getting): |
| 3222 if not env.directives['nonecheck'] or not self.base.may_be_none(): |
| 3223 return |
| 3224 |
| 3225 if self.base.type.is_memoryviewslice: |
| 3226 if self.is_memslice_copy and not getting: |
| 3227 msg = "Cannot assign to None memoryview slice" |
| 3228 elif self.memslice_slice: |
| 3229 msg = "Cannot slice None memoryview slice" |
| 3230 else: |
| 3231 msg = "Cannot index None memoryview slice" |
| 3232 else: |
| 3233 msg = "'NoneType' object is not subscriptable" |
| 3234 |
| 3235 self.base = self.base.as_none_safe_node(msg) |
| 3236 |
| 3237 def parse_index_as_types(self, env, required=True): |
| 3238 if isinstance(self.index, TupleNode): |
| 3239 indices = self.index.args |
| 3240 else: |
| 3241 indices = [self.index] |
| 3242 type_indices = [] |
| 3243 for index in indices: |
| 3244 type_indices.append(index.analyse_as_type(env)) |
| 3245 if type_indices[-1] is None: |
| 3246 if required: |
| 3247 error(index.pos, "not parsable as a type") |
| 3248 return None |
| 3249 return type_indices |
| 3250 |
| 3251 def parse_indexed_fused_cdef(self, env): |
| 3252 """ |
| 3253 Interpret fused_cdef_func[specific_type1, ...] |
| 3254 |
| 3255 Note that if this method is called, we are an indexed cdef function |
| 3256 with fused argument types, and this IndexNode will be replaced by the |
| 3257 NameNode with specific entry just after analysis of expressions by |
| 3258 AnalyseExpressionsTransform. |
| 3259 """ |
| 3260 self.type = PyrexTypes.error_type |
| 3261 |
| 3262 self.is_fused_index = True |
| 3263 |
| 3264 base_type = self.base.type |
| 3265 specific_types = [] |
| 3266 positions = [] |
| 3267 |
| 3268 if self.index.is_name or self.index.is_attribute: |
| 3269 positions.append(self.index.pos) |
| 3270 elif isinstance(self.index, TupleNode): |
| 3271 for arg in self.index.args: |
| 3272 positions.append(arg.pos) |
| 3273 specific_types = self.parse_index_as_types(env, required=False) |
| 3274 |
| 3275 if specific_types is None: |
| 3276 self.index = self.index.analyse_types(env) |
| 3277 |
| 3278 if not self.base.entry.as_variable: |
| 3279 error(self.pos, "Can only index fused functions with types") |
| 3280 else: |
| 3281 # A cpdef function indexed with Python objects |
| 3282 self.base.entry = self.entry = self.base.entry.as_variable |
| 3283 self.base.type = self.type = self.entry.type |
| 3284 |
| 3285 self.base.is_temp = True |
| 3286 self.is_temp = True |
| 3287 |
| 3288 self.entry.used = True |
| 3289 |
| 3290 self.is_fused_index = False |
| 3291 return |
| 3292 |
| 3293 for i, type in enumerate(specific_types): |
| 3294 specific_types[i] = type.specialize_fused(env) |
| 3295 |
| 3296 fused_types = base_type.get_fused_types() |
| 3297 if len(specific_types) > len(fused_types): |
| 3298 return error(self.pos, "Too many types specified") |
| 3299 elif len(specific_types) < len(fused_types): |
| 3300 t = fused_types[len(specific_types)] |
| 3301 return error(self.pos, "Not enough types specified to specialize " |
| 3302 "the function, %s is still fused" % t) |
| 3303 |
| 3304 # See if our index types form valid specializations |
| 3305 for pos, specific_type, fused_type in zip(positions, |
| 3306 specific_types, |
| 3307 fused_types): |
| 3308 if not Utils.any([specific_type.same_as(t) |
| 3309 for t in fused_type.types]): |
| 3310 return error(pos, "Type not in fused type") |
| 3311 |
| 3312 if specific_type is None or specific_type.is_error: |
| 3313 return |
| 3314 |
| 3315 fused_to_specific = dict(zip(fused_types, specific_types)) |
| 3316 type = base_type.specialize(fused_to_specific) |
| 3317 |
| 3318 if type.is_fused: |
| 3319 # Only partially specific, this is invalid |
| 3320 error(self.pos, |
| 3321 "Index operation makes function only partially specific") |
| 3322 else: |
| 3323 # Fully specific, find the signature with the specialized entry |
| 3324 for signature in self.base.type.get_all_specialized_function_types()
: |
| 3325 if type.same_as(signature): |
| 3326 self.type = signature |
| 3327 |
| 3328 if self.base.is_attribute: |
| 3329 # Pretend to be a normal attribute, for cdef extension |
| 3330 # methods |
| 3331 self.entry = signature.entry |
| 3332 self.is_attribute = True |
| 3333 self.obj = self.base.obj |
| 3334 |
| 3335 self.type.entry.used = True |
| 3336 self.base.type = signature |
| 3337 self.base.entry = signature.entry |
| 3338 |
| 3339 break |
| 3340 else: |
| 3341 # This is a bug |
| 3342 raise InternalError("Couldn't find the right signature") |
| 3343 |
| 3344 gil_message = "Indexing Python object" |
| 3345 |
| 3346 def nogil_check(self, env): |
| 3347 if self.is_buffer_access or self.memslice_index or self.memslice_slice: |
| 3348 if not self.memslice_slice and env.directives['boundscheck']: |
| 3349 # error(self.pos, "Cannot check buffer index bounds without gil;
" |
| 3350 # "use boundscheck(False) directive") |
| 3351 warning(self.pos, "Use boundscheck(False) for faster access", |
| 3352 level=1) |
| 3353 if self.type.is_pyobject: |
| 3354 error(self.pos, "Cannot access buffer with object dtype without
gil") |
| 3355 return |
| 3356 super(IndexNode, self).nogil_check(env) |
| 3357 |
| 3358 |
| 3359 def check_const_addr(self): |
| 3360 return self.base.check_const_addr() and self.index.check_const() |
| 3361 |
| 3362 def is_lvalue(self): |
| 3363 # NOTE: references currently have both is_reference and is_ptr |
| 3364 # set. Since pointers and references have different lvalue |
| 3365 # rules, we must be careful to separate the two. |
| 3366 if self.type.is_reference: |
| 3367 if self.type.ref_base_type.is_array: |
| 3368 # fixed-sized arrays aren't l-values |
| 3369 return False |
| 3370 elif self.type.is_ptr: |
| 3371 # non-const pointers can always be reassigned |
| 3372 return True |
| 3373 elif self.type.is_array: |
| 3374 # fixed-sized arrays aren't l-values |
| 3375 return False |
| 3376 # Just about everything else returned by the index operator |
| 3377 # can be an lvalue. |
| 3378 return True |
| 3379 |
| 3380 def calculate_result_code(self): |
| 3381 if self.is_buffer_access: |
| 3382 return "(*%s)" % self.buffer_ptr_code |
| 3383 elif self.is_memslice_copy: |
| 3384 return self.base.result() |
| 3385 elif self.base.type in (list_type, tuple_type, bytearray_type): |
| 3386 if self.base.type is list_type: |
| 3387 index_code = "PyList_GET_ITEM(%s, %s)" |
| 3388 elif self.base.type is tuple_type: |
| 3389 index_code = "PyTuple_GET_ITEM(%s, %s)" |
| 3390 elif self.base.type is bytearray_type: |
| 3391 index_code = "((unsigned char)(PyByteArray_AS_STRING(%s)[%s]))" |
| 3392 else: |
| 3393 assert False, "unexpected base type in indexing: %s" % self.base
.type |
| 3394 elif self.base.type.is_cfunction: |
| 3395 return "%s<%s>" % ( |
| 3396 self.base.result(), |
| 3397 ",".join([param.declaration_code("") for param in self.type_indi
ces])) |
| 3398 else: |
| 3399 if (self.type.is_ptr or self.type.is_array) and self.type == self.ba
se.type: |
| 3400 error(self.pos, "Invalid use of pointer slice") |
| 3401 return |
| 3402 index_code = "(%s[%s])" |
| 3403 return index_code % (self.base.result(), self.index.result()) |
| 3404 |
| 3405 def extra_index_params(self, code): |
| 3406 if self.index.type.is_int: |
| 3407 is_list = self.base.type is list_type |
| 3408 wraparound = ( |
| 3409 bool(code.globalstate.directives['wraparound']) and |
| 3410 self.original_index_type.signed and |
| 3411 not (isinstance(self.index.constant_result, (int, long)) |
| 3412 and self.index.constant_result >= 0)) |
| 3413 boundscheck = bool(code.globalstate.directives['boundscheck']) |
| 3414 return ", %s, %d, %s, %d, %d, %d" % ( |
| 3415 self.original_index_type.declaration_code(""), |
| 3416 self.original_index_type.signed and 1 or 0, |
| 3417 self.original_index_type.to_py_function, |
| 3418 is_list, wraparound, boundscheck) |
| 3419 else: |
| 3420 return "" |
| 3421 |
| 3422 def generate_subexpr_evaluation_code(self, code): |
| 3423 self.base.generate_evaluation_code(code) |
| 3424 if self.type_indices is not None: |
| 3425 pass |
| 3426 elif self.indices is None: |
| 3427 self.index.generate_evaluation_code(code) |
| 3428 else: |
| 3429 for i in self.indices: |
| 3430 i.generate_evaluation_code(code) |
| 3431 |
| 3432 def generate_subexpr_disposal_code(self, code): |
| 3433 self.base.generate_disposal_code(code) |
| 3434 if self.type_indices is not None: |
| 3435 pass |
| 3436 elif self.indices is None: |
| 3437 self.index.generate_disposal_code(code) |
| 3438 else: |
| 3439 for i in self.indices: |
| 3440 i.generate_disposal_code(code) |
| 3441 |
| 3442 def free_subexpr_temps(self, code): |
| 3443 self.base.free_temps(code) |
| 3444 if self.indices is None: |
| 3445 self.index.free_temps(code) |
| 3446 else: |
| 3447 for i in self.indices: |
| 3448 i.free_temps(code) |
| 3449 |
| 3450 def generate_result_code(self, code): |
| 3451 if self.is_buffer_access or self.memslice_index: |
| 3452 buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code) |
| 3453 if self.type.is_pyobject: |
| 3454 # is_temp is True, so must pull out value and incref it. |
| 3455 # NOTE: object temporary results for nodes are declared |
| 3456 # as PyObject *, so we need a cast |
| 3457 code.putln("%s = (PyObject *) *%s;" % (self.temp_code, |
| 3458 self.buffer_ptr_code)) |
| 3459 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.temp_code) |
| 3460 |
| 3461 elif self.memslice_slice: |
| 3462 self.put_memoryviewslice_slice_code(code) |
| 3463 |
| 3464 elif self.is_temp: |
| 3465 if self.type.is_pyobject: |
| 3466 error_value = 'NULL' |
| 3467 if self.index.type.is_int: |
| 3468 if self.base.type is list_type: |
| 3469 function = "__Pyx_GetItemInt_List" |
| 3470 elif self.base.type is tuple_type: |
| 3471 function = "__Pyx_GetItemInt_Tuple" |
| 3472 else: |
| 3473 function = "__Pyx_GetItemInt" |
| 3474 code.globalstate.use_utility_code( |
| 3475 TempitaUtilityCode.load_cached("GetItemInt", "ObjectHand
ling.c")) |
| 3476 else: |
| 3477 if self.base.type is dict_type: |
| 3478 function = "__Pyx_PyDict_GetItem" |
| 3479 code.globalstate.use_utility_code( |
| 3480 UtilityCode.load_cached("DictGetItem", "ObjectHandli
ng.c")) |
| 3481 else: |
| 3482 function = "PyObject_GetItem" |
| 3483 elif self.type.is_unicode_char and self.base.type is unicode_type: |
| 3484 assert self.index.type.is_int |
| 3485 function = "__Pyx_GetItemInt_Unicode" |
| 3486 error_value = '(Py_UCS4)-1' |
| 3487 code.globalstate.use_utility_code( |
| 3488 UtilityCode.load_cached("GetItemIntUnicode", "StringTools.c"
)) |
| 3489 elif self.base.type is bytearray_type: |
| 3490 assert self.index.type.is_int |
| 3491 assert self.type.is_int |
| 3492 function = "__Pyx_GetItemInt_ByteArray" |
| 3493 error_value = '-1' |
| 3494 code.globalstate.use_utility_code( |
| 3495 UtilityCode.load_cached("GetItemIntByteArray", "StringTools.
c")) |
| 3496 else: |
| 3497 assert False, "unexpected type %s and base type %s for indexing"
% ( |
| 3498 self.type, self.base.type) |
| 3499 |
| 3500 if self.index.type.is_int: |
| 3501 index_code = self.index.result() |
| 3502 else: |
| 3503 index_code = self.index.py_result() |
| 3504 |
| 3505 code.putln( |
| 3506 "%s = %s(%s, %s%s); if (unlikely(%s == %s)) %s;" % ( |
| 3507 self.result(), |
| 3508 function, |
| 3509 self.base.py_result(), |
| 3510 index_code, |
| 3511 self.extra_index_params(code), |
| 3512 self.result(), |
| 3513 error_value, |
| 3514 code.error_goto(self.pos))) |
| 3515 if self.type.is_pyobject: |
| 3516 code.put_gotref(self.py_result()) |
| 3517 |
| 3518 def generate_setitem_code(self, value_code, code): |
| 3519 if self.index.type.is_int: |
| 3520 if self.base.type is bytearray_type: |
| 3521 code.globalstate.use_utility_code( |
| 3522 UtilityCode.load_cached("SetItemIntByteArray", "StringTools.
c")) |
| 3523 function = "__Pyx_SetItemInt_ByteArray" |
| 3524 else: |
| 3525 code.globalstate.use_utility_code( |
| 3526 UtilityCode.load_cached("SetItemInt", "ObjectHandling.c")) |
| 3527 function = "__Pyx_SetItemInt" |
| 3528 index_code = self.index.result() |
| 3529 else: |
| 3530 index_code = self.index.py_result() |
| 3531 if self.base.type is dict_type: |
| 3532 function = "PyDict_SetItem" |
| 3533 # It would seem that we could specialized lists/tuples, but that |
| 3534 # shouldn't happen here. |
| 3535 # Both PyList_SetItem() and PyTuple_SetItem() take a Py_ssize_t as |
| 3536 # index instead of an object, and bad conversion here would give |
| 3537 # the wrong exception. Also, tuples are supposed to be immutable, |
| 3538 # and raise a TypeError when trying to set their entries |
| 3539 # (PyTuple_SetItem() is for creating new tuples from scratch). |
| 3540 else: |
| 3541 function = "PyObject_SetItem" |
| 3542 code.putln( |
| 3543 "if (unlikely(%s(%s, %s, %s%s) < 0)) %s" % ( |
| 3544 function, |
| 3545 self.base.py_result(), |
| 3546 index_code, |
| 3547 value_code, |
| 3548 self.extra_index_params(code), |
| 3549 code.error_goto(self.pos))) |
| 3550 |
| 3551 def generate_buffer_setitem_code(self, rhs, code, op=""): |
| 3552 # Used from generate_assignment_code and InPlaceAssignmentNode |
| 3553 buffer_entry, ptrexpr = self.buffer_lookup_code(code) |
| 3554 |
| 3555 if self.buffer_type.dtype.is_pyobject: |
| 3556 # Must manage refcounts. Decref what is already there |
| 3557 # and incref what we put in. |
| 3558 ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type, |
| 3559 manage_ref=False) |
| 3560 rhs_code = rhs.result() |
| 3561 code.putln("%s = %s;" % (ptr, ptrexpr)) |
| 3562 code.put_gotref("*%s" % ptr) |
| 3563 code.putln("__Pyx_INCREF(%s); __Pyx_DECREF(*%s);" % ( |
| 3564 rhs_code, ptr)) |
| 3565 code.putln("*%s %s= %s;" % (ptr, op, rhs_code)) |
| 3566 code.put_giveref("*%s" % ptr) |
| 3567 code.funcstate.release_temp(ptr) |
| 3568 else: |
| 3569 # Simple case |
| 3570 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result())) |
| 3571 |
| 3572 def generate_assignment_code(self, rhs, code): |
| 3573 generate_evaluation_code = (self.is_memslice_scalar_assignment or |
| 3574 self.memslice_slice) |
| 3575 if generate_evaluation_code: |
| 3576 self.generate_evaluation_code(code) |
| 3577 else: |
| 3578 self.generate_subexpr_evaluation_code(code) |
| 3579 |
| 3580 if self.is_buffer_access or self.memslice_index: |
| 3581 self.generate_buffer_setitem_code(rhs, code) |
| 3582 elif self.is_memslice_scalar_assignment: |
| 3583 self.generate_memoryviewslice_assign_scalar_code(rhs, code) |
| 3584 elif self.memslice_slice or self.is_memslice_copy: |
| 3585 self.generate_memoryviewslice_setslice_code(rhs, code) |
| 3586 elif self.type.is_pyobject: |
| 3587 self.generate_setitem_code(rhs.py_result(), code) |
| 3588 elif self.base.type is bytearray_type: |
| 3589 value_code = self._check_byte_value(code, rhs) |
| 3590 self.generate_setitem_code(value_code, code) |
| 3591 else: |
| 3592 code.putln( |
| 3593 "%s = %s;" % ( |
| 3594 self.result(), rhs.result())) |
| 3595 |
| 3596 if generate_evaluation_code: |
| 3597 self.generate_disposal_code(code) |
| 3598 else: |
| 3599 self.generate_subexpr_disposal_code(code) |
| 3600 self.free_subexpr_temps(code) |
| 3601 |
| 3602 rhs.generate_disposal_code(code) |
| 3603 rhs.free_temps(code) |
| 3604 |
| 3605 def _check_byte_value(self, code, rhs): |
| 3606 # TODO: should we do this generally on downcasts, or just here? |
| 3607 assert rhs.type.is_int, repr(rhs.type) |
| 3608 value_code = rhs.result() |
| 3609 if rhs.has_constant_result(): |
| 3610 if 0 <= rhs.constant_result < 256: |
| 3611 return value_code |
| 3612 needs_cast = True # make at least the C compiler happy |
| 3613 warning(rhs.pos, |
| 3614 "value outside of range(0, 256)" |
| 3615 " when assigning to byte: %s" % rhs.constant_result, |
| 3616 level=1) |
| 3617 else: |
| 3618 needs_cast = rhs.type != PyrexTypes.c_uchar_type |
| 3619 |
| 3620 if not self.nogil: |
| 3621 conditions = [] |
| 3622 if rhs.is_literal or rhs.type.signed: |
| 3623 conditions.append('%s < 0' % value_code) |
| 3624 if (rhs.is_literal or not |
| 3625 (rhs.is_temp and rhs.type in ( |
| 3626 PyrexTypes.c_uchar_type, PyrexTypes.c_char_type, |
| 3627 PyrexTypes.c_schar_type))): |
| 3628 conditions.append('%s > 255' % value_code) |
| 3629 if conditions: |
| 3630 code.putln("if (unlikely(%s)) {" % ' || '.join(conditions)) |
| 3631 code.putln( |
| 3632 'PyErr_SetString(PyExc_ValueError,' |
| 3633 ' "byte must be in range(0, 256)"); %s' % |
| 3634 code.error_goto(self.pos)) |
| 3635 code.putln("}") |
| 3636 |
| 3637 if needs_cast: |
| 3638 value_code = '((unsigned char)%s)' % value_code |
| 3639 return value_code |
| 3640 |
| 3641 def generate_deletion_code(self, code, ignore_nonexisting=False): |
| 3642 self.generate_subexpr_evaluation_code(code) |
| 3643 #if self.type.is_pyobject: |
| 3644 if self.index.type.is_int: |
| 3645 function = "__Pyx_DelItemInt" |
| 3646 index_code = self.index.result() |
| 3647 code.globalstate.use_utility_code( |
| 3648 UtilityCode.load_cached("DelItemInt", "ObjectHandling.c")) |
| 3649 else: |
| 3650 index_code = self.index.py_result() |
| 3651 if self.base.type is dict_type: |
| 3652 function = "PyDict_DelItem" |
| 3653 else: |
| 3654 function = "PyObject_DelItem" |
| 3655 code.putln( |
| 3656 "if (%s(%s, %s%s) < 0) %s" % ( |
| 3657 function, |
| 3658 self.base.py_result(), |
| 3659 index_code, |
| 3660 self.extra_index_params(code), |
| 3661 code.error_goto(self.pos))) |
| 3662 self.generate_subexpr_disposal_code(code) |
| 3663 self.free_subexpr_temps(code) |
| 3664 |
| 3665 def buffer_entry(self): |
| 3666 import Buffer, MemoryView |
| 3667 |
| 3668 base = self.base |
| 3669 if self.base.is_nonecheck: |
| 3670 base = base.arg |
| 3671 |
| 3672 if base.is_name: |
| 3673 entry = base.entry |
| 3674 else: |
| 3675 # SimpleCallNode is_simple is not consistent with coerce_to_simple |
| 3676 assert base.is_simple() or base.is_temp |
| 3677 cname = base.result() |
| 3678 entry = Symtab.Entry(cname, cname, self.base.type, self.base.pos) |
| 3679 |
| 3680 if entry.type.is_buffer: |
| 3681 buffer_entry = Buffer.BufferEntry(entry) |
| 3682 else: |
| 3683 buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry) |
| 3684 |
| 3685 return buffer_entry |
| 3686 |
| 3687 def buffer_lookup_code(self, code): |
| 3688 "ndarray[1, 2, 3] and memslice[1, 2, 3]" |
| 3689 # Assign indices to temps |
| 3690 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) |
| 3691 for i in self.indices] |
| 3692 |
| 3693 for temp, index in zip(index_temps, self.indices): |
| 3694 code.putln("%s = %s;" % (temp, index.result())) |
| 3695 |
| 3696 # Generate buffer access code using these temps |
| 3697 import Buffer |
| 3698 buffer_entry = self.buffer_entry() |
| 3699 if buffer_entry.type.is_buffer: |
| 3700 negative_indices = buffer_entry.type.negative_indices |
| 3701 else: |
| 3702 negative_indices = Buffer.buffer_defaults['negative_indices'] |
| 3703 |
| 3704 return buffer_entry, Buffer.put_buffer_lookup_code( |
| 3705 entry=buffer_entry, |
| 3706 index_signeds=[i.type.signed for i in self.indices], |
| 3707 index_cnames=index_temps, |
| 3708 directives=code.globalstate.directives, |
| 3709 pos=self.pos, code=code, |
| 3710 negative_indices=negative_indices, |
| 3711 in_nogil_context=self.in_nogil_context) |
| 3712 |
| 3713 def put_memoryviewslice_slice_code(self, code): |
| 3714 "memslice[:]" |
| 3715 buffer_entry = self.buffer_entry() |
| 3716 have_gil = not self.in_nogil_context |
| 3717 |
| 3718 if sys.version_info < (3,): |
| 3719 def next_(it): |
| 3720 return it.next() |
| 3721 else: |
| 3722 next_ = next |
| 3723 |
| 3724 have_slices = False |
| 3725 it = iter(self.indices) |
| 3726 for index in self.original_indices: |
| 3727 is_slice = isinstance(index, SliceNode) |
| 3728 have_slices = have_slices or is_slice |
| 3729 if is_slice: |
| 3730 if not index.start.is_none: |
| 3731 index.start = next_(it) |
| 3732 if not index.stop.is_none: |
| 3733 index.stop = next_(it) |
| 3734 if not index.step.is_none: |
| 3735 index.step = next_(it) |
| 3736 else: |
| 3737 next_(it) |
| 3738 |
| 3739 assert not list(it) |
| 3740 |
| 3741 buffer_entry.generate_buffer_slice_code(code, self.original_indices, |
| 3742 self.result(), |
| 3743 have_gil=have_gil, |
| 3744 have_slices=have_slices, |
| 3745 directives=code.globalstate.dire
ctives) |
| 3746 |
| 3747 def generate_memoryviewslice_setslice_code(self, rhs, code): |
| 3748 "memslice1[...] = memslice2 or memslice1[:] = memslice2" |
| 3749 import MemoryView |
| 3750 MemoryView.copy_broadcast_memview_src_to_dst(rhs, self, code) |
| 3751 |
| 3752 def generate_memoryviewslice_assign_scalar_code(self, rhs, code): |
| 3753 "memslice1[...] = 0.0 or memslice1[:] = 0.0" |
| 3754 import MemoryView |
| 3755 MemoryView.assign_scalar(self, rhs, code) |
| 3756 |
| 3757 |
| 3758 class SliceIndexNode(ExprNode): |
| 3759 # 2-element slice indexing |
| 3760 # |
| 3761 # base ExprNode |
| 3762 # start ExprNode or None |
| 3763 # stop ExprNode or None |
| 3764 # slice ExprNode or None constant slice object |
| 3765 |
| 3766 subexprs = ['base', 'start', 'stop', 'slice'] |
| 3767 |
| 3768 slice = None |
| 3769 |
| 3770 def infer_type(self, env): |
| 3771 base_type = self.base.infer_type(env) |
| 3772 if base_type.is_string or base_type.is_cpp_class: |
| 3773 return bytes_type |
| 3774 elif base_type.is_pyunicode_ptr: |
| 3775 return unicode_type |
| 3776 elif base_type in (bytes_type, str_type, unicode_type, |
| 3777 basestring_type, list_type, tuple_type): |
| 3778 return base_type |
| 3779 elif base_type.is_ptr or base_type.is_array: |
| 3780 return PyrexTypes.c_array_type(base_type.base_type, None) |
| 3781 return py_object_type |
| 3782 |
| 3783 def may_be_none(self): |
| 3784 base_type = self.base.type |
| 3785 if base_type: |
| 3786 if base_type.is_string: |
| 3787 return False |
| 3788 if base_type in (bytes_type, str_type, unicode_type, |
| 3789 basestring_type, list_type, tuple_type): |
| 3790 return False |
| 3791 return ExprNode.may_be_none(self) |
| 3792 |
| 3793 def calculate_constant_result(self): |
| 3794 if self.start is None: |
| 3795 start = None |
| 3796 else: |
| 3797 start = self.start.constant_result |
| 3798 if self.stop is None: |
| 3799 stop = None |
| 3800 else: |
| 3801 stop = self.stop.constant_result |
| 3802 self.constant_result = self.base.constant_result[start:stop] |
| 3803 |
| 3804 def compile_time_value(self, denv): |
| 3805 base = self.base.compile_time_value(denv) |
| 3806 if self.start is None: |
| 3807 start = 0 |
| 3808 else: |
| 3809 start = self.start.compile_time_value(denv) |
| 3810 if self.stop is None: |
| 3811 stop = None |
| 3812 else: |
| 3813 stop = self.stop.compile_time_value(denv) |
| 3814 try: |
| 3815 return base[start:stop] |
| 3816 except Exception, e: |
| 3817 self.compile_time_value_error(e) |
| 3818 |
| 3819 def analyse_target_declaration(self, env): |
| 3820 pass |
| 3821 |
| 3822 def analyse_target_types(self, env): |
| 3823 node = self.analyse_types(env, getting=False) |
| 3824 # when assigning, we must accept any Python type |
| 3825 if node.type.is_pyobject: |
| 3826 node.type = py_object_type |
| 3827 return node |
| 3828 |
| 3829 def analyse_types(self, env, getting=True): |
| 3830 self.base = self.base.analyse_types(env) |
| 3831 |
| 3832 if self.base.type.is_memoryviewslice: |
| 3833 none_node = NoneNode(self.pos) |
| 3834 index = SliceNode(self.pos, |
| 3835 start=self.start or none_node, |
| 3836 stop=self.stop or none_node, |
| 3837 step=none_node) |
| 3838 index_node = IndexNode(self.pos, index, base=self.base) |
| 3839 return index_node.analyse_base_and_index_types( |
| 3840 env, getting=getting, setting=not getting, |
| 3841 analyse_base=False) |
| 3842 |
| 3843 if self.start: |
| 3844 self.start = self.start.analyse_types(env) |
| 3845 if self.stop: |
| 3846 self.stop = self.stop.analyse_types(env) |
| 3847 |
| 3848 if not env.directives['wraparound']: |
| 3849 check_negative_indices(self.start, self.stop) |
| 3850 |
| 3851 base_type = self.base.type |
| 3852 if base_type.is_string or base_type.is_cpp_string: |
| 3853 self.type = default_str_type(env) |
| 3854 elif base_type.is_pyunicode_ptr: |
| 3855 self.type = unicode_type |
| 3856 elif base_type.is_ptr: |
| 3857 self.type = base_type |
| 3858 elif base_type.is_array: |
| 3859 # we need a ptr type here instead of an array type, as |
| 3860 # array types can result in invalid type casts in the C |
| 3861 # code |
| 3862 self.type = PyrexTypes.CPtrType(base_type.base_type) |
| 3863 else: |
| 3864 self.base = self.base.coerce_to_pyobject(env) |
| 3865 self.type = py_object_type |
| 3866 if base_type.is_builtin_type: |
| 3867 # slicing builtin types returns something of the same type |
| 3868 self.type = base_type |
| 3869 self.base = self.base.as_none_safe_node("'NoneType' object is not su
bscriptable") |
| 3870 |
| 3871 if self.type is py_object_type: |
| 3872 if (not self.start or self.start.is_literal) and \ |
| 3873 (not self.stop or self.stop.is_literal): |
| 3874 # cache the constant slice object, in case we need it |
| 3875 none_node = NoneNode(self.pos) |
| 3876 self.slice = SliceNode( |
| 3877 self.pos, |
| 3878 start=copy.deepcopy(self.start or none_node), |
| 3879 stop=copy.deepcopy(self.stop or none_node), |
| 3880 step=none_node |
| 3881 ).analyse_types(env) |
| 3882 else: |
| 3883 c_int = PyrexTypes.c_py_ssize_t_type |
| 3884 if self.start: |
| 3885 self.start = self.start.coerce_to(c_int, env) |
| 3886 if self.stop: |
| 3887 self.stop = self.stop.coerce_to(c_int, env) |
| 3888 self.is_temp = 1 |
| 3889 return self |
| 3890 |
| 3891 nogil_check = Node.gil_error |
| 3892 gil_message = "Slicing Python object" |
| 3893 |
| 3894 get_slice_utility_code = TempitaUtilityCode.load( |
| 3895 "SliceObject", "ObjectHandling.c", context={'access': 'Get'}) |
| 3896 |
| 3897 set_slice_utility_code = TempitaUtilityCode.load( |
| 3898 "SliceObject", "ObjectHandling.c", context={'access': 'Set'}) |
| 3899 |
| 3900 def coerce_to(self, dst_type, env): |
| 3901 if ((self.base.type.is_string or self.base.type.is_cpp_string) |
| 3902 and dst_type in (bytes_type, bytearray_type, str_type, unicode_t
ype)): |
| 3903 if (dst_type not in (bytes_type, bytearray_type) |
| 3904 and not env.directives['c_string_encoding']): |
| 3905 error(self.pos, |
| 3906 "default encoding required for conversion from '%s' to '%s'"
% |
| 3907 (self.base.type, dst_type)) |
| 3908 self.type = dst_type |
| 3909 return super(SliceIndexNode, self).coerce_to(dst_type, env) |
| 3910 |
| 3911 def generate_result_code(self, code): |
| 3912 if not self.type.is_pyobject: |
| 3913 error(self.pos, |
| 3914 "Slicing is not currently supported for '%s'." % self.type) |
| 3915 return |
| 3916 |
| 3917 base_result = self.base.result() |
| 3918 result = self.result() |
| 3919 start_code = self.start_code() |
| 3920 stop_code = self.stop_code() |
| 3921 if self.base.type.is_string: |
| 3922 base_result = self.base.result() |
| 3923 if self.base.type != PyrexTypes.c_char_ptr_type: |
| 3924 base_result = '((const char*)%s)' % base_result |
| 3925 if self.type is bytearray_type: |
| 3926 type_name = 'ByteArray' |
| 3927 else: |
| 3928 type_name = self.type.name.title() |
| 3929 if self.stop is None: |
| 3930 code.putln( |
| 3931 "%s = __Pyx_Py%s_FromString(%s + %s); %s" % ( |
| 3932 result, |
| 3933 type_name, |
| 3934 base_result, |
| 3935 start_code, |
| 3936 code.error_goto_if_null(result, self.pos))) |
| 3937 else: |
| 3938 code.putln( |
| 3939 "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" %
( |
| 3940 result, |
| 3941 type_name, |
| 3942 base_result, |
| 3943 start_code, |
| 3944 stop_code, |
| 3945 start_code, |
| 3946 code.error_goto_if_null(result, self.pos))) |
| 3947 elif self.base.type.is_pyunicode_ptr: |
| 3948 base_result = self.base.result() |
| 3949 if self.base.type != PyrexTypes.c_py_unicode_ptr_type: |
| 3950 base_result = '((const Py_UNICODE*)%s)' % base_result |
| 3951 if self.stop is None: |
| 3952 code.putln( |
| 3953 "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % ( |
| 3954 result, |
| 3955 base_result, |
| 3956 start_code, |
| 3957 code.error_goto_if_null(result, self.pos))) |
| 3958 else: |
| 3959 code.putln( |
| 3960 "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s)
; %s" % ( |
| 3961 result, |
| 3962 base_result, |
| 3963 start_code, |
| 3964 stop_code, |
| 3965 start_code, |
| 3966 code.error_goto_if_null(result, self.pos))) |
| 3967 |
| 3968 elif self.base.type is unicode_type: |
| 3969 code.globalstate.use_utility_code( |
| 3970 UtilityCode.load_cached("PyUnicode_Substring", "String
Tools.c")) |
| 3971 code.putln( |
| 3972 "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % ( |
| 3973 result, |
| 3974 base_result, |
| 3975 start_code, |
| 3976 stop_code, |
| 3977 code.error_goto_if_null(result, self.pos))) |
| 3978 elif self.type is py_object_type: |
| 3979 code.globalstate.use_utility_code(self.get_slice_utility_code) |
| 3980 (has_c_start, has_c_stop, c_start, c_stop, |
| 3981 py_start, py_stop, py_slice) = self.get_slice_config() |
| 3982 code.putln( |
| 3983 "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d
); %s" % ( |
| 3984 result, |
| 3985 self.base.py_result(), |
| 3986 c_start, c_stop, |
| 3987 py_start, py_stop, py_slice, |
| 3988 has_c_start, has_c_stop, |
| 3989 bool(code.globalstate.directives['wraparound']), |
| 3990 code.error_goto_if_null(result, self.pos))) |
| 3991 else: |
| 3992 if self.base.type is list_type: |
| 3993 code.globalstate.use_utility_code( |
| 3994 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectH
andling.c")) |
| 3995 cfunc = '__Pyx_PyList_GetSlice' |
| 3996 elif self.base.type is tuple_type: |
| 3997 code.globalstate.use_utility_code( |
| 3998 TempitaUtilityCode.load_cached("SliceTupleAndList", "ObjectH
andling.c")) |
| 3999 cfunc = '__Pyx_PyTuple_GetSlice' |
| 4000 else: |
| 4001 cfunc = '__Pyx_PySequence_GetSlice' |
| 4002 code.putln( |
| 4003 "%s = %s(%s, %s, %s); %s" % ( |
| 4004 result, |
| 4005 cfunc, |
| 4006 self.base.py_result(), |
| 4007 start_code, |
| 4008 stop_code, |
| 4009 code.error_goto_if_null(result, self.pos))) |
| 4010 code.put_gotref(self.py_result()) |
| 4011 |
| 4012 def generate_assignment_code(self, rhs, code): |
| 4013 self.generate_subexpr_evaluation_code(code) |
| 4014 if self.type.is_pyobject: |
| 4015 code.globalstate.use_utility_code(self.set_slice_utility_code) |
| 4016 (has_c_start, has_c_stop, c_start, c_stop, |
| 4017 py_start, py_stop, py_slice) = self.get_slice_config() |
| 4018 code.put_error_if_neg(self.pos, |
| 4019 "__Pyx_PyObject_SetSlice(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)
" % ( |
| 4020 self.base.py_result(), |
| 4021 rhs.py_result(), |
| 4022 c_start, c_stop, |
| 4023 py_start, py_stop, py_slice, |
| 4024 has_c_start, has_c_stop, |
| 4025 bool(code.globalstate.directives['wraparound']))) |
| 4026 else: |
| 4027 start_offset = '' |
| 4028 if self.start: |
| 4029 start_offset = self.start_code() |
| 4030 if start_offset == '0': |
| 4031 start_offset = '' |
| 4032 else: |
| 4033 start_offset += '+' |
| 4034 if rhs.type.is_array: |
| 4035 array_length = rhs.type.size |
| 4036 self.generate_slice_guard_code(code, array_length) |
| 4037 else: |
| 4038 error(self.pos, |
| 4039 "Slice assignments from pointers are not yet supported.") |
| 4040 # FIXME: fix the array size according to start/stop |
| 4041 array_length = self.base.type.size |
| 4042 for i in range(array_length): |
| 4043 code.putln("%s[%s%s] = %s[%d];" % ( |
| 4044 self.base.result(), start_offset, i, |
| 4045 rhs.result(), i)) |
| 4046 self.generate_subexpr_disposal_code(code) |
| 4047 self.free_subexpr_temps(code) |
| 4048 rhs.generate_disposal_code(code) |
| 4049 rhs.free_temps(code) |
| 4050 |
| 4051 def generate_deletion_code(self, code, ignore_nonexisting=False): |
| 4052 if not self.base.type.is_pyobject: |
| 4053 error(self.pos, |
| 4054 "Deleting slices is only supported for Python types, not '%s'.
" % self.type) |
| 4055 return |
| 4056 self.generate_subexpr_evaluation_code(code) |
| 4057 code.globalstate.use_utility_code(self.set_slice_utility_code) |
| 4058 (has_c_start, has_c_stop, c_start, c_stop, |
| 4059 py_start, py_stop, py_slice) = self.get_slice_config() |
| 4060 code.put_error_if_neg(self.pos, |
| 4061 "__Pyx_PyObject_DelSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d)" % ( |
| 4062 self.base.py_result(), |
| 4063 c_start, c_stop, |
| 4064 py_start, py_stop, py_slice, |
| 4065 has_c_start, has_c_stop, |
| 4066 bool(code.globalstate.directives['wraparound']))) |
| 4067 self.generate_subexpr_disposal_code(code) |
| 4068 self.free_subexpr_temps(code) |
| 4069 |
| 4070 def get_slice_config(self): |
| 4071 has_c_start, c_start, py_start = False, '0', 'NULL' |
| 4072 if self.start: |
| 4073 has_c_start = not self.start.type.is_pyobject |
| 4074 if has_c_start: |
| 4075 c_start = self.start.result() |
| 4076 else: |
| 4077 py_start = '&%s' % self.start.py_result() |
| 4078 has_c_stop, c_stop, py_stop = False, '0', 'NULL' |
| 4079 if self.stop: |
| 4080 has_c_stop = not self.stop.type.is_pyobject |
| 4081 if has_c_stop: |
| 4082 c_stop = self.stop.result() |
| 4083 else: |
| 4084 py_stop = '&%s' % self.stop.py_result() |
| 4085 py_slice = self.slice and '&%s' % self.slice.py_result() or 'NULL' |
| 4086 return (has_c_start, has_c_stop, c_start, c_stop, |
| 4087 py_start, py_stop, py_slice) |
| 4088 |
| 4089 def generate_slice_guard_code(self, code, target_size): |
| 4090 if not self.base.type.is_array: |
| 4091 return |
| 4092 slice_size = self.base.type.size |
| 4093 start = stop = None |
| 4094 if self.stop: |
| 4095 stop = self.stop.result() |
| 4096 try: |
| 4097 stop = int(stop) |
| 4098 if stop < 0: |
| 4099 slice_size = self.base.type.size + stop |
| 4100 else: |
| 4101 slice_size = stop |
| 4102 stop = None |
| 4103 except ValueError: |
| 4104 pass |
| 4105 if self.start: |
| 4106 start = self.start.result() |
| 4107 try: |
| 4108 start = int(start) |
| 4109 if start < 0: |
| 4110 start = self.base.type.size + start |
| 4111 slice_size -= start |
| 4112 start = None |
| 4113 except ValueError: |
| 4114 pass |
| 4115 check = None |
| 4116 if slice_size < 0: |
| 4117 if target_size > 0: |
| 4118 error(self.pos, "Assignment to empty slice.") |
| 4119 elif start is None and stop is None: |
| 4120 # we know the exact slice length |
| 4121 if target_size != slice_size: |
| 4122 error(self.pos, "Assignment to slice of wrong length, expected %
d, got %d" % ( |
| 4123 slice_size, target_size)) |
| 4124 elif start is not None: |
| 4125 if stop is None: |
| 4126 stop = slice_size |
| 4127 check = "(%s)-(%s)" % (stop, start) |
| 4128 else: # stop is not None: |
| 4129 check = stop |
| 4130 if check: |
| 4131 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size)) |
| 4132 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of w
rong length, expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_
T "d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % ( |
| 4133 target_size, check)) |
| 4134 code.putln(code.error_goto(self.pos)) |
| 4135 code.putln("}") |
| 4136 |
| 4137 def start_code(self): |
| 4138 if self.start: |
| 4139 return self.start.result() |
| 4140 else: |
| 4141 return "0" |
| 4142 |
| 4143 def stop_code(self): |
| 4144 if self.stop: |
| 4145 return self.stop.result() |
| 4146 elif self.base.type.is_array: |
| 4147 return self.base.type.size |
| 4148 else: |
| 4149 return "PY_SSIZE_T_MAX" |
| 4150 |
| 4151 def calculate_result_code(self): |
| 4152 # self.result() is not used, but this method must exist |
| 4153 return "<unused>" |
| 4154 |
| 4155 |
| 4156 class SliceNode(ExprNode): |
| 4157 # start:stop:step in subscript list |
| 4158 # |
| 4159 # start ExprNode |
| 4160 # stop ExprNode |
| 4161 # step ExprNode |
| 4162 |
| 4163 subexprs = ['start', 'stop', 'step'] |
| 4164 |
| 4165 type = slice_type |
| 4166 is_temp = 1 |
| 4167 |
| 4168 def calculate_constant_result(self): |
| 4169 self.constant_result = slice( |
| 4170 self.start.constant_result, |
| 4171 self.stop.constant_result, |
| 4172 self.step.constant_result) |
| 4173 |
| 4174 def compile_time_value(self, denv): |
| 4175 start = self.start.compile_time_value(denv) |
| 4176 stop = self.stop.compile_time_value(denv) |
| 4177 step = self.step.compile_time_value(denv) |
| 4178 try: |
| 4179 return slice(start, stop, step) |
| 4180 except Exception, e: |
| 4181 self.compile_time_value_error(e) |
| 4182 |
| 4183 def may_be_none(self): |
| 4184 return False |
| 4185 |
| 4186 def analyse_types(self, env): |
| 4187 start = self.start.analyse_types(env) |
| 4188 stop = self.stop.analyse_types(env) |
| 4189 step = self.step.analyse_types(env) |
| 4190 self.start = start.coerce_to_pyobject(env) |
| 4191 self.stop = stop.coerce_to_pyobject(env) |
| 4192 self.step = step.coerce_to_pyobject(env) |
| 4193 if self.start.is_literal and self.stop.is_literal and self.step.is_liter
al: |
| 4194 self.is_literal = True |
| 4195 self.is_temp = False |
| 4196 return self |
| 4197 |
| 4198 gil_message = "Constructing Python slice object" |
| 4199 |
| 4200 def calculate_result_code(self): |
| 4201 return self.result_code |
| 4202 |
| 4203 def generate_result_code(self, code): |
| 4204 if self.is_literal: |
| 4205 self.result_code = code.get_py_const(py_object_type, 'slice', cleanu
p_level=2) |
| 4206 code = code.get_cached_constants_writer() |
| 4207 code.mark_pos(self.pos) |
| 4208 |
| 4209 code.putln( |
| 4210 "%s = PySlice_New(%s, %s, %s); %s" % ( |
| 4211 self.result(), |
| 4212 self.start.py_result(), |
| 4213 self.stop.py_result(), |
| 4214 self.step.py_result(), |
| 4215 code.error_goto_if_null(self.result(), self.pos))) |
| 4216 code.put_gotref(self.py_result()) |
| 4217 if self.is_literal: |
| 4218 code.put_giveref(self.py_result()) |
| 4219 |
| 4220 def __deepcopy__(self, memo): |
| 4221 """ |
| 4222 There is a copy bug in python 2.4 for slice objects. |
| 4223 """ |
| 4224 return SliceNode( |
| 4225 self.pos, |
| 4226 start=copy.deepcopy(self.start, memo), |
| 4227 stop=copy.deepcopy(self.stop, memo), |
| 4228 step=copy.deepcopy(self.step, memo), |
| 4229 is_temp=self.is_temp, |
| 4230 is_literal=self.is_literal, |
| 4231 constant_result=self.constant_result) |
| 4232 |
| 4233 |
| 4234 class CallNode(ExprNode): |
| 4235 |
| 4236 # allow overriding the default 'may_be_none' behaviour |
| 4237 may_return_none = None |
| 4238 |
| 4239 def infer_type(self, env): |
| 4240 function = self.function |
| 4241 func_type = function.infer_type(env) |
| 4242 if isinstance(function, NewExprNode): |
| 4243 # note: needs call to infer_type() above |
| 4244 return PyrexTypes.CPtrType(function.class_type) |
| 4245 if func_type is py_object_type: |
| 4246 # function might have lied for safety => try to find better type |
| 4247 entry = getattr(function, 'entry', None) |
| 4248 if entry is not None: |
| 4249 func_type = entry.type or func_type |
| 4250 if func_type.is_ptr: |
| 4251 func_type = func_type.base_type |
| 4252 if func_type.is_cfunction: |
| 4253 return func_type.return_type |
| 4254 elif func_type is type_type: |
| 4255 if function.is_name and function.entry and function.entry.type: |
| 4256 result_type = function.entry.type |
| 4257 if result_type.is_extension_type: |
| 4258 return result_type |
| 4259 elif result_type.is_builtin_type: |
| 4260 if function.entry.name == 'float': |
| 4261 return PyrexTypes.c_double_type |
| 4262 elif function.entry.name in Builtin.types_that_construct_the
ir_instance: |
| 4263 return result_type |
| 4264 return py_object_type |
| 4265 |
| 4266 def type_dependencies(self, env): |
| 4267 # TODO: Update when Danilo's C++ code merged in to handle the |
| 4268 # the case of function overloading. |
| 4269 return self.function.type_dependencies(env) |
| 4270 |
| 4271 def is_simple(self): |
| 4272 # C function calls could be considered simple, but they may |
| 4273 # have side-effects that may hit when multiple operations must |
| 4274 # be effected in order, e.g. when constructing the argument |
| 4275 # sequence for a function call or comparing values. |
| 4276 return False |
| 4277 |
| 4278 def may_be_none(self): |
| 4279 if self.may_return_none is not None: |
| 4280 return self.may_return_none |
| 4281 func_type = self.function.type |
| 4282 if func_type is type_type and self.function.is_name: |
| 4283 entry = self.function.entry |
| 4284 if entry.type.is_extension_type: |
| 4285 return False |
| 4286 if (entry.type.is_builtin_type and |
| 4287 entry.name in Builtin.types_that_construct_their_instance): |
| 4288 return False |
| 4289 return ExprNode.may_be_none(self) |
| 4290 |
| 4291 def analyse_as_type_constructor(self, env): |
| 4292 type = self.function.analyse_as_type(env) |
| 4293 if type and type.is_struct_or_union: |
| 4294 args, kwds = self.explicit_args_kwds() |
| 4295 items = [] |
| 4296 for arg, member in zip(args, type.scope.var_entries): |
| 4297 items.append(DictItemNode(pos=arg.pos, key=StringNode(pos=arg.po
s, value=member.name), value=arg)) |
| 4298 if kwds: |
| 4299 items += kwds.key_value_pairs |
| 4300 self.key_value_pairs = items |
| 4301 self.__class__ = DictNode |
| 4302 self.analyse_types(env) # FIXME |
| 4303 self.coerce_to(type, env) |
| 4304 return True |
| 4305 elif type and type.is_cpp_class: |
| 4306 self.args = [ arg.analyse_types(env) for arg in self.args ] |
| 4307 constructor = type.scope.lookup("<init>") |
| 4308 self.function = RawCNameExprNode(self.function.pos, constructor.type
) |
| 4309 self.function.entry = constructor |
| 4310 self.function.set_cname(type.declaration_code("")) |
| 4311 self.analyse_c_function_call(env) |
| 4312 self.type = type |
| 4313 return True |
| 4314 |
| 4315 def is_lvalue(self): |
| 4316 return self.type.is_reference |
| 4317 |
| 4318 def nogil_check(self, env): |
| 4319 func_type = self.function_type() |
| 4320 if func_type.is_pyobject: |
| 4321 self.gil_error() |
| 4322 elif not getattr(func_type, 'nogil', False): |
| 4323 self.gil_error() |
| 4324 |
| 4325 gil_message = "Calling gil-requiring function" |
| 4326 |
| 4327 |
| 4328 class SimpleCallNode(CallNode): |
| 4329 # Function call without keyword, * or ** args. |
| 4330 # |
| 4331 # function ExprNode |
| 4332 # args [ExprNode] |
| 4333 # arg_tuple ExprNode or None used internally |
| 4334 # self ExprNode or None used internally |
| 4335 # coerced_self ExprNode or None used internally |
| 4336 # wrapper_call bool used internally |
| 4337 # has_optional_args bool used internally |
| 4338 # nogil bool used internally |
| 4339 |
| 4340 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] |
| 4341 |
| 4342 self = None |
| 4343 coerced_self = None |
| 4344 arg_tuple = None |
| 4345 wrapper_call = False |
| 4346 has_optional_args = False |
| 4347 nogil = False |
| 4348 analysed = False |
| 4349 |
| 4350 def compile_time_value(self, denv): |
| 4351 function = self.function.compile_time_value(denv) |
| 4352 args = [arg.compile_time_value(denv) for arg in self.args] |
| 4353 try: |
| 4354 return function(*args) |
| 4355 except Exception, e: |
| 4356 self.compile_time_value_error(e) |
| 4357 |
| 4358 def analyse_as_type(self, env): |
| 4359 attr = self.function.as_cython_attribute() |
| 4360 if attr == 'pointer': |
| 4361 if len(self.args) != 1: |
| 4362 error(self.args.pos, "only one type allowed.") |
| 4363 else: |
| 4364 type = self.args[0].analyse_as_type(env) |
| 4365 if not type: |
| 4366 error(self.args[0].pos, "Unknown type") |
| 4367 else: |
| 4368 return PyrexTypes.CPtrType(type) |
| 4369 |
| 4370 def explicit_args_kwds(self): |
| 4371 return self.args, None |
| 4372 |
| 4373 def analyse_types(self, env): |
| 4374 if self.analyse_as_type_constructor(env): |
| 4375 return self |
| 4376 if self.analysed: |
| 4377 return self |
| 4378 self.analysed = True |
| 4379 self.function.is_called = 1 |
| 4380 self.function = self.function.analyse_types(env) |
| 4381 function = self.function |
| 4382 |
| 4383 if function.is_attribute and function.entry and function.entry.is_cmetho
d: |
| 4384 # Take ownership of the object from which the attribute |
| 4385 # was obtained, because we need to pass it as 'self'. |
| 4386 self.self = function.obj |
| 4387 function.obj = CloneNode(self.self) |
| 4388 |
| 4389 func_type = self.function_type() |
| 4390 if func_type.is_pyobject: |
| 4391 self.arg_tuple = TupleNode(self.pos, args = self.args) |
| 4392 self.arg_tuple = self.arg_tuple.analyse_types(env) |
| 4393 self.args = None |
| 4394 if func_type is Builtin.type_type and function.is_name and \ |
| 4395 function.entry and \ |
| 4396 function.entry.is_builtin and \ |
| 4397 function.entry.name in Builtin.types_that_construct_their_ins
tance: |
| 4398 # calling a builtin type that returns a specific object type |
| 4399 if function.entry.name == 'float': |
| 4400 # the following will come true later on in a transform |
| 4401 self.type = PyrexTypes.c_double_type |
| 4402 self.result_ctype = PyrexTypes.c_double_type |
| 4403 else: |
| 4404 self.type = Builtin.builtin_types[function.entry.name] |
| 4405 self.result_ctype = py_object_type |
| 4406 self.may_return_none = False |
| 4407 elif function.is_name and function.type_entry: |
| 4408 # We are calling an extension type constructor. As |
| 4409 # long as we do not support __new__(), the result type |
| 4410 # is clear |
| 4411 self.type = function.type_entry.type |
| 4412 self.result_ctype = py_object_type |
| 4413 self.may_return_none = False |
| 4414 else: |
| 4415 self.type = py_object_type |
| 4416 self.is_temp = 1 |
| 4417 else: |
| 4418 self.args = [ arg.analyse_types(env) for arg in self.args ] |
| 4419 self.analyse_c_function_call(env) |
| 4420 return self |
| 4421 |
| 4422 def function_type(self): |
| 4423 # Return the type of the function being called, coercing a function |
| 4424 # pointer to a function if necessary. If the function has fused |
| 4425 # arguments, return the specific type. |
| 4426 func_type = self.function.type |
| 4427 |
| 4428 if func_type.is_ptr: |
| 4429 func_type = func_type.base_type |
| 4430 |
| 4431 return func_type |
| 4432 |
| 4433 def analyse_c_function_call(self, env): |
| 4434 if self.function.type is error_type: |
| 4435 self.type = error_type |
| 4436 return |
| 4437 |
| 4438 if self.self: |
| 4439 args = [self.self] + self.args |
| 4440 else: |
| 4441 args = self.args |
| 4442 |
| 4443 if self.function.type.is_cpp_class: |
| 4444 overloaded_entry = self.function.type.scope.lookup("operator()") |
| 4445 if overloaded_entry is None: |
| 4446 self.type = PyrexTypes.error_type |
| 4447 self.result_code = "<error>" |
| 4448 return |
| 4449 elif hasattr(self.function, 'entry'): |
| 4450 overloaded_entry = self.function.entry |
| 4451 elif (isinstance(self.function, IndexNode) and |
| 4452 self.function.is_fused_index): |
| 4453 overloaded_entry = self.function.type.entry |
| 4454 else: |
| 4455 overloaded_entry = None |
| 4456 |
| 4457 if overloaded_entry: |
| 4458 if self.function.type.is_fused: |
| 4459 functypes = self.function.type.get_all_specialized_function_type
s() |
| 4460 alternatives = [f.entry for f in functypes] |
| 4461 else: |
| 4462 alternatives = overloaded_entry.all_alternatives() |
| 4463 |
| 4464 entry = PyrexTypes.best_match(args, alternatives, self.pos, env) |
| 4465 |
| 4466 if not entry: |
| 4467 self.type = PyrexTypes.error_type |
| 4468 self.result_code = "<error>" |
| 4469 return |
| 4470 |
| 4471 entry.used = True |
| 4472 self.function.entry = entry |
| 4473 self.function.type = entry.type |
| 4474 func_type = self.function_type() |
| 4475 else: |
| 4476 entry = None |
| 4477 func_type = self.function_type() |
| 4478 if not func_type.is_cfunction: |
| 4479 error(self.pos, "Calling non-function type '%s'" % func_type) |
| 4480 self.type = PyrexTypes.error_type |
| 4481 self.result_code = "<error>" |
| 4482 return |
| 4483 |
| 4484 # Check no. of args |
| 4485 max_nargs = len(func_type.args) |
| 4486 expected_nargs = max_nargs - func_type.optional_arg_count |
| 4487 actual_nargs = len(args) |
| 4488 if func_type.optional_arg_count and expected_nargs != actual_nargs: |
| 4489 self.has_optional_args = 1 |
| 4490 self.is_temp = 1 |
| 4491 |
| 4492 # check 'self' argument |
| 4493 if entry and entry.is_cmethod and func_type.args: |
| 4494 formal_arg = func_type.args[0] |
| 4495 arg = args[0] |
| 4496 if formal_arg.not_none: |
| 4497 if self.self: |
| 4498 self.self = self.self.as_none_safe_node( |
| 4499 "'NoneType' object has no attribute '%s'", |
| 4500 error='PyExc_AttributeError', |
| 4501 format_args=[entry.name]) |
| 4502 else: |
| 4503 # unbound method |
| 4504 arg = arg.as_none_safe_node( |
| 4505 "descriptor '%s' requires a '%s' object but received a '
NoneType'", |
| 4506 format_args=[entry.name, formal_arg.type.name]) |
| 4507 if self.self: |
| 4508 if formal_arg.accept_builtin_subtypes: |
| 4509 arg = CMethodSelfCloneNode(self.self) |
| 4510 else: |
| 4511 arg = CloneNode(self.self) |
| 4512 arg = self.coerced_self = arg.coerce_to(formal_arg.type, env) |
| 4513 elif formal_arg.type.is_builtin_type: |
| 4514 # special case: unbound methods of builtins accept subtypes |
| 4515 arg = arg.coerce_to(formal_arg.type, env) |
| 4516 if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode): |
| 4517 arg.exact_builtin_type = False |
| 4518 args[0] = arg |
| 4519 |
| 4520 # Coerce arguments |
| 4521 some_args_in_temps = False |
| 4522 for i in xrange(min(max_nargs, actual_nargs)): |
| 4523 formal_arg = func_type.args[i] |
| 4524 formal_type = formal_arg.type |
| 4525 arg = args[i].coerce_to(formal_type, env) |
| 4526 if formal_arg.not_none: |
| 4527 # C methods must do the None checks at *call* time |
| 4528 arg = arg.as_none_safe_node( |
| 4529 "cannot pass None into a C function argument that is declare
d 'not None'") |
| 4530 if arg.is_temp: |
| 4531 if i > 0: |
| 4532 # first argument in temp doesn't impact subsequent arguments |
| 4533 some_args_in_temps = True |
| 4534 elif arg.type.is_pyobject and not env.nogil: |
| 4535 if i == 0 and self.self is not None: |
| 4536 # a method's cloned "self" argument is ok |
| 4537 pass |
| 4538 elif arg.nonlocally_immutable(): |
| 4539 # plain local variables are ok |
| 4540 pass |
| 4541 else: |
| 4542 # we do not safely own the argument's reference, |
| 4543 # but we must make sure it cannot be collected |
| 4544 # before we return from the function, so we create |
| 4545 # an owned temp reference to it |
| 4546 if i > 0: # first argument doesn't matter |
| 4547 some_args_in_temps = True |
| 4548 arg = arg.coerce_to_temp(env) |
| 4549 args[i] = arg |
| 4550 |
| 4551 # handle additional varargs parameters |
| 4552 for i in xrange(max_nargs, actual_nargs): |
| 4553 arg = args[i] |
| 4554 if arg.type.is_pyobject: |
| 4555 arg_ctype = arg.type.default_coerced_ctype() |
| 4556 if arg_ctype is None: |
| 4557 error(self.args[i].pos, |
| 4558 "Python object cannot be passed as a varargs parameter
") |
| 4559 else: |
| 4560 args[i] = arg = arg.coerce_to(arg_ctype, env) |
| 4561 if arg.is_temp and i > 0: |
| 4562 some_args_in_temps = True |
| 4563 |
| 4564 if some_args_in_temps: |
| 4565 # if some args are temps and others are not, they may get |
| 4566 # constructed in the wrong order (temps first) => make |
| 4567 # sure they are either all temps or all not temps (except |
| 4568 # for the last argument, which is evaluated last in any |
| 4569 # case) |
| 4570 for i in xrange(actual_nargs-1): |
| 4571 if i == 0 and self.self is not None: |
| 4572 continue # self is ok |
| 4573 arg = args[i] |
| 4574 if arg.nonlocally_immutable(): |
| 4575 # locals, C functions, unassignable types are safe. |
| 4576 pass |
| 4577 elif arg.type.is_cpp_class: |
| 4578 # Assignment has side effects, avoid. |
| 4579 pass |
| 4580 elif env.nogil and arg.type.is_pyobject: |
| 4581 # can't copy a Python reference into a temp in nogil |
| 4582 # env (this is safe: a construction would fail in |
| 4583 # nogil anyway) |
| 4584 pass |
| 4585 else: |
| 4586 #self.args[i] = arg.coerce_to_temp(env) |
| 4587 # instead: issue a warning |
| 4588 if i > 0 or i == 1 and self.self is not None: # skip first a
rg |
| 4589 warning(arg.pos, "Argument evaluation order in C functio
n call is undefined and may not be as expected", 0) |
| 4590 break |
| 4591 |
| 4592 self.args[:] = args |
| 4593 |
| 4594 # Calc result type and code fragment |
| 4595 if isinstance(self.function, NewExprNode): |
| 4596 self.type = PyrexTypes.CPtrType(self.function.class_type) |
| 4597 else: |
| 4598 self.type = func_type.return_type |
| 4599 |
| 4600 if self.function.is_name or self.function.is_attribute: |
| 4601 if self.function.entry and self.function.entry.utility_code: |
| 4602 self.is_temp = 1 # currently doesn't work for self.calculate_res
ult_code() |
| 4603 |
| 4604 if self.type.is_pyobject: |
| 4605 self.result_ctype = py_object_type |
| 4606 self.is_temp = 1 |
| 4607 elif func_type.exception_value is not None \ |
| 4608 or func_type.exception_check: |
| 4609 self.is_temp = 1 |
| 4610 elif self.type.is_memoryviewslice: |
| 4611 self.is_temp = 1 |
| 4612 # func_type.exception_check = True |
| 4613 |
| 4614 # Called in 'nogil' context? |
| 4615 self.nogil = env.nogil |
| 4616 if (self.nogil and |
| 4617 func_type.exception_check and |
| 4618 func_type.exception_check != '+'): |
| 4619 env.use_utility_code(pyerr_occurred_withgil_utility_code) |
| 4620 # C++ exception handler |
| 4621 if func_type.exception_check == '+': |
| 4622 if func_type.exception_value is None: |
| 4623 env.use_utility_code(UtilityCode.load_cached("CppExceptionConver
sion", "CppSupport.cpp")) |
| 4624 |
| 4625 def calculate_result_code(self): |
| 4626 return self.c_call_code() |
| 4627 |
| 4628 def c_call_code(self): |
| 4629 func_type = self.function_type() |
| 4630 if self.type is PyrexTypes.error_type or not func_type.is_cfunction: |
| 4631 return "<error>" |
| 4632 formal_args = func_type.args |
| 4633 arg_list_code = [] |
| 4634 args = list(zip(formal_args, self.args)) |
| 4635 max_nargs = len(func_type.args) |
| 4636 expected_nargs = max_nargs - func_type.optional_arg_count |
| 4637 actual_nargs = len(self.args) |
| 4638 for formal_arg, actual_arg in args[:expected_nargs]: |
| 4639 arg_code = actual_arg.result_as(formal_arg.type) |
| 4640 arg_list_code.append(arg_code) |
| 4641 |
| 4642 if func_type.is_overridable: |
| 4643 arg_list_code.append(str(int(self.wrapper_call or self.function.entr
y.is_unbound_cmethod))) |
| 4644 |
| 4645 if func_type.optional_arg_count: |
| 4646 if expected_nargs == actual_nargs: |
| 4647 optional_args = 'NULL' |
| 4648 else: |
| 4649 optional_args = "&%s" % self.opt_arg_struct |
| 4650 arg_list_code.append(optional_args) |
| 4651 |
| 4652 for actual_arg in self.args[len(formal_args):]: |
| 4653 arg_list_code.append(actual_arg.result()) |
| 4654 |
| 4655 result = "%s(%s)" % (self.function.result(), ', '.join(arg_list_code)) |
| 4656 return result |
| 4657 |
| 4658 def generate_result_code(self, code): |
| 4659 func_type = self.function_type() |
| 4660 if self.function.is_name or self.function.is_attribute: |
| 4661 if self.function.entry and self.function.entry.utility_code: |
| 4662 code.globalstate.use_utility_code(self.function.entry.utility_co
de) |
| 4663 if func_type.is_pyobject: |
| 4664 arg_code = self.arg_tuple.py_result() |
| 4665 code.globalstate.use_utility_code(UtilityCode.load_cached( |
| 4666 "PyObjectCall", "ObjectHandling.c")) |
| 4667 code.putln( |
| 4668 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % ( |
| 4669 self.result(), |
| 4670 self.function.py_result(), |
| 4671 arg_code, |
| 4672 code.error_goto_if_null(self.result(), self.pos))) |
| 4673 code.put_gotref(self.py_result()) |
| 4674 elif func_type.is_cfunction: |
| 4675 if self.has_optional_args: |
| 4676 actual_nargs = len(self.args) |
| 4677 expected_nargs = len(func_type.args) - func_type.optional_arg_co
unt |
| 4678 self.opt_arg_struct = code.funcstate.allocate_temp( |
| 4679 func_type.op_arg_struct.base_type, manage_ref=True) |
| 4680 code.putln("%s.%s = %s;" % ( |
| 4681 self.opt_arg_struct, |
| 4682 Naming.pyrex_prefix + "n", |
| 4683 len(self.args) - expected_nargs)) |
| 4684 args = list(zip(func_type.args, self.args)) |
| 4685 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]: |
| 4686 code.putln("%s.%s = %s;" % ( |
| 4687 self.opt_arg_struct, |
| 4688 func_type.opt_arg_cname(formal_arg.name), |
| 4689 actual_arg.result_as(formal_arg.type))) |
| 4690 exc_checks = [] |
| 4691 if self.type.is_pyobject and self.is_temp: |
| 4692 exc_checks.append("!%s" % self.result()) |
| 4693 elif self.type.is_memoryviewslice: |
| 4694 assert self.is_temp |
| 4695 exc_checks.append(self.type.error_condition(self.result())) |
| 4696 else: |
| 4697 exc_val = func_type.exception_value |
| 4698 exc_check = func_type.exception_check |
| 4699 if exc_val is not None: |
| 4700 exc_checks.append("%s == %s" % (self.result(), exc_val)) |
| 4701 if exc_check: |
| 4702 if self.nogil: |
| 4703 exc_checks.append("__Pyx_ErrOccurredWithGIL()") |
| 4704 else: |
| 4705 exc_checks.append("PyErr_Occurred()") |
| 4706 if self.is_temp or exc_checks: |
| 4707 rhs = self.c_call_code() |
| 4708 if self.result(): |
| 4709 lhs = "%s = " % self.result() |
| 4710 if self.is_temp and self.type.is_pyobject: |
| 4711 #return_type = self.type # func_type.return_type |
| 4712 #print "SimpleCallNode.generate_result_code: casting", r
hs, \ |
| 4713 # "from", return_type, "to pyobject" ### |
| 4714 rhs = typecast(py_object_type, self.type, rhs) |
| 4715 else: |
| 4716 lhs = "" |
| 4717 if func_type.exception_check == '+': |
| 4718 if func_type.exception_value is None: |
| 4719 raise_py_exception = "__Pyx_CppExn2PyErr();" |
| 4720 elif func_type.exception_value.type.is_pyobject: |
| 4721 raise_py_exception = 'try { throw; } catch(const std::ex
ception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s
); }' % ( |
| 4722 func_type.exception_value.entry.cname, |
| 4723 func_type.exception_value.entry.cname) |
| 4724 else: |
| 4725 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr
_SetString(PyExc_RuntimeError , "Error converting c++ exception.");' % func_type
.exception_value.entry.cname |
| 4726 code.putln("try {") |
| 4727 code.putln("%s%s;" % (lhs, rhs)) |
| 4728 code.putln("} catch(...) {") |
| 4729 if self.nogil: |
| 4730 code.put_ensure_gil(declare_gilstate=True) |
| 4731 code.putln(raise_py_exception) |
| 4732 if self.nogil: |
| 4733 code.put_release_ensured_gil() |
| 4734 code.putln(code.error_goto(self.pos)) |
| 4735 code.putln("}") |
| 4736 else: |
| 4737 if exc_checks: |
| 4738 goto_error = code.error_goto_if(" && ".join(exc_checks),
self.pos) |
| 4739 else: |
| 4740 goto_error = "" |
| 4741 code.putln("%s%s; %s" % (lhs, rhs, goto_error)) |
| 4742 if self.type.is_pyobject and self.result(): |
| 4743 code.put_gotref(self.py_result()) |
| 4744 if self.has_optional_args: |
| 4745 code.funcstate.release_temp(self.opt_arg_struct) |
| 4746 |
| 4747 |
| 4748 class InlinedDefNodeCallNode(CallNode): |
| 4749 # Inline call to defnode |
| 4750 # |
| 4751 # function PyCFunctionNode |
| 4752 # function_name NameNode |
| 4753 # args [ExprNode] |
| 4754 |
| 4755 subexprs = ['args', 'function_name'] |
| 4756 is_temp = 1 |
| 4757 type = py_object_type |
| 4758 function = None |
| 4759 function_name = None |
| 4760 |
| 4761 def can_be_inlined(self): |
| 4762 func_type= self.function.def_node |
| 4763 if func_type.star_arg or func_type.starstar_arg: |
| 4764 return False |
| 4765 if len(func_type.args) != len(self.args): |
| 4766 return False |
| 4767 return True |
| 4768 |
| 4769 def analyse_types(self, env): |
| 4770 self.function_name = self.function_name.analyse_types(env) |
| 4771 |
| 4772 self.args = [ arg.analyse_types(env) for arg in self.args ] |
| 4773 func_type = self.function.def_node |
| 4774 actual_nargs = len(self.args) |
| 4775 |
| 4776 # Coerce arguments |
| 4777 some_args_in_temps = False |
| 4778 for i in xrange(actual_nargs): |
| 4779 formal_type = func_type.args[i].type |
| 4780 arg = self.args[i].coerce_to(formal_type, env) |
| 4781 if arg.is_temp: |
| 4782 if i > 0: |
| 4783 # first argument in temp doesn't impact subsequent arguments |
| 4784 some_args_in_temps = True |
| 4785 elif arg.type.is_pyobject and not env.nogil: |
| 4786 if arg.nonlocally_immutable(): |
| 4787 # plain local variables are ok |
| 4788 pass |
| 4789 else: |
| 4790 # we do not safely own the argument's reference, |
| 4791 # but we must make sure it cannot be collected |
| 4792 # before we return from the function, so we create |
| 4793 # an owned temp reference to it |
| 4794 if i > 0: # first argument doesn't matter |
| 4795 some_args_in_temps = True |
| 4796 arg = arg.coerce_to_temp(env) |
| 4797 self.args[i] = arg |
| 4798 |
| 4799 if some_args_in_temps: |
| 4800 # if some args are temps and others are not, they may get |
| 4801 # constructed in the wrong order (temps first) => make |
| 4802 # sure they are either all temps or all not temps (except |
| 4803 # for the last argument, which is evaluated last in any |
| 4804 # case) |
| 4805 for i in xrange(actual_nargs-1): |
| 4806 arg = self.args[i] |
| 4807 if arg.nonlocally_immutable(): |
| 4808 # locals, C functions, unassignable types are safe. |
| 4809 pass |
| 4810 elif arg.type.is_cpp_class: |
| 4811 # Assignment has side effects, avoid. |
| 4812 pass |
| 4813 elif env.nogil and arg.type.is_pyobject: |
| 4814 # can't copy a Python reference into a temp in nogil |
| 4815 # env (this is safe: a construction would fail in |
| 4816 # nogil anyway) |
| 4817 pass |
| 4818 else: |
| 4819 #self.args[i] = arg.coerce_to_temp(env) |
| 4820 # instead: issue a warning |
| 4821 if i > 0: |
| 4822 warning(arg.pos, "Argument evaluation order in C functio
n call is undefined and may not be as expected", 0) |
| 4823 break |
| 4824 return self |
| 4825 |
| 4826 def generate_result_code(self, code): |
| 4827 arg_code = [self.function_name.py_result()] |
| 4828 func_type = self.function.def_node |
| 4829 for arg, proto_arg in zip(self.args, func_type.args): |
| 4830 if arg.type.is_pyobject: |
| 4831 arg_code.append(arg.result_as(proto_arg.type)) |
| 4832 else: |
| 4833 arg_code.append(arg.result()) |
| 4834 arg_code = ', '.join(arg_code) |
| 4835 code.putln( |
| 4836 "%s = %s(%s); %s" % ( |
| 4837 self.result(), |
| 4838 self.function.def_node.entry.pyfunc_cname, |
| 4839 arg_code, |
| 4840 code.error_goto_if_null(self.result(), self.pos))) |
| 4841 code.put_gotref(self.py_result()) |
| 4842 |
| 4843 |
| 4844 class PythonCapiFunctionNode(ExprNode): |
| 4845 subexprs = [] |
| 4846 |
| 4847 def __init__(self, pos, py_name, cname, func_type, utility_code = None): |
| 4848 ExprNode.__init__(self, pos, name=py_name, cname=cname, |
| 4849 type=func_type, utility_code=utility_code) |
| 4850 |
| 4851 def analyse_types(self, env): |
| 4852 return self |
| 4853 |
| 4854 def generate_result_code(self, code): |
| 4855 if self.utility_code: |
| 4856 code.globalstate.use_utility_code(self.utility_code) |
| 4857 |
| 4858 def calculate_result_code(self): |
| 4859 return self.cname |
| 4860 |
| 4861 |
| 4862 class PythonCapiCallNode(SimpleCallNode): |
| 4863 # Python C-API Function call (only created in transforms) |
| 4864 |
| 4865 # By default, we assume that the call never returns None, as this |
| 4866 # is true for most C-API functions in CPython. If this does not |
| 4867 # apply to a call, set the following to True (or None to inherit |
| 4868 # the default behaviour). |
| 4869 may_return_none = False |
| 4870 |
| 4871 def __init__(self, pos, function_name, func_type, |
| 4872 utility_code = None, py_name=None, **kwargs): |
| 4873 self.type = func_type.return_type |
| 4874 self.result_ctype = self.type |
| 4875 self.function = PythonCapiFunctionNode( |
| 4876 pos, py_name, function_name, func_type, |
| 4877 utility_code = utility_code) |
| 4878 # call this last so that we can override the constructed |
| 4879 # attributes above with explicit keyword arguments if required |
| 4880 SimpleCallNode.__init__(self, pos, **kwargs) |
| 4881 |
| 4882 |
| 4883 class GeneralCallNode(CallNode): |
| 4884 # General Python function call, including keyword, |
| 4885 # * and ** arguments. |
| 4886 # |
| 4887 # function ExprNode |
| 4888 # positional_args ExprNode Tuple of positional arguments |
| 4889 # keyword_args ExprNode or None Dict of keyword arguments |
| 4890 |
| 4891 type = py_object_type |
| 4892 |
| 4893 subexprs = ['function', 'positional_args', 'keyword_args'] |
| 4894 |
| 4895 nogil_check = Node.gil_error |
| 4896 |
| 4897 def compile_time_value(self, denv): |
| 4898 function = self.function.compile_time_value(denv) |
| 4899 positional_args = self.positional_args.compile_time_value(denv) |
| 4900 keyword_args = self.keyword_args.compile_time_value(denv) |
| 4901 try: |
| 4902 return function(*positional_args, **keyword_args) |
| 4903 except Exception, e: |
| 4904 self.compile_time_value_error(e) |
| 4905 |
| 4906 def explicit_args_kwds(self): |
| 4907 if (self.keyword_args and not isinstance(self.keyword_args, DictNode) or |
| 4908 not isinstance(self.positional_args, TupleNode)): |
| 4909 raise CompileError(self.pos, |
| 4910 'Compile-time keyword arguments must be explicit.') |
| 4911 return self.positional_args.args, self.keyword_args |
| 4912 |
| 4913 def analyse_types(self, env): |
| 4914 if self.analyse_as_type_constructor(env): |
| 4915 return self |
| 4916 self.function = self.function.analyse_types(env) |
| 4917 if not self.function.type.is_pyobject: |
| 4918 if self.function.type.is_error: |
| 4919 self.type = error_type |
| 4920 return self |
| 4921 if hasattr(self.function, 'entry'): |
| 4922 node = self.map_to_simple_call_node() |
| 4923 if node is not None and node is not self: |
| 4924 return node.analyse_types(env) |
| 4925 elif self.function.entry.as_variable: |
| 4926 self.function = self.function.coerce_to_pyobject(env) |
| 4927 elif node is self: |
| 4928 error(self.pos, |
| 4929 "Non-trivial keyword arguments and starred " |
| 4930 "arguments not allowed in cdef functions.") |
| 4931 else: |
| 4932 # error was already reported |
| 4933 pass |
| 4934 else: |
| 4935 self.function = self.function.coerce_to_pyobject(env) |
| 4936 if self.keyword_args: |
| 4937 self.keyword_args = self.keyword_args.analyse_types(env) |
| 4938 self.positional_args = self.positional_args.analyse_types(env) |
| 4939 self.positional_args = \ |
| 4940 self.positional_args.coerce_to_pyobject(env) |
| 4941 function = self.function |
| 4942 if function.is_name and function.type_entry: |
| 4943 # We are calling an extension type constructor. As long |
| 4944 # as we do not support __new__(), the result type is clear |
| 4945 self.type = function.type_entry.type |
| 4946 self.result_ctype = py_object_type |
| 4947 self.may_return_none = False |
| 4948 else: |
| 4949 self.type = py_object_type |
| 4950 self.is_temp = 1 |
| 4951 return self |
| 4952 |
| 4953 def map_to_simple_call_node(self): |
| 4954 """ |
| 4955 Tries to map keyword arguments to declared positional arguments. |
| 4956 Returns self to try a Python call, None to report an error |
| 4957 or a SimpleCallNode if the mapping succeeds. |
| 4958 """ |
| 4959 if not isinstance(self.positional_args, TupleNode): |
| 4960 # has starred argument |
| 4961 return self |
| 4962 if not isinstance(self.keyword_args, DictNode): |
| 4963 # keywords come from arbitrary expression => nothing to do here |
| 4964 return self |
| 4965 function = self.function |
| 4966 entry = getattr(function, 'entry', None) |
| 4967 if not entry: |
| 4968 return self |
| 4969 function_type = entry.type |
| 4970 if function_type.is_ptr: |
| 4971 function_type = function_type.base_type |
| 4972 if not function_type.is_cfunction: |
| 4973 return self |
| 4974 |
| 4975 pos_args = self.positional_args.args |
| 4976 kwargs = self.keyword_args |
| 4977 declared_args = function_type.args |
| 4978 if entry.is_cmethod: |
| 4979 declared_args = declared_args[1:] # skip 'self' |
| 4980 |
| 4981 if len(pos_args) > len(declared_args): |
| 4982 error(self.pos, "function call got too many positional arguments, " |
| 4983 "expected %d, got %s" % (len(declared_args), |
| 4984 len(pos_args))) |
| 4985 return None |
| 4986 |
| 4987 matched_args = set([ arg.name for arg in declared_args[:len(pos_args)] |
| 4988 if arg.name ]) |
| 4989 unmatched_args = declared_args[len(pos_args):] |
| 4990 matched_kwargs_count = 0 |
| 4991 args = list(pos_args) |
| 4992 |
| 4993 # check for duplicate keywords |
| 4994 seen = set(matched_args) |
| 4995 has_errors = False |
| 4996 for arg in kwargs.key_value_pairs: |
| 4997 name = arg.key.value |
| 4998 if name in seen: |
| 4999 error(arg.pos, "argument '%s' passed twice" % name) |
| 5000 has_errors = True |
| 5001 # continue to report more errors if there are any |
| 5002 seen.add(name) |
| 5003 |
| 5004 # match keywords that are passed in order |
| 5005 for decl_arg, arg in zip(unmatched_args, kwargs.key_value_pairs): |
| 5006 name = arg.key.value |
| 5007 if decl_arg.name == name: |
| 5008 matched_args.add(name) |
| 5009 matched_kwargs_count += 1 |
| 5010 args.append(arg.value) |
| 5011 else: |
| 5012 break |
| 5013 |
| 5014 # match keyword arguments that are passed out-of-order, but keep |
| 5015 # the evaluation of non-simple arguments in order by moving them |
| 5016 # into temps |
| 5017 from Cython.Compiler.UtilNodes import EvalWithTempExprNode, LetRefNode |
| 5018 temps = [] |
| 5019 if len(kwargs.key_value_pairs) > matched_kwargs_count: |
| 5020 unmatched_args = declared_args[len(args):] |
| 5021 keywords = dict([ (arg.key.value, (i+len(pos_args), arg)) |
| 5022 for i, arg in enumerate(kwargs.key_value_pairs) ]) |
| 5023 first_missing_keyword = None |
| 5024 for decl_arg in unmatched_args: |
| 5025 name = decl_arg.name |
| 5026 if name not in keywords: |
| 5027 # missing keyword argument => either done or error |
| 5028 if not first_missing_keyword: |
| 5029 first_missing_keyword = name |
| 5030 continue |
| 5031 elif first_missing_keyword: |
| 5032 if entry.as_variable: |
| 5033 # we might be able to convert the function to a Python |
| 5034 # object, which then allows full calling semantics |
| 5035 # with default values in gaps - currently, we only |
| 5036 # support optional arguments at the end |
| 5037 return self |
| 5038 # wasn't the last keyword => gaps are not supported |
| 5039 error(self.pos, "C function call is missing " |
| 5040 "argument '%s'" % first_missing_keyword) |
| 5041 return None |
| 5042 pos, arg = keywords[name] |
| 5043 matched_args.add(name) |
| 5044 matched_kwargs_count += 1 |
| 5045 if arg.value.is_simple(): |
| 5046 args.append(arg.value) |
| 5047 else: |
| 5048 temp = LetRefNode(arg.value) |
| 5049 assert temp.is_simple() |
| 5050 args.append(temp) |
| 5051 temps.append((pos, temp)) |
| 5052 |
| 5053 if temps: |
| 5054 # may have to move preceding non-simple args into temps |
| 5055 final_args = [] |
| 5056 new_temps = [] |
| 5057 first_temp_arg = temps[0][-1] |
| 5058 for arg_value in args: |
| 5059 if arg_value is first_temp_arg: |
| 5060 break # done |
| 5061 if arg_value.is_simple(): |
| 5062 final_args.append(arg_value) |
| 5063 else: |
| 5064 temp = LetRefNode(arg_value) |
| 5065 new_temps.append(temp) |
| 5066 final_args.append(temp) |
| 5067 if new_temps: |
| 5068 args = final_args |
| 5069 temps = new_temps + [ arg for i,arg in sorted(temps) ] |
| 5070 |
| 5071 # check for unexpected keywords |
| 5072 for arg in kwargs.key_value_pairs: |
| 5073 name = arg.key.value |
| 5074 if name not in matched_args: |
| 5075 has_errors = True |
| 5076 error(arg.pos, |
| 5077 "C function got unexpected keyword argument '%s'" % |
| 5078 name) |
| 5079 |
| 5080 if has_errors: |
| 5081 # error was reported already |
| 5082 return None |
| 5083 |
| 5084 # all keywords mapped to positional arguments |
| 5085 # if we are missing arguments, SimpleCallNode will figure it out |
| 5086 node = SimpleCallNode(self.pos, function=function, args=args) |
| 5087 for temp in temps[::-1]: |
| 5088 node = EvalWithTempExprNode(temp, node) |
| 5089 return node |
| 5090 |
| 5091 def generate_result_code(self, code): |
| 5092 if self.type.is_error: return |
| 5093 if self.keyword_args: |
| 5094 kwargs = self.keyword_args.py_result() |
| 5095 else: |
| 5096 kwargs = 'NULL' |
| 5097 code.globalstate.use_utility_code(UtilityCode.load_cached( |
| 5098 "PyObjectCall", "ObjectHandling.c")) |
| 5099 code.putln( |
| 5100 "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % ( |
| 5101 self.result(), |
| 5102 self.function.py_result(), |
| 5103 self.positional_args.py_result(), |
| 5104 kwargs, |
| 5105 code.error_goto_if_null(self.result(), self.pos))) |
| 5106 code.put_gotref(self.py_result()) |
| 5107 |
| 5108 |
| 5109 class AsTupleNode(ExprNode): |
| 5110 # Convert argument to tuple. Used for normalising |
| 5111 # the * argument of a function call. |
| 5112 # |
| 5113 # arg ExprNode |
| 5114 |
| 5115 subexprs = ['arg'] |
| 5116 |
| 5117 def calculate_constant_result(self): |
| 5118 self.constant_result = tuple(self.arg.constant_result) |
| 5119 |
| 5120 def compile_time_value(self, denv): |
| 5121 arg = self.arg.compile_time_value(denv) |
| 5122 try: |
| 5123 return tuple(arg) |
| 5124 except Exception, e: |
| 5125 self.compile_time_value_error(e) |
| 5126 |
| 5127 def analyse_types(self, env): |
| 5128 self.arg = self.arg.analyse_types(env) |
| 5129 self.arg = self.arg.coerce_to_pyobject(env) |
| 5130 self.type = tuple_type |
| 5131 self.is_temp = 1 |
| 5132 return self |
| 5133 |
| 5134 def may_be_none(self): |
| 5135 return False |
| 5136 |
| 5137 nogil_check = Node.gil_error |
| 5138 gil_message = "Constructing Python tuple" |
| 5139 |
| 5140 def generate_result_code(self, code): |
| 5141 code.putln( |
| 5142 "%s = PySequence_Tuple(%s); %s" % ( |
| 5143 self.result(), |
| 5144 self.arg.py_result(), |
| 5145 code.error_goto_if_null(self.result(), self.pos))) |
| 5146 code.put_gotref(self.py_result()) |
| 5147 |
| 5148 |
| 5149 class AttributeNode(ExprNode): |
| 5150 # obj.attribute |
| 5151 # |
| 5152 # obj ExprNode |
| 5153 # attribute string |
| 5154 # needs_none_check boolean Used if obj is an extension type. |
| 5155 # If set to True, it is known that the type
is not None. |
| 5156 # |
| 5157 # Used internally: |
| 5158 # |
| 5159 # is_py_attr boolean Is a Python getattr operation |
| 5160 # member string C name of struct member |
| 5161 # is_called boolean Function call is being done on result |
| 5162 # entry Entry Symbol table entry of attribute |
| 5163 |
| 5164 is_attribute = 1 |
| 5165 subexprs = ['obj'] |
| 5166 |
| 5167 type = PyrexTypes.error_type |
| 5168 entry = None |
| 5169 is_called = 0 |
| 5170 needs_none_check = True |
| 5171 is_memslice_transpose = False |
| 5172 is_special_lookup = False |
| 5173 |
| 5174 def as_cython_attribute(self): |
| 5175 if (isinstance(self.obj, NameNode) and |
| 5176 self.obj.is_cython_module and not |
| 5177 self.attribute == u"parallel"): |
| 5178 return self.attribute |
| 5179 |
| 5180 cy = self.obj.as_cython_attribute() |
| 5181 if cy: |
| 5182 return "%s.%s" % (cy, self.attribute) |
| 5183 return None |
| 5184 |
| 5185 def coerce_to(self, dst_type, env): |
| 5186 # If coercing to a generic pyobject and this is a cpdef function |
| 5187 # we can create the corresponding attribute |
| 5188 if dst_type is py_object_type: |
| 5189 entry = self.entry |
| 5190 if entry and entry.is_cfunction and entry.as_variable: |
| 5191 # must be a cpdef function |
| 5192 self.is_temp = 1 |
| 5193 self.entry = entry.as_variable |
| 5194 self.analyse_as_python_attribute(env) |
| 5195 return self |
| 5196 return ExprNode.coerce_to(self, dst_type, env) |
| 5197 |
| 5198 def calculate_constant_result(self): |
| 5199 attr = self.attribute |
| 5200 if attr.startswith("__") and attr.endswith("__"): |
| 5201 return |
| 5202 self.constant_result = getattr(self.obj.constant_result, attr) |
| 5203 |
| 5204 def compile_time_value(self, denv): |
| 5205 attr = self.attribute |
| 5206 if attr.startswith("__") and attr.endswith("__"): |
| 5207 error(self.pos, |
| 5208 "Invalid attribute name '%s' in compile-time expression" % att
r) |
| 5209 return None |
| 5210 obj = self.obj.compile_time_value(denv) |
| 5211 try: |
| 5212 return getattr(obj, attr) |
| 5213 except Exception, e: |
| 5214 self.compile_time_value_error(e) |
| 5215 |
| 5216 def type_dependencies(self, env): |
| 5217 return self.obj.type_dependencies(env) |
| 5218 |
| 5219 def infer_type(self, env): |
| 5220 # FIXME: this is way too redundant with analyse_types() |
| 5221 node = self.analyse_as_cimported_attribute_node(env, target=False) |
| 5222 if node is not None: |
| 5223 return node.entry.type |
| 5224 node = self.analyse_as_unbound_cmethod_node(env) |
| 5225 if node is not None: |
| 5226 return node.entry.type |
| 5227 obj_type = self.obj.infer_type(env) |
| 5228 self.analyse_attribute(env, obj_type=obj_type) |
| 5229 if obj_type.is_builtin_type and self.type.is_cfunction: |
| 5230 # special case: C-API replacements for C methods of |
| 5231 # builtin types cannot be inferred as C functions as |
| 5232 # that would prevent their use as bound methods |
| 5233 return py_object_type |
| 5234 return self.type |
| 5235 |
| 5236 def analyse_target_declaration(self, env): |
| 5237 pass |
| 5238 |
| 5239 def analyse_target_types(self, env): |
| 5240 node = self.analyse_types(env, target = 1) |
| 5241 if node.type.is_const: |
| 5242 error(self.pos, "Assignment to const attribute '%s'" % self.attribut
e) |
| 5243 if not node.is_lvalue(): |
| 5244 error(self.pos, "Assignment to non-lvalue of type '%s'" % self.type) |
| 5245 return node |
| 5246 |
| 5247 def analyse_types(self, env, target = 0): |
| 5248 self.initialized_check = env.directives['initializedcheck'] |
| 5249 node = self.analyse_as_cimported_attribute_node(env, target) |
| 5250 if node is None and not target: |
| 5251 node = self.analyse_as_unbound_cmethod_node(env) |
| 5252 if node is None: |
| 5253 node = self.analyse_as_ordinary_attribute_node(env, target) |
| 5254 assert node is not None |
| 5255 if node.entry: |
| 5256 node.entry.used = True |
| 5257 if node.is_attribute: |
| 5258 node.wrap_obj_in_nonecheck(env) |
| 5259 return node |
| 5260 |
| 5261 def analyse_as_cimported_attribute_node(self, env, target): |
| 5262 # Try to interpret this as a reference to an imported |
| 5263 # C const, type, var or function. If successful, mutates |
| 5264 # this node into a NameNode and returns 1, otherwise |
| 5265 # returns 0. |
| 5266 module_scope = self.obj.analyse_as_module(env) |
| 5267 if module_scope: |
| 5268 entry = module_scope.lookup_here(self.attribute) |
| 5269 if entry and ( |
| 5270 entry.is_cglobal or entry.is_cfunction |
| 5271 or entry.is_type or entry.is_const): |
| 5272 return self.as_name_node(env, entry, target) |
| 5273 return None |
| 5274 |
| 5275 def analyse_as_unbound_cmethod_node(self, env): |
| 5276 # Try to interpret this as a reference to an unbound |
| 5277 # C method of an extension type or builtin type. If successful, |
| 5278 # creates a corresponding NameNode and returns it, otherwise |
| 5279 # returns None. |
| 5280 type = self.obj.analyse_as_extension_type(env) |
| 5281 if type: |
| 5282 entry = type.scope.lookup_here(self.attribute) |
| 5283 if entry and entry.is_cmethod: |
| 5284 if type.is_builtin_type: |
| 5285 if not self.is_called: |
| 5286 # must handle this as Python object |
| 5287 return None |
| 5288 ubcm_entry = entry |
| 5289 else: |
| 5290 # Create a temporary entry describing the C method |
| 5291 # as an ordinary function. |
| 5292 ubcm_entry = Symtab.Entry(entry.name, |
| 5293 "%s->%s" % (type.vtabptr_cname, entry.cname), |
| 5294 entry.type) |
| 5295 ubcm_entry.is_cfunction = 1 |
| 5296 ubcm_entry.func_cname = entry.func_cname |
| 5297 ubcm_entry.is_unbound_cmethod = 1 |
| 5298 return self.as_name_node(env, ubcm_entry, target=False) |
| 5299 return None |
| 5300 |
| 5301 def analyse_as_type(self, env): |
| 5302 module_scope = self.obj.analyse_as_module(env) |
| 5303 if module_scope: |
| 5304 return module_scope.lookup_type(self.attribute) |
| 5305 if not self.obj.is_string_literal: |
| 5306 base_type = self.obj.analyse_as_type(env) |
| 5307 if base_type and hasattr(base_type, 'scope') and base_type.scope is
not None: |
| 5308 return base_type.scope.lookup_type(self.attribute) |
| 5309 return None |
| 5310 |
| 5311 def analyse_as_extension_type(self, env): |
| 5312 # Try to interpret this as a reference to an extension type |
| 5313 # in a cimported module. Returns the extension type, or None. |
| 5314 module_scope = self.obj.analyse_as_module(env) |
| 5315 if module_scope: |
| 5316 entry = module_scope.lookup_here(self.attribute) |
| 5317 if entry and entry.is_type: |
| 5318 if entry.type.is_extension_type or entry.type.is_builtin_type: |
| 5319 return entry.type |
| 5320 return None |
| 5321 |
| 5322 def analyse_as_module(self, env): |
| 5323 # Try to interpret this as a reference to a cimported module |
| 5324 # in another cimported module. Returns the module scope, or None. |
| 5325 module_scope = self.obj.analyse_as_module(env) |
| 5326 if module_scope: |
| 5327 entry = module_scope.lookup_here(self.attribute) |
| 5328 if entry and entry.as_module: |
| 5329 return entry.as_module |
| 5330 return None |
| 5331 |
| 5332 def as_name_node(self, env, entry, target): |
| 5333 # Create a corresponding NameNode from this node and complete the |
| 5334 # analyse_types phase. |
| 5335 node = NameNode.from_node(self, name=self.attribute, entry=entry) |
| 5336 if target: |
| 5337 node = node.analyse_target_types(env) |
| 5338 else: |
| 5339 node = node.analyse_rvalue_entry(env) |
| 5340 node.entry.used = 1 |
| 5341 return node |
| 5342 |
| 5343 def analyse_as_ordinary_attribute_node(self, env, target): |
| 5344 self.obj = self.obj.analyse_types(env) |
| 5345 self.analyse_attribute(env) |
| 5346 if self.entry and self.entry.is_cmethod and not self.is_called: |
| 5347 # error(self.pos, "C method can only be called") |
| 5348 pass |
| 5349 ## Reference to C array turns into pointer to first element. |
| 5350 #while self.type.is_array: |
| 5351 # self.type = self.type.element_ptr_type() |
| 5352 if self.is_py_attr: |
| 5353 if not target: |
| 5354 self.is_temp = 1 |
| 5355 self.result_ctype = py_object_type |
| 5356 elif target and self.obj.type.is_builtin_type: |
| 5357 error(self.pos, "Assignment to an immutable object field") |
| 5358 #elif self.type.is_memoryviewslice and not target: |
| 5359 # self.is_temp = True |
| 5360 return self |
| 5361 |
| 5362 def analyse_attribute(self, env, obj_type = None): |
| 5363 # Look up attribute and set self.type and self.member. |
| 5364 immutable_obj = obj_type is not None # used during type inference |
| 5365 self.is_py_attr = 0 |
| 5366 self.member = self.attribute |
| 5367 if obj_type is None: |
| 5368 if self.obj.type.is_string or self.obj.type.is_pyunicode_ptr: |
| 5369 self.obj = self.obj.coerce_to_pyobject(env) |
| 5370 obj_type = self.obj.type |
| 5371 else: |
| 5372 if obj_type.is_string or obj_type.is_pyunicode_ptr: |
| 5373 obj_type = py_object_type |
| 5374 if obj_type.is_ptr or obj_type.is_array: |
| 5375 obj_type = obj_type.base_type |
| 5376 self.op = "->" |
| 5377 elif obj_type.is_extension_type or obj_type.is_builtin_type: |
| 5378 self.op = "->" |
| 5379 else: |
| 5380 self.op = "." |
| 5381 if obj_type.has_attributes: |
| 5382 if obj_type.attributes_known(): |
| 5383 if (obj_type.is_memoryviewslice and not |
| 5384 obj_type.scope.lookup_here(self.attribute)): |
| 5385 if self.attribute == 'T': |
| 5386 self.is_memslice_transpose = True |
| 5387 self.is_temp = True |
| 5388 self.use_managed_ref = True |
| 5389 self.type = self.obj.type |
| 5390 return |
| 5391 else: |
| 5392 obj_type.declare_attribute(self.attribute, env, self.pos
) |
| 5393 entry = obj_type.scope.lookup_here(self.attribute) |
| 5394 if entry and entry.is_member: |
| 5395 entry = None |
| 5396 else: |
| 5397 error(self.pos, |
| 5398 "Cannot select attribute of incomplete type '%s'" |
| 5399 % obj_type) |
| 5400 self.type = PyrexTypes.error_type |
| 5401 return |
| 5402 self.entry = entry |
| 5403 if entry: |
| 5404 if obj_type.is_extension_type and entry.name == "__weakref__": |
| 5405 error(self.pos, "Illegal use of special attribute __weakref_
_") |
| 5406 |
| 5407 # def methods need the normal attribute lookup |
| 5408 # because they do not have struct entries |
| 5409 # fused function go through assignment synthesis |
| 5410 # (foo = pycfunction(foo_func_obj)) and need to go through |
| 5411 # regular Python lookup as well |
| 5412 if (entry.is_variable and not entry.fused_cfunction) or entry.is
_cmethod: |
| 5413 self.type = entry.type |
| 5414 self.member = entry.cname |
| 5415 return |
| 5416 else: |
| 5417 # If it's not a variable or C method, it must be a Python |
| 5418 # method of an extension type, so we treat it like a Python |
| 5419 # attribute. |
| 5420 pass |
| 5421 # If we get here, the base object is not a struct/union/extension |
| 5422 # type, or it is an extension type and the attribute is either not |
| 5423 # declared or is declared as a Python method. Treat it as a Python |
| 5424 # attribute reference. |
| 5425 self.analyse_as_python_attribute(env, obj_type, immutable_obj) |
| 5426 |
| 5427 def analyse_as_python_attribute(self, env, obj_type=None, immutable_obj=Fals
e): |
| 5428 if obj_type is None: |
| 5429 obj_type = self.obj.type |
| 5430 # mangle private '__*' Python attributes used inside of a class |
| 5431 self.attribute = env.mangle_class_private_name(self.attribute) |
| 5432 self.member = self.attribute |
| 5433 self.type = py_object_type |
| 5434 self.is_py_attr = 1 |
| 5435 if not obj_type.is_pyobject and not obj_type.is_error: |
| 5436 if obj_type.can_coerce_to_pyobject(env): |
| 5437 if not immutable_obj: |
| 5438 self.obj = self.obj.coerce_to_pyobject(env) |
| 5439 elif (obj_type.is_cfunction and (self.obj.is_name or self.obj.is_att
ribute) |
| 5440 and self.obj.entry.as_variable |
| 5441 and self.obj.entry.as_variable.type.is_pyobject): |
| 5442 # might be an optimised builtin function => unpack it |
| 5443 if not immutable_obj: |
| 5444 self.obj = self.obj.coerce_to_pyobject(env) |
| 5445 else: |
| 5446 error(self.pos, |
| 5447 "Object of type '%s' has no attribute '%s'" % |
| 5448 (obj_type, self.attribute)) |
| 5449 |
| 5450 def wrap_obj_in_nonecheck(self, env): |
| 5451 if not env.directives['nonecheck']: |
| 5452 return |
| 5453 |
| 5454 msg = None |
| 5455 format_args = () |
| 5456 if (self.obj.type.is_extension_type and self.needs_none_check and not |
| 5457 self.is_py_attr): |
| 5458 msg = "'NoneType' object has no attribute '%s'" |
| 5459 format_args = (self.attribute,) |
| 5460 elif self.obj.type.is_memoryviewslice: |
| 5461 if self.is_memslice_transpose: |
| 5462 msg = "Cannot transpose None memoryview slice" |
| 5463 else: |
| 5464 entry = self.obj.type.scope.lookup_here(self.attribute) |
| 5465 if entry: |
| 5466 # copy/is_c_contig/shape/strides etc |
| 5467 msg = "Cannot access '%s' attribute of None memoryview slice
" |
| 5468 format_args = (entry.name,) |
| 5469 |
| 5470 if msg: |
| 5471 self.obj = self.obj.as_none_safe_node(msg, 'PyExc_AttributeError', |
| 5472 format_args=format_args) |
| 5473 |
| 5474 |
| 5475 def nogil_check(self, env): |
| 5476 if self.is_py_attr: |
| 5477 self.gil_error() |
| 5478 elif self.type.is_memoryviewslice: |
| 5479 import MemoryView |
| 5480 MemoryView.err_if_nogil_initialized_check(self.pos, env, 'attribute'
) |
| 5481 |
| 5482 gil_message = "Accessing Python attribute" |
| 5483 |
| 5484 def is_simple(self): |
| 5485 if self.obj: |
| 5486 return self.result_in_temp() or self.obj.is_simple() |
| 5487 else: |
| 5488 return NameNode.is_simple(self) |
| 5489 |
| 5490 def is_lvalue(self): |
| 5491 if self.obj: |
| 5492 return not self.type.is_array |
| 5493 else: |
| 5494 return NameNode.is_lvalue(self) |
| 5495 |
| 5496 def is_ephemeral(self): |
| 5497 if self.obj: |
| 5498 return self.obj.is_ephemeral() |
| 5499 else: |
| 5500 return NameNode.is_ephemeral(self) |
| 5501 |
| 5502 def calculate_result_code(self): |
| 5503 #print "AttributeNode.calculate_result_code:", self.member ### |
| 5504 #print "...obj node =", self.obj, "code", self.obj.result() ### |
| 5505 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ### |
| 5506 obj = self.obj |
| 5507 obj_code = obj.result_as(obj.type) |
| 5508 #print "...obj_code =", obj_code ### |
| 5509 if self.entry and self.entry.is_cmethod: |
| 5510 if obj.type.is_extension_type and not self.entry.is_builtin_cmethod: |
| 5511 if self.entry.final_func_cname: |
| 5512 return self.entry.final_func_cname |
| 5513 |
| 5514 if self.type.from_fused: |
| 5515 # If the attribute was specialized through indexing, make |
| 5516 # sure to get the right fused name, as our entry was |
| 5517 # replaced by our parent index node |
| 5518 # (AnalyseExpressionsTransform) |
| 5519 self.member = self.entry.cname |
| 5520 |
| 5521 return "((struct %s *)%s%s%s)->%s" % ( |
| 5522 obj.type.vtabstruct_cname, obj_code, self.op, |
| 5523 obj.type.vtabslot_cname, self.member) |
| 5524 elif self.result_is_used: |
| 5525 return self.member |
| 5526 # Generating no code at all for unused access to optimised builtin |
| 5527 # methods fixes the problem that some optimisations only exist as |
| 5528 # macros, i.e. there is no function pointer to them, so we would |
| 5529 # generate invalid C code here. |
| 5530 return |
| 5531 elif obj.type.is_complex: |
| 5532 return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code) |
| 5533 else: |
| 5534 if obj.type.is_builtin_type and self.entry and self.entry.is_variabl
e: |
| 5535 # accessing a field of a builtin type, need to cast better than
result_as() does |
| 5536 obj_code = obj.type.cast_code(obj.result(), to_object_struct = T
rue) |
| 5537 return "%s%s%s" % (obj_code, self.op, self.member) |
| 5538 |
| 5539 def generate_result_code(self, code): |
| 5540 if self.is_py_attr: |
| 5541 if self.is_special_lookup: |
| 5542 code.globalstate.use_utility_code( |
| 5543 UtilityCode.load_cached("PyObjectLookupSpecial", "ObjectHand
ling.c")) |
| 5544 lookup_func_name = '__Pyx_PyObject_LookupSpecial' |
| 5545 else: |
| 5546 code.globalstate.use_utility_code( |
| 5547 UtilityCode.load_cached("PyObjectGetAttrStr", "ObjectHandlin
g.c")) |
| 5548 lookup_func_name = '__Pyx_PyObject_GetAttrStr' |
| 5549 code.putln( |
| 5550 '%s = %s(%s, %s); %s' % ( |
| 5551 self.result(), |
| 5552 lookup_func_name, |
| 5553 self.obj.py_result(), |
| 5554 code.intern_identifier(self.attribute), |
| 5555 code.error_goto_if_null(self.result(), self.pos))) |
| 5556 code.put_gotref(self.py_result()) |
| 5557 elif self.type.is_memoryviewslice: |
| 5558 if self.is_memslice_transpose: |
| 5559 # transpose the slice |
| 5560 for access, packing in self.type.axes: |
| 5561 if access == 'ptr': |
| 5562 error(self.pos, "Transposing not supported for slices " |
| 5563 "with indirect dimensions") |
| 5564 return |
| 5565 |
| 5566 code.putln("%s = %s;" % (self.result(), self.obj.result())) |
| 5567 if self.obj.is_name or (self.obj.is_attribute and |
| 5568 self.obj.is_memslice_transpose): |
| 5569 code.put_incref_memoryviewslice(self.result(), have_gil=True
) |
| 5570 |
| 5571 T = "__pyx_memslice_transpose(&%s) == 0" |
| 5572 code.putln(code.error_goto_if(T % self.result(), self.pos)) |
| 5573 elif self.initialized_check: |
| 5574 code.putln( |
| 5575 'if (unlikely(!%s.memview)) {' |
| 5576 'PyErr_SetString(PyExc_AttributeError,' |
| 5577 '"Memoryview is not initialized");' |
| 5578 '%s' |
| 5579 '}' % (self.result(), code.error_goto(self.pos))) |
| 5580 else: |
| 5581 # result_code contains what is needed, but we may need to insert |
| 5582 # a check and raise an exception |
| 5583 if self.obj.type.is_extension_type: |
| 5584 pass |
| 5585 elif self.entry and self.entry.is_cmethod and self.entry.utility_cod
e: |
| 5586 # C method implemented as function call with utility code |
| 5587 code.globalstate.use_utility_code(self.entry.utility_code) |
| 5588 |
| 5589 def generate_disposal_code(self, code): |
| 5590 if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_tr
anspose: |
| 5591 # mirror condition for putting the memview incref here: |
| 5592 if self.obj.is_name or (self.obj.is_attribute and |
| 5593 self.obj.is_memslice_transpose): |
| 5594 code.put_xdecref_memoryviewslice( |
| 5595 self.result(), have_gil=True) |
| 5596 else: |
| 5597 ExprNode.generate_disposal_code(self, code) |
| 5598 |
| 5599 def generate_assignment_code(self, rhs, code): |
| 5600 self.obj.generate_evaluation_code(code) |
| 5601 if self.is_py_attr: |
| 5602 code.globalstate.use_utility_code( |
| 5603 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"
)) |
| 5604 code.put_error_if_neg(self.pos, |
| 5605 '__Pyx_PyObject_SetAttrStr(%s, %s, %s)' % ( |
| 5606 self.obj.py_result(), |
| 5607 code.intern_identifier(self.attribute), |
| 5608 rhs.py_result())) |
| 5609 rhs.generate_disposal_code(code) |
| 5610 rhs.free_temps(code) |
| 5611 elif self.obj.type.is_complex: |
| 5612 code.putln("__Pyx_SET_C%s(%s, %s);" % ( |
| 5613 self.member.upper(), |
| 5614 self.obj.result_as(self.obj.type), |
| 5615 rhs.result_as(self.ctype()))) |
| 5616 else: |
| 5617 select_code = self.result() |
| 5618 if self.type.is_pyobject and self.use_managed_ref: |
| 5619 rhs.make_owned_reference(code) |
| 5620 code.put_giveref(rhs.py_result()) |
| 5621 code.put_gotref(select_code) |
| 5622 code.put_decref(select_code, self.ctype()) |
| 5623 elif self.type.is_memoryviewslice: |
| 5624 import MemoryView |
| 5625 MemoryView.put_assign_to_memviewslice( |
| 5626 select_code, rhs, rhs.result(), self.type, code) |
| 5627 |
| 5628 if not self.type.is_memoryviewslice: |
| 5629 code.putln( |
| 5630 "%s = %s;" % ( |
| 5631 select_code, |
| 5632 rhs.result_as(self.ctype()))) |
| 5633 #rhs.result())) |
| 5634 rhs.generate_post_assignment_code(code) |
| 5635 rhs.free_temps(code) |
| 5636 self.obj.generate_disposal_code(code) |
| 5637 self.obj.free_temps(code) |
| 5638 |
| 5639 def generate_deletion_code(self, code, ignore_nonexisting=False): |
| 5640 self.obj.generate_evaluation_code(code) |
| 5641 if self.is_py_attr or (self.entry.scope.is_property_scope |
| 5642 and u'__del__' in self.entry.scope.entries): |
| 5643 code.globalstate.use_utility_code( |
| 5644 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"
)) |
| 5645 code.put_error_if_neg(self.pos, |
| 5646 '__Pyx_PyObject_DelAttrStr(%s, %s)' % ( |
| 5647 self.obj.py_result(), |
| 5648 code.intern_identifier(self.attribute))) |
| 5649 else: |
| 5650 error(self.pos, "Cannot delete C attribute of extension type") |
| 5651 self.obj.generate_disposal_code(code) |
| 5652 self.obj.free_temps(code) |
| 5653 |
| 5654 def annotate(self, code): |
| 5655 if self.is_py_attr: |
| 5656 style, text = 'py_attr', 'python attribute (%s)' |
| 5657 else: |
| 5658 style, text = 'c_attr', 'c attribute (%s)' |
| 5659 code.annotate(self.pos, AnnotationItem(style, text % self.type, size=len
(self.attribute))) |
| 5660 |
| 5661 |
| 5662 #------------------------------------------------------------------- |
| 5663 # |
| 5664 # Constructor nodes |
| 5665 # |
| 5666 #------------------------------------------------------------------- |
| 5667 |
| 5668 class StarredTargetNode(ExprNode): |
| 5669 # A starred expression like "*a" |
| 5670 # |
| 5671 # This is only allowed in sequence assignment targets such as |
| 5672 # |
| 5673 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4] |
| 5674 # |
| 5675 # and will be removed during type analysis (or generate an error |
| 5676 # if it's found at unexpected places). |
| 5677 # |
| 5678 # target ExprNode |
| 5679 |
| 5680 subexprs = ['target'] |
| 5681 is_starred = 1 |
| 5682 type = py_object_type |
| 5683 is_temp = 1 |
| 5684 |
| 5685 def __init__(self, pos, target): |
| 5686 ExprNode.__init__(self, pos) |
| 5687 self.target = target |
| 5688 |
| 5689 def analyse_declarations(self, env): |
| 5690 error(self.pos, "can use starred expression only as assignment target") |
| 5691 self.target.analyse_declarations(env) |
| 5692 |
| 5693 def analyse_types(self, env): |
| 5694 error(self.pos, "can use starred expression only as assignment target") |
| 5695 self.target = self.target.analyse_types(env) |
| 5696 self.type = self.target.type |
| 5697 return self |
| 5698 |
| 5699 def analyse_target_declaration(self, env): |
| 5700 self.target.analyse_target_declaration(env) |
| 5701 |
| 5702 def analyse_target_types(self, env): |
| 5703 self.target = self.target.analyse_target_types(env) |
| 5704 self.type = self.target.type |
| 5705 return self |
| 5706 |
| 5707 def calculate_result_code(self): |
| 5708 return "" |
| 5709 |
| 5710 def generate_result_code(self, code): |
| 5711 pass |
| 5712 |
| 5713 |
| 5714 class SequenceNode(ExprNode): |
| 5715 # Base class for list and tuple constructor nodes. |
| 5716 # Contains common code for performing sequence unpacking. |
| 5717 # |
| 5718 # args [ExprNode] |
| 5719 # unpacked_items [ExprNode] or None |
| 5720 # coerced_unpacked_items [ExprNode] or None |
| 5721 # mult_factor ExprNode the integer number of content repeti
tions ([1,2]*3) |
| 5722 |
| 5723 subexprs = ['args', 'mult_factor'] |
| 5724 |
| 5725 is_sequence_constructor = 1 |
| 5726 unpacked_items = None |
| 5727 mult_factor = None |
| 5728 slow = False # trade speed for code size (e.g. use PyTuple_Pack()) |
| 5729 |
| 5730 def compile_time_value_list(self, denv): |
| 5731 return [arg.compile_time_value(denv) for arg in self.args] |
| 5732 |
| 5733 def replace_starred_target_node(self): |
| 5734 # replace a starred node in the targets by the contained expression |
| 5735 self.starred_assignment = False |
| 5736 args = [] |
| 5737 for arg in self.args: |
| 5738 if arg.is_starred: |
| 5739 if self.starred_assignment: |
| 5740 error(arg.pos, "more than 1 starred expression in assignment
") |
| 5741 self.starred_assignment = True |
| 5742 arg = arg.target |
| 5743 arg.is_starred = True |
| 5744 args.append(arg) |
| 5745 self.args = args |
| 5746 |
| 5747 def analyse_target_declaration(self, env): |
| 5748 self.replace_starred_target_node() |
| 5749 for arg in self.args: |
| 5750 arg.analyse_target_declaration(env) |
| 5751 |
| 5752 def analyse_types(self, env, skip_children=False): |
| 5753 for i in range(len(self.args)): |
| 5754 arg = self.args[i] |
| 5755 if not skip_children: arg = arg.analyse_types(env) |
| 5756 self.args[i] = arg.coerce_to_pyobject(env) |
| 5757 if self.mult_factor: |
| 5758 self.mult_factor = self.mult_factor.analyse_types(env) |
| 5759 if not self.mult_factor.type.is_int: |
| 5760 self.mult_factor = self.mult_factor.coerce_to_pyobject(env) |
| 5761 self.is_temp = 1 |
| 5762 # not setting self.type here, subtypes do this |
| 5763 return self |
| 5764 |
| 5765 def may_be_none(self): |
| 5766 return False |
| 5767 |
| 5768 def analyse_target_types(self, env): |
| 5769 if self.mult_factor: |
| 5770 error(self.pos, "can't assign to multiplied sequence") |
| 5771 self.unpacked_items = [] |
| 5772 self.coerced_unpacked_items = [] |
| 5773 self.any_coerced_items = False |
| 5774 for i, arg in enumerate(self.args): |
| 5775 arg = self.args[i] = arg.analyse_target_types(env) |
| 5776 if arg.is_starred: |
| 5777 if not arg.type.assignable_from(Builtin.list_type): |
| 5778 error(arg.pos, |
| 5779 "starred target must have Python object (list) type") |
| 5780 if arg.type is py_object_type: |
| 5781 arg.type = Builtin.list_type |
| 5782 unpacked_item = PyTempNode(self.pos, env) |
| 5783 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env) |
| 5784 if unpacked_item is not coerced_unpacked_item: |
| 5785 self.any_coerced_items = True |
| 5786 self.unpacked_items.append(unpacked_item) |
| 5787 self.coerced_unpacked_items.append(coerced_unpacked_item) |
| 5788 self.type = py_object_type |
| 5789 return self |
| 5790 |
| 5791 def generate_result_code(self, code): |
| 5792 self.generate_operation_code(code) |
| 5793 |
| 5794 def generate_sequence_packing_code(self, code, target=None, plain=False): |
| 5795 if target is None: |
| 5796 target = self.result() |
| 5797 size_factor = c_mult = '' |
| 5798 mult_factor = None |
| 5799 |
| 5800 if self.mult_factor and not plain: |
| 5801 mult_factor = self.mult_factor |
| 5802 if mult_factor.type.is_int: |
| 5803 c_mult = mult_factor.result() |
| 5804 if isinstance(mult_factor.constant_result, (int,long)) \ |
| 5805 and mult_factor.constant_result > 0: |
| 5806 size_factor = ' * %s' % mult_factor.constant_result |
| 5807 else: |
| 5808 size_factor = ' * ((%s<0) ? 0:%s)' % (c_mult, c_mult) |
| 5809 |
| 5810 if self.type is Builtin.tuple_type and (self.is_literal or self.slow) an
d not c_mult: |
| 5811 # use PyTuple_Pack() to avoid generating huge amounts of one-time co
de |
| 5812 code.putln('%s = PyTuple_Pack(%d, %s); %s' % ( |
| 5813 target, |
| 5814 len(self.args), |
| 5815 ', '.join([ arg.py_result() for arg in self.args ]), |
| 5816 code.error_goto_if_null(target, self.pos))) |
| 5817 code.put_gotref(target) |
| 5818 else: |
| 5819 # build the tuple/list step by step, potentially multiplying it as w
e go |
| 5820 if self.type is Builtin.list_type: |
| 5821 create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM' |
| 5822 elif self.type is Builtin.tuple_type: |
| 5823 create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM' |
| 5824 else: |
| 5825 raise InternalError("sequence packing for unexpected type %s" %
self.type) |
| 5826 arg_count = len(self.args) |
| 5827 code.putln("%s = %s(%s%s); %s" % ( |
| 5828 target, create_func, arg_count, size_factor, |
| 5829 code.error_goto_if_null(target, self.pos))) |
| 5830 code.put_gotref(target) |
| 5831 |
| 5832 if c_mult: |
| 5833 # FIXME: can't use a temp variable here as the code may |
| 5834 # end up in the constant building function. Temps |
| 5835 # currently don't work there. |
| 5836 |
| 5837 #counter = code.funcstate.allocate_temp(mult_factor.type, manage
_ref=False) |
| 5838 counter = Naming.quick_temp_cname |
| 5839 code.putln('{ Py_ssize_t %s;' % counter) |
| 5840 if arg_count == 1: |
| 5841 offset = counter |
| 5842 else: |
| 5843 offset = '%s * %s' % (counter, arg_count) |
| 5844 code.putln('for (%s=0; %s < %s; %s++) {' % ( |
| 5845 counter, counter, c_mult, counter |
| 5846 )) |
| 5847 else: |
| 5848 offset = '' |
| 5849 |
| 5850 for i in xrange(arg_count): |
| 5851 arg = self.args[i] |
| 5852 if c_mult or not arg.result_in_temp(): |
| 5853 code.put_incref(arg.result(), arg.ctype()) |
| 5854 code.putln("%s(%s, %s, %s);" % ( |
| 5855 set_item_func, |
| 5856 target, |
| 5857 (offset and i) and ('%s + %s' % (offset, i)) or (offset or i
), |
| 5858 arg.py_result())) |
| 5859 code.put_giveref(arg.py_result()) |
| 5860 |
| 5861 if c_mult: |
| 5862 code.putln('}') |
| 5863 #code.funcstate.release_temp(counter) |
| 5864 code.putln('}') |
| 5865 |
| 5866 if mult_factor is not None and mult_factor.type.is_pyobject: |
| 5867 code.putln('{ PyObject* %s = PyNumber_InPlaceMultiply(%s, %s); %s' %
( |
| 5868 Naming.quick_temp_cname, target, mult_factor.py_result(), |
| 5869 code.error_goto_if_null(Naming.quick_temp_cname, self.pos) |
| 5870 )) |
| 5871 code.put_gotref(Naming.quick_temp_cname) |
| 5872 code.put_decref(target, py_object_type) |
| 5873 code.putln('%s = %s;' % (target, Naming.quick_temp_cname)) |
| 5874 code.putln('}') |
| 5875 |
| 5876 def generate_subexpr_disposal_code(self, code): |
| 5877 if self.mult_factor and self.mult_factor.type.is_int: |
| 5878 super(SequenceNode, self).generate_subexpr_disposal_code(code) |
| 5879 elif self.type is Builtin.tuple_type and (self.is_literal or self.slow): |
| 5880 super(SequenceNode, self).generate_subexpr_disposal_code(code) |
| 5881 else: |
| 5882 # We call generate_post_assignment_code here instead |
| 5883 # of generate_disposal_code, because values were stored |
| 5884 # in the tuple using a reference-stealing operation. |
| 5885 for arg in self.args: |
| 5886 arg.generate_post_assignment_code(code) |
| 5887 # Should NOT call free_temps -- this is invoked by the default |
| 5888 # generate_evaluation_code which will do that. |
| 5889 if self.mult_factor: |
| 5890 self.mult_factor.generate_disposal_code(code) |
| 5891 |
| 5892 def generate_assignment_code(self, rhs, code): |
| 5893 if self.starred_assignment: |
| 5894 self.generate_starred_assignment_code(rhs, code) |
| 5895 else: |
| 5896 self.generate_parallel_assignment_code(rhs, code) |
| 5897 |
| 5898 for item in self.unpacked_items: |
| 5899 item.release(code) |
| 5900 rhs.free_temps(code) |
| 5901 |
| 5902 _func_iternext_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( |
| 5903 PyrexTypes.py_object_type, [ |
| 5904 PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None), |
| 5905 ])) |
| 5906 |
| 5907 def generate_parallel_assignment_code(self, rhs, code): |
| 5908 # Need to work around the fact that generate_evaluation_code |
| 5909 # allocates the temps in a rather hacky way -- the assignment |
| 5910 # is evaluated twice, within each if-block. |
| 5911 for item in self.unpacked_items: |
| 5912 item.allocate(code) |
| 5913 special_unpack = (rhs.type is py_object_type |
| 5914 or rhs.type in (tuple_type, list_type) |
| 5915 or not rhs.type.is_builtin_type) |
| 5916 long_enough_for_a_loop = len(self.unpacked_items) > 3 |
| 5917 |
| 5918 if special_unpack: |
| 5919 self.generate_special_parallel_unpacking_code( |
| 5920 code, rhs, use_loop=long_enough_for_a_loop) |
| 5921 else: |
| 5922 code.putln("{") |
| 5923 self.generate_generic_parallel_unpacking_code( |
| 5924 code, rhs, self.unpacked_items, use_loop=long_enough_for_a_loop) |
| 5925 code.putln("}") |
| 5926 |
| 5927 for value_node in self.coerced_unpacked_items: |
| 5928 value_node.generate_evaluation_code(code) |
| 5929 for i in range(len(self.args)): |
| 5930 self.args[i].generate_assignment_code( |
| 5931 self.coerced_unpacked_items[i], code) |
| 5932 |
| 5933 def generate_special_parallel_unpacking_code(self, code, rhs, use_loop): |
| 5934 sequence_type_test = '1' |
| 5935 none_check = "likely(%s != Py_None)" % rhs.py_result() |
| 5936 if rhs.type is list_type: |
| 5937 sequence_types = ['List'] |
| 5938 if rhs.may_be_none(): |
| 5939 sequence_type_test = none_check |
| 5940 elif rhs.type is tuple_type: |
| 5941 sequence_types = ['Tuple'] |
| 5942 if rhs.may_be_none(): |
| 5943 sequence_type_test = none_check |
| 5944 else: |
| 5945 sequence_types = ['Tuple', 'List'] |
| 5946 tuple_check = 'likely(PyTuple_CheckExact(%s))' % rhs.py_result() |
| 5947 list_check = 'PyList_CheckExact(%s)' % rhs.py_result() |
| 5948 sequence_type_test = "(%s) || (%s)" % (tuple_check, list_check) |
| 5949 |
| 5950 code.putln("if (%s) {" % sequence_type_test) |
| 5951 code.putln("PyObject* sequence = %s;" % rhs.py_result()) |
| 5952 |
| 5953 # list/tuple => check size |
| 5954 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") |
| 5955 code.putln("Py_ssize_t size = Py_SIZE(sequence);") |
| 5956 code.putln("#else") |
| 5957 code.putln("Py_ssize_t size = PySequence_Size(sequence);") # < 0 => exc
eption |
| 5958 code.putln("#endif") |
| 5959 code.putln("if (unlikely(size != %d)) {" % len(self.args)) |
| 5960 code.globalstate.use_utility_code(raise_too_many_values_to_unpack) |
| 5961 code.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % ( |
| 5962 len(self.args), len(self.args))) |
| 5963 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) |
| 5964 code.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);") |
| 5965 code.putln(code.error_goto(self.pos)) |
| 5966 code.putln("}") |
| 5967 |
| 5968 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") |
| 5969 # unpack items from list/tuple in unrolled loop (can't fail) |
| 5970 if len(sequence_types) == 2: |
| 5971 code.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_typ
es[0]) |
| 5972 for i, item in enumerate(self.unpacked_items): |
| 5973 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( |
| 5974 item.result(), sequence_types[0], i)) |
| 5975 if len(sequence_types) == 2: |
| 5976 code.putln("} else {") |
| 5977 for i, item in enumerate(self.unpacked_items): |
| 5978 code.putln("%s = Py%s_GET_ITEM(sequence, %d); " % ( |
| 5979 item.result(), sequence_types[1], i)) |
| 5980 code.putln("}") |
| 5981 for item in self.unpacked_items: |
| 5982 code.put_incref(item.result(), item.ctype()) |
| 5983 |
| 5984 code.putln("#else") |
| 5985 # in non-CPython, use the PySequence protocol (which can fail) |
| 5986 if not use_loop: |
| 5987 for i, item in enumerate(self.unpacked_items): |
| 5988 code.putln("%s = PySequence_ITEM(sequence, %d); %s" % ( |
| 5989 item.result(), i, |
| 5990 code.error_goto_if_null(item.result(), self.pos))) |
| 5991 code.put_gotref(item.result()) |
| 5992 else: |
| 5993 code.putln("{") |
| 5994 code.putln("Py_ssize_t i;") |
| 5995 code.putln("PyObject** temps[%s] = {%s};" % ( |
| 5996 len(self.unpacked_items), |
| 5997 ','.join(['&%s' % item.result() for item in self.unpacked_items]
))) |
| 5998 code.putln("for (i=0; i < %s; i++) {" % len(self.unpacked_items)) |
| 5999 code.putln("PyObject* item = PySequence_ITEM(sequence, i); %s" % ( |
| 6000 code.error_goto_if_null('item', self.pos))) |
| 6001 code.put_gotref('item') |
| 6002 code.putln("*(temps[i]) = item;") |
| 6003 code.putln("}") |
| 6004 code.putln("}") |
| 6005 |
| 6006 code.putln("#endif") |
| 6007 rhs.generate_disposal_code(code) |
| 6008 |
| 6009 if sequence_type_test == '1': |
| 6010 code.putln("}") # all done |
| 6011 elif sequence_type_test == none_check: |
| 6012 # either tuple/list or None => save some code by generating the erro
r directly |
| 6013 code.putln("} else {") |
| 6014 code.globalstate.use_utility_code( |
| 6015 UtilityCode.load_cached("RaiseNoneIterError", "ObjectHandling.c"
)) |
| 6016 code.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code.error_goto
(self.pos)) |
| 6017 code.putln("}") # all done |
| 6018 else: |
| 6019 code.putln("} else {") # needs iteration fallback code |
| 6020 self.generate_generic_parallel_unpacking_code( |
| 6021 code, rhs, self.unpacked_items, use_loop=use_loop) |
| 6022 code.putln("}") |
| 6023 |
| 6024 def generate_generic_parallel_unpacking_code(self, code, rhs, unpacked_items
, use_loop, terminate=True): |
| 6025 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) |
| 6026 code.globalstate.use_utility_code(UtilityCode.load_cached("IterFinish",
"ObjectHandling.c")) |
| 6027 code.putln("Py_ssize_t index = -1;") # must be at the start of a C block
! |
| 6028 |
| 6029 if use_loop: |
| 6030 code.putln("PyObject** temps[%s] = {%s};" % ( |
| 6031 len(self.unpacked_items), |
| 6032 ','.join(['&%s' % item.result() for item in unpacked_items]))) |
| 6033 |
| 6034 iterator_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=
True) |
| 6035 code.putln( |
| 6036 "%s = PyObject_GetIter(%s); %s" % ( |
| 6037 iterator_temp, |
| 6038 rhs.py_result(), |
| 6039 code.error_goto_if_null(iterator_temp, self.pos))) |
| 6040 code.put_gotref(iterator_temp) |
| 6041 rhs.generate_disposal_code(code) |
| 6042 |
| 6043 iternext_func = code.funcstate.allocate_temp(self._func_iternext_type, m
anage_ref=False) |
| 6044 code.putln("%s = Py_TYPE(%s)->tp_iternext;" % ( |
| 6045 iternext_func, iterator_temp)) |
| 6046 |
| 6047 unpacking_error_label = code.new_label('unpacking_failed') |
| 6048 unpack_code = "%s(%s)" % (iternext_func, iterator_temp) |
| 6049 if use_loop: |
| 6050 code.putln("for (index=0; index < %s; index++) {" % len(unpacked_ite
ms)) |
| 6051 code.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code) |
| 6052 code.put_goto(unpacking_error_label) |
| 6053 code.put_gotref("item") |
| 6054 code.putln("*(temps[index]) = item;") |
| 6055 code.putln("}") |
| 6056 else: |
| 6057 for i, item in enumerate(unpacked_items): |
| 6058 code.put( |
| 6059 "index = %d; %s = %s; if (unlikely(!%s)) " % ( |
| 6060 i, |
| 6061 item.result(), |
| 6062 unpack_code, |
| 6063 item.result())) |
| 6064 code.put_goto(unpacking_error_label) |
| 6065 code.put_gotref(item.py_result()) |
| 6066 |
| 6067 if terminate: |
| 6068 code.globalstate.use_utility_code( |
| 6069 UtilityCode.load_cached("UnpackItemEndCheck", "ObjectHandling.c"
)) |
| 6070 code.put_error_if_neg(self.pos, "__Pyx_IternextUnpackEndCheck(%s, %d
)" % ( |
| 6071 unpack_code, |
| 6072 len(unpacked_items))) |
| 6073 code.putln("%s = NULL;" % iternext_func) |
| 6074 code.put_decref_clear(iterator_temp, py_object_type) |
| 6075 |
| 6076 unpacking_done_label = code.new_label('unpacking_done') |
| 6077 code.put_goto(unpacking_done_label) |
| 6078 |
| 6079 code.put_label(unpacking_error_label) |
| 6080 code.put_decref_clear(iterator_temp, py_object_type) |
| 6081 code.putln("%s = NULL;" % iternext_func) |
| 6082 code.putln("if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(
index);") |
| 6083 code.putln(code.error_goto(self.pos)) |
| 6084 code.put_label(unpacking_done_label) |
| 6085 |
| 6086 code.funcstate.release_temp(iternext_func) |
| 6087 if terminate: |
| 6088 code.funcstate.release_temp(iterator_temp) |
| 6089 iterator_temp = None |
| 6090 |
| 6091 return iterator_temp |
| 6092 |
| 6093 def generate_starred_assignment_code(self, rhs, code): |
| 6094 for i, arg in enumerate(self.args): |
| 6095 if arg.is_starred: |
| 6096 starred_target = self.unpacked_items[i] |
| 6097 unpacked_fixed_items_left = self.unpacked_items[:i] |
| 6098 unpacked_fixed_items_right = self.unpacked_items[i+1:] |
| 6099 break |
| 6100 else: |
| 6101 assert False |
| 6102 |
| 6103 iterator_temp = None |
| 6104 if unpacked_fixed_items_left: |
| 6105 for item in unpacked_fixed_items_left: |
| 6106 item.allocate(code) |
| 6107 code.putln('{') |
| 6108 iterator_temp = self.generate_generic_parallel_unpacking_code( |
| 6109 code, rhs, unpacked_fixed_items_left, |
| 6110 use_loop=True, terminate=False) |
| 6111 for i, item in enumerate(unpacked_fixed_items_left): |
| 6112 value_node = self.coerced_unpacked_items[i] |
| 6113 value_node.generate_evaluation_code(code) |
| 6114 code.putln('}') |
| 6115 |
| 6116 starred_target.allocate(code) |
| 6117 target_list = starred_target.result() |
| 6118 code.putln("%s = PySequence_List(%s); %s" % ( |
| 6119 target_list, |
| 6120 iterator_temp or rhs.py_result(), |
| 6121 code.error_goto_if_null(target_list, self.pos))) |
| 6122 code.put_gotref(target_list) |
| 6123 |
| 6124 if iterator_temp: |
| 6125 code.put_decref_clear(iterator_temp, py_object_type) |
| 6126 code.funcstate.release_temp(iterator_temp) |
| 6127 else: |
| 6128 rhs.generate_disposal_code(code) |
| 6129 |
| 6130 if unpacked_fixed_items_right: |
| 6131 code.globalstate.use_utility_code(raise_need_more_values_to_unpack) |
| 6132 length_temp = code.funcstate.allocate_temp(PyrexTypes.c_py_ssize_t_t
ype, manage_ref=False) |
| 6133 code.putln('%s = PyList_GET_SIZE(%s);' % (length_temp, target_list)) |
| 6134 code.putln("if (unlikely(%s < %d)) {" % (length_temp, len(unpacked_f
ixed_items_right))) |
| 6135 code.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % ( |
| 6136 len(unpacked_fixed_items_left), length_temp, |
| 6137 code.error_goto(self.pos))) |
| 6138 code.putln('}') |
| 6139 |
| 6140 for item in unpacked_fixed_items_right[::-1]: |
| 6141 item.allocate(code) |
| 6142 for i, (item, coerced_arg) in enumerate(zip(unpacked_fixed_items_rig
ht[::-1], |
| 6143 self.coerced_unpacked_it
ems[::-1])): |
| 6144 code.putln('#if CYTHON_COMPILING_IN_CPYTHON') |
| 6145 code.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % ( |
| 6146 item.py_result(), target_list, length_temp, i+1)) |
| 6147 # resize the list the hard way |
| 6148 code.putln("((PyVarObject*)%s)->ob_size--;" % target_list) |
| 6149 code.putln('#else') |
| 6150 code.putln("%s = PySequence_ITEM(%s, %s-%d); " % ( |
| 6151 item.py_result(), target_list, length_temp, i+1)) |
| 6152 code.putln('#endif') |
| 6153 code.put_gotref(item.py_result()) |
| 6154 coerced_arg.generate_evaluation_code(code) |
| 6155 |
| 6156 code.putln('#if !CYTHON_COMPILING_IN_CPYTHON') |
| 6157 sublist_temp = code.funcstate.allocate_temp(py_object_type, manage_r
ef=True) |
| 6158 code.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % ( |
| 6159 sublist_temp, target_list, length_temp, len(unpacked_fixed_items
_right), |
| 6160 code.error_goto_if_null(sublist_temp, self.pos))) |
| 6161 code.put_gotref(sublist_temp) |
| 6162 code.funcstate.release_temp(length_temp) |
| 6163 code.put_decref(target_list, py_object_type) |
| 6164 code.putln('%s = %s; %s = NULL;' % (target_list, sublist_temp, subli
st_temp)) |
| 6165 code.putln('#else') |
| 6166 code.putln('%s = %s;' % (sublist_temp, sublist_temp)) # avoid warnin
g about unused variable |
| 6167 code.funcstate.release_temp(sublist_temp) |
| 6168 code.putln('#endif') |
| 6169 |
| 6170 for i, arg in enumerate(self.args): |
| 6171 arg.generate_assignment_code(self.coerced_unpacked_items[i], code) |
| 6172 |
| 6173 def annotate(self, code): |
| 6174 for arg in self.args: |
| 6175 arg.annotate(code) |
| 6176 if self.unpacked_items: |
| 6177 for arg in self.unpacked_items: |
| 6178 arg.annotate(code) |
| 6179 for arg in self.coerced_unpacked_items: |
| 6180 arg.annotate(code) |
| 6181 |
| 6182 |
| 6183 class TupleNode(SequenceNode): |
| 6184 # Tuple constructor. |
| 6185 |
| 6186 type = tuple_type |
| 6187 is_partly_literal = False |
| 6188 |
| 6189 gil_message = "Constructing Python tuple" |
| 6190 |
| 6191 def analyse_types(self, env, skip_children=False): |
| 6192 if len(self.args) == 0: |
| 6193 node = self |
| 6194 node.is_temp = False |
| 6195 node.is_literal = True |
| 6196 else: |
| 6197 node = SequenceNode.analyse_types(self, env, skip_children) |
| 6198 for child in node.args: |
| 6199 if not child.is_literal: |
| 6200 break |
| 6201 else: |
| 6202 if not node.mult_factor or node.mult_factor.is_literal and \ |
| 6203 isinstance(node.mult_factor.constant_result, (int, long))
: |
| 6204 node.is_temp = False |
| 6205 node.is_literal = True |
| 6206 else: |
| 6207 if not node.mult_factor.type.is_pyobject: |
| 6208 node.mult_factor = node.mult_factor.coerce_to_pyobject(e
nv) |
| 6209 node.is_temp = True |
| 6210 node.is_partly_literal = True |
| 6211 return node |
| 6212 |
| 6213 def is_simple(self): |
| 6214 # either temp or constant => always simple |
| 6215 return True |
| 6216 |
| 6217 def nonlocally_immutable(self): |
| 6218 # either temp or constant => always safe |
| 6219 return True |
| 6220 |
| 6221 def calculate_result_code(self): |
| 6222 if len(self.args) > 0: |
| 6223 return self.result_code |
| 6224 else: |
| 6225 return Naming.empty_tuple |
| 6226 |
| 6227 def calculate_constant_result(self): |
| 6228 self.constant_result = tuple([ |
| 6229 arg.constant_result for arg in self.args]) |
| 6230 |
| 6231 def compile_time_value(self, denv): |
| 6232 values = self.compile_time_value_list(denv) |
| 6233 try: |
| 6234 return tuple(values) |
| 6235 except Exception, e: |
| 6236 self.compile_time_value_error(e) |
| 6237 |
| 6238 def generate_operation_code(self, code): |
| 6239 if len(self.args) == 0: |
| 6240 # result_code is Naming.empty_tuple |
| 6241 return |
| 6242 if self.is_partly_literal: |
| 6243 # underlying tuple is const, but factor is not |
| 6244 tuple_target = code.get_py_const(py_object_type, 'tuple', cleanup_le
vel=2) |
| 6245 const_code = code.get_cached_constants_writer() |
| 6246 const_code.mark_pos(self.pos) |
| 6247 self.generate_sequence_packing_code(const_code, tuple_target, plain=
True) |
| 6248 const_code.put_giveref(tuple_target) |
| 6249 code.putln('%s = PyNumber_Multiply(%s, %s); %s' % ( |
| 6250 self.result(), tuple_target, self.mult_factor.py_result(), |
| 6251 code.error_goto_if_null(self.result(), self.pos) |
| 6252 )) |
| 6253 code.put_gotref(self.py_result()) |
| 6254 elif self.is_literal: |
| 6255 # non-empty cached tuple => result is global constant, |
| 6256 # creation code goes into separate code writer |
| 6257 self.result_code = code.get_py_const(py_object_type, 'tuple', cleanu
p_level=2) |
| 6258 code = code.get_cached_constants_writer() |
| 6259 code.mark_pos(self.pos) |
| 6260 self.generate_sequence_packing_code(code) |
| 6261 code.put_giveref(self.py_result()) |
| 6262 else: |
| 6263 self.generate_sequence_packing_code(code) |
| 6264 |
| 6265 |
| 6266 class ListNode(SequenceNode): |
| 6267 # List constructor. |
| 6268 |
| 6269 # obj_conversion_errors [PyrexError] used internally |
| 6270 # orignial_args [ExprNode] used internally |
| 6271 |
| 6272 obj_conversion_errors = [] |
| 6273 type = list_type |
| 6274 in_module_scope = False |
| 6275 |
| 6276 gil_message = "Constructing Python list" |
| 6277 |
| 6278 def type_dependencies(self, env): |
| 6279 return () |
| 6280 |
| 6281 def infer_type(self, env): |
| 6282 # TOOD: Infer non-object list arrays. |
| 6283 return list_type |
| 6284 |
| 6285 def analyse_expressions(self, env): |
| 6286 node = SequenceNode.analyse_expressions(self, env) |
| 6287 return node.coerce_to_pyobject(env) |
| 6288 |
| 6289 def analyse_types(self, env): |
| 6290 hold_errors() |
| 6291 self.original_args = list(self.args) |
| 6292 node = SequenceNode.analyse_types(self, env) |
| 6293 node.obj_conversion_errors = held_errors() |
| 6294 release_errors(ignore=True) |
| 6295 if env.is_module_scope: |
| 6296 self.in_module_scope = True |
| 6297 return node |
| 6298 |
| 6299 def coerce_to(self, dst_type, env): |
| 6300 if dst_type.is_pyobject: |
| 6301 for err in self.obj_conversion_errors: |
| 6302 report_error(err) |
| 6303 self.obj_conversion_errors = [] |
| 6304 if not self.type.subtype_of(dst_type): |
| 6305 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) |
| 6306 elif self.mult_factor: |
| 6307 error(self.pos, "Cannot coerce multiplied list to '%s'" % dst_type) |
| 6308 elif dst_type.is_ptr and dst_type.base_type is not PyrexTypes.c_void_typ
e: |
| 6309 base_type = dst_type.base_type |
| 6310 self.type = PyrexTypes.CArrayType(base_type, len(self.args)) |
| 6311 for i in range(len(self.original_args)): |
| 6312 arg = self.args[i] |
| 6313 if isinstance(arg, CoerceToPyTypeNode): |
| 6314 arg = arg.arg |
| 6315 self.args[i] = arg.coerce_to(base_type, env) |
| 6316 elif dst_type.is_struct: |
| 6317 if len(self.args) > len(dst_type.scope.var_entries): |
| 6318 error(self.pos, "Too may members for '%s'" % dst_type) |
| 6319 else: |
| 6320 if len(self.args) < len(dst_type.scope.var_entries): |
| 6321 warning(self.pos, "Too few members for '%s'" % dst_type, 1) |
| 6322 for i, (arg, member) in enumerate(zip(self.original_args, dst_ty
pe.scope.var_entries)): |
| 6323 if isinstance(arg, CoerceToPyTypeNode): |
| 6324 arg = arg.arg |
| 6325 self.args[i] = arg.coerce_to(member.type, env) |
| 6326 self.type = dst_type |
| 6327 else: |
| 6328 self.type = error_type |
| 6329 error(self.pos, "Cannot coerce list to type '%s'" % dst_type) |
| 6330 return self |
| 6331 |
| 6332 def as_tuple(self): |
| 6333 t = TupleNode(self.pos, args=self.args, mult_factor=self.mult_factor) |
| 6334 if isinstance(self.constant_result, list): |
| 6335 t.constant_result = tuple(self.constant_result) |
| 6336 return t |
| 6337 |
| 6338 def allocate_temp_result(self, code): |
| 6339 if self.type.is_array and self.in_module_scope: |
| 6340 self.temp_code = code.funcstate.allocate_temp( |
| 6341 self.type, manage_ref=False, static=True) |
| 6342 else: |
| 6343 SequenceNode.allocate_temp_result(self, code) |
| 6344 |
| 6345 def release_temp_result(self, env): |
| 6346 if self.type.is_array: |
| 6347 # To be valid C++, we must allocate the memory on the stack |
| 6348 # manually and be sure not to reuse it for something else. |
| 6349 pass |
| 6350 else: |
| 6351 SequenceNode.release_temp_result(self, env) |
| 6352 |
| 6353 def calculate_constant_result(self): |
| 6354 if self.mult_factor: |
| 6355 raise ValueError() # may exceed the compile time memory |
| 6356 self.constant_result = [ |
| 6357 arg.constant_result for arg in self.args] |
| 6358 |
| 6359 def compile_time_value(self, denv): |
| 6360 l = self.compile_time_value_list(denv) |
| 6361 if self.mult_factor: |
| 6362 l *= self.mult_factor.compile_time_value(denv) |
| 6363 return l |
| 6364 |
| 6365 def generate_operation_code(self, code): |
| 6366 if self.type.is_pyobject: |
| 6367 for err in self.obj_conversion_errors: |
| 6368 report_error(err) |
| 6369 self.generate_sequence_packing_code(code) |
| 6370 elif self.type.is_array: |
| 6371 for i, arg in enumerate(self.args): |
| 6372 code.putln("%s[%s] = %s;" % ( |
| 6373 self.result(), |
| 6374 i, |
| 6375 arg.result())) |
| 6376 elif self.type.is_struct: |
| 6377 for arg, member in zip(self.args, self.type.scope.var_entries): |
| 6378 code.putln("%s.%s = %s;" % ( |
| 6379 self.result(), |
| 6380 member.cname, |
| 6381 arg.result())) |
| 6382 else: |
| 6383 raise InternalError("List type never specified") |
| 6384 |
| 6385 |
| 6386 class ScopedExprNode(ExprNode): |
| 6387 # Abstract base class for ExprNodes that have their own local |
| 6388 # scope, such as generator expressions. |
| 6389 # |
| 6390 # expr_scope Scope the inner scope of the expression |
| 6391 |
| 6392 subexprs = [] |
| 6393 expr_scope = None |
| 6394 |
| 6395 # does this node really have a local scope, e.g. does it leak loop |
| 6396 # variables or not? non-leaking Py3 behaviour is default, except |
| 6397 # for list comprehensions where the behaviour differs in Py2 and |
| 6398 # Py3 (set in Parsing.py based on parser context) |
| 6399 has_local_scope = True |
| 6400 |
| 6401 def init_scope(self, outer_scope, expr_scope=None): |
| 6402 if expr_scope is not None: |
| 6403 self.expr_scope = expr_scope |
| 6404 elif self.has_local_scope: |
| 6405 self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope) |
| 6406 else: |
| 6407 self.expr_scope = None |
| 6408 |
| 6409 def analyse_declarations(self, env): |
| 6410 self.init_scope(env) |
| 6411 |
| 6412 def analyse_scoped_declarations(self, env): |
| 6413 # this is called with the expr_scope as env |
| 6414 pass |
| 6415 |
| 6416 def analyse_types(self, env): |
| 6417 # no recursion here, the children will be analysed separately below |
| 6418 return self |
| 6419 |
| 6420 def analyse_scoped_expressions(self, env): |
| 6421 # this is called with the expr_scope as env |
| 6422 return self |
| 6423 |
| 6424 def generate_evaluation_code(self, code): |
| 6425 # set up local variables and free their references on exit |
| 6426 generate_inner_evaluation_code = super(ScopedExprNode, self).generate_ev
aluation_code |
| 6427 if not self.has_local_scope or not self.expr_scope.var_entries: |
| 6428 # no local variables => delegate, done |
| 6429 generate_inner_evaluation_code(code) |
| 6430 return |
| 6431 |
| 6432 code.putln('{ /* enter inner scope */') |
| 6433 py_entries = [] |
| 6434 for entry in self.expr_scope.var_entries: |
| 6435 if not entry.in_closure: |
| 6436 code.put_var_declaration(entry) |
| 6437 if entry.type.is_pyobject and entry.used: |
| 6438 py_entries.append(entry) |
| 6439 if not py_entries: |
| 6440 # no local Python references => no cleanup required |
| 6441 generate_inner_evaluation_code(code) |
| 6442 code.putln('} /* exit inner scope */') |
| 6443 return |
| 6444 |
| 6445 # must free all local Python references at each exit point |
| 6446 old_loop_labels = tuple(code.new_loop_labels()) |
| 6447 old_error_label = code.new_error_label() |
| 6448 |
| 6449 generate_inner_evaluation_code(code) |
| 6450 |
| 6451 # normal (non-error) exit |
| 6452 for entry in py_entries: |
| 6453 code.put_var_decref(entry) |
| 6454 |
| 6455 # error/loop body exit points |
| 6456 exit_scope = code.new_label('exit_scope') |
| 6457 code.put_goto(exit_scope) |
| 6458 for label, old_label in ([(code.error_label, old_error_label)] + |
| 6459 list(zip(code.get_loop_labels(), old_loop_label
s))): |
| 6460 if code.label_used(label): |
| 6461 code.put_label(label) |
| 6462 for entry in py_entries: |
| 6463 code.put_var_decref(entry) |
| 6464 code.put_goto(old_label) |
| 6465 code.put_label(exit_scope) |
| 6466 code.putln('} /* exit inner scope */') |
| 6467 |
| 6468 code.set_loop_labels(old_loop_labels) |
| 6469 code.error_label = old_error_label |
| 6470 |
| 6471 |
| 6472 class ComprehensionNode(ScopedExprNode): |
| 6473 # A list/set/dict comprehension |
| 6474 |
| 6475 child_attrs = ["loop"] |
| 6476 |
| 6477 is_temp = True |
| 6478 |
| 6479 def infer_type(self, env): |
| 6480 return self.type |
| 6481 |
| 6482 def analyse_declarations(self, env): |
| 6483 self.append.target = self # this is used in the PyList_Append of the inn
er loop |
| 6484 self.init_scope(env) |
| 6485 |
| 6486 def analyse_scoped_declarations(self, env): |
| 6487 self.loop.analyse_declarations(env) |
| 6488 |
| 6489 def analyse_types(self, env): |
| 6490 if not self.has_local_scope: |
| 6491 self.loop = self.loop.analyse_expressions(env) |
| 6492 return self |
| 6493 |
| 6494 def analyse_scoped_expressions(self, env): |
| 6495 if self.has_local_scope: |
| 6496 self.loop = self.loop.analyse_expressions(env) |
| 6497 return self |
| 6498 |
| 6499 def may_be_none(self): |
| 6500 return False |
| 6501 |
| 6502 def generate_result_code(self, code): |
| 6503 self.generate_operation_code(code) |
| 6504 |
| 6505 def generate_operation_code(self, code): |
| 6506 if self.type is Builtin.list_type: |
| 6507 create_code = 'PyList_New(0)' |
| 6508 elif self.type is Builtin.set_type: |
| 6509 create_code = 'PySet_New(NULL)' |
| 6510 elif self.type is Builtin.dict_type: |
| 6511 create_code = 'PyDict_New()' |
| 6512 else: |
| 6513 raise InternalError("illegal type for comprehension: %s" % self.type
) |
| 6514 code.putln('%s = %s; %s' % ( |
| 6515 self.result(), create_code, |
| 6516 code.error_goto_if_null(self.result(), self.pos))) |
| 6517 |
| 6518 code.put_gotref(self.result()) |
| 6519 self.loop.generate_execution_code(code) |
| 6520 |
| 6521 def annotate(self, code): |
| 6522 self.loop.annotate(code) |
| 6523 |
| 6524 |
| 6525 class ComprehensionAppendNode(Node): |
| 6526 # Need to be careful to avoid infinite recursion: |
| 6527 # target must not be in child_attrs/subexprs |
| 6528 |
| 6529 child_attrs = ['expr'] |
| 6530 target = None |
| 6531 |
| 6532 type = PyrexTypes.c_int_type |
| 6533 |
| 6534 def analyse_expressions(self, env): |
| 6535 self.expr = self.expr.analyse_expressions(env) |
| 6536 if not self.expr.type.is_pyobject: |
| 6537 self.expr = self.expr.coerce_to_pyobject(env) |
| 6538 return self |
| 6539 |
| 6540 def generate_execution_code(self, code): |
| 6541 if self.target.type is list_type: |
| 6542 code.globalstate.use_utility_code( |
| 6543 UtilityCode.load_cached("ListCompAppend", "Optimize.c")) |
| 6544 function = "__Pyx_ListComp_Append" |
| 6545 elif self.target.type is set_type: |
| 6546 function = "PySet_Add" |
| 6547 else: |
| 6548 raise InternalError( |
| 6549 "Invalid type for comprehension node: %s" % self.target.type) |
| 6550 |
| 6551 self.expr.generate_evaluation_code(code) |
| 6552 code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % ( |
| 6553 function, |
| 6554 self.target.result(), |
| 6555 self.expr.result() |
| 6556 ), self.pos)) |
| 6557 self.expr.generate_disposal_code(code) |
| 6558 self.expr.free_temps(code) |
| 6559 |
| 6560 def generate_function_definitions(self, env, code): |
| 6561 self.expr.generate_function_definitions(env, code) |
| 6562 |
| 6563 def annotate(self, code): |
| 6564 self.expr.annotate(code) |
| 6565 |
| 6566 class DictComprehensionAppendNode(ComprehensionAppendNode): |
| 6567 child_attrs = ['key_expr', 'value_expr'] |
| 6568 |
| 6569 def analyse_expressions(self, env): |
| 6570 self.key_expr = self.key_expr.analyse_expressions(env) |
| 6571 if not self.key_expr.type.is_pyobject: |
| 6572 self.key_expr = self.key_expr.coerce_to_pyobject(env) |
| 6573 self.value_expr = self.value_expr.analyse_expressions(env) |
| 6574 if not self.value_expr.type.is_pyobject: |
| 6575 self.value_expr = self.value_expr.coerce_to_pyobject(env) |
| 6576 return self |
| 6577 |
| 6578 def generate_execution_code(self, code): |
| 6579 self.key_expr.generate_evaluation_code(code) |
| 6580 self.value_expr.generate_evaluation_code(code) |
| 6581 code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObje
ct*)%s)" % ( |
| 6582 self.target.result(), |
| 6583 self.key_expr.result(), |
| 6584 self.value_expr.result() |
| 6585 ), self.pos)) |
| 6586 self.key_expr.generate_disposal_code(code) |
| 6587 self.key_expr.free_temps(code) |
| 6588 self.value_expr.generate_disposal_code(code) |
| 6589 self.value_expr.free_temps(code) |
| 6590 |
| 6591 def generate_function_definitions(self, env, code): |
| 6592 self.key_expr.generate_function_definitions(env, code) |
| 6593 self.value_expr.generate_function_definitions(env, code) |
| 6594 |
| 6595 def annotate(self, code): |
| 6596 self.key_expr.annotate(code) |
| 6597 self.value_expr.annotate(code) |
| 6598 |
| 6599 |
| 6600 class InlinedGeneratorExpressionNode(ScopedExprNode): |
| 6601 # An inlined generator expression for which the result is |
| 6602 # calculated inside of the loop. This will only be created by |
| 6603 # transforms when replacing builtin calls on generator |
| 6604 # expressions. |
| 6605 # |
| 6606 # loop ForStatNode the for-loop, not containing any YieldExpr
Nodes |
| 6607 # result_node ResultRefNode the reference to the result value temp |
| 6608 # orig_func String the name of the builtin function this node
replaces |
| 6609 |
| 6610 child_attrs = ["loop"] |
| 6611 loop_analysed = False |
| 6612 type = py_object_type |
| 6613 |
| 6614 def analyse_scoped_declarations(self, env): |
| 6615 self.loop.analyse_declarations(env) |
| 6616 |
| 6617 def may_be_none(self): |
| 6618 return False |
| 6619 |
| 6620 def annotate(self, code): |
| 6621 self.loop.annotate(code) |
| 6622 |
| 6623 def infer_type(self, env): |
| 6624 return self.result_node.infer_type(env) |
| 6625 |
| 6626 def analyse_types(self, env): |
| 6627 if not self.has_local_scope: |
| 6628 self.loop_analysed = True |
| 6629 self.loop = self.loop.analyse_expressions(env) |
| 6630 self.type = self.result_node.type |
| 6631 self.is_temp = True |
| 6632 return self |
| 6633 |
| 6634 def analyse_scoped_expressions(self, env): |
| 6635 self.loop_analysed = True |
| 6636 if self.has_local_scope: |
| 6637 self.loop = self.loop.analyse_expressions(env) |
| 6638 return self |
| 6639 |
| 6640 def coerce_to(self, dst_type, env): |
| 6641 if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_ana
lysed: |
| 6642 # We can optimise by dropping the aggregation variable and |
| 6643 # the add operations into C. This can only be done safely |
| 6644 # before analysing the loop body, after that, the result |
| 6645 # reference type will have infected expressions and |
| 6646 # assignments. |
| 6647 self.result_node.type = self.type = dst_type |
| 6648 return self |
| 6649 return super(InlinedGeneratorExpressionNode, self).coerce_to(dst_type, e
nv) |
| 6650 |
| 6651 def generate_result_code(self, code): |
| 6652 self.result_node.result_code = self.result() |
| 6653 self.loop.generate_execution_code(code) |
| 6654 |
| 6655 |
| 6656 class SetNode(ExprNode): |
| 6657 # Set constructor. |
| 6658 |
| 6659 type = set_type |
| 6660 |
| 6661 subexprs = ['args'] |
| 6662 |
| 6663 gil_message = "Constructing Python set" |
| 6664 |
| 6665 def analyse_types(self, env): |
| 6666 for i in range(len(self.args)): |
| 6667 arg = self.args[i] |
| 6668 arg = arg.analyse_types(env) |
| 6669 self.args[i] = arg.coerce_to_pyobject(env) |
| 6670 self.type = set_type |
| 6671 self.is_temp = 1 |
| 6672 return self |
| 6673 |
| 6674 def may_be_none(self): |
| 6675 return False |
| 6676 |
| 6677 def calculate_constant_result(self): |
| 6678 self.constant_result = set([ |
| 6679 arg.constant_result for arg in self.args]) |
| 6680 |
| 6681 def compile_time_value(self, denv): |
| 6682 values = [arg.compile_time_value(denv) for arg in self.args] |
| 6683 try: |
| 6684 return set(values) |
| 6685 except Exception, e: |
| 6686 self.compile_time_value_error(e) |
| 6687 |
| 6688 def generate_evaluation_code(self, code): |
| 6689 code.globalstate.use_utility_code(Builtin.py_set_utility_code) |
| 6690 self.allocate_temp_result(code) |
| 6691 code.putln( |
| 6692 "%s = PySet_New(0); %s" % ( |
| 6693 self.result(), |
| 6694 code.error_goto_if_null(self.result(), self.pos))) |
| 6695 code.put_gotref(self.py_result()) |
| 6696 for arg in self.args: |
| 6697 arg.generate_evaluation_code(code) |
| 6698 code.put_error_if_neg( |
| 6699 self.pos, |
| 6700 "PySet_Add(%s, %s)" % (self.result(), arg.py_result())) |
| 6701 arg.generate_disposal_code(code) |
| 6702 arg.free_temps(code) |
| 6703 |
| 6704 |
| 6705 class DictNode(ExprNode): |
| 6706 # Dictionary constructor. |
| 6707 # |
| 6708 # key_value_pairs [DictItemNode] |
| 6709 # exclude_null_values [boolean] Do not add NULL values to dict |
| 6710 # |
| 6711 # obj_conversion_errors [PyrexError] used internally |
| 6712 |
| 6713 subexprs = ['key_value_pairs'] |
| 6714 is_temp = 1 |
| 6715 exclude_null_values = False |
| 6716 type = dict_type |
| 6717 |
| 6718 obj_conversion_errors = [] |
| 6719 |
| 6720 @classmethod |
| 6721 def from_pairs(cls, pos, pairs): |
| 6722 return cls(pos, key_value_pairs=[ |
| 6723 DictItemNode(pos, key=k, value=v) for k, v in pairs]) |
| 6724 |
| 6725 def calculate_constant_result(self): |
| 6726 self.constant_result = dict([ |
| 6727 item.constant_result for item in self.key_value_pairs]) |
| 6728 |
| 6729 def compile_time_value(self, denv): |
| 6730 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_val
ue(denv)) |
| 6731 for item in self.key_value_pairs] |
| 6732 try: |
| 6733 return dict(pairs) |
| 6734 except Exception, e: |
| 6735 self.compile_time_value_error(e) |
| 6736 |
| 6737 def type_dependencies(self, env): |
| 6738 return () |
| 6739 |
| 6740 def infer_type(self, env): |
| 6741 # TOOD: Infer struct constructors. |
| 6742 return dict_type |
| 6743 |
| 6744 def analyse_types(self, env): |
| 6745 hold_errors() |
| 6746 self.key_value_pairs = [ item.analyse_types(env) |
| 6747 for item in self.key_value_pairs ] |
| 6748 self.obj_conversion_errors = held_errors() |
| 6749 release_errors(ignore=True) |
| 6750 return self |
| 6751 |
| 6752 def may_be_none(self): |
| 6753 return False |
| 6754 |
| 6755 def coerce_to(self, dst_type, env): |
| 6756 if dst_type.is_pyobject: |
| 6757 self.release_errors() |
| 6758 if not self.type.subtype_of(dst_type): |
| 6759 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) |
| 6760 elif dst_type.is_struct_or_union: |
| 6761 self.type = dst_type |
| 6762 if not dst_type.is_struct and len(self.key_value_pairs) != 1: |
| 6763 error(self.pos, "Exactly one field must be specified to convert
to union '%s'" % dst_type) |
| 6764 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type
.scope.var_entries): |
| 6765 warning(self.pos, "Not all members given for struct '%s'" % dst_
type, 1) |
| 6766 for item in self.key_value_pairs: |
| 6767 if isinstance(item.key, CoerceToPyTypeNode): |
| 6768 item.key = item.key.arg |
| 6769 if not item.key.is_string_literal: |
| 6770 error(item.key.pos, "Invalid struct field identifier") |
| 6771 item.key = StringNode(item.key.pos, value="<error>") |
| 6772 else: |
| 6773 key = str(item.key.value) # converts string literals to unic
ode in Py3 |
| 6774 member = dst_type.scope.lookup_here(key) |
| 6775 if not member: |
| 6776 error(item.key.pos, "struct '%s' has no field '%s'" % (d
st_type, key)) |
| 6777 else: |
| 6778 value = item.value |
| 6779 if isinstance(value, CoerceToPyTypeNode): |
| 6780 value = value.arg |
| 6781 item.value = value.coerce_to(member.type, env) |
| 6782 else: |
| 6783 self.type = error_type |
| 6784 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) |
| 6785 return self |
| 6786 |
| 6787 def release_errors(self): |
| 6788 for err in self.obj_conversion_errors: |
| 6789 report_error(err) |
| 6790 self.obj_conversion_errors = [] |
| 6791 |
| 6792 gil_message = "Constructing Python dict" |
| 6793 |
| 6794 def generate_evaluation_code(self, code): |
| 6795 # Custom method used here because key-value |
| 6796 # pairs are evaluated and used one at a time. |
| 6797 code.mark_pos(self.pos) |
| 6798 self.allocate_temp_result(code) |
| 6799 if self.type.is_pyobject: |
| 6800 self.release_errors() |
| 6801 code.putln( |
| 6802 "%s = PyDict_New(); %s" % ( |
| 6803 self.result(), |
| 6804 code.error_goto_if_null(self.result(), self.pos))) |
| 6805 code.put_gotref(self.py_result()) |
| 6806 for item in self.key_value_pairs: |
| 6807 item.generate_evaluation_code(code) |
| 6808 if self.type.is_pyobject: |
| 6809 if self.exclude_null_values: |
| 6810 code.putln('if (%s) {' % item.value.py_result()) |
| 6811 code.put_error_if_neg(self.pos, |
| 6812 "PyDict_SetItem(%s, %s, %s)" % ( |
| 6813 self.result(), |
| 6814 item.key.py_result(), |
| 6815 item.value.py_result())) |
| 6816 if self.exclude_null_values: |
| 6817 code.putln('}') |
| 6818 else: |
| 6819 code.putln("%s.%s = %s;" % ( |
| 6820 self.result(), |
| 6821 item.key.value, |
| 6822 item.value.result())) |
| 6823 item.generate_disposal_code(code) |
| 6824 item.free_temps(code) |
| 6825 |
| 6826 def annotate(self, code): |
| 6827 for item in self.key_value_pairs: |
| 6828 item.annotate(code) |
| 6829 |
| 6830 class DictItemNode(ExprNode): |
| 6831 # Represents a single item in a DictNode |
| 6832 # |
| 6833 # key ExprNode |
| 6834 # value ExprNode |
| 6835 subexprs = ['key', 'value'] |
| 6836 |
| 6837 nogil_check = None # Parent DictNode takes care of it |
| 6838 |
| 6839 def calculate_constant_result(self): |
| 6840 self.constant_result = ( |
| 6841 self.key.constant_result, self.value.constant_result) |
| 6842 |
| 6843 def analyse_types(self, env): |
| 6844 self.key = self.key.analyse_types(env) |
| 6845 self.value = self.value.analyse_types(env) |
| 6846 self.key = self.key.coerce_to_pyobject(env) |
| 6847 self.value = self.value.coerce_to_pyobject(env) |
| 6848 return self |
| 6849 |
| 6850 def generate_evaluation_code(self, code): |
| 6851 self.key.generate_evaluation_code(code) |
| 6852 self.value.generate_evaluation_code(code) |
| 6853 |
| 6854 def generate_disposal_code(self, code): |
| 6855 self.key.generate_disposal_code(code) |
| 6856 self.value.generate_disposal_code(code) |
| 6857 |
| 6858 def free_temps(self, code): |
| 6859 self.key.free_temps(code) |
| 6860 self.value.free_temps(code) |
| 6861 |
| 6862 def __iter__(self): |
| 6863 return iter([self.key, self.value]) |
| 6864 |
| 6865 |
| 6866 class SortedDictKeysNode(ExprNode): |
| 6867 # build sorted list of dict keys, e.g. for dir() |
| 6868 subexprs = ['arg'] |
| 6869 |
| 6870 is_temp = True |
| 6871 |
| 6872 def __init__(self, arg): |
| 6873 ExprNode.__init__(self, arg.pos, arg=arg) |
| 6874 self.type = Builtin.list_type |
| 6875 |
| 6876 def analyse_types(self, env): |
| 6877 arg = self.arg.analyse_types(env) |
| 6878 if arg.type is Builtin.dict_type: |
| 6879 arg = arg.as_none_safe_node( |
| 6880 "'NoneType' object is not iterable") |
| 6881 self.arg = arg |
| 6882 return self |
| 6883 |
| 6884 def may_be_none(self): |
| 6885 return False |
| 6886 |
| 6887 def generate_result_code(self, code): |
| 6888 dict_result = self.arg.py_result() |
| 6889 if self.arg.type is Builtin.dict_type: |
| 6890 function = 'PyDict_Keys' |
| 6891 else: |
| 6892 function = 'PyMapping_Keys' |
| 6893 code.putln('%s = %s(%s); %s' % ( |
| 6894 self.result(), function, dict_result, |
| 6895 code.error_goto_if_null(self.result(), self.pos))) |
| 6896 code.put_gotref(self.py_result()) |
| 6897 code.put_error_if_neg( |
| 6898 self.pos, 'PyList_Sort(%s)' % self.py_result()) |
| 6899 |
| 6900 |
| 6901 class ModuleNameMixin(object): |
| 6902 def get_py_mod_name(self, code): |
| 6903 return code.get_py_string_const( |
| 6904 self.module_name, identifier=True) |
| 6905 |
| 6906 def get_py_qualified_name(self, code): |
| 6907 return code.get_py_string_const( |
| 6908 self.qualname, identifier=True) |
| 6909 |
| 6910 |
| 6911 class ClassNode(ExprNode, ModuleNameMixin): |
| 6912 # Helper class used in the implementation of Python |
| 6913 # class definitions. Constructs a class object given |
| 6914 # a name, tuple of bases and class dictionary. |
| 6915 # |
| 6916 # name EncodedString Name of the class |
| 6917 # bases ExprNode Base class tuple |
| 6918 # dict ExprNode Class dict (not owned by this node) |
| 6919 # doc ExprNode or None Doc string |
| 6920 # module_name EncodedString Name of defining module |
| 6921 |
| 6922 subexprs = ['bases', 'doc'] |
| 6923 |
| 6924 def analyse_types(self, env): |
| 6925 self.bases = self.bases.analyse_types(env) |
| 6926 if self.doc: |
| 6927 self.doc = self.doc.analyse_types(env) |
| 6928 self.doc = self.doc.coerce_to_pyobject(env) |
| 6929 self.type = py_object_type |
| 6930 self.is_temp = 1 |
| 6931 env.use_utility_code(UtilityCode.load_cached("CreateClass", "ObjectHandl
ing.c")) |
| 6932 return self |
| 6933 |
| 6934 def may_be_none(self): |
| 6935 return True |
| 6936 |
| 6937 gil_message = "Constructing Python class" |
| 6938 |
| 6939 def generate_result_code(self, code): |
| 6940 cname = code.intern_identifier(self.name) |
| 6941 |
| 6942 if self.doc: |
| 6943 code.put_error_if_neg(self.pos, |
| 6944 'PyDict_SetItem(%s, %s, %s)' % ( |
| 6945 self.dict.py_result(), |
| 6946 code.intern_identifier( |
| 6947 StringEncoding.EncodedString("__doc__")), |
| 6948 self.doc.py_result())) |
| 6949 py_mod_name = self.get_py_mod_name(code) |
| 6950 qualname = self.get_py_qualified_name(code) |
| 6951 code.putln( |
| 6952 '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % ( |
| 6953 self.result(), |
| 6954 self.bases.py_result(), |
| 6955 self.dict.py_result(), |
| 6956 cname, |
| 6957 qualname, |
| 6958 py_mod_name, |
| 6959 code.error_goto_if_null(self.result(), self.pos))) |
| 6960 code.put_gotref(self.py_result()) |
| 6961 |
| 6962 |
| 6963 class Py3ClassNode(ExprNode): |
| 6964 # Helper class used in the implementation of Python3+ |
| 6965 # class definitions. Constructs a class object given |
| 6966 # a name, tuple of bases and class dictionary. |
| 6967 # |
| 6968 # name EncodedString Name of the class |
| 6969 # dict ExprNode Class dict (not owned by this node) |
| 6970 # module_name EncodedString Name of defining module |
| 6971 # calculate_metaclass bool should call CalculateMetaclass() |
| 6972 # allow_py2_metaclass bool should look for Py2 metaclass |
| 6973 |
| 6974 subexprs = [] |
| 6975 |
| 6976 def analyse_types(self, env): |
| 6977 self.type = py_object_type |
| 6978 self.is_temp = 1 |
| 6979 return self |
| 6980 |
| 6981 def may_be_none(self): |
| 6982 return True |
| 6983 |
| 6984 gil_message = "Constructing Python class" |
| 6985 |
| 6986 def generate_result_code(self, code): |
| 6987 code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreat
e", "ObjectHandling.c")) |
| 6988 cname = code.intern_identifier(self.name) |
| 6989 if self.mkw: |
| 6990 mkw = self.mkw.py_result() |
| 6991 else: |
| 6992 mkw = 'NULL' |
| 6993 if self.metaclass: |
| 6994 metaclass = self.metaclass.result() |
| 6995 else: |
| 6996 metaclass = "((PyObject*)&__Pyx_DefaultClassType)" |
| 6997 code.putln( |
| 6998 '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % ( |
| 6999 self.result(), |
| 7000 metaclass, |
| 7001 cname, |
| 7002 self.bases.py_result(), |
| 7003 self.dict.py_result(), |
| 7004 mkw, |
| 7005 self.calculate_metaclass, |
| 7006 self.allow_py2_metaclass, |
| 7007 code.error_goto_if_null(self.result(), self.pos))) |
| 7008 code.put_gotref(self.py_result()) |
| 7009 |
| 7010 class KeywordArgsNode(ExprNode): |
| 7011 # Helper class for keyword arguments. |
| 7012 # |
| 7013 # starstar_arg DictNode |
| 7014 # keyword_args [DictItemNode] |
| 7015 |
| 7016 subexprs = ['starstar_arg', 'keyword_args'] |
| 7017 is_temp = 1 |
| 7018 type = dict_type |
| 7019 |
| 7020 def calculate_constant_result(self): |
| 7021 result = dict(self.starstar_arg.constant_result) |
| 7022 for item in self.keyword_args: |
| 7023 key, value = item.constant_result |
| 7024 if key in result: |
| 7025 raise ValueError("duplicate keyword argument found: %s" % key) |
| 7026 result[key] = value |
| 7027 self.constant_result = result |
| 7028 |
| 7029 def compile_time_value(self, denv): |
| 7030 result = self.starstar_arg.compile_time_value(denv) |
| 7031 pairs = [ (item.key.compile_time_value(denv), item.value.compile_time_va
lue(denv)) |
| 7032 for item in self.keyword_args ] |
| 7033 try: |
| 7034 result = dict(result) |
| 7035 for key, value in pairs: |
| 7036 if key in result: |
| 7037 raise ValueError("duplicate keyword argument found: %s" % ke
y) |
| 7038 result[key] = value |
| 7039 except Exception, e: |
| 7040 self.compile_time_value_error(e) |
| 7041 return result |
| 7042 |
| 7043 def type_dependencies(self, env): |
| 7044 return () |
| 7045 |
| 7046 def infer_type(self, env): |
| 7047 return dict_type |
| 7048 |
| 7049 def analyse_types(self, env): |
| 7050 arg = self.starstar_arg.analyse_types(env) |
| 7051 arg = arg.coerce_to_pyobject(env) |
| 7052 self.starstar_arg = arg.as_none_safe_node( |
| 7053 # FIXME: CPython's error message starts with the runtime function na
me |
| 7054 'argument after ** must be a mapping, not NoneType') |
| 7055 self.keyword_args = [ item.analyse_types(env) |
| 7056 for item in self.keyword_args ] |
| 7057 return self |
| 7058 |
| 7059 def may_be_none(self): |
| 7060 return False |
| 7061 |
| 7062 gil_message = "Constructing Python dict" |
| 7063 |
| 7064 def generate_evaluation_code(self, code): |
| 7065 code.mark_pos(self.pos) |
| 7066 self.allocate_temp_result(code) |
| 7067 self.starstar_arg.generate_evaluation_code(code) |
| 7068 if self.starstar_arg.type is not Builtin.dict_type: |
| 7069 # CPython supports calling functions with non-dicts, so do we |
| 7070 code.putln('if (likely(PyDict_Check(%s))) {' % |
| 7071 self.starstar_arg.py_result()) |
| 7072 if self.keyword_args: |
| 7073 code.putln( |
| 7074 "%s = PyDict_Copy(%s); %s" % ( |
| 7075 self.result(), |
| 7076 self.starstar_arg.py_result(), |
| 7077 code.error_goto_if_null(self.result(), self.pos))) |
| 7078 code.put_gotref(self.py_result()) |
| 7079 else: |
| 7080 code.putln("%s = %s;" % ( |
| 7081 self.result(), |
| 7082 self.starstar_arg.py_result())) |
| 7083 code.put_incref(self.result(), py_object_type) |
| 7084 if self.starstar_arg.type is not Builtin.dict_type: |
| 7085 code.putln('} else {') |
| 7086 code.putln( |
| 7087 "%s = PyObject_CallFunctionObjArgs(" |
| 7088 "(PyObject*)&PyDict_Type, %s, NULL); %s" % ( |
| 7089 self.result(), |
| 7090 self.starstar_arg.py_result(), |
| 7091 code.error_goto_if_null(self.result(), self.pos))) |
| 7092 code.put_gotref(self.py_result()) |
| 7093 code.putln('}') |
| 7094 self.starstar_arg.generate_disposal_code(code) |
| 7095 self.starstar_arg.free_temps(code) |
| 7096 |
| 7097 if not self.keyword_args: |
| 7098 return |
| 7099 |
| 7100 code.globalstate.use_utility_code( |
| 7101 UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c"
)) |
| 7102 for item in self.keyword_args: |
| 7103 item.generate_evaluation_code(code) |
| 7104 code.putln("if (unlikely(PyDict_GetItem(%s, %s))) {" % ( |
| 7105 self.result(), |
| 7106 item.key.py_result())) |
| 7107 # FIXME: find out function name at runtime! |
| 7108 code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % ( |
| 7109 item.key.py_result(), |
| 7110 code.error_goto(self.pos))) |
| 7111 code.putln("}") |
| 7112 code.put_error_if_neg(self.pos, |
| 7113 "PyDict_SetItem(%s, %s, %s)" % ( |
| 7114 self.result(), |
| 7115 item.key.py_result(), |
| 7116 item.value.py_result())) |
| 7117 item.generate_disposal_code(code) |
| 7118 item.free_temps(code) |
| 7119 |
| 7120 def annotate(self, code): |
| 7121 self.starstar_arg.annotate(code) |
| 7122 for item in self.keyword_args: |
| 7123 item.annotate(code) |
| 7124 |
| 7125 class PyClassMetaclassNode(ExprNode): |
| 7126 # Helper class holds Python3 metaclass object |
| 7127 # |
| 7128 # bases ExprNode Base class tuple (not owned by this node) |
| 7129 # mkw ExprNode Class keyword arguments (not owned by thi
s node) |
| 7130 |
| 7131 subexprs = [] |
| 7132 |
| 7133 def analyse_types(self, env): |
| 7134 self.type = py_object_type |
| 7135 self.is_temp = True |
| 7136 return self |
| 7137 |
| 7138 def may_be_none(self): |
| 7139 return True |
| 7140 |
| 7141 def generate_result_code(self, code): |
| 7142 if self.mkw: |
| 7143 code.globalstate.use_utility_code( |
| 7144 UtilityCode.load_cached("Py3MetaclassGet", "ObjectHandling.c")) |
| 7145 call = "__Pyx_Py3MetaclassGet(%s, %s)" % ( |
| 7146 self.bases.result(), |
| 7147 self.mkw.result()) |
| 7148 else: |
| 7149 code.globalstate.use_utility_code( |
| 7150 UtilityCode.load_cached("CalculateMetaclass", "ObjectHandling.c"
)) |
| 7151 call = "__Pyx_CalculateMetaclass(NULL, %s)" % ( |
| 7152 self.bases.result()) |
| 7153 code.putln( |
| 7154 "%s = %s; %s" % ( |
| 7155 self.result(), call, |
| 7156 code.error_goto_if_null(self.result(), self.pos))) |
| 7157 code.put_gotref(self.py_result()) |
| 7158 |
| 7159 class PyClassNamespaceNode(ExprNode, ModuleNameMixin): |
| 7160 # Helper class holds Python3 namespace object |
| 7161 # |
| 7162 # All this are not owned by this node |
| 7163 # metaclass ExprNode Metaclass object |
| 7164 # bases ExprNode Base class tuple |
| 7165 # mkw ExprNode Class keyword arguments |
| 7166 # doc ExprNode or None Doc string (owned) |
| 7167 |
| 7168 subexprs = ['doc'] |
| 7169 |
| 7170 def analyse_types(self, env): |
| 7171 if self.doc: |
| 7172 self.doc = self.doc.analyse_types(env) |
| 7173 self.doc = self.doc.coerce_to_pyobject(env) |
| 7174 self.type = py_object_type |
| 7175 self.is_temp = 1 |
| 7176 return self |
| 7177 |
| 7178 def may_be_none(self): |
| 7179 return True |
| 7180 |
| 7181 def generate_result_code(self, code): |
| 7182 cname = code.intern_identifier(self.name) |
| 7183 py_mod_name = self.get_py_mod_name(code) |
| 7184 qualname = self.get_py_qualified_name(code) |
| 7185 if self.doc: |
| 7186 doc_code = self.doc.result() |
| 7187 else: |
| 7188 doc_code = '(PyObject *) NULL' |
| 7189 if self.mkw: |
| 7190 mkw = self.mkw.py_result() |
| 7191 else: |
| 7192 mkw = '(PyObject *) NULL' |
| 7193 if self.metaclass: |
| 7194 metaclass = self.metaclass.result() |
| 7195 else: |
| 7196 metaclass = "(PyObject *) NULL" |
| 7197 code.putln( |
| 7198 "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % ( |
| 7199 self.result(), |
| 7200 metaclass, |
| 7201 self.bases.result(), |
| 7202 cname, |
| 7203 qualname, |
| 7204 mkw, |
| 7205 py_mod_name, |
| 7206 doc_code, |
| 7207 code.error_goto_if_null(self.result(), self.pos))) |
| 7208 code.put_gotref(self.py_result()) |
| 7209 |
| 7210 |
| 7211 class ClassCellInjectorNode(ExprNode): |
| 7212 # Initialize CyFunction.func_classobj |
| 7213 is_temp = True |
| 7214 type = py_object_type |
| 7215 subexprs = [] |
| 7216 is_active = False |
| 7217 |
| 7218 def analyse_expressions(self, env): |
| 7219 if self.is_active: |
| 7220 env.use_utility_code( |
| 7221 UtilityCode.load_cached("CyFunctionClassCell", "CythonFunction.c
")) |
| 7222 return self |
| 7223 |
| 7224 def generate_evaluation_code(self, code): |
| 7225 if self.is_active: |
| 7226 self.allocate_temp_result(code) |
| 7227 code.putln( |
| 7228 '%s = PyList_New(0); %s' % ( |
| 7229 self.result(), |
| 7230 code.error_goto_if_null(self.result(), self.pos))) |
| 7231 code.put_gotref(self.result()) |
| 7232 |
| 7233 def generate_injection_code(self, code, classobj_cname): |
| 7234 if self.is_active: |
| 7235 code.putln('__Pyx_CyFunction_InitClassCell(%s, %s);' % ( |
| 7236 self.result(), classobj_cname)) |
| 7237 |
| 7238 |
| 7239 class ClassCellNode(ExprNode): |
| 7240 # Class Cell for noargs super() |
| 7241 subexprs = [] |
| 7242 is_temp = True |
| 7243 is_generator = False |
| 7244 type = py_object_type |
| 7245 |
| 7246 def analyse_types(self, env): |
| 7247 return self |
| 7248 |
| 7249 def generate_result_code(self, code): |
| 7250 if not self.is_generator: |
| 7251 code.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % ( |
| 7252 self.result(), |
| 7253 Naming.self_cname)) |
| 7254 else: |
| 7255 code.putln('%s = %s->classobj;' % ( |
| 7256 self.result(), Naming.generator_cname)) |
| 7257 code.putln( |
| 7258 'if (!%s) { PyErr_SetString(PyExc_SystemError, ' |
| 7259 '"super(): empty __class__ cell"); %s }' % ( |
| 7260 self.result(), |
| 7261 code.error_goto(self.pos))) |
| 7262 code.put_incref(self.result(), py_object_type) |
| 7263 |
| 7264 |
| 7265 class BoundMethodNode(ExprNode): |
| 7266 # Helper class used in the implementation of Python |
| 7267 # class definitions. Constructs an bound method |
| 7268 # object from a class and a function. |
| 7269 # |
| 7270 # function ExprNode Function object |
| 7271 # self_object ExprNode self object |
| 7272 |
| 7273 subexprs = ['function'] |
| 7274 |
| 7275 def analyse_types(self, env): |
| 7276 self.function = self.function.analyse_types(env) |
| 7277 self.type = py_object_type |
| 7278 self.is_temp = 1 |
| 7279 return self |
| 7280 |
| 7281 gil_message = "Constructing a bound method" |
| 7282 |
| 7283 def generate_result_code(self, code): |
| 7284 code.putln( |
| 7285 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % ( |
| 7286 self.result(), |
| 7287 self.function.py_result(), |
| 7288 self.self_object.py_result(), |
| 7289 self.self_object.py_result(), |
| 7290 code.error_goto_if_null(self.result(), self.pos))) |
| 7291 code.put_gotref(self.py_result()) |
| 7292 |
| 7293 class UnboundMethodNode(ExprNode): |
| 7294 # Helper class used in the implementation of Python |
| 7295 # class definitions. Constructs an unbound method |
| 7296 # object from a class and a function. |
| 7297 # |
| 7298 # function ExprNode Function object |
| 7299 |
| 7300 type = py_object_type |
| 7301 is_temp = 1 |
| 7302 |
| 7303 subexprs = ['function'] |
| 7304 |
| 7305 def analyse_types(self, env): |
| 7306 self.function = self.function.analyse_types(env) |
| 7307 return self |
| 7308 |
| 7309 def may_be_none(self): |
| 7310 return False |
| 7311 |
| 7312 gil_message = "Constructing an unbound method" |
| 7313 |
| 7314 def generate_result_code(self, code): |
| 7315 class_cname = code.pyclass_stack[-1].classobj.result() |
| 7316 code.putln( |
| 7317 "%s = PyMethod_New(%s, 0, %s); %s" % ( |
| 7318 self.result(), |
| 7319 self.function.py_result(), |
| 7320 class_cname, |
| 7321 code.error_goto_if_null(self.result(), self.pos))) |
| 7322 code.put_gotref(self.py_result()) |
| 7323 |
| 7324 |
| 7325 class PyCFunctionNode(ExprNode, ModuleNameMixin): |
| 7326 # Helper class used in the implementation of Python |
| 7327 # functions. Constructs a PyCFunction object |
| 7328 # from a PyMethodDef struct. |
| 7329 # |
| 7330 # pymethdef_cname string PyMethodDef structure |
| 7331 # self_object ExprNode or None |
| 7332 # binding bool |
| 7333 # def_node DefNode the Python function node |
| 7334 # module_name EncodedString Name of defining module |
| 7335 # code_object CodeObjectNode the PyCodeObject creator node |
| 7336 |
| 7337 subexprs = ['code_object', 'defaults_tuple', 'defaults_kwdict', |
| 7338 'annotations_dict'] |
| 7339 |
| 7340 self_object = None |
| 7341 code_object = None |
| 7342 binding = False |
| 7343 def_node = None |
| 7344 defaults = None |
| 7345 defaults_struct = None |
| 7346 defaults_pyobjects = 0 |
| 7347 defaults_tuple = None |
| 7348 defaults_kwdict = None |
| 7349 annotations_dict = None |
| 7350 |
| 7351 type = py_object_type |
| 7352 is_temp = 1 |
| 7353 |
| 7354 specialized_cpdefs = None |
| 7355 is_specialization = False |
| 7356 |
| 7357 @classmethod |
| 7358 def from_defnode(cls, node, binding): |
| 7359 return cls(node.pos, |
| 7360 def_node=node, |
| 7361 pymethdef_cname=node.entry.pymethdef_cname, |
| 7362 binding=binding or node.specialized_cpdefs, |
| 7363 specialized_cpdefs=node.specialized_cpdefs, |
| 7364 code_object=CodeObjectNode(node)) |
| 7365 |
| 7366 def analyse_types(self, env): |
| 7367 if self.binding: |
| 7368 self.analyse_default_args(env) |
| 7369 return self |
| 7370 |
| 7371 def analyse_default_args(self, env): |
| 7372 """ |
| 7373 Handle non-literal function's default arguments. |
| 7374 """ |
| 7375 nonliteral_objects = [] |
| 7376 nonliteral_other = [] |
| 7377 default_args = [] |
| 7378 default_kwargs = [] |
| 7379 annotations = [] |
| 7380 for arg in self.def_node.args: |
| 7381 if arg.default: |
| 7382 if not arg.default.is_literal: |
| 7383 arg.is_dynamic = True |
| 7384 if arg.type.is_pyobject: |
| 7385 nonliteral_objects.append(arg) |
| 7386 else: |
| 7387 nonliteral_other.append(arg) |
| 7388 else: |
| 7389 arg.default = DefaultLiteralArgNode(arg.pos, arg.default) |
| 7390 if arg.kw_only: |
| 7391 default_kwargs.append(arg) |
| 7392 else: |
| 7393 default_args.append(arg) |
| 7394 if arg.annotation: |
| 7395 arg.annotation = arg.annotation.analyse_types(env) |
| 7396 if not arg.annotation.type.is_pyobject: |
| 7397 arg.annotation = arg.annotation.coerce_to_pyobject(env) |
| 7398 annotations.append((arg.pos, arg.name, arg.annotation)) |
| 7399 if self.def_node.return_type_annotation: |
| 7400 annotations.append((self.def_node.return_type_annotation.pos, |
| 7401 StringEncoding.EncodedString("return"), |
| 7402 self.def_node.return_type_annotation)) |
| 7403 |
| 7404 if nonliteral_objects or nonliteral_other: |
| 7405 module_scope = env.global_scope() |
| 7406 cname = module_scope.next_id(Naming.defaults_struct_prefix) |
| 7407 scope = Symtab.StructOrUnionScope(cname) |
| 7408 self.defaults = [] |
| 7409 for arg in nonliteral_objects: |
| 7410 entry = scope.declare_var(arg.name, arg.type, None, |
| 7411 Naming.arg_prefix + arg.name, |
| 7412 allow_pyobject=True) |
| 7413 self.defaults.append((arg, entry)) |
| 7414 for arg in nonliteral_other: |
| 7415 entry = scope.declare_var(arg.name, arg.type, None, |
| 7416 Naming.arg_prefix + arg.name, |
| 7417 allow_pyobject=False) |
| 7418 self.defaults.append((arg, entry)) |
| 7419 entry = module_scope.declare_struct_or_union( |
| 7420 None, 'struct', scope, 1, None, cname=cname) |
| 7421 self.defaults_struct = scope |
| 7422 self.defaults_pyobjects = len(nonliteral_objects) |
| 7423 for arg, entry in self.defaults: |
| 7424 arg.default_value = '%s->%s' % ( |
| 7425 Naming.dynamic_args_cname, entry.cname) |
| 7426 self.def_node.defaults_struct = self.defaults_struct.name |
| 7427 |
| 7428 if default_args or default_kwargs: |
| 7429 if self.defaults_struct is None: |
| 7430 if default_args: |
| 7431 defaults_tuple = TupleNode(self.pos, args=[ |
| 7432 arg.default for arg in default_args]) |
| 7433 self.defaults_tuple = defaults_tuple.analyse_types(env) |
| 7434 if default_kwargs: |
| 7435 defaults_kwdict = DictNode(self.pos, key_value_pairs=[ |
| 7436 DictItemNode( |
| 7437 arg.pos, |
| 7438 key=IdentifierStringNode(arg.pos, value=arg.name), |
| 7439 value=arg.default) |
| 7440 for arg in default_kwargs]) |
| 7441 self.defaults_kwdict = defaults_kwdict.analyse_types(env) |
| 7442 else: |
| 7443 if default_args: |
| 7444 defaults_tuple = DefaultsTupleNode( |
| 7445 self.pos, default_args, self.defaults_struct) |
| 7446 else: |
| 7447 defaults_tuple = NoneNode(self.pos) |
| 7448 if default_kwargs: |
| 7449 defaults_kwdict = DefaultsKwDictNode( |
| 7450 self.pos, default_kwargs, self.defaults_struct) |
| 7451 else: |
| 7452 defaults_kwdict = NoneNode(self.pos) |
| 7453 |
| 7454 defaults_getter = Nodes.DefNode( |
| 7455 self.pos, args=[], star_arg=None, starstar_arg=None, |
| 7456 body=Nodes.ReturnStatNode( |
| 7457 self.pos, return_type=py_object_type, |
| 7458 value=TupleNode( |
| 7459 self.pos, args=[defaults_tuple, defaults_kwdict])), |
| 7460 decorators=None, |
| 7461 name=StringEncoding.EncodedString("__defaults__")) |
| 7462 defaults_getter.analyse_declarations(env) |
| 7463 defaults_getter = defaults_getter.analyse_expressions(env) |
| 7464 defaults_getter.body = defaults_getter.body.analyse_expressions( |
| 7465 defaults_getter.local_scope) |
| 7466 defaults_getter.py_wrapper_required = False |
| 7467 defaults_getter.pymethdef_required = False |
| 7468 self.def_node.defaults_getter = defaults_getter |
| 7469 if annotations: |
| 7470 annotations_dict = DictNode(self.pos, key_value_pairs=[ |
| 7471 DictItemNode( |
| 7472 pos, key=IdentifierStringNode(pos, value=name), |
| 7473 value=value) |
| 7474 for pos, name, value in annotations]) |
| 7475 self.annotations_dict = annotations_dict.analyse_types(env) |
| 7476 |
| 7477 def may_be_none(self): |
| 7478 return False |
| 7479 |
| 7480 gil_message = "Constructing Python function" |
| 7481 |
| 7482 def self_result_code(self): |
| 7483 if self.self_object is None: |
| 7484 self_result = "NULL" |
| 7485 else: |
| 7486 self_result = self.self_object.py_result() |
| 7487 return self_result |
| 7488 |
| 7489 def generate_result_code(self, code): |
| 7490 if self.binding: |
| 7491 self.generate_cyfunction_code(code) |
| 7492 else: |
| 7493 self.generate_pycfunction_code(code) |
| 7494 |
| 7495 def generate_pycfunction_code(self, code): |
| 7496 py_mod_name = self.get_py_mod_name(code) |
| 7497 code.putln( |
| 7498 '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % ( |
| 7499 self.result(), |
| 7500 self.pymethdef_cname, |
| 7501 self.self_result_code(), |
| 7502 py_mod_name, |
| 7503 code.error_goto_if_null(self.result(), self.pos))) |
| 7504 |
| 7505 code.put_gotref(self.py_result()) |
| 7506 |
| 7507 def generate_cyfunction_code(self, code): |
| 7508 if self.specialized_cpdefs: |
| 7509 def_node = self.specialized_cpdefs[0] |
| 7510 else: |
| 7511 def_node = self.def_node |
| 7512 |
| 7513 if self.specialized_cpdefs or self.is_specialization: |
| 7514 code.globalstate.use_utility_code( |
| 7515 UtilityCode.load_cached("FusedFunction", "CythonFunction.c")) |
| 7516 constructor = "__pyx_FusedFunction_NewEx" |
| 7517 else: |
| 7518 code.globalstate.use_utility_code( |
| 7519 UtilityCode.load_cached("CythonFunction", "CythonFunction.c")) |
| 7520 constructor = "__Pyx_CyFunction_NewEx" |
| 7521 |
| 7522 if self.code_object: |
| 7523 code_object_result = self.code_object.py_result() |
| 7524 else: |
| 7525 code_object_result = 'NULL' |
| 7526 |
| 7527 flags = [] |
| 7528 if def_node.is_staticmethod: |
| 7529 flags.append('__Pyx_CYFUNCTION_STATICMETHOD') |
| 7530 elif def_node.is_classmethod: |
| 7531 flags.append('__Pyx_CYFUNCTION_CLASSMETHOD') |
| 7532 |
| 7533 if def_node.local_scope.parent_scope.is_c_class_scope: |
| 7534 flags.append('__Pyx_CYFUNCTION_CCLASS') |
| 7535 |
| 7536 if flags: |
| 7537 flags = ' | '.join(flags) |
| 7538 else: |
| 7539 flags = '0' |
| 7540 |
| 7541 code.putln( |
| 7542 '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % ( |
| 7543 self.result(), |
| 7544 constructor, |
| 7545 self.pymethdef_cname, |
| 7546 flags, |
| 7547 self.get_py_qualified_name(code), |
| 7548 self.self_result_code(), |
| 7549 self.get_py_mod_name(code), |
| 7550 "PyModule_GetDict(%s)" % Naming.module_cname, |
| 7551 code_object_result, |
| 7552 code.error_goto_if_null(self.result(), self.pos))) |
| 7553 |
| 7554 code.put_gotref(self.py_result()) |
| 7555 |
| 7556 if def_node.requires_classobj: |
| 7557 assert code.pyclass_stack, "pyclass_stack is empty" |
| 7558 class_node = code.pyclass_stack[-1] |
| 7559 code.put_incref(self.py_result(), py_object_type) |
| 7560 code.putln( |
| 7561 'PyList_Append(%s, %s);' % ( |
| 7562 class_node.class_cell.result(), |
| 7563 self.result())) |
| 7564 code.put_giveref(self.py_result()) |
| 7565 |
| 7566 if self.defaults: |
| 7567 code.putln( |
| 7568 'if (!__Pyx_CyFunction_InitDefaults(%s, sizeof(%s), %d)) %s' % ( |
| 7569 self.result(), self.defaults_struct.name, |
| 7570 self.defaults_pyobjects, code.error_goto(self.pos))) |
| 7571 defaults = '__Pyx_CyFunction_Defaults(%s, %s)' % ( |
| 7572 self.defaults_struct.name, self.result()) |
| 7573 for arg, entry in self.defaults: |
| 7574 arg.generate_assignment_code(code, target='%s->%s' % ( |
| 7575 defaults, entry.cname)) |
| 7576 |
| 7577 if self.defaults_tuple: |
| 7578 code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % ( |
| 7579 self.result(), self.defaults_tuple.py_result())) |
| 7580 if self.defaults_kwdict: |
| 7581 code.putln('__Pyx_CyFunction_SetDefaultsKwDict(%s, %s);' % ( |
| 7582 self.result(), self.defaults_kwdict.py_result())) |
| 7583 if def_node.defaults_getter: |
| 7584 code.putln('__Pyx_CyFunction_SetDefaultsGetter(%s, %s);' % ( |
| 7585 self.result(), def_node.defaults_getter.entry.pyfunc_cname)) |
| 7586 if self.annotations_dict: |
| 7587 code.putln('__Pyx_CyFunction_SetAnnotationsDict(%s, %s);' % ( |
| 7588 self.result(), self.annotations_dict.py_result())) |
| 7589 |
| 7590 |
| 7591 class InnerFunctionNode(PyCFunctionNode): |
| 7592 # Special PyCFunctionNode that depends on a closure class |
| 7593 # |
| 7594 |
| 7595 binding = True |
| 7596 needs_self_code = True |
| 7597 |
| 7598 def self_result_code(self): |
| 7599 if self.needs_self_code: |
| 7600 return "((PyObject*)%s)" % Naming.cur_scope_cname |
| 7601 return "NULL" |
| 7602 |
| 7603 |
| 7604 class CodeObjectNode(ExprNode): |
| 7605 # Create a PyCodeObject for a CyFunction instance. |
| 7606 # |
| 7607 # def_node DefNode the Python function node |
| 7608 # varnames TupleNode a tuple with all local variable names |
| 7609 |
| 7610 subexprs = ['varnames'] |
| 7611 is_temp = False |
| 7612 |
| 7613 def __init__(self, def_node): |
| 7614 ExprNode.__init__(self, def_node.pos, def_node=def_node) |
| 7615 args = list(def_node.args) |
| 7616 # if we have args/kwargs, then the first two in var_entries are those |
| 7617 local_vars = [arg for arg in def_node.local_scope.var_entries if arg.nam
e] |
| 7618 self.varnames = TupleNode( |
| 7619 def_node.pos, |
| 7620 args=[IdentifierStringNode(arg.pos, value=arg.name) |
| 7621 for arg in args + local_vars], |
| 7622 is_temp=0, |
| 7623 is_literal=1) |
| 7624 |
| 7625 def may_be_none(self): |
| 7626 return False |
| 7627 |
| 7628 def calculate_result_code(self): |
| 7629 return self.result_code |
| 7630 |
| 7631 def generate_result_code(self, code): |
| 7632 self.result_code = code.get_py_const(py_object_type, 'codeobj', cleanup_
level=2) |
| 7633 |
| 7634 code = code.get_cached_constants_writer() |
| 7635 code.mark_pos(self.pos) |
| 7636 func = self.def_node |
| 7637 func_name = code.get_py_string_const( |
| 7638 func.name, identifier=True, is_str=False, unicode_value=func.name) |
| 7639 # FIXME: better way to get the module file path at module init time? Enc
oding to use? |
| 7640 file_path = StringEncoding.BytesLiteral(func.pos[0].get_filenametable_en
try().encode('utf8')) |
| 7641 file_path_const = code.get_py_string_const(file_path, identifier=False,
is_str=True) |
| 7642 |
| 7643 flags = [] |
| 7644 if self.def_node.star_arg: |
| 7645 flags.append('CO_VARARGS') |
| 7646 if self.def_node.starstar_arg: |
| 7647 flags.append('CO_VARKEYWORDS') |
| 7648 |
| 7649 code.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, %s, %s, %s,
%s, %s, %s, %s, %s, %s, %d, %s); %s" % ( |
| 7650 self.result_code, |
| 7651 len(func.args) - func.num_kwonly_args, # argcount |
| 7652 func.num_kwonly_args, # kwonlyargcount (Py3 only) |
| 7653 len(self.varnames.args), # nlocals |
| 7654 '|'.join(flags) or '0', # flags |
| 7655 Naming.empty_bytes, # code |
| 7656 Naming.empty_tuple, # consts |
| 7657 Naming.empty_tuple, # names (FIXME) |
| 7658 self.varnames.result(), # varnames |
| 7659 Naming.empty_tuple, # freevars (FIXME) |
| 7660 Naming.empty_tuple, # cellvars (FIXME) |
| 7661 file_path_const, # filename |
| 7662 func_name, # name |
| 7663 self.pos[1], # firstlineno |
| 7664 Naming.empty_bytes, # lnotab |
| 7665 code.error_goto_if_null(self.result_code, self.pos), |
| 7666 )) |
| 7667 |
| 7668 |
| 7669 class DefaultLiteralArgNode(ExprNode): |
| 7670 # CyFunction's literal argument default value |
| 7671 # |
| 7672 # Evaluate literal only once. |
| 7673 |
| 7674 subexprs = [] |
| 7675 is_literal = True |
| 7676 is_temp = False |
| 7677 |
| 7678 def __init__(self, pos, arg): |
| 7679 super(DefaultLiteralArgNode, self).__init__(pos) |
| 7680 self.arg = arg |
| 7681 self.type = self.arg.type |
| 7682 self.evaluated = False |
| 7683 |
| 7684 def analyse_types(self, env): |
| 7685 return self |
| 7686 |
| 7687 def generate_result_code(self, code): |
| 7688 pass |
| 7689 |
| 7690 def generate_evaluation_code(self, code): |
| 7691 if not self.evaluated: |
| 7692 self.arg.generate_evaluation_code(code) |
| 7693 self.evaluated = True |
| 7694 |
| 7695 def result(self): |
| 7696 return self.type.cast_code(self.arg.result()) |
| 7697 |
| 7698 |
| 7699 class DefaultNonLiteralArgNode(ExprNode): |
| 7700 # CyFunction's non-literal argument default value |
| 7701 |
| 7702 subexprs = [] |
| 7703 |
| 7704 def __init__(self, pos, arg, defaults_struct): |
| 7705 super(DefaultNonLiteralArgNode, self).__init__(pos) |
| 7706 self.arg = arg |
| 7707 self.defaults_struct = defaults_struct |
| 7708 |
| 7709 def analyse_types(self, env): |
| 7710 self.type = self.arg.type |
| 7711 self.is_temp = False |
| 7712 return self |
| 7713 |
| 7714 def generate_result_code(self, code): |
| 7715 pass |
| 7716 |
| 7717 def result(self): |
| 7718 return '__Pyx_CyFunction_Defaults(%s, %s)->%s' % ( |
| 7719 self.defaults_struct.name, Naming.self_cname, |
| 7720 self.defaults_struct.lookup(self.arg.name).cname) |
| 7721 |
| 7722 |
| 7723 class DefaultsTupleNode(TupleNode): |
| 7724 # CyFunction's __defaults__ tuple |
| 7725 |
| 7726 def __init__(self, pos, defaults, defaults_struct): |
| 7727 args = [] |
| 7728 for arg in defaults: |
| 7729 if not arg.default.is_literal: |
| 7730 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) |
| 7731 else: |
| 7732 arg = arg.default |
| 7733 args.append(arg) |
| 7734 super(DefaultsTupleNode, self).__init__(pos, args=args) |
| 7735 |
| 7736 |
| 7737 class DefaultsKwDictNode(DictNode): |
| 7738 # CyFunction's __kwdefaults__ dict |
| 7739 |
| 7740 def __init__(self, pos, defaults, defaults_struct): |
| 7741 items = [] |
| 7742 for arg in defaults: |
| 7743 name = IdentifierStringNode(arg.pos, value=arg.name) |
| 7744 if not arg.default.is_literal: |
| 7745 arg = DefaultNonLiteralArgNode(pos, arg, defaults_struct) |
| 7746 else: |
| 7747 arg = arg.default |
| 7748 items.append(DictItemNode(arg.pos, key=name, value=arg)) |
| 7749 super(DefaultsKwDictNode, self).__init__(pos, key_value_pairs=items) |
| 7750 |
| 7751 |
| 7752 class LambdaNode(InnerFunctionNode): |
| 7753 # Lambda expression node (only used as a function reference) |
| 7754 # |
| 7755 # args [CArgDeclNode] formal arguments |
| 7756 # star_arg PyArgDeclNode or None * argument |
| 7757 # starstar_arg PyArgDeclNode or None ** argument |
| 7758 # lambda_name string a module-globally unique lambda name |
| 7759 # result_expr ExprNode |
| 7760 # def_node DefNode the underlying function 'def' node |
| 7761 |
| 7762 child_attrs = ['def_node'] |
| 7763 |
| 7764 name = StringEncoding.EncodedString('<lambda>') |
| 7765 |
| 7766 def analyse_declarations(self, env): |
| 7767 self.def_node.no_assignment_synthesis = True |
| 7768 self.def_node.pymethdef_required = True |
| 7769 self.def_node.analyse_declarations(env) |
| 7770 self.def_node.is_cyfunction = True |
| 7771 self.pymethdef_cname = self.def_node.entry.pymethdef_cname |
| 7772 env.add_lambda_def(self.def_node) |
| 7773 |
| 7774 def analyse_types(self, env): |
| 7775 self.def_node = self.def_node.analyse_expressions(env) |
| 7776 return super(LambdaNode, self).analyse_types(env) |
| 7777 |
| 7778 def generate_result_code(self, code): |
| 7779 self.def_node.generate_execution_code(code) |
| 7780 super(LambdaNode, self).generate_result_code(code) |
| 7781 |
| 7782 |
| 7783 class GeneratorExpressionNode(LambdaNode): |
| 7784 # A generator expression, e.g. (i for i in range(10)) |
| 7785 # |
| 7786 # Result is a generator. |
| 7787 # |
| 7788 # loop ForStatNode the for-loop, containing a YieldExprNode |
| 7789 # def_node DefNode the underlying generator 'def' node |
| 7790 |
| 7791 name = StringEncoding.EncodedString('genexpr') |
| 7792 binding = False |
| 7793 |
| 7794 def analyse_declarations(self, env): |
| 7795 super(GeneratorExpressionNode, self).analyse_declarations(env) |
| 7796 # No pymethdef required |
| 7797 self.def_node.pymethdef_required = False |
| 7798 self.def_node.py_wrapper_required = False |
| 7799 self.def_node.is_cyfunction = False |
| 7800 # Force genexpr signature |
| 7801 self.def_node.entry.signature = TypeSlots.pyfunction_noargs |
| 7802 |
| 7803 def generate_result_code(self, code): |
| 7804 code.putln( |
| 7805 '%s = %s(%s); %s' % ( |
| 7806 self.result(), |
| 7807 self.def_node.entry.pyfunc_cname, |
| 7808 self.self_result_code(), |
| 7809 code.error_goto_if_null(self.result(), self.pos))) |
| 7810 code.put_gotref(self.py_result()) |
| 7811 |
| 7812 |
| 7813 class YieldExprNode(ExprNode): |
| 7814 # Yield expression node |
| 7815 # |
| 7816 # arg ExprNode the value to return from the generator |
| 7817 # label_num integer yield label number |
| 7818 # is_yield_from boolean is a YieldFromExprNode to delegate to another gener
ator |
| 7819 |
| 7820 subexprs = ['arg'] |
| 7821 type = py_object_type |
| 7822 label_num = 0 |
| 7823 is_yield_from = False |
| 7824 |
| 7825 def analyse_types(self, env): |
| 7826 if not self.label_num: |
| 7827 error(self.pos, "'yield' not supported here") |
| 7828 self.is_temp = 1 |
| 7829 if self.arg is not None: |
| 7830 self.arg = self.arg.analyse_types(env) |
| 7831 if not self.arg.type.is_pyobject: |
| 7832 self.coerce_yield_argument(env) |
| 7833 return self |
| 7834 |
| 7835 def coerce_yield_argument(self, env): |
| 7836 self.arg = self.arg.coerce_to_pyobject(env) |
| 7837 |
| 7838 def generate_evaluation_code(self, code): |
| 7839 if self.arg: |
| 7840 self.arg.generate_evaluation_code(code) |
| 7841 self.arg.make_owned_reference(code) |
| 7842 code.putln( |
| 7843 "%s = %s;" % ( |
| 7844 Naming.retval_cname, |
| 7845 self.arg.result_as(py_object_type))) |
| 7846 self.arg.generate_post_assignment_code(code) |
| 7847 self.arg.free_temps(code) |
| 7848 else: |
| 7849 code.put_init_to_py_none(Naming.retval_cname, py_object_type) |
| 7850 self.generate_yield_code(code) |
| 7851 |
| 7852 def generate_yield_code(self, code): |
| 7853 """ |
| 7854 Generate the code to return the argument in 'Naming.retval_cname' |
| 7855 and to continue at the yield label. |
| 7856 """ |
| 7857 label_num, label_name = code.new_yield_label() |
| 7858 code.use_label(label_name) |
| 7859 |
| 7860 saved = [] |
| 7861 code.funcstate.closure_temps.reset() |
| 7862 for cname, type, manage_ref in code.funcstate.temps_in_use(): |
| 7863 save_cname = code.funcstate.closure_temps.allocate_temp(type) |
| 7864 saved.append((cname, save_cname, type)) |
| 7865 if type.is_pyobject: |
| 7866 code.put_xgiveref(cname) |
| 7867 code.putln('%s->%s = %s;' % (Naming.cur_scope_cname, save_cname, cna
me)) |
| 7868 |
| 7869 code.put_xgiveref(Naming.retval_cname) |
| 7870 code.put_finish_refcount_context() |
| 7871 code.putln("/* return from generator, yielding value */") |
| 7872 code.putln("%s->resume_label = %d;" % ( |
| 7873 Naming.generator_cname, label_num)) |
| 7874 code.putln("return %s;" % Naming.retval_cname) |
| 7875 |
| 7876 code.put_label(label_name) |
| 7877 for cname, save_cname, type in saved: |
| 7878 code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cna
me)) |
| 7879 if type.is_pyobject: |
| 7880 code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname)) |
| 7881 code.put_xgotref(cname) |
| 7882 code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos)) |
| 7883 if self.result_is_used: |
| 7884 self.allocate_temp_result(code) |
| 7885 code.put('%s = %s; ' % (self.result(), Naming.sent_value_cname)) |
| 7886 code.put_incref(self.result(), py_object_type) |
| 7887 |
| 7888 |
| 7889 class YieldFromExprNode(YieldExprNode): |
| 7890 # "yield from GEN" expression |
| 7891 is_yield_from = True |
| 7892 |
| 7893 def coerce_yield_argument(self, env): |
| 7894 if not self.arg.type.is_string: |
| 7895 # FIXME: support C arrays and C++ iterators? |
| 7896 error(self.pos, "yielding from non-Python object not supported") |
| 7897 self.arg = self.arg.coerce_to_pyobject(env) |
| 7898 |
| 7899 def generate_evaluation_code(self, code): |
| 7900 code.globalstate.use_utility_code(UtilityCode.load_cached("YieldFrom", "
Generator.c")) |
| 7901 |
| 7902 self.arg.generate_evaluation_code(code) |
| 7903 code.putln("%s = __Pyx_Generator_Yield_From(%s, %s);" % ( |
| 7904 Naming.retval_cname, |
| 7905 Naming.generator_cname, |
| 7906 self.arg.result_as(py_object_type))) |
| 7907 self.arg.generate_disposal_code(code) |
| 7908 self.arg.free_temps(code) |
| 7909 code.put_xgotref(Naming.retval_cname) |
| 7910 |
| 7911 code.putln("if (likely(%s)) {" % Naming.retval_cname) |
| 7912 self.generate_yield_code(code) |
| 7913 code.putln("} else {") |
| 7914 # either error or sub-generator has normally terminated: return value =>
node result |
| 7915 if self.result_is_used: |
| 7916 # YieldExprNode has allocated the result temp for us |
| 7917 code.putln("%s = NULL;" % self.result()) |
| 7918 code.putln("if (unlikely(__Pyx_PyGen_FetchStopIterationValue(&%s) <
0)) %s" % ( |
| 7919 self.result(), |
| 7920 code.error_goto(self.pos))) |
| 7921 code.put_gotref(self.result()) |
| 7922 else: |
| 7923 code.putln("PyObject* exc_type = PyErr_Occurred();") |
| 7924 code.putln("if (exc_type) {") |
| 7925 code.putln("if (likely(exc_type == PyExc_StopIteration ||" |
| 7926 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIterati
on))) PyErr_Clear();") |
| 7927 code.putln("else %s" % code.error_goto(self.pos)) |
| 7928 code.putln("}") |
| 7929 code.putln("}") |
| 7930 |
| 7931 class GlobalsExprNode(AtomicExprNode): |
| 7932 type = dict_type |
| 7933 is_temp = 1 |
| 7934 |
| 7935 def analyse_types(self, env): |
| 7936 env.use_utility_code(Builtin.globals_utility_code) |
| 7937 return self |
| 7938 |
| 7939 gil_message = "Constructing globals dict" |
| 7940 |
| 7941 def may_be_none(self): |
| 7942 return False |
| 7943 |
| 7944 def generate_result_code(self, code): |
| 7945 code.putln('%s = __Pyx_Globals(); %s' % ( |
| 7946 self.result(), |
| 7947 code.error_goto_if_null(self.result(), self.pos))) |
| 7948 code.put_gotref(self.result()) |
| 7949 |
| 7950 |
| 7951 class LocalsDictItemNode(DictItemNode): |
| 7952 def analyse_types(self, env): |
| 7953 self.key = self.key.analyse_types(env) |
| 7954 self.value = self.value.analyse_types(env) |
| 7955 self.key = self.key.coerce_to_pyobject(env) |
| 7956 if self.value.type.can_coerce_to_pyobject(env): |
| 7957 self.value = self.value.coerce_to_pyobject(env) |
| 7958 else: |
| 7959 self.value = None |
| 7960 return self |
| 7961 |
| 7962 |
| 7963 class FuncLocalsExprNode(DictNode): |
| 7964 def __init__(self, pos, env): |
| 7965 local_vars = sorted([ |
| 7966 entry.name for entry in env.entries.values() if entry.name]) |
| 7967 items = [LocalsDictItemNode( |
| 7968 pos, key=IdentifierStringNode(pos, value=var), |
| 7969 value=NameNode(pos, name=var, allow_null=True)) |
| 7970 for var in local_vars] |
| 7971 DictNode.__init__(self, pos, key_value_pairs=items, |
| 7972 exclude_null_values=True) |
| 7973 |
| 7974 def analyse_types(self, env): |
| 7975 node = super(FuncLocalsExprNode, self).analyse_types(env) |
| 7976 node.key_value_pairs = [ i for i in node.key_value_pairs |
| 7977 if i.value is not None ] |
| 7978 return node |
| 7979 |
| 7980 |
| 7981 class PyClassLocalsExprNode(AtomicExprNode): |
| 7982 def __init__(self, pos, pyclass_dict): |
| 7983 AtomicExprNode.__init__(self, pos) |
| 7984 self.pyclass_dict = pyclass_dict |
| 7985 |
| 7986 def analyse_types(self, env): |
| 7987 self.type = self.pyclass_dict.type |
| 7988 self.is_temp = False |
| 7989 return self |
| 7990 |
| 7991 def may_be_none(self): |
| 7992 return False |
| 7993 |
| 7994 def result(self): |
| 7995 return self.pyclass_dict.result() |
| 7996 |
| 7997 def generate_result_code(self, code): |
| 7998 pass |
| 7999 |
| 8000 |
| 8001 def LocalsExprNode(pos, scope_node, env): |
| 8002 if env.is_module_scope: |
| 8003 return GlobalsExprNode(pos) |
| 8004 if env.is_py_class_scope: |
| 8005 return PyClassLocalsExprNode(pos, scope_node.dict) |
| 8006 return FuncLocalsExprNode(pos, env) |
| 8007 |
| 8008 |
| 8009 #------------------------------------------------------------------- |
| 8010 # |
| 8011 # Unary operator nodes |
| 8012 # |
| 8013 #------------------------------------------------------------------- |
| 8014 |
| 8015 compile_time_unary_operators = { |
| 8016 'not': operator.not_, |
| 8017 '~': operator.inv, |
| 8018 '-': operator.neg, |
| 8019 '+': operator.pos, |
| 8020 } |
| 8021 |
| 8022 class UnopNode(ExprNode): |
| 8023 # operator string |
| 8024 # operand ExprNode |
| 8025 # |
| 8026 # Processing during analyse_expressions phase: |
| 8027 # |
| 8028 # analyse_c_operation |
| 8029 # Called when the operand is not a pyobject. |
| 8030 # - Check operand type and coerce if needed. |
| 8031 # - Determine result type and result code fragment. |
| 8032 # - Allocate temporary for result if needed. |
| 8033 |
| 8034 subexprs = ['operand'] |
| 8035 infix = True |
| 8036 |
| 8037 def calculate_constant_result(self): |
| 8038 func = compile_time_unary_operators[self.operator] |
| 8039 self.constant_result = func(self.operand.constant_result) |
| 8040 |
| 8041 def compile_time_value(self, denv): |
| 8042 func = compile_time_unary_operators.get(self.operator) |
| 8043 if not func: |
| 8044 error(self.pos, |
| 8045 "Unary '%s' not supported in compile-time expression" |
| 8046 % self.operator) |
| 8047 operand = self.operand.compile_time_value(denv) |
| 8048 try: |
| 8049 return func(operand) |
| 8050 except Exception, e: |
| 8051 self.compile_time_value_error(e) |
| 8052 |
| 8053 def infer_type(self, env): |
| 8054 operand_type = self.operand.infer_type(env) |
| 8055 if operand_type.is_cpp_class or operand_type.is_ptr: |
| 8056 cpp_type = operand_type.find_cpp_operation_type(self.operator) |
| 8057 if cpp_type is not None: |
| 8058 return cpp_type |
| 8059 return self.infer_unop_type(env, operand_type) |
| 8060 |
| 8061 def infer_unop_type(self, env, operand_type): |
| 8062 if operand_type.is_pyobject: |
| 8063 return py_object_type |
| 8064 else: |
| 8065 return operand_type |
| 8066 |
| 8067 def may_be_none(self): |
| 8068 if self.operand.type and self.operand.type.is_builtin_type: |
| 8069 if self.operand.type is not type_type: |
| 8070 return False |
| 8071 return ExprNode.may_be_none(self) |
| 8072 |
| 8073 def analyse_types(self, env): |
| 8074 self.operand = self.operand.analyse_types(env) |
| 8075 if self.is_py_operation(): |
| 8076 self.coerce_operand_to_pyobject(env) |
| 8077 self.type = py_object_type |
| 8078 self.is_temp = 1 |
| 8079 elif self.is_cpp_operation(): |
| 8080 self.analyse_cpp_operation(env) |
| 8081 else: |
| 8082 self.analyse_c_operation(env) |
| 8083 return self |
| 8084 |
| 8085 def check_const(self): |
| 8086 return self.operand.check_const() |
| 8087 |
| 8088 def is_py_operation(self): |
| 8089 return self.operand.type.is_pyobject |
| 8090 |
| 8091 def nogil_check(self, env): |
| 8092 if self.is_py_operation(): |
| 8093 self.gil_error() |
| 8094 |
| 8095 def is_cpp_operation(self): |
| 8096 type = self.operand.type |
| 8097 return type.is_cpp_class |
| 8098 |
| 8099 def coerce_operand_to_pyobject(self, env): |
| 8100 self.operand = self.operand.coerce_to_pyobject(env) |
| 8101 |
| 8102 def generate_result_code(self, code): |
| 8103 if self.operand.type.is_pyobject: |
| 8104 self.generate_py_operation_code(code) |
| 8105 |
| 8106 def generate_py_operation_code(self, code): |
| 8107 function = self.py_operation_function() |
| 8108 code.putln( |
| 8109 "%s = %s(%s); %s" % ( |
| 8110 self.result(), |
| 8111 function, |
| 8112 self.operand.py_result(), |
| 8113 code.error_goto_if_null(self.result(), self.pos))) |
| 8114 code.put_gotref(self.py_result()) |
| 8115 |
| 8116 def type_error(self): |
| 8117 if not self.operand.type.is_error: |
| 8118 error(self.pos, "Invalid operand type for '%s' (%s)" % |
| 8119 (self.operator, self.operand.type)) |
| 8120 self.type = PyrexTypes.error_type |
| 8121 |
| 8122 def analyse_cpp_operation(self, env): |
| 8123 cpp_type = self.operand.type.find_cpp_operation_type(self.operator) |
| 8124 if cpp_type is None: |
| 8125 error(self.pos, "'%s' operator not defined for %s" % ( |
| 8126 self.operator, type)) |
| 8127 self.type_error() |
| 8128 return |
| 8129 self.type = cpp_type |
| 8130 |
| 8131 |
| 8132 class NotNode(UnopNode): |
| 8133 # 'not' operator |
| 8134 # |
| 8135 # operand ExprNode |
| 8136 operator = '!' |
| 8137 |
| 8138 type = PyrexTypes.c_bint_type |
| 8139 |
| 8140 def calculate_constant_result(self): |
| 8141 self.constant_result = not self.operand.constant_result |
| 8142 |
| 8143 def compile_time_value(self, denv): |
| 8144 operand = self.operand.compile_time_value(denv) |
| 8145 try: |
| 8146 return not operand |
| 8147 except Exception, e: |
| 8148 self.compile_time_value_error(e) |
| 8149 |
| 8150 def infer_unop_type(self, env, operand_type): |
| 8151 return PyrexTypes.c_bint_type |
| 8152 |
| 8153 def analyse_types(self, env): |
| 8154 self.operand = self.operand.analyse_types(env) |
| 8155 operand_type = self.operand.type |
| 8156 if operand_type.is_cpp_class: |
| 8157 cpp_type = operand_type.find_cpp_operation_type(self.operator) |
| 8158 if not cpp_type: |
| 8159 error(self.pos, "'!' operator not defined for %s" % operand_type
) |
| 8160 self.type = PyrexTypes.error_type |
| 8161 return |
| 8162 self.type = cpp_type |
| 8163 else: |
| 8164 self.operand = self.operand.coerce_to_boolean(env) |
| 8165 return self |
| 8166 |
| 8167 def calculate_result_code(self): |
| 8168 return "(!%s)" % self.operand.result() |
| 8169 |
| 8170 def generate_result_code(self, code): |
| 8171 pass |
| 8172 |
| 8173 |
| 8174 class UnaryPlusNode(UnopNode): |
| 8175 # unary '+' operator |
| 8176 |
| 8177 operator = '+' |
| 8178 |
| 8179 def analyse_c_operation(self, env): |
| 8180 self.type = PyrexTypes.widest_numeric_type( |
| 8181 self.operand.type, PyrexTypes.c_int_type) |
| 8182 |
| 8183 def py_operation_function(self): |
| 8184 return "PyNumber_Positive" |
| 8185 |
| 8186 def calculate_result_code(self): |
| 8187 if self.is_cpp_operation(): |
| 8188 return "(+%s)" % self.operand.result() |
| 8189 else: |
| 8190 return self.operand.result() |
| 8191 |
| 8192 |
| 8193 class UnaryMinusNode(UnopNode): |
| 8194 # unary '-' operator |
| 8195 |
| 8196 operator = '-' |
| 8197 |
| 8198 def analyse_c_operation(self, env): |
| 8199 if self.operand.type.is_numeric: |
| 8200 self.type = PyrexTypes.widest_numeric_type( |
| 8201 self.operand.type, PyrexTypes.c_int_type) |
| 8202 elif self.operand.type.is_enum: |
| 8203 self.type = PyrexTypes.c_int_type |
| 8204 else: |
| 8205 self.type_error() |
| 8206 if self.type.is_complex: |
| 8207 self.infix = False |
| 8208 |
| 8209 def py_operation_function(self): |
| 8210 return "PyNumber_Negative" |
| 8211 |
| 8212 def calculate_result_code(self): |
| 8213 if self.infix: |
| 8214 return "(-%s)" % self.operand.result() |
| 8215 else: |
| 8216 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.res
ult()) |
| 8217 |
| 8218 def get_constant_c_result_code(self): |
| 8219 value = self.operand.get_constant_c_result_code() |
| 8220 if value: |
| 8221 return "(-%s)" % value |
| 8222 |
| 8223 class TildeNode(UnopNode): |
| 8224 # unary '~' operator |
| 8225 |
| 8226 def analyse_c_operation(self, env): |
| 8227 if self.operand.type.is_int: |
| 8228 self.type = PyrexTypes.widest_numeric_type( |
| 8229 self.operand.type, PyrexTypes.c_int_type) |
| 8230 elif self.operand.type.is_enum: |
| 8231 self.type = PyrexTypes.c_int_type |
| 8232 else: |
| 8233 self.type_error() |
| 8234 |
| 8235 def py_operation_function(self): |
| 8236 return "PyNumber_Invert" |
| 8237 |
| 8238 def calculate_result_code(self): |
| 8239 return "(~%s)" % self.operand.result() |
| 8240 |
| 8241 |
| 8242 class CUnopNode(UnopNode): |
| 8243 |
| 8244 def is_py_operation(self): |
| 8245 return False |
| 8246 |
| 8247 class DereferenceNode(CUnopNode): |
| 8248 # unary * operator |
| 8249 |
| 8250 operator = '*' |
| 8251 |
| 8252 def infer_unop_type(self, env, operand_type): |
| 8253 if operand_type.is_ptr: |
| 8254 return operand_type.base_type |
| 8255 else: |
| 8256 return PyrexTypes.error_type |
| 8257 |
| 8258 def analyse_c_operation(self, env): |
| 8259 if self.operand.type.is_ptr: |
| 8260 self.type = self.operand.type.base_type |
| 8261 else: |
| 8262 self.type_error() |
| 8263 |
| 8264 def calculate_result_code(self): |
| 8265 return "(*%s)" % self.operand.result() |
| 8266 |
| 8267 |
| 8268 class DecrementIncrementNode(CUnopNode): |
| 8269 # unary ++/-- operator |
| 8270 |
| 8271 def analyse_c_operation(self, env): |
| 8272 if self.operand.type.is_numeric: |
| 8273 self.type = PyrexTypes.widest_numeric_type( |
| 8274 self.operand.type, PyrexTypes.c_int_type) |
| 8275 elif self.operand.type.is_ptr: |
| 8276 self.type = self.operand.type |
| 8277 else: |
| 8278 self.type_error() |
| 8279 |
| 8280 def calculate_result_code(self): |
| 8281 if self.is_prefix: |
| 8282 return "(%s%s)" % (self.operator, self.operand.result()) |
| 8283 else: |
| 8284 return "(%s%s)" % (self.operand.result(), self.operator) |
| 8285 |
| 8286 def inc_dec_constructor(is_prefix, operator): |
| 8287 return lambda pos, **kwds: DecrementIncrementNode(pos, is_prefix=is_prefix,
operator=operator, **kwds) |
| 8288 |
| 8289 |
| 8290 class AmpersandNode(CUnopNode): |
| 8291 # The C address-of operator. |
| 8292 # |
| 8293 # operand ExprNode |
| 8294 operator = '&' |
| 8295 |
| 8296 def infer_unop_type(self, env, operand_type): |
| 8297 return PyrexTypes.c_ptr_type(operand_type) |
| 8298 |
| 8299 def analyse_types(self, env): |
| 8300 self.operand = self.operand.analyse_types(env) |
| 8301 argtype = self.operand.type |
| 8302 if argtype.is_cpp_class: |
| 8303 cpp_type = argtype.find_cpp_operation_type(self.operator) |
| 8304 if cpp_type is not None: |
| 8305 self.type = cpp_type |
| 8306 return self |
| 8307 if not (argtype.is_cfunction or argtype.is_reference or self.operand.is_
addressable()): |
| 8308 if argtype.is_memoryviewslice: |
| 8309 self.error("Cannot take address of memoryview slice") |
| 8310 else: |
| 8311 self.error("Taking address of non-lvalue") |
| 8312 return self |
| 8313 if argtype.is_pyobject: |
| 8314 self.error("Cannot take address of Python variable") |
| 8315 return self |
| 8316 self.type = PyrexTypes.c_ptr_type(argtype) |
| 8317 return self |
| 8318 |
| 8319 def check_const(self): |
| 8320 return self.operand.check_const_addr() |
| 8321 |
| 8322 def error(self, mess): |
| 8323 error(self.pos, mess) |
| 8324 self.type = PyrexTypes.error_type |
| 8325 self.result_code = "<error>" |
| 8326 |
| 8327 def calculate_result_code(self): |
| 8328 return "(&%s)" % self.operand.result() |
| 8329 |
| 8330 def generate_result_code(self, code): |
| 8331 pass |
| 8332 |
| 8333 |
| 8334 unop_node_classes = { |
| 8335 "+": UnaryPlusNode, |
| 8336 "-": UnaryMinusNode, |
| 8337 "~": TildeNode, |
| 8338 } |
| 8339 |
| 8340 def unop_node(pos, operator, operand): |
| 8341 # Construct unnop node of appropriate class for |
| 8342 # given operator. |
| 8343 if isinstance(operand, IntNode) and operator == '-': |
| 8344 return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(opera
nd.value)), |
| 8345 longness=operand.longness, unsigned=operand.unsigned) |
| 8346 elif isinstance(operand, UnopNode) and operand.operator == operator in '+-': |
| 8347 warning(pos, "Python has no increment/decrement operator: %s%sx == %s(%s
x) == x" % ((operator,)*4), 5) |
| 8348 return unop_node_classes[operator](pos, |
| 8349 operator = operator, |
| 8350 operand = operand) |
| 8351 |
| 8352 |
| 8353 class TypecastNode(ExprNode): |
| 8354 # C type cast |
| 8355 # |
| 8356 # operand ExprNode |
| 8357 # base_type CBaseTypeNode |
| 8358 # declarator CDeclaratorNode |
| 8359 # typecheck boolean |
| 8360 # |
| 8361 # If used from a transform, one can if wanted specify the attribute |
| 8362 # "type" directly and leave base_type and declarator to None |
| 8363 |
| 8364 subexprs = ['operand'] |
| 8365 base_type = declarator = type = None |
| 8366 |
| 8367 def type_dependencies(self, env): |
| 8368 return () |
| 8369 |
| 8370 def infer_type(self, env): |
| 8371 if self.type is None: |
| 8372 base_type = self.base_type.analyse(env) |
| 8373 _, self.type = self.declarator.analyse(base_type, env) |
| 8374 return self.type |
| 8375 |
| 8376 def analyse_types(self, env): |
| 8377 if self.type is None: |
| 8378 base_type = self.base_type.analyse(env) |
| 8379 _, self.type = self.declarator.analyse(base_type, env) |
| 8380 if self.operand.has_constant_result(): |
| 8381 # Must be done after self.type is resolved. |
| 8382 self.calculate_constant_result() |
| 8383 if self.type.is_cfunction: |
| 8384 error(self.pos, |
| 8385 "Cannot cast to a function type") |
| 8386 self.type = PyrexTypes.error_type |
| 8387 self.operand = self.operand.analyse_types(env) |
| 8388 if self.type is PyrexTypes.c_bint_type: |
| 8389 # short circuit this to a coercion |
| 8390 return self.operand.coerce_to_boolean(env) |
| 8391 to_py = self.type.is_pyobject |
| 8392 from_py = self.operand.type.is_pyobject |
| 8393 if from_py and not to_py and self.operand.is_ephemeral(): |
| 8394 if not self.type.is_numeric and not self.type.is_cpp_class: |
| 8395 error(self.pos, "Casting temporary Python object to non-numeric
non-Python type") |
| 8396 if to_py and not from_py: |
| 8397 if self.type is bytes_type and self.operand.type.is_int: |
| 8398 return CoerceIntToBytesNode(self.operand, env) |
| 8399 elif self.operand.type.can_coerce_to_pyobject(env): |
| 8400 self.result_ctype = py_object_type |
| 8401 base_type = self.base_type.analyse(env) |
| 8402 self.operand = self.operand.coerce_to(base_type, env) |
| 8403 else: |
| 8404 if self.operand.type.is_ptr: |
| 8405 if not (self.operand.type.base_type.is_void or self.operand.
type.base_type.is_struct): |
| 8406 error(self.pos, "Python objects cannot be cast from poin
ters of primitive types") |
| 8407 else: |
| 8408 # Should this be an error? |
| 8409 warning(self.pos, "No conversion from %s to %s, python objec
t pointer used." % (self.operand.type, self.type)) |
| 8410 self.operand = self.operand.coerce_to_simple(env) |
| 8411 elif from_py and not to_py: |
| 8412 if self.type.create_from_py_utility_code(env): |
| 8413 self.operand = self.operand.coerce_to(self.type, env) |
| 8414 elif self.type.is_ptr: |
| 8415 if not (self.type.base_type.is_void or self.type.base_type.is_st
ruct): |
| 8416 error(self.pos, "Python objects cannot be cast to pointers o
f primitive types") |
| 8417 else: |
| 8418 warning(self.pos, "No conversion from %s to %s, python object po
inter used." % (self.type, self.operand.type)) |
| 8419 elif from_py and to_py: |
| 8420 if self.typecheck: |
| 8421 self.operand = PyTypeTestNode(self.operand, self.type, env, notn
one=True) |
| 8422 elif isinstance(self.operand, SliceIndexNode): |
| 8423 # This cast can influence the created type of string slices. |
| 8424 self.operand = self.operand.coerce_to(self.type, env) |
| 8425 elif self.type.is_complex and self.operand.type.is_complex: |
| 8426 self.operand = self.operand.coerce_to_simple(env) |
| 8427 elif self.operand.type.is_fused: |
| 8428 self.operand = self.operand.coerce_to(self.type, env) |
| 8429 #self.type = self.operand.type |
| 8430 return self |
| 8431 |
| 8432 def is_simple(self): |
| 8433 # either temp or a C cast => no side effects other than the operand's |
| 8434 return self.operand.is_simple() |
| 8435 |
| 8436 def nonlocally_immutable(self): |
| 8437 return self.is_temp or self.operand.nonlocally_immutable() |
| 8438 |
| 8439 def nogil_check(self, env): |
| 8440 if self.type and self.type.is_pyobject and self.is_temp: |
| 8441 self.gil_error() |
| 8442 |
| 8443 def check_const(self): |
| 8444 return self.operand.check_const() |
| 8445 |
| 8446 def calculate_constant_result(self): |
| 8447 self.constant_result = self.calculate_result_code(self.operand.constant_
result) |
| 8448 |
| 8449 def calculate_result_code(self, operand_result = None): |
| 8450 if operand_result is None: |
| 8451 operand_result = self.operand.result() |
| 8452 if self.type.is_complex: |
| 8453 operand_result = self.operand.result() |
| 8454 if self.operand.type.is_complex: |
| 8455 real_part = self.type.real_type.cast_code("__Pyx_CREAL(%s)" % op
erand_result) |
| 8456 imag_part = self.type.real_type.cast_code("__Pyx_CIMAG(%s)" % op
erand_result) |
| 8457 else: |
| 8458 real_part = self.type.real_type.cast_code(operand_result) |
| 8459 imag_part = "0" |
| 8460 return "%s(%s, %s)" % ( |
| 8461 self.type.from_parts, |
| 8462 real_part, |
| 8463 imag_part) |
| 8464 else: |
| 8465 return self.type.cast_code(operand_result) |
| 8466 |
| 8467 def get_constant_c_result_code(self): |
| 8468 operand_result = self.operand.get_constant_c_result_code() |
| 8469 if operand_result: |
| 8470 return self.type.cast_code(operand_result) |
| 8471 |
| 8472 def result_as(self, type): |
| 8473 if self.type.is_pyobject and not self.is_temp: |
| 8474 # Optimise away some unnecessary casting |
| 8475 return self.operand.result_as(type) |
| 8476 else: |
| 8477 return ExprNode.result_as(self, type) |
| 8478 |
| 8479 def generate_result_code(self, code): |
| 8480 if self.is_temp: |
| 8481 code.putln( |
| 8482 "%s = (PyObject *)%s;" % ( |
| 8483 self.result(), |
| 8484 self.operand.result())) |
| 8485 code.put_incref(self.result(), self.ctype()) |
| 8486 |
| 8487 |
| 8488 ERR_START = "Start may not be given" |
| 8489 ERR_NOT_STOP = "Stop must be provided to indicate shape" |
| 8490 ERR_STEPS = ("Strides may only be given to indicate contiguity. " |
| 8491 "Consider slicing it after conversion") |
| 8492 ERR_NOT_POINTER = "Can only create cython.array from pointer or array" |
| 8493 ERR_BASE_TYPE = "Pointer base type does not match cython.array base type" |
| 8494 |
| 8495 class CythonArrayNode(ExprNode): |
| 8496 """ |
| 8497 Used when a pointer of base_type is cast to a memoryviewslice with that |
| 8498 base type. i.e. |
| 8499 |
| 8500 <int[:M:1, :N]> p |
| 8501 |
| 8502 creates a fortran-contiguous cython.array. |
| 8503 |
| 8504 We leave the type set to object so coercions to object are more efficient |
| 8505 and less work. Acquiring a memoryviewslice from this will be just as |
| 8506 efficient. ExprNode.coerce_to() will do the additional typecheck on |
| 8507 self.compile_time_type |
| 8508 |
| 8509 This also handles <int[:, :]> my_c_array |
| 8510 |
| 8511 |
| 8512 operand ExprNode the thing we're casting |
| 8513 base_type_node MemoryViewSliceTypeNode the cast expression node |
| 8514 """ |
| 8515 |
| 8516 subexprs = ['operand', 'shapes'] |
| 8517 |
| 8518 shapes = None |
| 8519 is_temp = True |
| 8520 mode = "c" |
| 8521 array_dtype = None |
| 8522 |
| 8523 shape_type = PyrexTypes.c_py_ssize_t_type |
| 8524 |
| 8525 def analyse_types(self, env): |
| 8526 import MemoryView |
| 8527 |
| 8528 self.operand = self.operand.analyse_types(env) |
| 8529 if self.array_dtype: |
| 8530 array_dtype = self.array_dtype |
| 8531 else: |
| 8532 array_dtype = self.base_type_node.base_type_node.analyse(env) |
| 8533 axes = self.base_type_node.axes |
| 8534 |
| 8535 MemoryView.validate_memslice_dtype(self.pos, array_dtype) |
| 8536 |
| 8537 self.type = error_type |
| 8538 self.shapes = [] |
| 8539 ndim = len(axes) |
| 8540 |
| 8541 # Base type of the pointer or C array we are converting |
| 8542 base_type = self.operand.type |
| 8543 |
| 8544 if not self.operand.type.is_ptr and not self.operand.type.is_array: |
| 8545 error(self.operand.pos, ERR_NOT_POINTER) |
| 8546 return self |
| 8547 |
| 8548 # Dimension sizes of C array |
| 8549 array_dimension_sizes = [] |
| 8550 if base_type.is_array: |
| 8551 while base_type.is_array: |
| 8552 array_dimension_sizes.append(base_type.size) |
| 8553 base_type = base_type.base_type |
| 8554 elif base_type.is_ptr: |
| 8555 base_type = base_type.base_type |
| 8556 else: |
| 8557 error(self.pos, "unexpected base type %s found" % base_type) |
| 8558 return self |
| 8559 |
| 8560 if not (base_type.same_as(array_dtype) or base_type.is_void): |
| 8561 error(self.operand.pos, ERR_BASE_TYPE) |
| 8562 return self |
| 8563 elif self.operand.type.is_array and len(array_dimension_sizes) != ndim: |
| 8564 error(self.operand.pos, |
| 8565 "Expected %d dimensions, array has %d dimensions" % |
| 8566 (ndim, len(array_dimension_sizes))) |
| 8567 return self |
| 8568 |
| 8569 # Verify the start, stop and step values |
| 8570 # In case of a C array, use the size of C array in each dimension to |
| 8571 # get an automatic cast |
| 8572 for axis_no, axis in enumerate(axes): |
| 8573 if not axis.start.is_none: |
| 8574 error(axis.start.pos, ERR_START) |
| 8575 return self |
| 8576 |
| 8577 if axis.stop.is_none: |
| 8578 if array_dimension_sizes: |
| 8579 dimsize = array_dimension_sizes[axis_no] |
| 8580 axis.stop = IntNode(self.pos, value=str(dimsize), |
| 8581 constant_result=dimsize, |
| 8582 type=PyrexTypes.c_int_type) |
| 8583 else: |
| 8584 error(axis.pos, ERR_NOT_STOP) |
| 8585 return self |
| 8586 |
| 8587 axis.stop = axis.stop.analyse_types(env) |
| 8588 shape = axis.stop.coerce_to(self.shape_type, env) |
| 8589 if not shape.is_literal: |
| 8590 shape.coerce_to_temp(env) |
| 8591 |
| 8592 self.shapes.append(shape) |
| 8593 |
| 8594 first_or_last = axis_no in (0, ndim - 1) |
| 8595 if not axis.step.is_none and first_or_last: |
| 8596 # '1' in the first or last dimension denotes F or C contiguity |
| 8597 axis.step = axis.step.analyse_types(env) |
| 8598 if (not axis.step.type.is_int and axis.step.is_literal and not |
| 8599 axis.step.type.is_error): |
| 8600 error(axis.step.pos, "Expected an integer literal") |
| 8601 return self |
| 8602 |
| 8603 if axis.step.compile_time_value(env) != 1: |
| 8604 error(axis.step.pos, ERR_STEPS) |
| 8605 return self |
| 8606 |
| 8607 if axis_no == 0: |
| 8608 self.mode = "fortran" |
| 8609 |
| 8610 elif not axis.step.is_none and not first_or_last: |
| 8611 # step provided in some other dimension |
| 8612 error(axis.step.pos, ERR_STEPS) |
| 8613 return self |
| 8614 |
| 8615 if not self.operand.is_name: |
| 8616 self.operand = self.operand.coerce_to_temp(env) |
| 8617 |
| 8618 axes = [('direct', 'follow')] * len(axes) |
| 8619 if self.mode == "fortran": |
| 8620 axes[0] = ('direct', 'contig') |
| 8621 else: |
| 8622 axes[-1] = ('direct', 'contig') |
| 8623 |
| 8624 self.coercion_type = PyrexTypes.MemoryViewSliceType(array_dtype, axes) |
| 8625 self.type = self.get_cython_array_type(env) |
| 8626 MemoryView.use_cython_array_utility_code(env) |
| 8627 env.use_utility_code(MemoryView.typeinfo_to_format_code) |
| 8628 return self |
| 8629 |
| 8630 def allocate_temp_result(self, code): |
| 8631 if self.temp_code: |
| 8632 raise RuntimeError("temp allocated mulitple times") |
| 8633 |
| 8634 self.temp_code = code.funcstate.allocate_temp(self.type, True) |
| 8635 |
| 8636 def infer_type(self, env): |
| 8637 return self.get_cython_array_type(env) |
| 8638 |
| 8639 def get_cython_array_type(self, env): |
| 8640 return env.global_scope().context.cython_scope.viewscope.lookup("array")
.type |
| 8641 |
| 8642 def generate_result_code(self, code): |
| 8643 import Buffer |
| 8644 |
| 8645 shapes = [self.shape_type.cast_code(shape.result()) |
| 8646 for shape in self.shapes] |
| 8647 dtype = self.coercion_type.dtype |
| 8648 |
| 8649 shapes_temp = code.funcstate.allocate_temp(py_object_type, True) |
| 8650 format_temp = code.funcstate.allocate_temp(py_object_type, True) |
| 8651 |
| 8652 itemsize = "sizeof(%s)" % dtype.declaration_code("") |
| 8653 type_info = Buffer.get_type_information_cname(code, dtype) |
| 8654 |
| 8655 if self.operand.type.is_ptr: |
| 8656 code.putln("if (!%s) {" % self.operand.result()) |
| 8657 code.putln( 'PyErr_SetString(PyExc_ValueError,' |
| 8658 '"Cannot create cython.array from NULL pointer")
;') |
| 8659 code.putln(code.error_goto(self.operand.pos)) |
| 8660 code.putln("}") |
| 8661 |
| 8662 code.putln("%s = __pyx_format_from_typeinfo(&%s);" % |
| 8663 (format_temp, type_info)) |
| 8664 buildvalue_fmt = " __PYX_BUILD_PY_SSIZE_T " * len(shapes) |
| 8665 code.putln('%s = Py_BuildValue((char*) "(" %s ")", %s);' % ( |
| 8666 shapes_temp, buildvalue_fmt, ", ".join(shapes))) |
| 8667 |
| 8668 err = "!%s || !%s || !PyBytes_AsString(%s)" % (format_temp, |
| 8669 shapes_temp, |
| 8670 format_temp) |
| 8671 code.putln(code.error_goto_if(err, self.pos)) |
| 8672 code.put_gotref(format_temp) |
| 8673 code.put_gotref(shapes_temp) |
| 8674 |
| 8675 tup = (self.result(), shapes_temp, itemsize, format_temp, |
| 8676 self.mode, self.operand.result()) |
| 8677 code.putln('%s = __pyx_array_new(' |
| 8678 '%s, %s, PyBytes_AS_STRING(%s), ' |
| 8679 '(char *) "%s", (char *) %s);' % tup) |
| 8680 code.putln(code.error_goto_if_null(self.result(), self.pos)) |
| 8681 code.put_gotref(self.result()) |
| 8682 |
| 8683 def dispose(temp): |
| 8684 code.put_decref_clear(temp, py_object_type) |
| 8685 code.funcstate.release_temp(temp) |
| 8686 |
| 8687 dispose(shapes_temp) |
| 8688 dispose(format_temp) |
| 8689 |
| 8690 @classmethod |
| 8691 def from_carray(cls, src_node, env): |
| 8692 """ |
| 8693 Given a C array type, return a CythonArrayNode |
| 8694 """ |
| 8695 pos = src_node.pos |
| 8696 base_type = src_node.type |
| 8697 |
| 8698 none_node = NoneNode(pos) |
| 8699 axes = [] |
| 8700 |
| 8701 while base_type.is_array: |
| 8702 axes.append(SliceNode(pos, start=none_node, stop=none_node, |
| 8703 step=none_node)) |
| 8704 base_type = base_type.base_type |
| 8705 axes[-1].step = IntNode(pos, value="1", is_c_literal=True) |
| 8706 |
| 8707 memslicenode = Nodes.MemoryViewSliceTypeNode(pos, axes=axes, |
| 8708 base_type_node=base_type) |
| 8709 result = CythonArrayNode(pos, base_type_node=memslicenode, |
| 8710 operand=src_node, array_dtype=base_type) |
| 8711 result = result.analyse_types(env) |
| 8712 return result |
| 8713 |
| 8714 class SizeofNode(ExprNode): |
| 8715 # Abstract base class for sizeof(x) expression nodes. |
| 8716 |
| 8717 type = PyrexTypes.c_size_t_type |
| 8718 |
| 8719 def check_const(self): |
| 8720 return True |
| 8721 |
| 8722 def generate_result_code(self, code): |
| 8723 pass |
| 8724 |
| 8725 |
| 8726 class SizeofTypeNode(SizeofNode): |
| 8727 # C sizeof function applied to a type |
| 8728 # |
| 8729 # base_type CBaseTypeNode |
| 8730 # declarator CDeclaratorNode |
| 8731 |
| 8732 subexprs = [] |
| 8733 arg_type = None |
| 8734 |
| 8735 def analyse_types(self, env): |
| 8736 # we may have incorrectly interpreted a dotted name as a type rather tha
n an attribute |
| 8737 # this could be better handled by more uniformly treating types as runti
me-available objects |
| 8738 if 0 and self.base_type.module_path: |
| 8739 path = self.base_type.module_path |
| 8740 obj = env.lookup(path[0]) |
| 8741 if obj.as_module is None: |
| 8742 operand = NameNode(pos=self.pos, name=path[0]) |
| 8743 for attr in path[1:]: |
| 8744 operand = AttributeNode(pos=self.pos, obj=operand, attribute
=attr) |
| 8745 operand = AttributeNode(pos=self.pos, obj=operand, attribute=sel
f.base_type.name) |
| 8746 self.operand = operand |
| 8747 self.__class__ = SizeofVarNode |
| 8748 node = self.analyse_types(env) |
| 8749 return node |
| 8750 if self.arg_type is None: |
| 8751 base_type = self.base_type.analyse(env) |
| 8752 _, arg_type = self.declarator.analyse(base_type, env) |
| 8753 self.arg_type = arg_type |
| 8754 self.check_type() |
| 8755 return self |
| 8756 |
| 8757 def check_type(self): |
| 8758 arg_type = self.arg_type |
| 8759 if arg_type.is_pyobject and not arg_type.is_extension_type: |
| 8760 error(self.pos, "Cannot take sizeof Python object") |
| 8761 elif arg_type.is_void: |
| 8762 error(self.pos, "Cannot take sizeof void") |
| 8763 elif not arg_type.is_complete(): |
| 8764 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type
) |
| 8765 |
| 8766 def calculate_result_code(self): |
| 8767 if self.arg_type.is_extension_type: |
| 8768 # the size of the pointer is boring |
| 8769 # we want the size of the actual struct |
| 8770 arg_code = self.arg_type.declaration_code("", deref=1) |
| 8771 else: |
| 8772 arg_code = self.arg_type.declaration_code("") |
| 8773 return "(sizeof(%s))" % arg_code |
| 8774 |
| 8775 |
| 8776 class SizeofVarNode(SizeofNode): |
| 8777 # C sizeof function applied to a variable |
| 8778 # |
| 8779 # operand ExprNode |
| 8780 |
| 8781 subexprs = ['operand'] |
| 8782 |
| 8783 def analyse_types(self, env): |
| 8784 # We may actually be looking at a type rather than a variable... |
| 8785 # If we are, traditional analysis would fail... |
| 8786 operand_as_type = self.operand.analyse_as_type(env) |
| 8787 if operand_as_type: |
| 8788 self.arg_type = operand_as_type |
| 8789 if self.arg_type.is_fused: |
| 8790 self.arg_type = self.arg_type.specialize(env.fused_to_specific) |
| 8791 self.__class__ = SizeofTypeNode |
| 8792 self.check_type() |
| 8793 else: |
| 8794 self.operand = self.operand.analyse_types(env) |
| 8795 return self |
| 8796 |
| 8797 def calculate_result_code(self): |
| 8798 return "(sizeof(%s))" % self.operand.result() |
| 8799 |
| 8800 def generate_result_code(self, code): |
| 8801 pass |
| 8802 |
| 8803 class TypeofNode(ExprNode): |
| 8804 # Compile-time type of an expression, as a string. |
| 8805 # |
| 8806 # operand ExprNode |
| 8807 # literal StringNode # internal |
| 8808 |
| 8809 literal = None |
| 8810 type = py_object_type |
| 8811 |
| 8812 subexprs = ['literal'] # 'operand' will be ignored after type analysis! |
| 8813 |
| 8814 def analyse_types(self, env): |
| 8815 self.operand = self.operand.analyse_types(env) |
| 8816 value = StringEncoding.EncodedString(str(self.operand.type)) #self.opera
nd.type.typeof_name()) |
| 8817 literal = StringNode(self.pos, value=value) |
| 8818 literal = literal.analyse_types(env) |
| 8819 self.literal = literal.coerce_to_pyobject(env) |
| 8820 return self |
| 8821 |
| 8822 def may_be_none(self): |
| 8823 return False |
| 8824 |
| 8825 def generate_evaluation_code(self, code): |
| 8826 self.literal.generate_evaluation_code(code) |
| 8827 |
| 8828 def calculate_result_code(self): |
| 8829 return self.literal.calculate_result_code() |
| 8830 |
| 8831 #------------------------------------------------------------------- |
| 8832 # |
| 8833 # Binary operator nodes |
| 8834 # |
| 8835 #------------------------------------------------------------------- |
| 8836 |
| 8837 compile_time_binary_operators = { |
| 8838 '<': operator.lt, |
| 8839 '<=': operator.le, |
| 8840 '==': operator.eq, |
| 8841 '!=': operator.ne, |
| 8842 '>=': operator.ge, |
| 8843 '>': operator.gt, |
| 8844 'is': operator.is_, |
| 8845 'is_not': operator.is_not, |
| 8846 '+': operator.add, |
| 8847 '&': operator.and_, |
| 8848 '/': operator.truediv, |
| 8849 '//': operator.floordiv, |
| 8850 '<<': operator.lshift, |
| 8851 '%': operator.mod, |
| 8852 '*': operator.mul, |
| 8853 '|': operator.or_, |
| 8854 '**': operator.pow, |
| 8855 '>>': operator.rshift, |
| 8856 '-': operator.sub, |
| 8857 '^': operator.xor, |
| 8858 'in': lambda x, seq: x in seq, |
| 8859 'not_in': lambda x, seq: x not in seq, |
| 8860 } |
| 8861 |
| 8862 def get_compile_time_binop(node): |
| 8863 func = compile_time_binary_operators.get(node.operator) |
| 8864 if not func: |
| 8865 error(node.pos, |
| 8866 "Binary '%s' not supported in compile-time expression" |
| 8867 % node.operator) |
| 8868 return func |
| 8869 |
| 8870 class BinopNode(ExprNode): |
| 8871 # operator string |
| 8872 # operand1 ExprNode |
| 8873 # operand2 ExprNode |
| 8874 # |
| 8875 # Processing during analyse_expressions phase: |
| 8876 # |
| 8877 # analyse_c_operation |
| 8878 # Called when neither operand is a pyobject. |
| 8879 # - Check operand types and coerce if needed. |
| 8880 # - Determine result type and result code fragment. |
| 8881 # - Allocate temporary for result if needed. |
| 8882 |
| 8883 subexprs = ['operand1', 'operand2'] |
| 8884 inplace = False |
| 8885 |
| 8886 def calculate_constant_result(self): |
| 8887 func = compile_time_binary_operators[self.operator] |
| 8888 self.constant_result = func( |
| 8889 self.operand1.constant_result, |
| 8890 self.operand2.constant_result) |
| 8891 |
| 8892 def compile_time_value(self, denv): |
| 8893 func = get_compile_time_binop(self) |
| 8894 operand1 = self.operand1.compile_time_value(denv) |
| 8895 operand2 = self.operand2.compile_time_value(denv) |
| 8896 try: |
| 8897 return func(operand1, operand2) |
| 8898 except Exception, e: |
| 8899 self.compile_time_value_error(e) |
| 8900 |
| 8901 def infer_type(self, env): |
| 8902 return self.result_type(self.operand1.infer_type(env), |
| 8903 self.operand2.infer_type(env)) |
| 8904 |
| 8905 def analyse_types(self, env): |
| 8906 self.operand1 = self.operand1.analyse_types(env) |
| 8907 self.operand2 = self.operand2.analyse_types(env) |
| 8908 self.analyse_operation(env) |
| 8909 return self |
| 8910 |
| 8911 def analyse_operation(self, env): |
| 8912 if self.is_py_operation(): |
| 8913 self.coerce_operands_to_pyobjects(env) |
| 8914 self.type = self.result_type(self.operand1.type, |
| 8915 self.operand2.type) |
| 8916 assert self.type.is_pyobject |
| 8917 self.is_temp = 1 |
| 8918 elif self.is_cpp_operation(): |
| 8919 self.analyse_cpp_operation(env) |
| 8920 else: |
| 8921 self.analyse_c_operation(env) |
| 8922 |
| 8923 def is_py_operation(self): |
| 8924 return self.is_py_operation_types(self.operand1.type, self.operand2.type
) |
| 8925 |
| 8926 def is_py_operation_types(self, type1, type2): |
| 8927 return type1.is_pyobject or type2.is_pyobject |
| 8928 |
| 8929 def is_cpp_operation(self): |
| 8930 return (self.operand1.type.is_cpp_class |
| 8931 or self.operand2.type.is_cpp_class) |
| 8932 |
| 8933 def analyse_cpp_operation(self, env): |
| 8934 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2
]) |
| 8935 if not entry: |
| 8936 self.type_error() |
| 8937 return |
| 8938 func_type = entry.type |
| 8939 if func_type.is_ptr: |
| 8940 func_type = func_type.base_type |
| 8941 if len(func_type.args) == 1: |
| 8942 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) |
| 8943 else: |
| 8944 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) |
| 8945 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) |
| 8946 self.type = func_type.return_type |
| 8947 |
| 8948 def result_type(self, type1, type2): |
| 8949 if self.is_py_operation_types(type1, type2): |
| 8950 if type2.is_string: |
| 8951 type2 = Builtin.bytes_type |
| 8952 elif type2.is_pyunicode_ptr: |
| 8953 type2 = Builtin.unicode_type |
| 8954 if type1.is_string: |
| 8955 type1 = Builtin.bytes_type |
| 8956 elif type1.is_pyunicode_ptr: |
| 8957 type1 = Builtin.unicode_type |
| 8958 if type1.is_builtin_type or type2.is_builtin_type: |
| 8959 if type1 is type2 and self.operator in '**%+|&^': |
| 8960 # FIXME: at least these operators should be safe - others? |
| 8961 return type1 |
| 8962 result_type = self.infer_builtin_types_operation(type1, type2) |
| 8963 if result_type is not None: |
| 8964 return result_type |
| 8965 return py_object_type |
| 8966 else: |
| 8967 return self.compute_c_result_type(type1, type2) |
| 8968 |
| 8969 def infer_builtin_types_operation(self, type1, type2): |
| 8970 return None |
| 8971 |
| 8972 def nogil_check(self, env): |
| 8973 if self.is_py_operation(): |
| 8974 self.gil_error() |
| 8975 |
| 8976 def coerce_operands_to_pyobjects(self, env): |
| 8977 self.operand1 = self.operand1.coerce_to_pyobject(env) |
| 8978 self.operand2 = self.operand2.coerce_to_pyobject(env) |
| 8979 |
| 8980 def check_const(self): |
| 8981 return self.operand1.check_const() and self.operand2.check_const() |
| 8982 |
| 8983 def generate_result_code(self, code): |
| 8984 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 #
## |
| 8985 if self.operand1.type.is_pyobject: |
| 8986 function = self.py_operation_function() |
| 8987 if self.operator == '**': |
| 8988 extra_args = ", Py_None" |
| 8989 else: |
| 8990 extra_args = "" |
| 8991 code.putln( |
| 8992 "%s = %s(%s, %s%s); %s" % ( |
| 8993 self.result(), |
| 8994 function, |
| 8995 self.operand1.py_result(), |
| 8996 self.operand2.py_result(), |
| 8997 extra_args, |
| 8998 code.error_goto_if_null(self.result(), self.pos))) |
| 8999 code.put_gotref(self.py_result()) |
| 9000 elif self.is_temp: |
| 9001 code.putln("%s = %s;" % (self.result(), self.calculate_result_code()
)) |
| 9002 |
| 9003 def type_error(self): |
| 9004 if not (self.operand1.type.is_error |
| 9005 or self.operand2.type.is_error): |
| 9006 error(self.pos, "Invalid operand types for '%s' (%s; %s)" % |
| 9007 (self.operator, self.operand1.type, |
| 9008 self.operand2.type)) |
| 9009 self.type = PyrexTypes.error_type |
| 9010 |
| 9011 |
| 9012 class CBinopNode(BinopNode): |
| 9013 |
| 9014 def analyse_types(self, env): |
| 9015 node = BinopNode.analyse_types(self, env) |
| 9016 if node.is_py_operation(): |
| 9017 node.type = PyrexTypes.error_type |
| 9018 return node |
| 9019 |
| 9020 def py_operation_function(self): |
| 9021 return "" |
| 9022 |
| 9023 def calculate_result_code(self): |
| 9024 return "(%s %s %s)" % ( |
| 9025 self.operand1.result(), |
| 9026 self.operator, |
| 9027 self.operand2.result()) |
| 9028 |
| 9029 def compute_c_result_type(self, type1, type2): |
| 9030 cpp_type = None |
| 9031 if type1.is_cpp_class or type1.is_ptr: |
| 9032 cpp_type = type1.find_cpp_operation_type(self.operator, type2) |
| 9033 # FIXME: handle the reversed case? |
| 9034 #if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): |
| 9035 # cpp_type = type2.find_cpp_operation_type(self.operator, type1) |
| 9036 # FIXME: do we need to handle other cases here? |
| 9037 return cpp_type |
| 9038 |
| 9039 |
| 9040 def c_binop_constructor(operator): |
| 9041 def make_binop_node(pos, **operands): |
| 9042 return CBinopNode(pos, operator=operator, **operands) |
| 9043 return make_binop_node |
| 9044 |
| 9045 class NumBinopNode(BinopNode): |
| 9046 # Binary operation taking numeric arguments. |
| 9047 |
| 9048 infix = True |
| 9049 overflow_check = False |
| 9050 overflow_bit_node = None |
| 9051 |
| 9052 def analyse_c_operation(self, env): |
| 9053 type1 = self.operand1.type |
| 9054 type2 = self.operand2.type |
| 9055 self.type = self.compute_c_result_type(type1, type2) |
| 9056 if not self.type: |
| 9057 self.type_error() |
| 9058 return |
| 9059 if self.type.is_complex: |
| 9060 self.infix = False |
| 9061 if (self.type.is_int |
| 9062 and env.directives['overflowcheck'] |
| 9063 and self.operator in self.overflow_op_names): |
| 9064 if (self.operator in ('+', '*') |
| 9065 and self.operand1.has_constant_result() |
| 9066 and not self.operand2.has_constant_result()): |
| 9067 self.operand1, self.operand2 = self.operand2, self.operand1 |
| 9068 self.overflow_check = True |
| 9069 self.overflow_fold = env.directives['overflowcheck.fold'] |
| 9070 self.func = self.type.overflow_check_binop( |
| 9071 self.overflow_op_names[self.operator], |
| 9072 env, |
| 9073 const_rhs = self.operand2.has_constant_result()) |
| 9074 self.is_temp = True |
| 9075 if not self.infix or (type1.is_numeric and type2.is_numeric): |
| 9076 self.operand1 = self.operand1.coerce_to(self.type, env) |
| 9077 self.operand2 = self.operand2.coerce_to(self.type, env) |
| 9078 |
| 9079 def compute_c_result_type(self, type1, type2): |
| 9080 if self.c_types_okay(type1, type2): |
| 9081 widest_type = PyrexTypes.widest_numeric_type(type1, type2) |
| 9082 if widest_type is PyrexTypes.c_bint_type: |
| 9083 if self.operator not in '|^&': |
| 9084 # False + False == 0 # not False! |
| 9085 widest_type = PyrexTypes.c_int_type |
| 9086 else: |
| 9087 widest_type = PyrexTypes.widest_numeric_type( |
| 9088 widest_type, PyrexTypes.c_int_type) |
| 9089 return widest_type |
| 9090 else: |
| 9091 return None |
| 9092 |
| 9093 def may_be_none(self): |
| 9094 if self.type and self.type.is_builtin_type: |
| 9095 # if we know the result type, we know the operation, so it can't be
None |
| 9096 return False |
| 9097 type1 = self.operand1.type |
| 9098 type2 = self.operand2.type |
| 9099 if type1 and type1.is_builtin_type and type2 and type2.is_builtin_type: |
| 9100 # XXX: I can't think of any case where a binary operation |
| 9101 # on builtin types evaluates to None - add a special case |
| 9102 # here if there is one. |
| 9103 return False |
| 9104 return super(NumBinopNode, self).may_be_none() |
| 9105 |
| 9106 def get_constant_c_result_code(self): |
| 9107 value1 = self.operand1.get_constant_c_result_code() |
| 9108 value2 = self.operand2.get_constant_c_result_code() |
| 9109 if value1 and value2: |
| 9110 return "(%s %s %s)" % (value1, self.operator, value2) |
| 9111 else: |
| 9112 return None |
| 9113 |
| 9114 def c_types_okay(self, type1, type2): |
| 9115 #print "NumBinopNode.c_types_okay:", type1, type2 ### |
| 9116 return (type1.is_numeric or type1.is_enum) \ |
| 9117 and (type2.is_numeric or type2.is_enum) |
| 9118 |
| 9119 def generate_evaluation_code(self, code): |
| 9120 if self.overflow_check: |
| 9121 self.overflow_bit_node = self |
| 9122 self.overflow_bit = code.funcstate.allocate_temp(PyrexTypes.c_int_ty
pe, manage_ref=False) |
| 9123 code.putln("%s = 0;" % self.overflow_bit) |
| 9124 super(NumBinopNode, self).generate_evaluation_code(code) |
| 9125 if self.overflow_check: |
| 9126 code.putln("if (unlikely(%s)) {" % self.overflow_bit) |
| 9127 code.putln('PyErr_SetString(PyExc_OverflowError, "value too large");
') |
| 9128 code.putln(code.error_goto(self.pos)) |
| 9129 code.putln("}") |
| 9130 code.funcstate.release_temp(self.overflow_bit) |
| 9131 |
| 9132 def calculate_result_code(self): |
| 9133 if self.overflow_bit_node is not None: |
| 9134 return "%s(%s, %s, &%s)" % ( |
| 9135 self.func, |
| 9136 self.operand1.result(), |
| 9137 self.operand2.result(), |
| 9138 self.overflow_bit_node.overflow_bit) |
| 9139 elif self.infix: |
| 9140 return "(%s %s %s)" % ( |
| 9141 self.operand1.result(), |
| 9142 self.operator, |
| 9143 self.operand2.result()) |
| 9144 else: |
| 9145 func = self.type.binary_op(self.operator) |
| 9146 if func is None: |
| 9147 error(self.pos, "binary operator %s not supported for %s" % (sel
f.operator, self.type)) |
| 9148 return "%s(%s, %s)" % ( |
| 9149 func, |
| 9150 self.operand1.result(), |
| 9151 self.operand2.result()) |
| 9152 |
| 9153 def is_py_operation_types(self, type1, type2): |
| 9154 return (type1.is_unicode_char or |
| 9155 type2.is_unicode_char or |
| 9156 BinopNode.is_py_operation_types(self, type1, type2)) |
| 9157 |
| 9158 def py_operation_function(self): |
| 9159 function_name = self.py_functions[self.operator] |
| 9160 if self.inplace: |
| 9161 function_name = function_name.replace('PyNumber_', 'PyNumber_InPlace
') |
| 9162 return function_name |
| 9163 |
| 9164 py_functions = { |
| 9165 "|": "PyNumber_Or", |
| 9166 "^": "PyNumber_Xor", |
| 9167 "&": "PyNumber_And", |
| 9168 "<<": "PyNumber_Lshift", |
| 9169 ">>": "PyNumber_Rshift", |
| 9170 "+": "PyNumber_Add", |
| 9171 "-": "PyNumber_Subtract", |
| 9172 "*": "PyNumber_Multiply", |
| 9173 "/": "__Pyx_PyNumber_Divide", |
| 9174 "//": "PyNumber_FloorDivide", |
| 9175 "%": "PyNumber_Remainder", |
| 9176 "**": "PyNumber_Power" |
| 9177 } |
| 9178 |
| 9179 overflow_op_names = { |
| 9180 "+": "add", |
| 9181 "-": "sub", |
| 9182 "*": "mul", |
| 9183 "<<": "lshift", |
| 9184 } |
| 9185 |
| 9186 |
| 9187 class IntBinopNode(NumBinopNode): |
| 9188 # Binary operation taking integer arguments. |
| 9189 |
| 9190 def c_types_okay(self, type1, type2): |
| 9191 #print "IntBinopNode.c_types_okay:", type1, type2 ### |
| 9192 return (type1.is_int or type1.is_enum) \ |
| 9193 and (type2.is_int or type2.is_enum) |
| 9194 |
| 9195 |
| 9196 class AddNode(NumBinopNode): |
| 9197 # '+' operator. |
| 9198 |
| 9199 def is_py_operation_types(self, type1, type2): |
| 9200 if type1.is_string and type2.is_string or type1.is_pyunicode_ptr and typ
e2.is_pyunicode_ptr: |
| 9201 return 1 |
| 9202 else: |
| 9203 return NumBinopNode.is_py_operation_types(self, type1, type2) |
| 9204 |
| 9205 def infer_builtin_types_operation(self, type1, type2): |
| 9206 # b'abc' + 'abc' raises an exception in Py3, |
| 9207 # so we can safely infer the Py2 type for bytes here |
| 9208 string_types = [bytes_type, str_type, basestring_type, unicode_type] #
Py2.4 lacks tuple.index() |
| 9209 if type1 in string_types and type2 in string_types: |
| 9210 return string_types[max(string_types.index(type1), |
| 9211 string_types.index(type2))] |
| 9212 return None |
| 9213 |
| 9214 def compute_c_result_type(self, type1, type2): |
| 9215 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ### |
| 9216 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): |
| 9217 return type1 |
| 9218 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum
): |
| 9219 return type2 |
| 9220 else: |
| 9221 return NumBinopNode.compute_c_result_type( |
| 9222 self, type1, type2) |
| 9223 |
| 9224 def py_operation_function(self): |
| 9225 type1, type2 = self.operand1.type, self.operand2.type |
| 9226 if type1 is unicode_type or type2 is unicode_type: |
| 9227 if type1.is_builtin_type and type2.is_builtin_type: |
| 9228 if self.operand1.may_be_none() or self.operand2.may_be_none(): |
| 9229 return '__Pyx_PyUnicode_ConcatSafe' |
| 9230 else: |
| 9231 return '__Pyx_PyUnicode_Concat' |
| 9232 return super(AddNode, self).py_operation_function() |
| 9233 |
| 9234 |
| 9235 class SubNode(NumBinopNode): |
| 9236 # '-' operator. |
| 9237 |
| 9238 def compute_c_result_type(self, type1, type2): |
| 9239 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum): |
| 9240 return type1 |
| 9241 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_arra
y): |
| 9242 return PyrexTypes.c_ptrdiff_t_type |
| 9243 else: |
| 9244 return NumBinopNode.compute_c_result_type( |
| 9245 self, type1, type2) |
| 9246 |
| 9247 |
| 9248 class MulNode(NumBinopNode): |
| 9249 # '*' operator. |
| 9250 |
| 9251 def is_py_operation_types(self, type1, type2): |
| 9252 if ((type1.is_string and type2.is_int) or |
| 9253 (type2.is_string and type1.is_int)): |
| 9254 return 1 |
| 9255 else: |
| 9256 return NumBinopNode.is_py_operation_types(self, type1, type2) |
| 9257 |
| 9258 def infer_builtin_types_operation(self, type1, type2): |
| 9259 # let's assume that whatever builtin type you multiply a string with |
| 9260 # will either return a string of the same type or fail with an exception |
| 9261 string_types = (bytes_type, str_type, basestring_type, unicode_type) |
| 9262 if type1 in string_types and type2.is_builtin_type: |
| 9263 return type1 |
| 9264 if type2 in string_types and type1.is_builtin_type: |
| 9265 return type2 |
| 9266 # multiplication of containers/numbers with an integer value |
| 9267 # always (?) returns the same type |
| 9268 if type1.is_int: |
| 9269 return type2 |
| 9270 if type2.is_int: |
| 9271 return type1 |
| 9272 return None |
| 9273 |
| 9274 |
| 9275 class DivNode(NumBinopNode): |
| 9276 # '/' or '//' operator. |
| 9277 |
| 9278 cdivision = None |
| 9279 truedivision = None # == "unknown" if operator == '/' |
| 9280 ctruedivision = False |
| 9281 cdivision_warnings = False |
| 9282 zerodivision_check = None |
| 9283 |
| 9284 def find_compile_time_binary_operator(self, op1, op2): |
| 9285 func = compile_time_binary_operators[self.operator] |
| 9286 if self.operator == '/' and self.truedivision is None: |
| 9287 # => true div for floats, floor div for integers |
| 9288 if isinstance(op1, (int,long)) and isinstance(op2, (int,long)): |
| 9289 func = compile_time_binary_operators['//'] |
| 9290 return func |
| 9291 |
| 9292 def calculate_constant_result(self): |
| 9293 op1 = self.operand1.constant_result |
| 9294 op2 = self.operand2.constant_result |
| 9295 func = self.find_compile_time_binary_operator(op1, op2) |
| 9296 self.constant_result = func( |
| 9297 self.operand1.constant_result, |
| 9298 self.operand2.constant_result) |
| 9299 |
| 9300 def compile_time_value(self, denv): |
| 9301 operand1 = self.operand1.compile_time_value(denv) |
| 9302 operand2 = self.operand2.compile_time_value(denv) |
| 9303 try: |
| 9304 func = self.find_compile_time_binary_operator( |
| 9305 operand1, operand2) |
| 9306 return func(operand1, operand2) |
| 9307 except Exception, e: |
| 9308 self.compile_time_value_error(e) |
| 9309 |
| 9310 def analyse_operation(self, env): |
| 9311 if self.cdivision or env.directives['cdivision']: |
| 9312 self.ctruedivision = False |
| 9313 else: |
| 9314 self.ctruedivision = self.truedivision |
| 9315 NumBinopNode.analyse_operation(self, env) |
| 9316 if self.is_cpp_operation(): |
| 9317 self.cdivision = True |
| 9318 if not self.type.is_pyobject: |
| 9319 self.zerodivision_check = ( |
| 9320 self.cdivision is None and not env.directives['cdivision'] |
| 9321 and (not self.operand2.has_constant_result() or |
| 9322 self.operand2.constant_result == 0)) |
| 9323 if self.zerodivision_check or env.directives['cdivision_warnings']: |
| 9324 # Need to check ahead of time to warn or raise zero division err
or |
| 9325 self.operand1 = self.operand1.coerce_to_simple(env) |
| 9326 self.operand2 = self.operand2.coerce_to_simple(env) |
| 9327 |
| 9328 def compute_c_result_type(self, type1, type2): |
| 9329 if self.operator == '/' and self.ctruedivision: |
| 9330 if not type1.is_float and not type2.is_float: |
| 9331 widest_type = PyrexTypes.widest_numeric_type(type1, PyrexTypes.c
_double_type) |
| 9332 widest_type = PyrexTypes.widest_numeric_type(type2, widest_type) |
| 9333 return widest_type |
| 9334 return NumBinopNode.compute_c_result_type(self, type1, type2) |
| 9335 |
| 9336 def zero_division_message(self): |
| 9337 if self.type.is_int: |
| 9338 return "integer division or modulo by zero" |
| 9339 else: |
| 9340 return "float division" |
| 9341 |
| 9342 def generate_evaluation_code(self, code): |
| 9343 if not self.type.is_pyobject and not self.type.is_complex: |
| 9344 if self.cdivision is None: |
| 9345 self.cdivision = (code.globalstate.directives['cdivision'] |
| 9346 or not self.type.signed |
| 9347 or self.type.is_float) |
| 9348 if not self.cdivision: |
| 9349 code.globalstate.use_utility_code(div_int_utility_code.specializ
e(self.type)) |
| 9350 NumBinopNode.generate_evaluation_code(self, code) |
| 9351 self.generate_div_warning_code(code) |
| 9352 |
| 9353 def generate_div_warning_code(self, code): |
| 9354 if not self.type.is_pyobject: |
| 9355 if self.zerodivision_check: |
| 9356 if not self.infix: |
| 9357 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.ope
rand2.result()) |
| 9358 else: |
| 9359 zero_test = "%s == 0" % self.operand2.result() |
| 9360 code.putln("if (unlikely(%s)) {" % zero_test) |
| 9361 code.put_ensure_gil() |
| 9362 code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % s
elf.zero_division_message()) |
| 9363 code.put_release_ensured_gil() |
| 9364 code.putln(code.error_goto(self.pos)) |
| 9365 code.putln("}") |
| 9366 if self.type.is_int and self.type.signed and self.operator != '%
': |
| 9367 code.globalstate.use_utility_code(division_overflow_test_cod
e) |
| 9368 if self.operand2.type.signed == 2: |
| 9369 # explicitly signed, no runtime check needed |
| 9370 minus1_check = 'unlikely(%s == -1)' % self.operand2.resu
lt() |
| 9371 else: |
| 9372 type_of_op2 = self.operand2.type.declaration_code('') |
| 9373 minus1_check = '(!(((%s)-1) > 0)) && unlikely(%s == (%s)
-1)' % ( |
| 9374 type_of_op2, self.operand2.result(), type_of_op2) |
| 9375 code.putln("else if (sizeof(%s) == sizeof(long) && %s " |
| 9376 " && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" %
( |
| 9377 self.type.declaration_code(''), |
| 9378 minus1_check, |
| 9379 self.operand1.result())) |
| 9380 code.put_ensure_gil() |
| 9381 code.putln('PyErr_SetString(PyExc_OverflowError, "value too
large to perform division");') |
| 9382 code.put_release_ensured_gil() |
| 9383 code.putln(code.error_goto(self.pos)) |
| 9384 code.putln("}") |
| 9385 if code.globalstate.directives['cdivision_warnings'] and self.operat
or != '/': |
| 9386 code.globalstate.use_utility_code(cdivision_warning_utility_code
) |
| 9387 code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % ( |
| 9388 self.operand1.result(), |
| 9389 self.operand2.result())) |
| 9390 code.put_ensure_gil() |
| 9391 code.putln(code.set_error_info(self.pos, used=True)) |
| 9392 code.putln("if (__Pyx_cdivision_warning(%(FILENAME)s, " |
| 9393 "%(LINENO)s)) {" % { |
| 9394 'FILENAME': Naming.filename_cname, |
| 9395 'LINENO': Naming.lineno_cname, |
| 9396 }) |
| 9397 code.put_release_ensured_gil() |
| 9398 code.put_goto(code.error_label) |
| 9399 code.putln("}") |
| 9400 code.put_release_ensured_gil() |
| 9401 code.putln("}") |
| 9402 |
| 9403 def calculate_result_code(self): |
| 9404 if self.type.is_complex: |
| 9405 return NumBinopNode.calculate_result_code(self) |
| 9406 elif self.type.is_float and self.operator == '//': |
| 9407 return "floor(%s / %s)" % ( |
| 9408 self.operand1.result(), |
| 9409 self.operand2.result()) |
| 9410 elif self.truedivision or self.cdivision: |
| 9411 op1 = self.operand1.result() |
| 9412 op2 = self.operand2.result() |
| 9413 if self.truedivision: |
| 9414 if self.type != self.operand1.type: |
| 9415 op1 = self.type.cast_code(op1) |
| 9416 if self.type != self.operand2.type: |
| 9417 op2 = self.type.cast_code(op2) |
| 9418 return "(%s / %s)" % (op1, op2) |
| 9419 else: |
| 9420 return "__Pyx_div_%s(%s, %s)" % ( |
| 9421 self.type.specialization_name(), |
| 9422 self.operand1.result(), |
| 9423 self.operand2.result()) |
| 9424 |
| 9425 |
| 9426 class ModNode(DivNode): |
| 9427 # '%' operator. |
| 9428 |
| 9429 def is_py_operation_types(self, type1, type2): |
| 9430 return (type1.is_string |
| 9431 or type2.is_string |
| 9432 or NumBinopNode.is_py_operation_types(self, type1, type2)) |
| 9433 |
| 9434 def infer_builtin_types_operation(self, type1, type2): |
| 9435 # b'%s' % xyz raises an exception in Py3, so it's safe to infer the typ
e for Py2 |
| 9436 if type1 is unicode_type: |
| 9437 # None + xyz may be implemented by RHS |
| 9438 if type2.is_builtin_type or not self.operand1.may_be_none(): |
| 9439 return type1 |
| 9440 elif type1 in (bytes_type, str_type, basestring_type): |
| 9441 if type2 is unicode_type: |
| 9442 return type2 |
| 9443 elif type2.is_numeric: |
| 9444 return type1 |
| 9445 elif type1 is bytes_type and not type2.is_builtin_type: |
| 9446 return None # RHS might implement '% operator differently in P
y3 |
| 9447 else: |
| 9448 return basestring_type # either str or unicode, can't tell |
| 9449 return None |
| 9450 |
| 9451 def zero_division_message(self): |
| 9452 if self.type.is_int: |
| 9453 return "integer division or modulo by zero" |
| 9454 else: |
| 9455 return "float divmod()" |
| 9456 |
| 9457 def analyse_operation(self, env): |
| 9458 DivNode.analyse_operation(self, env) |
| 9459 if not self.type.is_pyobject: |
| 9460 if self.cdivision is None: |
| 9461 self.cdivision = env.directives['cdivision'] or not self.type.si
gned |
| 9462 if not self.cdivision and not self.type.is_int and not self.type.is_
float: |
| 9463 error(self.pos, "mod operator not supported for type '%s'" % sel
f.type) |
| 9464 |
| 9465 def generate_evaluation_code(self, code): |
| 9466 if not self.type.is_pyobject and not self.cdivision: |
| 9467 if self.type.is_int: |
| 9468 code.globalstate.use_utility_code( |
| 9469 mod_int_utility_code.specialize(self.type)) |
| 9470 else: # float |
| 9471 code.globalstate.use_utility_code( |
| 9472 mod_float_utility_code.specialize( |
| 9473 self.type, math_h_modifier=self.type.math_h_modifier)) |
| 9474 # note: skipping over DivNode here |
| 9475 NumBinopNode.generate_evaluation_code(self, code) |
| 9476 self.generate_div_warning_code(code) |
| 9477 |
| 9478 def calculate_result_code(self): |
| 9479 if self.cdivision: |
| 9480 if self.type.is_float: |
| 9481 return "fmod%s(%s, %s)" % ( |
| 9482 self.type.math_h_modifier, |
| 9483 self.operand1.result(), |
| 9484 self.operand2.result()) |
| 9485 else: |
| 9486 return "(%s %% %s)" % ( |
| 9487 self.operand1.result(), |
| 9488 self.operand2.result()) |
| 9489 else: |
| 9490 return "__Pyx_mod_%s(%s, %s)" % ( |
| 9491 self.type.specialization_name(), |
| 9492 self.operand1.result(), |
| 9493 self.operand2.result()) |
| 9494 |
| 9495 def py_operation_function(self): |
| 9496 if self.operand1.type is unicode_type: |
| 9497 if self.operand1.may_be_none(): |
| 9498 return '__Pyx_PyUnicode_FormatSafe' |
| 9499 else: |
| 9500 return 'PyUnicode_Format' |
| 9501 elif self.operand1.type is str_type: |
| 9502 if self.operand1.may_be_none(): |
| 9503 return '__Pyx_PyString_FormatSafe' |
| 9504 else: |
| 9505 return '__Pyx_PyString_Format' |
| 9506 return super(ModNode, self).py_operation_function() |
| 9507 |
| 9508 |
| 9509 class PowNode(NumBinopNode): |
| 9510 # '**' operator. |
| 9511 |
| 9512 def analyse_c_operation(self, env): |
| 9513 NumBinopNode.analyse_c_operation(self, env) |
| 9514 if self.type.is_complex: |
| 9515 if self.type.real_type.is_float: |
| 9516 self.operand1 = self.operand1.coerce_to(self.type, env) |
| 9517 self.operand2 = self.operand2.coerce_to(self.type, env) |
| 9518 self.pow_func = "__Pyx_c_pow" + self.type.real_type.math_h_modif
ier |
| 9519 else: |
| 9520 error(self.pos, "complex int powers not supported") |
| 9521 self.pow_func = "<error>" |
| 9522 elif self.type.is_float: |
| 9523 self.pow_func = "pow" + self.type.math_h_modifier |
| 9524 elif self.type.is_int: |
| 9525 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').repl
ace(' ', '_') |
| 9526 env.use_utility_code( |
| 9527 int_pow_utility_code.specialize( |
| 9528 func_name=self.pow_func, |
| 9529 type=self.type.declaration_code(''), |
| 9530 signed=self.type.signed and 1 or 0)) |
| 9531 elif not self.type.is_error: |
| 9532 error(self.pos, "got unexpected types for C power operator: %s, %s"
% |
| 9533 (self.operand1.type, self.operand2.type)) |
| 9534 |
| 9535 def calculate_result_code(self): |
| 9536 # Work around MSVC overloading ambiguity. |
| 9537 def typecast(operand): |
| 9538 if self.type == operand.type: |
| 9539 return operand.result() |
| 9540 else: |
| 9541 return self.type.cast_code(operand.result()) |
| 9542 return "%s(%s, %s)" % ( |
| 9543 self.pow_func, |
| 9544 typecast(self.operand1), |
| 9545 typecast(self.operand2)) |
| 9546 |
| 9547 |
| 9548 # Note: This class is temporarily "shut down" into an ineffective temp |
| 9549 # allocation mode. |
| 9550 # |
| 9551 # More sophisticated temp reuse was going on before, one could have a |
| 9552 # look at adding this again after /all/ classes are converted to the |
| 9553 # new temp scheme. (The temp juggling cannot work otherwise). |
| 9554 class BoolBinopNode(ExprNode): |
| 9555 # Short-circuiting boolean operation. |
| 9556 # |
| 9557 # operator string |
| 9558 # operand1 ExprNode |
| 9559 # operand2 ExprNode |
| 9560 |
| 9561 subexprs = ['operand1', 'operand2'] |
| 9562 |
| 9563 def infer_type(self, env): |
| 9564 type1 = self.operand1.infer_type(env) |
| 9565 type2 = self.operand2.infer_type(env) |
| 9566 return PyrexTypes.independent_spanning_type(type1, type2) |
| 9567 |
| 9568 def may_be_none(self): |
| 9569 if self.operator == 'or': |
| 9570 return self.operand2.may_be_none() |
| 9571 else: |
| 9572 return self.operand1.may_be_none() or self.operand2.may_be_none() |
| 9573 |
| 9574 def calculate_constant_result(self): |
| 9575 if self.operator == 'and': |
| 9576 self.constant_result = \ |
| 9577 self.operand1.constant_result and \ |
| 9578 self.operand2.constant_result |
| 9579 else: |
| 9580 self.constant_result = \ |
| 9581 self.operand1.constant_result or \ |
| 9582 self.operand2.constant_result |
| 9583 |
| 9584 def compile_time_value(self, denv): |
| 9585 if self.operator == 'and': |
| 9586 return self.operand1.compile_time_value(denv) \ |
| 9587 and self.operand2.compile_time_value(denv) |
| 9588 else: |
| 9589 return self.operand1.compile_time_value(denv) \ |
| 9590 or self.operand2.compile_time_value(denv) |
| 9591 |
| 9592 def coerce_to_boolean(self, env): |
| 9593 return BoolBinopNode( |
| 9594 self.pos, |
| 9595 operator = self.operator, |
| 9596 operand1 = self.operand1.coerce_to_boolean(env), |
| 9597 operand2 = self.operand2.coerce_to_boolean(env), |
| 9598 type = PyrexTypes.c_bint_type, |
| 9599 is_temp = self.is_temp) |
| 9600 |
| 9601 def analyse_types(self, env): |
| 9602 self.operand1 = self.operand1.analyse_types(env) |
| 9603 self.operand2 = self.operand2.analyse_types(env) |
| 9604 self.type = PyrexTypes.independent_spanning_type(self.operand1.type, sel
f.operand2.type) |
| 9605 self.operand1 = self.operand1.coerce_to(self.type, env) |
| 9606 self.operand2 = self.operand2.coerce_to(self.type, env) |
| 9607 |
| 9608 # For what we're about to do, it's vital that |
| 9609 # both operands be temp nodes. |
| 9610 self.operand1 = self.operand1.coerce_to_simple(env) |
| 9611 self.operand2 = self.operand2.coerce_to_simple(env) |
| 9612 self.is_temp = 1 |
| 9613 return self |
| 9614 |
| 9615 gil_message = "Truth-testing Python object" |
| 9616 |
| 9617 def check_const(self): |
| 9618 return self.operand1.check_const() and self.operand2.check_const() |
| 9619 |
| 9620 def generate_evaluation_code(self, code): |
| 9621 code.mark_pos(self.pos) |
| 9622 self.operand1.generate_evaluation_code(code) |
| 9623 test_result, uses_temp = self.generate_operand1_test(code) |
| 9624 if self.operator == 'and': |
| 9625 sense = "" |
| 9626 else: |
| 9627 sense = "!" |
| 9628 code.putln( |
| 9629 "if (%s%s) {" % ( |
| 9630 sense, |
| 9631 test_result)) |
| 9632 if uses_temp: |
| 9633 code.funcstate.release_temp(test_result) |
| 9634 self.operand1.generate_disposal_code(code) |
| 9635 self.operand2.generate_evaluation_code(code) |
| 9636 self.allocate_temp_result(code) |
| 9637 self.operand2.make_owned_reference(code) |
| 9638 code.putln("%s = %s;" % (self.result(), self.operand2.result())) |
| 9639 self.operand2.generate_post_assignment_code(code) |
| 9640 self.operand2.free_temps(code) |
| 9641 code.putln("} else {") |
| 9642 self.operand1.make_owned_reference(code) |
| 9643 code.putln("%s = %s;" % (self.result(), self.operand1.result())) |
| 9644 self.operand1.generate_post_assignment_code(code) |
| 9645 self.operand1.free_temps(code) |
| 9646 code.putln("}") |
| 9647 |
| 9648 def generate_operand1_test(self, code): |
| 9649 # Generate code to test the truth of the first operand. |
| 9650 if self.type.is_pyobject: |
| 9651 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type, |
| 9652 manage_ref=False) |
| 9653 code.putln( |
| 9654 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( |
| 9655 test_result, |
| 9656 self.operand1.py_result(), |
| 9657 code.error_goto_if_neg(test_result, self.pos))) |
| 9658 else: |
| 9659 test_result = self.operand1.result() |
| 9660 return (test_result, self.type.is_pyobject) |
| 9661 |
| 9662 |
| 9663 class CondExprNode(ExprNode): |
| 9664 # Short-circuiting conditional expression. |
| 9665 # |
| 9666 # test ExprNode |
| 9667 # true_val ExprNode |
| 9668 # false_val ExprNode |
| 9669 |
| 9670 true_val = None |
| 9671 false_val = None |
| 9672 |
| 9673 subexprs = ['test', 'true_val', 'false_val'] |
| 9674 |
| 9675 def type_dependencies(self, env): |
| 9676 return self.true_val.type_dependencies(env) + self.false_val.type_depend
encies(env) |
| 9677 |
| 9678 def infer_type(self, env): |
| 9679 return PyrexTypes.independent_spanning_type( |
| 9680 self.true_val.infer_type(env), |
| 9681 self.false_val.infer_type(env)) |
| 9682 |
| 9683 def calculate_constant_result(self): |
| 9684 if self.test.constant_result: |
| 9685 self.constant_result = self.true_val.constant_result |
| 9686 else: |
| 9687 self.constant_result = self.false_val.constant_result |
| 9688 |
| 9689 def analyse_types(self, env): |
| 9690 self.test = self.test.analyse_types(env).coerce_to_boolean(env) |
| 9691 self.true_val = self.true_val.analyse_types(env) |
| 9692 self.false_val = self.false_val.analyse_types(env) |
| 9693 self.is_temp = 1 |
| 9694 return self.analyse_result_type(env) |
| 9695 |
| 9696 def analyse_result_type(self, env): |
| 9697 self.type = PyrexTypes.independent_spanning_type( |
| 9698 self.true_val.type, self.false_val.type) |
| 9699 if self.type.is_pyobject: |
| 9700 self.result_ctype = py_object_type |
| 9701 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject: |
| 9702 self.true_val = self.true_val.coerce_to(self.type, env) |
| 9703 self.false_val = self.false_val.coerce_to(self.type, env) |
| 9704 if self.type == PyrexTypes.error_type: |
| 9705 self.type_error() |
| 9706 return self |
| 9707 |
| 9708 def coerce_to(self, dst_type, env): |
| 9709 self.true_val = self.true_val.coerce_to(dst_type, env) |
| 9710 self.false_val = self.false_val.coerce_to(dst_type, env) |
| 9711 self.result_ctype = None |
| 9712 return self.analyse_result_type(env) |
| 9713 |
| 9714 def type_error(self): |
| 9715 if not (self.true_val.type.is_error or self.false_val.type.is_error): |
| 9716 error(self.pos, "Incompatible types in conditional expression (%s; %
s)" % |
| 9717 (self.true_val.type, self.false_val.type)) |
| 9718 self.type = PyrexTypes.error_type |
| 9719 |
| 9720 def check_const(self): |
| 9721 return (self.test.check_const() |
| 9722 and self.true_val.check_const() |
| 9723 and self.false_val.check_const()) |
| 9724 |
| 9725 def generate_evaluation_code(self, code): |
| 9726 # Because subexprs may not be evaluated we can use a more optimal |
| 9727 # subexpr allocation strategy than the default, so override evaluation_c
ode. |
| 9728 |
| 9729 code.mark_pos(self.pos) |
| 9730 self.allocate_temp_result(code) |
| 9731 self.test.generate_evaluation_code(code) |
| 9732 code.putln("if (%s) {" % self.test.result() ) |
| 9733 self.eval_and_get(code, self.true_val) |
| 9734 code.putln("} else {") |
| 9735 self.eval_and_get(code, self.false_val) |
| 9736 code.putln("}") |
| 9737 self.test.generate_disposal_code(code) |
| 9738 self.test.free_temps(code) |
| 9739 |
| 9740 def eval_and_get(self, code, expr): |
| 9741 expr.generate_evaluation_code(code) |
| 9742 expr.make_owned_reference(code) |
| 9743 code.putln('%s = %s;' % (self.result(), expr.result_as(self.ctype()))) |
| 9744 expr.generate_post_assignment_code(code) |
| 9745 expr.free_temps(code) |
| 9746 |
| 9747 richcmp_constants = { |
| 9748 "<" : "Py_LT", |
| 9749 "<=": "Py_LE", |
| 9750 "==": "Py_EQ", |
| 9751 "!=": "Py_NE", |
| 9752 "<>": "Py_NE", |
| 9753 ">" : "Py_GT", |
| 9754 ">=": "Py_GE", |
| 9755 # the following are faked by special compare functions |
| 9756 "in" : "Py_EQ", |
| 9757 "not_in": "Py_NE", |
| 9758 } |
| 9759 |
| 9760 class CmpNode(object): |
| 9761 # Mixin class containing code common to PrimaryCmpNodes |
| 9762 # and CascadedCmpNodes. |
| 9763 |
| 9764 special_bool_cmp_function = None |
| 9765 special_bool_cmp_utility_code = None |
| 9766 |
| 9767 def infer_type(self, env): |
| 9768 # TODO: Actually implement this (after merging with -unstable). |
| 9769 return py_object_type |
| 9770 |
| 9771 def calculate_cascaded_constant_result(self, operand1_result): |
| 9772 func = compile_time_binary_operators[self.operator] |
| 9773 operand2_result = self.operand2.constant_result |
| 9774 if (isinstance(operand1_result, (bytes, unicode)) and |
| 9775 isinstance(operand2_result, (bytes, unicode)) and |
| 9776 type(operand1_result) != type(operand2_result)): |
| 9777 # string comparison of different types isn't portable |
| 9778 return |
| 9779 |
| 9780 if self.operator in ('in', 'not_in'): |
| 9781 if isinstance(self.operand2, (ListNode, TupleNode, SetNode)): |
| 9782 if not self.operand2.args: |
| 9783 self.constant_result = self.operator == 'not_in' |
| 9784 return |
| 9785 elif isinstance(self.operand2, ListNode) and not self.cascade: |
| 9786 # tuples are more efficient to store than lists |
| 9787 self.operand2 = self.operand2.as_tuple() |
| 9788 elif isinstance(self.operand2, DictNode): |
| 9789 if not self.operand2.key_value_pairs: |
| 9790 self.constant_result = self.operator == 'not_in' |
| 9791 return |
| 9792 |
| 9793 self.constant_result = func(operand1_result, operand2_result) |
| 9794 |
| 9795 def cascaded_compile_time_value(self, operand1, denv): |
| 9796 func = get_compile_time_binop(self) |
| 9797 operand2 = self.operand2.compile_time_value(denv) |
| 9798 try: |
| 9799 result = func(operand1, operand2) |
| 9800 except Exception, e: |
| 9801 self.compile_time_value_error(e) |
| 9802 result = None |
| 9803 if result: |
| 9804 cascade = self.cascade |
| 9805 if cascade: |
| 9806 result = result and cascade.cascaded_compile_time_value(operand2
, denv) |
| 9807 return result |
| 9808 |
| 9809 def is_cpp_comparison(self): |
| 9810 return self.operand1.type.is_cpp_class or self.operand2.type.is_cpp_clas
s |
| 9811 |
| 9812 def find_common_int_type(self, env, op, operand1, operand2): |
| 9813 # type1 != type2 and at least one of the types is not a C int |
| 9814 type1 = operand1.type |
| 9815 type2 = operand2.type |
| 9816 type1_can_be_int = False |
| 9817 type2_can_be_int = False |
| 9818 |
| 9819 if operand1.is_string_literal and operand1.can_coerce_to_char_literal(): |
| 9820 type1_can_be_int = True |
| 9821 if operand2.is_string_literal and operand2.can_coerce_to_char_literal(): |
| 9822 type2_can_be_int = True |
| 9823 |
| 9824 if type1.is_int: |
| 9825 if type2_can_be_int: |
| 9826 return type1 |
| 9827 elif type2.is_int: |
| 9828 if type1_can_be_int: |
| 9829 return type2 |
| 9830 elif type1_can_be_int: |
| 9831 if type2_can_be_int: |
| 9832 if Builtin.unicode_type in (type1, type2): |
| 9833 return PyrexTypes.c_py_ucs4_type |
| 9834 else: |
| 9835 return PyrexTypes.c_uchar_type |
| 9836 |
| 9837 return None |
| 9838 |
| 9839 def find_common_type(self, env, op, operand1, common_type=None): |
| 9840 operand2 = self.operand2 |
| 9841 type1 = operand1.type |
| 9842 type2 = operand2.type |
| 9843 |
| 9844 new_common_type = None |
| 9845 |
| 9846 # catch general errors |
| 9847 if type1 == str_type and (type2.is_string or type2 in (bytes_type, unico
de_type)) or \ |
| 9848 type2 == str_type and (type1.is_string or type1 in (bytes_type, u
nicode_type)): |
| 9849 error(self.pos, "Comparisons between bytes/unicode and str are not p
ortable to Python 3") |
| 9850 new_common_type = error_type |
| 9851 |
| 9852 # try to use numeric comparisons where possible |
| 9853 elif type1.is_complex or type2.is_complex: |
| 9854 if op not in ('==', '!=') \ |
| 9855 and (type1.is_complex or type1.is_numeric) \ |
| 9856 and (type2.is_complex or type2.is_numeric): |
| 9857 error(self.pos, "complex types are unordered") |
| 9858 new_common_type = error_type |
| 9859 elif type1.is_pyobject: |
| 9860 new_common_type = type1 |
| 9861 elif type2.is_pyobject: |
| 9862 new_common_type = type2 |
| 9863 else: |
| 9864 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) |
| 9865 elif type1.is_numeric and type2.is_numeric: |
| 9866 new_common_type = PyrexTypes.widest_numeric_type(type1, type2) |
| 9867 elif common_type is None or not common_type.is_pyobject: |
| 9868 new_common_type = self.find_common_int_type(env, op, operand1, opera
nd2) |
| 9869 |
| 9870 if new_common_type is None: |
| 9871 # fall back to generic type compatibility tests |
| 9872 if type1 == type2: |
| 9873 new_common_type = type1 |
| 9874 elif type1.is_pyobject or type2.is_pyobject: |
| 9875 if type2.is_numeric or type2.is_string: |
| 9876 if operand2.check_for_coercion_error(type1, env): |
| 9877 new_common_type = error_type |
| 9878 else: |
| 9879 new_common_type = py_object_type |
| 9880 elif type1.is_numeric or type1.is_string: |
| 9881 if operand1.check_for_coercion_error(type2, env): |
| 9882 new_common_type = error_type |
| 9883 else: |
| 9884 new_common_type = py_object_type |
| 9885 elif py_object_type.assignable_from(type1) and py_object_type.as
signable_from(type2): |
| 9886 new_common_type = py_object_type |
| 9887 else: |
| 9888 # one Python type and one non-Python type, not assignable |
| 9889 self.invalid_types_error(operand1, op, operand2) |
| 9890 new_common_type = error_type |
| 9891 elif type1.assignable_from(type2): |
| 9892 new_common_type = type1 |
| 9893 elif type2.assignable_from(type1): |
| 9894 new_common_type = type2 |
| 9895 else: |
| 9896 # C types that we couldn't handle up to here are an error |
| 9897 self.invalid_types_error(operand1, op, operand2) |
| 9898 new_common_type = error_type |
| 9899 |
| 9900 if new_common_type.is_string and (isinstance(operand1, BytesNode) or |
| 9901 isinstance(operand2, BytesNode)): |
| 9902 # special case when comparing char* to bytes literal: must |
| 9903 # compare string values! |
| 9904 new_common_type = bytes_type |
| 9905 |
| 9906 # recursively merge types |
| 9907 if common_type is None or new_common_type.is_error: |
| 9908 common_type = new_common_type |
| 9909 else: |
| 9910 # we could do a lot better by splitting the comparison |
| 9911 # into a non-Python part and a Python part, but this is |
| 9912 # safer for now |
| 9913 common_type = PyrexTypes.spanning_type(common_type, new_common_type) |
| 9914 |
| 9915 if self.cascade: |
| 9916 common_type = self.cascade.find_common_type(env, self.operator, oper
and2, common_type) |
| 9917 |
| 9918 return common_type |
| 9919 |
| 9920 def invalid_types_error(self, operand1, op, operand2): |
| 9921 error(self.pos, "Invalid types for '%s' (%s, %s)" % |
| 9922 (op, operand1.type, operand2.type)) |
| 9923 |
| 9924 def is_python_comparison(self): |
| 9925 return (not self.is_ptr_contains() |
| 9926 and not self.is_c_string_contains() |
| 9927 and (self.has_python_operands() |
| 9928 or (self.cascade and self.cascade.is_python_comparison()) |
| 9929 or self.operator in ('in', 'not_in'))) |
| 9930 |
| 9931 def coerce_operands_to(self, dst_type, env): |
| 9932 operand2 = self.operand2 |
| 9933 if operand2.type != dst_type: |
| 9934 self.operand2 = operand2.coerce_to(dst_type, env) |
| 9935 if self.cascade: |
| 9936 self.cascade.coerce_operands_to(dst_type, env) |
| 9937 |
| 9938 def is_python_result(self): |
| 9939 return ((self.has_python_operands() and |
| 9940 self.special_bool_cmp_function is None and |
| 9941 self.operator not in ('is', 'is_not', 'in', 'not_in') and |
| 9942 not self.is_c_string_contains() and |
| 9943 not self.is_ptr_contains()) |
| 9944 or (self.cascade and self.cascade.is_python_result())) |
| 9945 |
| 9946 def is_c_string_contains(self): |
| 9947 return self.operator in ('in', 'not_in') and \ |
| 9948 ((self.operand1.type.is_int |
| 9949 and (self.operand2.type.is_string or self.operand2.type is byte
s_type)) or |
| 9950 (self.operand1.type.is_unicode_char |
| 9951 and self.operand2.type is unicode_type)) |
| 9952 |
| 9953 def is_ptr_contains(self): |
| 9954 if self.operator in ('in', 'not_in'): |
| 9955 container_type = self.operand2.type |
| 9956 return (container_type.is_ptr or container_type.is_array) \ |
| 9957 and not container_type.is_string |
| 9958 |
| 9959 def find_special_bool_compare_function(self, env, operand1, result_is_bool=F
alse): |
| 9960 # note: currently operand1 must get coerced to a Python object if we suc
ceed here! |
| 9961 if self.operator in ('==', '!='): |
| 9962 type1, type2 = operand1.type, self.operand2.type |
| 9963 if result_is_bool or (type1.is_builtin_type and type2.is_builtin_typ
e): |
| 9964 if type1 is Builtin.unicode_type or type2 is Builtin.unicode_typ
e: |
| 9965 self.special_bool_cmp_utility_code = UtilityCode.load_cached
("UnicodeEquals", "StringTools.c") |
| 9966 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" |
| 9967 return True |
| 9968 elif type1 is Builtin.bytes_type or type2 is Builtin.bytes_type: |
| 9969 self.special_bool_cmp_utility_code = UtilityCode.load_cached
("BytesEquals", "StringTools.c") |
| 9970 self.special_bool_cmp_function = "__Pyx_PyBytes_Equals" |
| 9971 return True |
| 9972 elif type1 is Builtin.basestring_type or type2 is Builtin.basest
ring_type: |
| 9973 self.special_bool_cmp_utility_code = UtilityCode.load_cached
("UnicodeEquals", "StringTools.c") |
| 9974 self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals" |
| 9975 return True |
| 9976 elif type1 is Builtin.str_type or type2 is Builtin.str_type: |
| 9977 self.special_bool_cmp_utility_code = UtilityCode.load_cached
("StrEquals", "StringTools.c") |
| 9978 self.special_bool_cmp_function = "__Pyx_PyString_Equals" |
| 9979 return True |
| 9980 elif self.operator in ('in', 'not_in'): |
| 9981 if self.operand2.type is Builtin.dict_type: |
| 9982 self.operand2 = self.operand2.as_none_safe_node("'NoneType' obje
ct is not iterable") |
| 9983 self.special_bool_cmp_utility_code = UtilityCode.load_cached("Py
DictContains", "ObjectHandling.c") |
| 9984 self.special_bool_cmp_function = "__Pyx_PyDict_Contains" |
| 9985 return True |
| 9986 elif self.operand2.type is Builtin.unicode_type: |
| 9987 self.operand2 = self.operand2.as_none_safe_node("'NoneType' obje
ct is not iterable") |
| 9988 self.special_bool_cmp_utility_code = UtilityCode.load_cached("Py
UnicodeContains", "StringTools.c") |
| 9989 self.special_bool_cmp_function = "__Pyx_PyUnicode_Contains" |
| 9990 return True |
| 9991 else: |
| 9992 if not self.operand2.type.is_pyobject: |
| 9993 self.operand2 = self.operand2.coerce_to_pyobject(env) |
| 9994 self.special_bool_cmp_utility_code = UtilityCode.load_cached("Py
SequenceContains", "ObjectHandling.c") |
| 9995 self.special_bool_cmp_function = "__Pyx_PySequence_Contains" |
| 9996 return True |
| 9997 return False |
| 9998 |
| 9999 def generate_operation_code(self, code, result_code, |
| 10000 operand1, op , operand2): |
| 10001 if self.type.is_pyobject: |
| 10002 error_clause = code.error_goto_if_null |
| 10003 got_ref = "__Pyx_XGOTREF(%s); " % result_code |
| 10004 if self.special_bool_cmp_function: |
| 10005 code.globalstate.use_utility_code( |
| 10006 UtilityCode.load_cached("PyBoolOrNullFromLong", "ObjectHandl
ing.c")) |
| 10007 coerce_result = "__Pyx_PyBoolOrNull_FromLong" |
| 10008 else: |
| 10009 coerce_result = "__Pyx_PyBool_FromLong" |
| 10010 else: |
| 10011 error_clause = code.error_goto_if_neg |
| 10012 got_ref = "" |
| 10013 coerce_result = "" |
| 10014 |
| 10015 if self.special_bool_cmp_function: |
| 10016 if operand1.type.is_pyobject: |
| 10017 result1 = operand1.py_result() |
| 10018 else: |
| 10019 result1 = operand1.result() |
| 10020 if operand2.type.is_pyobject: |
| 10021 result2 = operand2.py_result() |
| 10022 else: |
| 10023 result2 = operand2.result() |
| 10024 if self.special_bool_cmp_utility_code: |
| 10025 code.globalstate.use_utility_code(self.special_bool_cmp_utility_
code) |
| 10026 code.putln( |
| 10027 "%s = %s(%s(%s, %s, %s)); %s%s" % ( |
| 10028 result_code, |
| 10029 coerce_result, |
| 10030 self.special_bool_cmp_function, |
| 10031 result1, result2, richcmp_constants[op], |
| 10032 got_ref, |
| 10033 error_clause(result_code, self.pos))) |
| 10034 |
| 10035 elif operand1.type.is_pyobject and op not in ('is', 'is_not'): |
| 10036 assert op not in ('in', 'not_in'), op |
| 10037 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s%s" % ( |
| 10038 result_code, |
| 10039 operand1.py_result(), |
| 10040 operand2.py_result(), |
| 10041 richcmp_constants[op], |
| 10042 got_ref, |
| 10043 error_clause(result_code, self.pos))) |
| 10044 |
| 10045 elif operand1.type.is_complex: |
| 10046 code.putln("%s = %s(%s%s(%s, %s));" % ( |
| 10047 result_code, |
| 10048 coerce_result, |
| 10049 op == "!=" and "!" or "", |
| 10050 operand1.type.unary_op('eq'), |
| 10051 operand1.result(), |
| 10052 operand2.result())) |
| 10053 |
| 10054 else: |
| 10055 type1 = operand1.type |
| 10056 type2 = operand2.type |
| 10057 if (type1.is_extension_type or type2.is_extension_type) \ |
| 10058 and not type1.same_as(type2): |
| 10059 common_type = py_object_type |
| 10060 elif type1.is_numeric: |
| 10061 common_type = PyrexTypes.widest_numeric_type(type1, type2) |
| 10062 else: |
| 10063 common_type = type1 |
| 10064 code1 = operand1.result_as(common_type) |
| 10065 code2 = operand2.result_as(common_type) |
| 10066 code.putln("%s = %s(%s %s %s);" % ( |
| 10067 result_code, |
| 10068 coerce_result, |
| 10069 code1, |
| 10070 self.c_operator(op), |
| 10071 code2)) |
| 10072 |
| 10073 def c_operator(self, op): |
| 10074 if op == 'is': |
| 10075 return "==" |
| 10076 elif op == 'is_not': |
| 10077 return "!=" |
| 10078 else: |
| 10079 return op |
| 10080 |
| 10081 class PrimaryCmpNode(ExprNode, CmpNode): |
| 10082 # Non-cascaded comparison or first comparison of |
| 10083 # a cascaded sequence. |
| 10084 # |
| 10085 # operator string |
| 10086 # operand1 ExprNode |
| 10087 # operand2 ExprNode |
| 10088 # cascade CascadedCmpNode |
| 10089 |
| 10090 # We don't use the subexprs mechanism, because |
| 10091 # things here are too complicated for it to handle. |
| 10092 # Instead, we override all the framework methods |
| 10093 # which use it. |
| 10094 |
| 10095 child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade'] |
| 10096 |
| 10097 cascade = None |
| 10098 coerced_operand2 = None |
| 10099 is_memslice_nonecheck = False |
| 10100 |
| 10101 def infer_type(self, env): |
| 10102 # TODO: Actually implement this (after merging with -unstable). |
| 10103 return py_object_type |
| 10104 |
| 10105 def type_dependencies(self, env): |
| 10106 return () |
| 10107 |
| 10108 def calculate_constant_result(self): |
| 10109 assert not self.cascade |
| 10110 self.calculate_cascaded_constant_result(self.operand1.constant_result) |
| 10111 |
| 10112 def compile_time_value(self, denv): |
| 10113 operand1 = self.operand1.compile_time_value(denv) |
| 10114 return self.cascaded_compile_time_value(operand1, denv) |
| 10115 |
| 10116 def analyse_types(self, env): |
| 10117 self.operand1 = self.operand1.analyse_types(env) |
| 10118 self.operand2 = self.operand2.analyse_types(env) |
| 10119 if self.is_cpp_comparison(): |
| 10120 self.analyse_cpp_comparison(env) |
| 10121 if self.cascade: |
| 10122 error(self.pos, "Cascading comparison not yet supported for cpp
types.") |
| 10123 return self |
| 10124 |
| 10125 if self.analyse_memoryviewslice_comparison(env): |
| 10126 return self |
| 10127 |
| 10128 if self.cascade: |
| 10129 self.cascade = self.cascade.analyse_types(env) |
| 10130 |
| 10131 if self.operator in ('in', 'not_in'): |
| 10132 if self.is_c_string_contains(): |
| 10133 self.is_pycmp = False |
| 10134 common_type = None |
| 10135 if self.cascade: |
| 10136 error(self.pos, "Cascading comparison not yet supported for
'int_val in string'.") |
| 10137 return self |
| 10138 if self.operand2.type is unicode_type: |
| 10139 env.use_utility_code(UtilityCode.load_cached("PyUCS4InUnicod
e", "StringTools.c")) |
| 10140 else: |
| 10141 if self.operand1.type is PyrexTypes.c_uchar_type: |
| 10142 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_cha
r_type, env) |
| 10143 if self.operand2.type is not bytes_type: |
| 10144 self.operand2 = self.operand2.coerce_to(bytes_type, env) |
| 10145 env.use_utility_code(UtilityCode.load_cached("BytesContains"
, "StringTools.c")) |
| 10146 self.operand2 = self.operand2.as_none_safe_node( |
| 10147 "argument of type 'NoneType' is not iterable") |
| 10148 elif self.is_ptr_contains(): |
| 10149 if self.cascade: |
| 10150 error(self.pos, "Cascading comparison not supported for 'val
in sliced pointer'.") |
| 10151 self.type = PyrexTypes.c_bint_type |
| 10152 # Will be transformed by IterationTransform |
| 10153 return self |
| 10154 elif self.find_special_bool_compare_function(env, self.operand1): |
| 10155 if not self.operand1.type.is_pyobject: |
| 10156 self.operand1 = self.operand1.coerce_to_pyobject(env) |
| 10157 common_type = None # if coercion needed, the method call above h
as already done it |
| 10158 self.is_pycmp = False # result is bint |
| 10159 else: |
| 10160 common_type = py_object_type |
| 10161 self.is_pycmp = True |
| 10162 elif self.find_special_bool_compare_function(env, self.operand1): |
| 10163 if not self.operand1.type.is_pyobject: |
| 10164 self.operand1 = self.operand1.coerce_to_pyobject(env) |
| 10165 common_type = None # if coercion needed, the method call above has a
lready done it |
| 10166 self.is_pycmp = False # result is bint |
| 10167 else: |
| 10168 common_type = self.find_common_type(env, self.operator, self.operand
1) |
| 10169 self.is_pycmp = common_type.is_pyobject |
| 10170 |
| 10171 if common_type is not None and not common_type.is_error: |
| 10172 if self.operand1.type != common_type: |
| 10173 self.operand1 = self.operand1.coerce_to(common_type, env) |
| 10174 self.coerce_operands_to(common_type, env) |
| 10175 |
| 10176 if self.cascade: |
| 10177 self.operand2 = self.operand2.coerce_to_simple(env) |
| 10178 self.cascade.coerce_cascaded_operands_to_temp(env) |
| 10179 operand2 = self.cascade.optimise_comparison(self.operand2, env) |
| 10180 if operand2 is not self.operand2: |
| 10181 self.coerced_operand2 = operand2 |
| 10182 if self.is_python_result(): |
| 10183 self.type = PyrexTypes.py_object_type |
| 10184 else: |
| 10185 self.type = PyrexTypes.c_bint_type |
| 10186 cdr = self.cascade |
| 10187 while cdr: |
| 10188 cdr.type = self.type |
| 10189 cdr = cdr.cascade |
| 10190 if self.is_pycmp or self.cascade or self.special_bool_cmp_function: |
| 10191 # 1) owned reference, 2) reused value, 3) potential function error r
eturn value |
| 10192 self.is_temp = 1 |
| 10193 return self |
| 10194 |
| 10195 def analyse_cpp_comparison(self, env): |
| 10196 type1 = self.operand1.type |
| 10197 type2 = self.operand2.type |
| 10198 entry = env.lookup_operator(self.operator, [self.operand1, self.operand2
]) |
| 10199 if entry is None: |
| 10200 error(self.pos, "Invalid types for '%s' (%s, %s)" % |
| 10201 (self.operator, type1, type2)) |
| 10202 self.type = PyrexTypes.error_type |
| 10203 self.result_code = "<error>" |
| 10204 return |
| 10205 func_type = entry.type |
| 10206 if func_type.is_ptr: |
| 10207 func_type = func_type.base_type |
| 10208 if len(func_type.args) == 1: |
| 10209 self.operand2 = self.operand2.coerce_to(func_type.args[0].type, env) |
| 10210 else: |
| 10211 self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) |
| 10212 self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) |
| 10213 self.is_pycmp = False |
| 10214 self.type = func_type.return_type |
| 10215 |
| 10216 def analyse_memoryviewslice_comparison(self, env): |
| 10217 have_none = self.operand1.is_none or self.operand2.is_none |
| 10218 have_slice = (self.operand1.type.is_memoryviewslice or |
| 10219 self.operand2.type.is_memoryviewslice) |
| 10220 ops = ('==', '!=', 'is', 'is_not') |
| 10221 if have_slice and have_none and self.operator in ops: |
| 10222 self.is_pycmp = False |
| 10223 self.type = PyrexTypes.c_bint_type |
| 10224 self.is_memslice_nonecheck = True |
| 10225 return True |
| 10226 |
| 10227 return False |
| 10228 |
| 10229 def coerce_to_boolean(self, env): |
| 10230 if self.is_pycmp: |
| 10231 # coercing to bool => may allow for more efficient comparison code |
| 10232 if self.find_special_bool_compare_function( |
| 10233 env, self.operand1, result_is_bool=True): |
| 10234 self.is_pycmp = False |
| 10235 self.type = PyrexTypes.c_bint_type |
| 10236 self.is_temp = 1 |
| 10237 if self.cascade: |
| 10238 operand2 = self.cascade.optimise_comparison( |
| 10239 self.operand2, env, result_is_bool=True) |
| 10240 if operand2 is not self.operand2: |
| 10241 self.coerced_operand2 = operand2 |
| 10242 return self |
| 10243 # TODO: check if we can optimise parts of the cascade here |
| 10244 return ExprNode.coerce_to_boolean(self, env) |
| 10245 |
| 10246 def has_python_operands(self): |
| 10247 return (self.operand1.type.is_pyobject |
| 10248 or self.operand2.type.is_pyobject) |
| 10249 |
| 10250 def check_const(self): |
| 10251 if self.cascade: |
| 10252 self.not_const() |
| 10253 return False |
| 10254 else: |
| 10255 return self.operand1.check_const() and self.operand2.check_const() |
| 10256 |
| 10257 def calculate_result_code(self): |
| 10258 if self.operand1.type.is_complex: |
| 10259 if self.operator == "!=": |
| 10260 negation = "!" |
| 10261 else: |
| 10262 negation = "" |
| 10263 return "(%s%s(%s, %s))" % ( |
| 10264 negation, |
| 10265 self.operand1.type.binary_op('=='), |
| 10266 self.operand1.result(), |
| 10267 self.operand2.result()) |
| 10268 elif self.is_c_string_contains(): |
| 10269 if self.operand2.type is unicode_type: |
| 10270 method = "__Pyx_UnicodeContainsUCS4" |
| 10271 else: |
| 10272 method = "__Pyx_BytesContains" |
| 10273 if self.operator == "not_in": |
| 10274 negation = "!" |
| 10275 else: |
| 10276 negation = "" |
| 10277 return "(%s%s(%s, %s))" % ( |
| 10278 negation, |
| 10279 method, |
| 10280 self.operand2.result(), |
| 10281 self.operand1.result()) |
| 10282 else: |
| 10283 result1 = self.operand1.result() |
| 10284 result2 = self.operand2.result() |
| 10285 if self.is_memslice_nonecheck: |
| 10286 if self.operand1.type.is_memoryviewslice: |
| 10287 result1 = "((PyObject *) %s.memview)" % result1 |
| 10288 else: |
| 10289 result2 = "((PyObject *) %s.memview)" % result2 |
| 10290 |
| 10291 return "(%s %s %s)" % ( |
| 10292 result1, |
| 10293 self.c_operator(self.operator), |
| 10294 result2) |
| 10295 |
| 10296 def generate_evaluation_code(self, code): |
| 10297 self.operand1.generate_evaluation_code(code) |
| 10298 self.operand2.generate_evaluation_code(code) |
| 10299 if self.is_temp: |
| 10300 self.allocate_temp_result(code) |
| 10301 self.generate_operation_code(code, self.result(), |
| 10302 self.operand1, self.operator, self.operand2) |
| 10303 if self.cascade: |
| 10304 self.cascade.generate_evaluation_code( |
| 10305 code, self.result(), self.coerced_operand2 or self.operand2, |
| 10306 needs_evaluation=self.coerced_operand2 is not None) |
| 10307 self.operand1.generate_disposal_code(code) |
| 10308 self.operand1.free_temps(code) |
| 10309 self.operand2.generate_disposal_code(code) |
| 10310 self.operand2.free_temps(code) |
| 10311 |
| 10312 def generate_subexpr_disposal_code(self, code): |
| 10313 # If this is called, it is a non-cascaded cmp, |
| 10314 # so only need to dispose of the two main operands. |
| 10315 self.operand1.generate_disposal_code(code) |
| 10316 self.operand2.generate_disposal_code(code) |
| 10317 |
| 10318 def free_subexpr_temps(self, code): |
| 10319 # If this is called, it is a non-cascaded cmp, |
| 10320 # so only need to dispose of the two main operands. |
| 10321 self.operand1.free_temps(code) |
| 10322 self.operand2.free_temps(code) |
| 10323 |
| 10324 def annotate(self, code): |
| 10325 self.operand1.annotate(code) |
| 10326 self.operand2.annotate(code) |
| 10327 if self.cascade: |
| 10328 self.cascade.annotate(code) |
| 10329 |
| 10330 |
| 10331 class CascadedCmpNode(Node, CmpNode): |
| 10332 # A CascadedCmpNode is not a complete expression node. It |
| 10333 # hangs off the side of another comparison node, shares |
| 10334 # its left operand with that node, and shares its result |
| 10335 # with the PrimaryCmpNode at the head of the chain. |
| 10336 # |
| 10337 # operator string |
| 10338 # operand2 ExprNode |
| 10339 # cascade CascadedCmpNode |
| 10340 |
| 10341 child_attrs = ['operand2', 'coerced_operand2', 'cascade'] |
| 10342 |
| 10343 cascade = None |
| 10344 coerced_operand2 = None |
| 10345 constant_result = constant_value_not_set # FIXME: where to calculate this? |
| 10346 |
| 10347 def infer_type(self, env): |
| 10348 # TODO: Actually implement this (after merging with -unstable). |
| 10349 return py_object_type |
| 10350 |
| 10351 def type_dependencies(self, env): |
| 10352 return () |
| 10353 |
| 10354 def has_constant_result(self): |
| 10355 return self.constant_result is not constant_value_not_set and \ |
| 10356 self.constant_result is not not_a_constant |
| 10357 |
| 10358 def analyse_types(self, env): |
| 10359 self.operand2 = self.operand2.analyse_types(env) |
| 10360 if self.cascade: |
| 10361 self.cascade = self.cascade.analyse_types(env) |
| 10362 return self |
| 10363 |
| 10364 def has_python_operands(self): |
| 10365 return self.operand2.type.is_pyobject |
| 10366 |
| 10367 def optimise_comparison(self, operand1, env, result_is_bool=False): |
| 10368 if self.find_special_bool_compare_function(env, operand1, result_is_bool
): |
| 10369 self.is_pycmp = False |
| 10370 self.type = PyrexTypes.c_bint_type |
| 10371 if not operand1.type.is_pyobject: |
| 10372 operand1 = operand1.coerce_to_pyobject(env) |
| 10373 if self.cascade: |
| 10374 operand2 = self.cascade.optimise_comparison(self.operand2, env, resu
lt_is_bool) |
| 10375 if operand2 is not self.operand2: |
| 10376 self.coerced_operand2 = operand2 |
| 10377 return operand1 |
| 10378 |
| 10379 def coerce_operands_to_pyobjects(self, env): |
| 10380 self.operand2 = self.operand2.coerce_to_pyobject(env) |
| 10381 if self.operand2.type is dict_type and self.operator in ('in', 'not_in')
: |
| 10382 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object i
s not iterable") |
| 10383 if self.cascade: |
| 10384 self.cascade.coerce_operands_to_pyobjects(env) |
| 10385 |
| 10386 def coerce_cascaded_operands_to_temp(self, env): |
| 10387 if self.cascade: |
| 10388 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT |
| 10389 self.operand2 = self.operand2.coerce_to_simple(env) |
| 10390 self.cascade.coerce_cascaded_operands_to_temp(env) |
| 10391 |
| 10392 def generate_evaluation_code(self, code, result, operand1, needs_evaluation=
False): |
| 10393 if self.type.is_pyobject: |
| 10394 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result) |
| 10395 code.put_decref(result, self.type) |
| 10396 else: |
| 10397 code.putln("if (%s) {" % result) |
| 10398 if needs_evaluation: |
| 10399 operand1.generate_evaluation_code(code) |
| 10400 self.operand2.generate_evaluation_code(code) |
| 10401 self.generate_operation_code(code, result, |
| 10402 operand1, self.operator, self.operand2) |
| 10403 if self.cascade: |
| 10404 self.cascade.generate_evaluation_code( |
| 10405 code, result, self.coerced_operand2 or self.operand2, |
| 10406 needs_evaluation=self.coerced_operand2 is not None) |
| 10407 if needs_evaluation: |
| 10408 operand1.generate_disposal_code(code) |
| 10409 operand1.free_temps(code) |
| 10410 # Cascaded cmp result is always temp |
| 10411 self.operand2.generate_disposal_code(code) |
| 10412 self.operand2.free_temps(code) |
| 10413 code.putln("}") |
| 10414 |
| 10415 def annotate(self, code): |
| 10416 self.operand2.annotate(code) |
| 10417 if self.cascade: |
| 10418 self.cascade.annotate(code) |
| 10419 |
| 10420 |
| 10421 binop_node_classes = { |
| 10422 "or": BoolBinopNode, |
| 10423 "and": BoolBinopNode, |
| 10424 "|": IntBinopNode, |
| 10425 "^": IntBinopNode, |
| 10426 "&": IntBinopNode, |
| 10427 "<<": IntBinopNode, |
| 10428 ">>": IntBinopNode, |
| 10429 "+": AddNode, |
| 10430 "-": SubNode, |
| 10431 "*": MulNode, |
| 10432 "/": DivNode, |
| 10433 "//": DivNode, |
| 10434 "%": ModNode, |
| 10435 "**": PowNode |
| 10436 } |
| 10437 |
| 10438 def binop_node(pos, operator, operand1, operand2, inplace=False): |
| 10439 # Construct binop node of appropriate class for |
| 10440 # given operator. |
| 10441 return binop_node_classes[operator](pos, |
| 10442 operator = operator, |
| 10443 operand1 = operand1, |
| 10444 operand2 = operand2, |
| 10445 inplace = inplace) |
| 10446 |
| 10447 #------------------------------------------------------------------- |
| 10448 # |
| 10449 # Coercion nodes |
| 10450 # |
| 10451 # Coercion nodes are special in that they are created during |
| 10452 # the analyse_types phase of parse tree processing. |
| 10453 # Their __init__ methods consequently incorporate some aspects |
| 10454 # of that phase. |
| 10455 # |
| 10456 #------------------------------------------------------------------- |
| 10457 |
| 10458 class CoercionNode(ExprNode): |
| 10459 # Abstract base class for coercion nodes. |
| 10460 # |
| 10461 # arg ExprNode node being coerced |
| 10462 |
| 10463 subexprs = ['arg'] |
| 10464 constant_result = not_a_constant |
| 10465 |
| 10466 def __init__(self, arg): |
| 10467 super(CoercionNode, self).__init__(arg.pos) |
| 10468 self.arg = arg |
| 10469 if debug_coercion: |
| 10470 print("%s Coercing %s" % (self, self.arg)) |
| 10471 |
| 10472 def calculate_constant_result(self): |
| 10473 # constant folding can break type coercion, so this is disabled |
| 10474 pass |
| 10475 |
| 10476 def annotate(self, code): |
| 10477 self.arg.annotate(code) |
| 10478 if self.arg.type != self.type: |
| 10479 file, line, col = self.pos |
| 10480 code.annotate((file, line, col-1), AnnotationItem( |
| 10481 style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.ty
pe, self.type))) |
| 10482 |
| 10483 class CoerceToMemViewSliceNode(CoercionNode): |
| 10484 """ |
| 10485 Coerce an object to a memoryview slice. This holds a new reference in |
| 10486 a managed temp. |
| 10487 """ |
| 10488 |
| 10489 def __init__(self, arg, dst_type, env): |
| 10490 assert dst_type.is_memoryviewslice |
| 10491 assert not arg.type.is_memoryviewslice |
| 10492 CoercionNode.__init__(self, arg) |
| 10493 self.type = dst_type |
| 10494 self.is_temp = 1 |
| 10495 self.env = env |
| 10496 self.use_managed_ref = True |
| 10497 self.arg = arg |
| 10498 |
| 10499 def generate_result_code(self, code): |
| 10500 self.type.create_from_py_utility_code(self.env) |
| 10501 code.putln("%s = %s(%s);" % (self.result(), |
| 10502 self.type.from_py_function, |
| 10503 self.arg.py_result())) |
| 10504 |
| 10505 error_cond = self.type.error_condition(self.result()) |
| 10506 code.putln(code.error_goto_if(error_cond, self.pos)) |
| 10507 |
| 10508 |
| 10509 class CastNode(CoercionNode): |
| 10510 # Wrap a node in a C type cast. |
| 10511 |
| 10512 def __init__(self, arg, new_type): |
| 10513 CoercionNode.__init__(self, arg) |
| 10514 self.type = new_type |
| 10515 |
| 10516 def may_be_none(self): |
| 10517 return self.arg.may_be_none() |
| 10518 |
| 10519 def calculate_result_code(self): |
| 10520 return self.arg.result_as(self.type) |
| 10521 |
| 10522 def generate_result_code(self, code): |
| 10523 self.arg.generate_result_code(code) |
| 10524 |
| 10525 |
| 10526 class PyTypeTestNode(CoercionNode): |
| 10527 # This node is used to check that a generic Python |
| 10528 # object is an instance of a particular extension type. |
| 10529 # This node borrows the result of its argument node. |
| 10530 |
| 10531 exact_builtin_type = True |
| 10532 |
| 10533 def __init__(self, arg, dst_type, env, notnone=False): |
| 10534 # The arg is know to be a Python object, and |
| 10535 # the dst_type is known to be an extension type. |
| 10536 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTe
st on non extension type" |
| 10537 CoercionNode.__init__(self, arg) |
| 10538 self.type = dst_type |
| 10539 self.result_ctype = arg.ctype() |
| 10540 self.notnone = notnone |
| 10541 |
| 10542 nogil_check = Node.gil_error |
| 10543 gil_message = "Python type test" |
| 10544 |
| 10545 def analyse_types(self, env): |
| 10546 return self |
| 10547 |
| 10548 def may_be_none(self): |
| 10549 if self.notnone: |
| 10550 return False |
| 10551 return self.arg.may_be_none() |
| 10552 |
| 10553 def is_simple(self): |
| 10554 return self.arg.is_simple() |
| 10555 |
| 10556 def result_in_temp(self): |
| 10557 return self.arg.result_in_temp() |
| 10558 |
| 10559 def is_ephemeral(self): |
| 10560 return self.arg.is_ephemeral() |
| 10561 |
| 10562 def nonlocally_immutable(self): |
| 10563 return self.arg.nonlocally_immutable() |
| 10564 |
| 10565 def calculate_constant_result(self): |
| 10566 # FIXME |
| 10567 pass |
| 10568 |
| 10569 def calculate_result_code(self): |
| 10570 return self.arg.result() |
| 10571 |
| 10572 def generate_result_code(self, code): |
| 10573 if self.type.typeobj_is_available(): |
| 10574 if self.type.is_builtin_type: |
| 10575 type_test = self.type.type_test_code( |
| 10576 self.arg.py_result(), |
| 10577 self.notnone, exact=self.exact_builtin_type) |
| 10578 else: |
| 10579 type_test = self.type.type_test_code( |
| 10580 self.arg.py_result(), self.notnone) |
| 10581 code.globalstate.use_utility_code( |
| 10582 UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c")) |
| 10583 code.putln("if (!(%s)) %s" % ( |
| 10584 type_test, code.error_goto(self.pos))) |
| 10585 else: |
| 10586 error(self.pos, "Cannot test type of extern C class " |
| 10587 "without type object name specification") |
| 10588 |
| 10589 def generate_post_assignment_code(self, code): |
| 10590 self.arg.generate_post_assignment_code(code) |
| 10591 |
| 10592 def free_temps(self, code): |
| 10593 self.arg.free_temps(code) |
| 10594 |
| 10595 |
| 10596 class NoneCheckNode(CoercionNode): |
| 10597 # This node is used to check that a Python object is not None and |
| 10598 # raises an appropriate exception (as specified by the creating |
| 10599 # transform). |
| 10600 |
| 10601 is_nonecheck = True |
| 10602 |
| 10603 def __init__(self, arg, exception_type_cname, exception_message, |
| 10604 exception_format_args): |
| 10605 CoercionNode.__init__(self, arg) |
| 10606 self.type = arg.type |
| 10607 self.result_ctype = arg.ctype() |
| 10608 self.exception_type_cname = exception_type_cname |
| 10609 self.exception_message = exception_message |
| 10610 self.exception_format_args = tuple(exception_format_args or ()) |
| 10611 |
| 10612 nogil_check = None # this node only guards an operation that would fail alre
ady |
| 10613 |
| 10614 def analyse_types(self, env): |
| 10615 return self |
| 10616 |
| 10617 def may_be_none(self): |
| 10618 return False |
| 10619 |
| 10620 def is_simple(self): |
| 10621 return self.arg.is_simple() |
| 10622 |
| 10623 def result_in_temp(self): |
| 10624 return self.arg.result_in_temp() |
| 10625 |
| 10626 def nonlocally_immutable(self): |
| 10627 return self.arg.nonlocally_immutable() |
| 10628 |
| 10629 def calculate_result_code(self): |
| 10630 return self.arg.result() |
| 10631 |
| 10632 def condition(self): |
| 10633 if self.type.is_pyobject: |
| 10634 return self.arg.py_result() |
| 10635 elif self.type.is_memoryviewslice: |
| 10636 return "((PyObject *) %s.memview)" % self.arg.result() |
| 10637 else: |
| 10638 raise Exception("unsupported type") |
| 10639 |
| 10640 def put_nonecheck(self, code): |
| 10641 code.putln( |
| 10642 "if (unlikely(%s == Py_None)) {" % self.condition()) |
| 10643 |
| 10644 if self.in_nogil_context: |
| 10645 code.put_ensure_gil() |
| 10646 |
| 10647 escape = StringEncoding.escape_byte_string |
| 10648 if self.exception_format_args: |
| 10649 code.putln('PyErr_Format(%s, "%s", %s);' % ( |
| 10650 self.exception_type_cname, |
| 10651 StringEncoding.escape_byte_string( |
| 10652 self.exception_message.encode('UTF-8')), |
| 10653 ', '.join([ '"%s"' % escape(str(arg).encode('UTF-8')) |
| 10654 for arg in self.exception_format_args ]))) |
| 10655 else: |
| 10656 code.putln('PyErr_SetString(%s, "%s");' % ( |
| 10657 self.exception_type_cname, |
| 10658 escape(self.exception_message.encode('UTF-8')))) |
| 10659 |
| 10660 if self.in_nogil_context: |
| 10661 code.put_release_ensured_gil() |
| 10662 |
| 10663 code.putln(code.error_goto(self.pos)) |
| 10664 code.putln("}") |
| 10665 |
| 10666 def generate_result_code(self, code): |
| 10667 self.put_nonecheck(code) |
| 10668 |
| 10669 def generate_post_assignment_code(self, code): |
| 10670 self.arg.generate_post_assignment_code(code) |
| 10671 |
| 10672 def free_temps(self, code): |
| 10673 self.arg.free_temps(code) |
| 10674 |
| 10675 |
| 10676 class CoerceToPyTypeNode(CoercionNode): |
| 10677 # This node is used to convert a C data type |
| 10678 # to a Python object. |
| 10679 |
| 10680 type = py_object_type |
| 10681 is_temp = 1 |
| 10682 |
| 10683 def __init__(self, arg, env, type=py_object_type): |
| 10684 if not arg.type.create_to_py_utility_code(env): |
| 10685 error(arg.pos, "Cannot convert '%s' to Python object" % arg.type) |
| 10686 elif arg.type.is_complex: |
| 10687 # special case: complex coercion is so complex that it |
| 10688 # uses a macro ("__pyx_PyComplex_FromComplex()"), for |
| 10689 # which the argument must be simple |
| 10690 arg = arg.coerce_to_simple(env) |
| 10691 CoercionNode.__init__(self, arg) |
| 10692 if type is py_object_type: |
| 10693 # be specific about some known types |
| 10694 if arg.type.is_string or arg.type.is_cpp_string: |
| 10695 self.type = default_str_type(env) |
| 10696 elif arg.type.is_pyunicode_ptr or arg.type.is_unicode_char: |
| 10697 self.type = unicode_type |
| 10698 elif arg.type.is_complex: |
| 10699 self.type = Builtin.complex_type |
| 10700 elif arg.type.is_string or arg.type.is_cpp_string: |
| 10701 if (type not in (bytes_type, bytearray_type) |
| 10702 and not env.directives['c_string_encoding']): |
| 10703 error(arg.pos, |
| 10704 "default encoding required for conversion from '%s' to '%s'"
% |
| 10705 (arg.type, type)) |
| 10706 self.type = type |
| 10707 else: |
| 10708 # FIXME: check that the target type and the resulting type are compa
tible |
| 10709 pass |
| 10710 |
| 10711 if arg.type.is_memoryviewslice: |
| 10712 # Register utility codes at this point |
| 10713 arg.type.get_to_py_function(env, arg) |
| 10714 |
| 10715 self.env = env |
| 10716 |
| 10717 gil_message = "Converting to Python object" |
| 10718 |
| 10719 def may_be_none(self): |
| 10720 # FIXME: is this always safe? |
| 10721 return False |
| 10722 |
| 10723 def coerce_to_boolean(self, env): |
| 10724 arg_type = self.arg.type |
| 10725 if (arg_type == PyrexTypes.c_bint_type or |
| 10726 (arg_type.is_pyobject and arg_type.name == 'bool')): |
| 10727 return self.arg.coerce_to_temp(env) |
| 10728 else: |
| 10729 return CoerceToBooleanNode(self, env) |
| 10730 |
| 10731 def coerce_to_integer(self, env): |
| 10732 # If not already some C integer type, coerce to longint. |
| 10733 if self.arg.type.is_int: |
| 10734 return self.arg |
| 10735 else: |
| 10736 return self.arg.coerce_to(PyrexTypes.c_long_type, env) |
| 10737 |
| 10738 def analyse_types(self, env): |
| 10739 # The arg is always already analysed |
| 10740 return self |
| 10741 |
| 10742 def generate_result_code(self, code): |
| 10743 arg_type = self.arg.type |
| 10744 if arg_type.is_memoryviewslice: |
| 10745 funccall = arg_type.get_to_py_function(self.env, self.arg) |
| 10746 else: |
| 10747 func = arg_type.to_py_function |
| 10748 if arg_type.is_string or arg_type.is_cpp_string: |
| 10749 if self.type in (bytes_type, str_type, unicode_type): |
| 10750 func = func.replace("Object", self.type.name.title()) |
| 10751 elif self.type is bytearray_type: |
| 10752 func = func.replace("Object", "ByteArray") |
| 10753 funccall = "%s(%s)" % (func, self.arg.result()) |
| 10754 |
| 10755 code.putln('%s = %s; %s' % ( |
| 10756 self.result(), |
| 10757 funccall, |
| 10758 code.error_goto_if_null(self.result(), self.pos))) |
| 10759 |
| 10760 code.put_gotref(self.py_result()) |
| 10761 |
| 10762 |
| 10763 class CoerceIntToBytesNode(CoerceToPyTypeNode): |
| 10764 # This node is used to convert a C int type to a Python bytes |
| 10765 # object. |
| 10766 |
| 10767 is_temp = 1 |
| 10768 |
| 10769 def __init__(self, arg, env): |
| 10770 arg = arg.coerce_to_simple(env) |
| 10771 CoercionNode.__init__(self, arg) |
| 10772 self.type = Builtin.bytes_type |
| 10773 |
| 10774 def generate_result_code(self, code): |
| 10775 arg = self.arg |
| 10776 arg_result = arg.result() |
| 10777 if arg.type not in (PyrexTypes.c_char_type, |
| 10778 PyrexTypes.c_uchar_type, |
| 10779 PyrexTypes.c_schar_type): |
| 10780 if arg.type.signed: |
| 10781 code.putln("if ((%s < 0) || (%s > 255)) {" % ( |
| 10782 arg_result, arg_result)) |
| 10783 else: |
| 10784 code.putln("if (%s > 255) {" % arg_result) |
| 10785 code.putln('PyErr_SetString(PyExc_OverflowError, ' |
| 10786 '"value too large to pack into a byte"); %s' % ( |
| 10787 code.error_goto(self.pos))) |
| 10788 code.putln('}') |
| 10789 temp = None |
| 10790 if arg.type is not PyrexTypes.c_char_type: |
| 10791 temp = code.funcstate.allocate_temp(PyrexTypes.c_char_type, manage_r
ef=False) |
| 10792 code.putln("%s = (char)%s;" % (temp, arg_result)) |
| 10793 arg_result = temp |
| 10794 code.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % ( |
| 10795 self.result(), |
| 10796 arg_result, |
| 10797 code.error_goto_if_null(self.result(), self.pos))) |
| 10798 if temp is not None: |
| 10799 code.funcstate.release_temp(temp) |
| 10800 code.put_gotref(self.py_result()) |
| 10801 |
| 10802 |
| 10803 class CoerceFromPyTypeNode(CoercionNode): |
| 10804 # This node is used to convert a Python object |
| 10805 # to a C data type. |
| 10806 |
| 10807 def __init__(self, result_type, arg, env): |
| 10808 CoercionNode.__init__(self, arg) |
| 10809 self.type = result_type |
| 10810 self.is_temp = 1 |
| 10811 if not result_type.create_from_py_utility_code(env): |
| 10812 error(arg.pos, |
| 10813 "Cannot convert Python object to '%s'" % result_type) |
| 10814 if self.type.is_string or self.type.is_pyunicode_ptr: |
| 10815 if self.arg.is_ephemeral(): |
| 10816 error(arg.pos, |
| 10817 "Obtaining '%s' from temporary Python value" % result_type
) |
| 10818 elif self.arg.is_name and self.arg.entry and self.arg.entry.is_pyglo
bal: |
| 10819 warning(arg.pos, |
| 10820 "Obtaining '%s' from externally modifiable global Python
value" % result_type, |
| 10821 level=1) |
| 10822 |
| 10823 def analyse_types(self, env): |
| 10824 # The arg is always already analysed |
| 10825 return self |
| 10826 |
| 10827 def generate_result_code(self, code): |
| 10828 function = self.type.from_py_function |
| 10829 operand = self.arg.py_result() |
| 10830 rhs = "%s(%s)" % (function, operand) |
| 10831 if self.type.is_enum: |
| 10832 rhs = typecast(self.type, c_long_type, rhs) |
| 10833 code.putln('%s = %s; %s' % ( |
| 10834 self.result(), |
| 10835 rhs, |
| 10836 code.error_goto_if(self.type.error_condition(self.result()), self.po
s))) |
| 10837 if self.type.is_pyobject: |
| 10838 code.put_gotref(self.py_result()) |
| 10839 |
| 10840 def nogil_check(self, env): |
| 10841 error(self.pos, "Coercion from Python not allowed without the GIL") |
| 10842 |
| 10843 |
| 10844 class CoerceToBooleanNode(CoercionNode): |
| 10845 # This node is used when a result needs to be used |
| 10846 # in a boolean context. |
| 10847 |
| 10848 type = PyrexTypes.c_bint_type |
| 10849 |
| 10850 _special_builtins = { |
| 10851 Builtin.list_type : 'PyList_GET_SIZE', |
| 10852 Builtin.tuple_type : 'PyTuple_GET_SIZE', |
| 10853 Builtin.bytes_type : 'PyBytes_GET_SIZE', |
| 10854 Builtin.unicode_type : 'PyUnicode_GET_SIZE', |
| 10855 } |
| 10856 |
| 10857 def __init__(self, arg, env): |
| 10858 CoercionNode.__init__(self, arg) |
| 10859 if arg.type.is_pyobject: |
| 10860 self.is_temp = 1 |
| 10861 |
| 10862 def nogil_check(self, env): |
| 10863 if self.arg.type.is_pyobject and self._special_builtins.get(self.arg.typ
e) is None: |
| 10864 self.gil_error() |
| 10865 |
| 10866 gil_message = "Truth-testing Python object" |
| 10867 |
| 10868 def check_const(self): |
| 10869 if self.is_temp: |
| 10870 self.not_const() |
| 10871 return False |
| 10872 return self.arg.check_const() |
| 10873 |
| 10874 def calculate_result_code(self): |
| 10875 return "(%s != 0)" % self.arg.result() |
| 10876 |
| 10877 def generate_result_code(self, code): |
| 10878 if not self.is_temp: |
| 10879 return |
| 10880 test_func = self._special_builtins.get(self.arg.type) |
| 10881 if test_func is not None: |
| 10882 code.putln("%s = (%s != Py_None) && (%s(%s) != 0);" % ( |
| 10883 self.result(), |
| 10884 self.arg.py_result(), |
| 10885 test_func, |
| 10886 self.arg.py_result())) |
| 10887 else: |
| 10888 code.putln( |
| 10889 "%s = __Pyx_PyObject_IsTrue(%s); %s" % ( |
| 10890 self.result(), |
| 10891 self.arg.py_result(), |
| 10892 code.error_goto_if_neg(self.result(), self.pos))) |
| 10893 |
| 10894 class CoerceToComplexNode(CoercionNode): |
| 10895 |
| 10896 def __init__(self, arg, dst_type, env): |
| 10897 if arg.type.is_complex: |
| 10898 arg = arg.coerce_to_simple(env) |
| 10899 self.type = dst_type |
| 10900 CoercionNode.__init__(self, arg) |
| 10901 dst_type.create_declaration_utility_code(env) |
| 10902 |
| 10903 def calculate_result_code(self): |
| 10904 if self.arg.type.is_complex: |
| 10905 real_part = "__Pyx_CREAL(%s)" % self.arg.result() |
| 10906 imag_part = "__Pyx_CIMAG(%s)" % self.arg.result() |
| 10907 else: |
| 10908 real_part = self.arg.result() |
| 10909 imag_part = "0" |
| 10910 return "%s(%s, %s)" % ( |
| 10911 self.type.from_parts, |
| 10912 real_part, |
| 10913 imag_part) |
| 10914 |
| 10915 def generate_result_code(self, code): |
| 10916 pass |
| 10917 |
| 10918 class CoerceToTempNode(CoercionNode): |
| 10919 # This node is used to force the result of another node |
| 10920 # to be stored in a temporary. It is only used if the |
| 10921 # argument node's result is not already in a temporary. |
| 10922 |
| 10923 def __init__(self, arg, env): |
| 10924 CoercionNode.__init__(self, arg) |
| 10925 self.type = self.arg.type.as_argument_type() |
| 10926 self.constant_result = self.arg.constant_result |
| 10927 self.is_temp = 1 |
| 10928 if self.type.is_pyobject: |
| 10929 self.result_ctype = py_object_type |
| 10930 |
| 10931 gil_message = "Creating temporary Python reference" |
| 10932 |
| 10933 def analyse_types(self, env): |
| 10934 # The arg is always already analysed |
| 10935 return self |
| 10936 |
| 10937 def coerce_to_boolean(self, env): |
| 10938 self.arg = self.arg.coerce_to_boolean(env) |
| 10939 if self.arg.is_simple(): |
| 10940 return self.arg |
| 10941 self.type = self.arg.type |
| 10942 self.result_ctype = self.type |
| 10943 return self |
| 10944 |
| 10945 def generate_result_code(self, code): |
| 10946 #self.arg.generate_evaluation_code(code) # Already done |
| 10947 # by generic generate_subexpr_evaluation_code! |
| 10948 code.putln("%s = %s;" % ( |
| 10949 self.result(), self.arg.result_as(self.ctype()))) |
| 10950 if self.use_managed_ref: |
| 10951 if self.type.is_pyobject: |
| 10952 code.put_incref(self.result(), self.ctype()) |
| 10953 elif self.type.is_memoryviewslice: |
| 10954 code.put_incref_memoryviewslice(self.result(), |
| 10955 not self.in_nogil_context) |
| 10956 |
| 10957 class ProxyNode(CoercionNode): |
| 10958 """ |
| 10959 A node that should not be replaced by transforms or other means, |
| 10960 and hence can be useful to wrap the argument to a clone node |
| 10961 |
| 10962 MyNode -> ProxyNode -> ArgNode |
| 10963 CloneNode -^ |
| 10964 """ |
| 10965 |
| 10966 nogil_check = None |
| 10967 |
| 10968 def __init__(self, arg): |
| 10969 super(ProxyNode, self).__init__(arg) |
| 10970 self.constant_result = arg.constant_result |
| 10971 self._proxy_type() |
| 10972 |
| 10973 def analyse_expressions(self, env): |
| 10974 self.arg = self.arg.analyse_expressions(env) |
| 10975 self._proxy_type() |
| 10976 return self |
| 10977 |
| 10978 def _proxy_type(self): |
| 10979 if hasattr(self.arg, 'type'): |
| 10980 self.type = self.arg.type |
| 10981 self.result_ctype = self.arg.result_ctype |
| 10982 if hasattr(self.arg, 'entry'): |
| 10983 self.entry = self.arg.entry |
| 10984 |
| 10985 def generate_result_code(self, code): |
| 10986 self.arg.generate_result_code(code) |
| 10987 |
| 10988 def result(self): |
| 10989 return self.arg.result() |
| 10990 |
| 10991 def is_simple(self): |
| 10992 return self.arg.is_simple() |
| 10993 |
| 10994 def may_be_none(self): |
| 10995 return self.arg.may_be_none() |
| 10996 |
| 10997 def generate_evaluation_code(self, code): |
| 10998 self.arg.generate_evaluation_code(code) |
| 10999 |
| 11000 def generate_result_code(self, code): |
| 11001 self.arg.generate_result_code(code) |
| 11002 |
| 11003 def generate_disposal_code(self, code): |
| 11004 self.arg.generate_disposal_code(code) |
| 11005 |
| 11006 def free_temps(self, code): |
| 11007 self.arg.free_temps(code) |
| 11008 |
| 11009 class CloneNode(CoercionNode): |
| 11010 # This node is employed when the result of another node needs |
| 11011 # to be used multiple times. The argument node's result must |
| 11012 # be in a temporary. This node "borrows" the result from the |
| 11013 # argument node, and does not generate any evaluation or |
| 11014 # disposal code for it. The original owner of the argument |
| 11015 # node is responsible for doing those things. |
| 11016 |
| 11017 subexprs = [] # Arg is not considered a subexpr |
| 11018 nogil_check = None |
| 11019 |
| 11020 def __init__(self, arg): |
| 11021 CoercionNode.__init__(self, arg) |
| 11022 self.constant_result = arg.constant_result |
| 11023 if hasattr(arg, 'type'): |
| 11024 self.type = arg.type |
| 11025 self.result_ctype = arg.result_ctype |
| 11026 if hasattr(arg, 'entry'): |
| 11027 self.entry = arg.entry |
| 11028 |
| 11029 def result(self): |
| 11030 return self.arg.result() |
| 11031 |
| 11032 def may_be_none(self): |
| 11033 return self.arg.may_be_none() |
| 11034 |
| 11035 def type_dependencies(self, env): |
| 11036 return self.arg.type_dependencies(env) |
| 11037 |
| 11038 def infer_type(self, env): |
| 11039 return self.arg.infer_type(env) |
| 11040 |
| 11041 def analyse_types(self, env): |
| 11042 self.type = self.arg.type |
| 11043 self.result_ctype = self.arg.result_ctype |
| 11044 self.is_temp = 1 |
| 11045 if hasattr(self.arg, 'entry'): |
| 11046 self.entry = self.arg.entry |
| 11047 return self |
| 11048 |
| 11049 def is_simple(self): |
| 11050 return True # result is always in a temp (or a name) |
| 11051 |
| 11052 def generate_evaluation_code(self, code): |
| 11053 pass |
| 11054 |
| 11055 def generate_result_code(self, code): |
| 11056 pass |
| 11057 |
| 11058 def generate_disposal_code(self, code): |
| 11059 pass |
| 11060 |
| 11061 def free_temps(self, code): |
| 11062 pass |
| 11063 |
| 11064 |
| 11065 class CMethodSelfCloneNode(CloneNode): |
| 11066 # Special CloneNode for the self argument of builtin C methods |
| 11067 # that accepts subtypes of the builtin type. This is safe only |
| 11068 # for 'final' subtypes, as subtypes of the declared type may |
| 11069 # override the C method. |
| 11070 |
| 11071 def coerce_to(self, dst_type, env): |
| 11072 if dst_type.is_builtin_type and self.type.subtype_of(dst_type): |
| 11073 return self |
| 11074 return CloneNode.coerce_to(self, dst_type, env) |
| 11075 |
| 11076 |
| 11077 class ModuleRefNode(ExprNode): |
| 11078 # Simple returns the module object |
| 11079 |
| 11080 type = py_object_type |
| 11081 is_temp = False |
| 11082 subexprs = [] |
| 11083 |
| 11084 def analyse_types(self, env): |
| 11085 return self |
| 11086 |
| 11087 def may_be_none(self): |
| 11088 return False |
| 11089 |
| 11090 def calculate_result_code(self): |
| 11091 return Naming.module_cname |
| 11092 |
| 11093 def generate_result_code(self, code): |
| 11094 pass |
| 11095 |
| 11096 class DocstringRefNode(ExprNode): |
| 11097 # Extracts the docstring of the body element |
| 11098 |
| 11099 subexprs = ['body'] |
| 11100 type = py_object_type |
| 11101 is_temp = True |
| 11102 |
| 11103 def __init__(self, pos, body): |
| 11104 ExprNode.__init__(self, pos) |
| 11105 assert body.type.is_pyobject |
| 11106 self.body = body |
| 11107 |
| 11108 def analyse_types(self, env): |
| 11109 return self |
| 11110 |
| 11111 def generate_result_code(self, code): |
| 11112 code.putln('%s = __Pyx_GetAttr(%s, %s); %s' % ( |
| 11113 self.result(), self.body.result(), |
| 11114 code.intern_identifier(StringEncoding.EncodedString("__doc__")), |
| 11115 code.error_goto_if_null(self.result(), self.pos))) |
| 11116 code.put_gotref(self.result()) |
| 11117 |
| 11118 |
| 11119 |
| 11120 #-------------------------------------------------------------------------------
----- |
| 11121 # |
| 11122 # Runtime support code |
| 11123 # |
| 11124 #-------------------------------------------------------------------------------
----- |
| 11125 |
| 11126 pyerr_occurred_withgil_utility_code= UtilityCode( |
| 11127 proto = """ |
| 11128 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */ |
| 11129 """, |
| 11130 impl = """ |
| 11131 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) { |
| 11132 int err; |
| 11133 #ifdef WITH_THREAD |
| 11134 PyGILState_STATE _save = PyGILState_Ensure(); |
| 11135 #endif |
| 11136 err = !!PyErr_Occurred(); |
| 11137 #ifdef WITH_THREAD |
| 11138 PyGILState_Release(_save); |
| 11139 #endif |
| 11140 return err; |
| 11141 } |
| 11142 """ |
| 11143 ) |
| 11144 |
| 11145 #-------------------------------------------------------------------------------
----- |
| 11146 |
| 11147 raise_unbound_local_error_utility_code = UtilityCode( |
| 11148 proto = """ |
| 11149 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); |
| 11150 """, |
| 11151 impl = """ |
| 11152 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { |
| 11153 PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before
assignment", varname); |
| 11154 } |
| 11155 """) |
| 11156 |
| 11157 raise_closure_name_error_utility_code = UtilityCode( |
| 11158 proto = """ |
| 11159 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname); |
| 11160 """, |
| 11161 impl = """ |
| 11162 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) { |
| 11163 PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignme
nt in enclosing scope", varname); |
| 11164 } |
| 11165 """) |
| 11166 |
| 11167 # Don't inline the function, it should really never be called in production |
| 11168 raise_unbound_memoryview_utility_code_nogil = UtilityCode( |
| 11169 proto = """ |
| 11170 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname); |
| 11171 """, |
| 11172 impl = """ |
| 11173 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) { |
| 11174 #ifdef WITH_THREAD |
| 11175 PyGILState_STATE gilstate = PyGILState_Ensure(); |
| 11176 #endif |
| 11177 __Pyx_RaiseUnboundLocalError(varname); |
| 11178 #ifdef WITH_THREAD |
| 11179 PyGILState_Release(gilstate); |
| 11180 #endif |
| 11181 } |
| 11182 """, |
| 11183 requires = [raise_unbound_local_error_utility_code]) |
| 11184 |
| 11185 #-------------------------------------------------------------------------------
----- |
| 11186 |
| 11187 raise_too_many_values_to_unpack = UtilityCode.load_cached("RaiseTooManyValuesToU
npack", "ObjectHandling.c") |
| 11188 raise_need_more_values_to_unpack = UtilityCode.load_cached("RaiseNeedMoreValuesT
oUnpack", "ObjectHandling.c") |
| 11189 tuple_unpacking_error_code = UtilityCode.load_cached("UnpackTupleError", "Object
Handling.c") |
| 11190 |
| 11191 #-------------------------------------------------------------------------------
----- |
| 11192 |
| 11193 int_pow_utility_code = UtilityCode( |
| 11194 proto=""" |
| 11195 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */ |
| 11196 """, |
| 11197 impl=""" |
| 11198 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) { |
| 11199 %(type)s t = b; |
| 11200 switch (e) { |
| 11201 case 3: |
| 11202 t *= b; |
| 11203 case 2: |
| 11204 t *= b; |
| 11205 case 1: |
| 11206 return t; |
| 11207 case 0: |
| 11208 return 1; |
| 11209 } |
| 11210 #if %(signed)s |
| 11211 if (unlikely(e<0)) return 0; |
| 11212 #endif |
| 11213 t = 1; |
| 11214 while (likely(e)) { |
| 11215 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */ |
| 11216 b *= b; |
| 11217 e >>= 1; |
| 11218 } |
| 11219 return t; |
| 11220 } |
| 11221 """) |
| 11222 |
| 11223 # ------------------------------ Division ------------------------------------ |
| 11224 |
| 11225 div_int_utility_code = UtilityCode( |
| 11226 proto=""" |
| 11227 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* pr
oto */ |
| 11228 """, |
| 11229 impl=""" |
| 11230 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) { |
| 11231 %(type)s q = a / b; |
| 11232 %(type)s r = a - q*b; |
| 11233 q -= ((r != 0) & ((r ^ b) < 0)); |
| 11234 return q; |
| 11235 } |
| 11236 """) |
| 11237 |
| 11238 mod_int_utility_code = UtilityCode( |
| 11239 proto=""" |
| 11240 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* pr
oto */ |
| 11241 """, |
| 11242 impl=""" |
| 11243 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { |
| 11244 %(type)s r = a %% b; |
| 11245 r += ((r != 0) & ((r ^ b) < 0)) * b; |
| 11246 return r; |
| 11247 } |
| 11248 """) |
| 11249 |
| 11250 mod_float_utility_code = UtilityCode( |
| 11251 proto=""" |
| 11252 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* pr
oto */ |
| 11253 """, |
| 11254 impl=""" |
| 11255 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { |
| 11256 %(type)s r = fmod%(math_h_modifier)s(a, b); |
| 11257 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b; |
| 11258 return r; |
| 11259 } |
| 11260 """) |
| 11261 |
| 11262 cdivision_warning_utility_code = UtilityCode( |
| 11263 proto=""" |
| 11264 static int __Pyx_cdivision_warning(const char *, int); /* proto */ |
| 11265 """, |
| 11266 impl=""" |
| 11267 static int __Pyx_cdivision_warning(const char *filename, int lineno) { |
| 11268 #if CYTHON_COMPILING_IN_PYPY |
| 11269 filename++; // avoid compiler warnings |
| 11270 lineno++; |
| 11271 return PyErr_Warn(PyExc_RuntimeWarning, |
| 11272 "division with oppositely signed operands, C and Python sem
antics differ"); |
| 11273 #else |
| 11274 return PyErr_WarnExplicit(PyExc_RuntimeWarning, |
| 11275 "division with oppositely signed operands, C and P
ython semantics differ", |
| 11276 filename, |
| 11277 lineno, |
| 11278 __Pyx_MODULE_NAME, |
| 11279 NULL); |
| 11280 #endif |
| 11281 } |
| 11282 """) |
| 11283 |
| 11284 # from intobject.c |
| 11285 division_overflow_test_code = UtilityCode( |
| 11286 proto=""" |
| 11287 #define UNARY_NEG_WOULD_OVERFLOW(x) \ |
| 11288 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) |
| 11289 """) |
OLD | NEW |