2 # Parse tree nodes for expressions
6 cython
.declare(error
=object, warning
=object, warn_once
=object, InternalError
=object,
7 CompileError
=object, UtilityCode
=object, TempitaUtilityCode
=object,
8 StringEncoding
=object, operator
=object,
9 Naming
=object, Nodes
=object, PyrexTypes
=object, py_object_type
=object,
10 list_type
=object, tuple_type
=object, set_type
=object, dict_type
=object,
11 unicode_type
=object, str_type
=object, bytes_type
=object, type_type
=object,
12 Builtin
=object, Symtab
=object, Utils
=object, find_coercion_error
=object,
13 debug_disposal_code
=object, debug_temp_alloc
=object, debug_coercion
=object,
14 bytearray_type
=object, slice_type
=object)
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
26 from Nodes
import Node
28 from PyrexTypes
import py_object_type
, c_long_type
, typecast
, error_type
, \
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
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
, \
43 from __builtin__
import basestring
45 basestring
= str # Python 3
48 from builtins
import bytes
50 bytes
= str # Python 2
53 class NotConstant(object):
57 if NotConstant
._obj
is None:
58 NotConstant
._obj
= super(NotConstant
, cls
).__new
__(cls
)
60 return NotConstant
._obj
63 return "<NOT CONSTANT>"
65 not_a_constant
= NotConstant()
66 constant_value_not_set
= object()
68 # error messages when coercing from key[0] to key[1]
69 coercion_error_dict
= {
70 # string related errors
71 (Builtin
.unicode_type
, Builtin
.bytes_type
) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
72 (Builtin
.unicode_type
, Builtin
.str_type
) : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
73 (Builtin
.unicode_type
, PyrexTypes
.c_char_ptr_type
) : "Unicode objects only support coercion to Py_UNICODE*.",
74 (Builtin
.unicode_type
, PyrexTypes
.c_uchar_ptr_type
) : "Unicode objects only support coercion to Py_UNICODE*.",
75 (Builtin
.bytes_type
, Builtin
.unicode_type
) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
76 (Builtin
.bytes_type
, Builtin
.str_type
) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
77 (Builtin
.bytes_type
, Builtin
.basestring_type
) : "Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3.",
78 (Builtin
.bytes_type
, PyrexTypes
.c_py_unicode_ptr_type
) : "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.",
79 (Builtin
.basestring_type
, Builtin
.bytes_type
) : "Cannot convert 'basestring' object to bytes implicitly. This is not portable.",
80 (Builtin
.str_type
, Builtin
.unicode_type
) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
81 (Builtin
.str_type
, Builtin
.bytes_type
) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
82 (Builtin
.str_type
, PyrexTypes
.c_char_ptr_type
) : "'str' objects do not support coercion to C types (use 'bytes'?).",
83 (Builtin
.str_type
, PyrexTypes
.c_uchar_ptr_type
) : "'str' objects do not support coercion to C types (use 'bytes'?).",
84 (Builtin
.str_type
, PyrexTypes
.c_py_unicode_ptr_type
) : "'str' objects do not support coercion to C types (use 'unicode'?).",
85 (PyrexTypes
.c_char_ptr_type
, Builtin
.unicode_type
) : "Cannot convert 'char*' to unicode implicitly, decoding required",
86 (PyrexTypes
.c_uchar_ptr_type
, Builtin
.unicode_type
) : "Cannot convert 'char*' to unicode implicitly, decoding required",
89 def find_coercion_error(type_tuple
, default
, env
):
90 err
= coercion_error_dict
.get(type_tuple
)
93 elif ((PyrexTypes
.c_char_ptr_type
in type_tuple
or PyrexTypes
.c_uchar_ptr_type
in type_tuple
)
94 and env
.directives
['c_string_encoding']):
95 if type_tuple
[1].is_pyobject
:
97 elif env
.directives
['c_string_encoding'] in ('ascii', 'default'):
100 return "'%s' objects do not support coercion to C types with non-ascii or non-default c_string_encoding" % type_tuple
[0].name
105 def default_str_type(env
):
108 'bytearray': bytearray_type
,
110 'unicode': unicode_type
111 }.get(env
.directives
['c_string_type'])
114 def check_negative_indices(*nodes
):
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.
121 or not isinstance(node
.constant_result
, (int, float, long))):
123 if node
.constant_result
< 0:
125 "the result of using negative indices inside of "
126 "code sections marked as 'wraparound=False' is "
127 "undefined", level
=1)
130 def infer_sequence_item_type(env
, seq_node
, index_node
=None, seq_type
=None):
131 if not seq_node
.is_sequence_constructor
:
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:
138 seq_node
= seq_node
.cf_state
[0].rhs
139 except AttributeError:
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():
144 item
= seq_node
.args
[index_node
.constant_result
]
145 except (ValueError, TypeError, IndexError):
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()
156 class ExprNode(Node
):
157 # subexprs [string] Class var holding names of subexpr node attrs
158 # type PyrexType Type of the result
159 # result_code string Code fragment
160 # result_ctype string C type of result_code if different from type
161 # is_temp boolean Result is in a temporary variable
162 # is_sequence_constructor
163 # boolean Is a list or tuple constructor expression
164 # is_starred boolean Is a starred expression (e.g. '*a')
165 # saved_subexpr_nodes
166 # [ExprNode or [ExprNode or None] or None]
167 # Cached result of subexpr_nodes()
168 # use_managed_ref boolean use ref-counted temps/assignments/etc.
169 # result_is_used boolean indicates that the result will be dropped and the
170 # result_code/temp_result can safely be set to None
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
179 # The Analyse Expressions phase for expressions is split
180 # into two sub-phases:
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
190 # Allocates temporary variables where needed, and fills
191 # in the result_code field of each node.
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.
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.
206 # The framework makes use of a number of abstract methods.
207 # Their responsibilities are as follows.
209 # Declaration Analysis phase
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
217 # Expression Analysis phase
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.
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.
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.
238 # - Check that this node and its subnodes form a
239 # legal constant expression. If so, do nothing,
240 # otherwise call not_const.
242 # The default implementation of check_const
243 # assumes that the expression is not constant.
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.
250 # The default implementation of calc_const_addr
251 # assumes that the expression is not a constant
254 # Code Generation phase
256 # generate_evaluation_code
257 # - Call generate_evaluation_code for sub-expressions.
258 # - Perform the functions of generate_result_code
260 # - If result is temporary, call generate_disposal_code
261 # on all sub-expressions.
263 # A default implementation of generate_evaluation_code
264 # is provided which uses the following abstract methods:
266 # generate_result_code
267 # - Generate any C statements necessary to calculate
268 # the result of this node from the results of its
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
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.
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.
292 is_sequence_constructor
= 0
293 is_string_literal
= 0
297 saved_subexpr_nodes
= None
302 constant_result
= constant_value_not_set
304 # whether this node with a memoryview type should be broadcast
305 memslice_broadcast
= False
307 child_attrs
= property(fget
=operator
.attrgetter('subexprs'))
309 def not_implemented(self
, method_name
):
310 print_call_chain(method_name
, "not implemented") ###
312 "%s.%s not implemented" %
313 (self
.__class
__.__name
__, method_name
))
318 def is_addressable(self
):
319 return self
.is_lvalue() and not self
.type.is_memoryviewslice
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
329 def subexpr_nodes(self
):
330 # Extract a list of subexpression nodes based
331 # on the contents of the subexprs class attribute.
333 for name
in self
.subexprs
:
334 item
= getattr(self
, name
)
336 if type(item
) is list:
344 return self
.temp_code
346 return self
.calculate_result_code()
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())
358 # Return the result code cast to PyObject *.
359 return self
.result_as(py_object_type
)
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
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.
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.
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
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.
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
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")
397 def compile_time_value_error(self
, e
):
398 error(self
.pos
, "Error in compile-time expression: %s: %s" % (
399 e
.__class
__.__name
__, e
))
401 # ------------- Declaration Analysis ----------------
403 def analyse_target_declaration(self
, env
):
404 error(self
.pos
, "Cannot assign to or delete this")
406 # ------------- Expression Analysis ----------------
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
)
417 def analyse_expressions(self
, env
):
418 # Convenience routine performing both the Type
419 # Analysis and Temp Allocation phases for a whole
421 return self
.analyse_types(env
)
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
427 return self
.analyse_target_types(env
)
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
)
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
)
446 # --------------- Type Inference -----------------
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:
453 return sum([node
.type_dependencies(env
) for node
in self
.subexpr_nodes()], ())
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:
462 elif hasattr(self
, 'entry') and self
.entry
is not None:
463 return self
.entry
.type
465 self
.not_implemented("infer_type")
467 def nonlocally_immutable(self
):
468 # Returns whether this variable is a safe reference, i.e.
469 # can't be modified as part of globals or closures.
470 return self
.is_literal
or self
.is_temp
or self
.type.is_array
or self
.type.is_cfunction
472 # --------------- Type Analysis ------------------
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.
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.
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.
489 def analyse_types(self
, env
):
490 self
.not_implemented("analyse_types")
492 def analyse_target_types(self
, env
):
493 return self
.analyse_types(env
)
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
:
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")
506 def check_const(self
):
511 error(self
.pos
, "Not allowed in a constant expression")
513 def check_const_addr(self
):
514 self
.addr_not_const()
517 def addr_not_const(self
):
518 error(self
.pos
, "Address is not constant")
520 # ----------------- Result Allocation -----------------
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
529 def target_code(self
):
530 # Return code fragment for use as LHS of a C assignment.
531 return self
.calculate_result_code()
533 def calculate_result_code(self
):
534 self
.not_implemented("calculate_result_code")
536 # def release_target_temp(self, env):
537 # # Release temporaries used by LHS of an assignment.
538 # self.release_subexpr_temps(env)
540 def allocate_temp_result(self
, code
):
542 raise RuntimeError("Temp allocated multiple times in %r: %r" % (self
.__class
__.__name
__, self
.pos
))
546 type = PyrexTypes
.py_object_type
547 self
.temp_code
= code
.funcstate
.allocate_temp(
548 type, manage_ref
=self
.use_managed_ref
)
550 self
.temp_code
= None
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
558 raise RuntimeError("temp %s released multiple times in %s" % (
559 self
.old_temp
, self
.__class
__.__name
__))
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
567 # ---------------- Code Generation -----------------
569 def make_owned_reference(self
, code
):
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.
574 if self
.type.is_pyobject
and not self
.result_in_temp():
575 code
.put_incref(self
.result(), self
.ctype())
577 def make_owned_memoryviewslice(self
, code
):
579 Make sure we own the reference to this memoryview slice.
581 if not self
.result_in_temp():
582 code
.put_incref_memoryviewslice(self
.result(),
583 have_gil
=self
.in_nogil_context
)
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
)
591 code
.mark_pos(self
.pos
)
593 self
.allocate_temp_result(code
)
595 self
.generate_result_code(code
)
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
)
602 def generate_subexpr_evaluation_code(self
, code
):
603 for node
in self
.subexpr_nodes():
604 node
.generate_evaluation_code(code
)
606 def generate_result_code(self
, code
):
607 self
.not_implemented("generate_result_code")
609 def generate_disposal_code(self
, code
):
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
)
618 # Already done if self.is_temp
619 self
.generate_subexpr_disposal_code(code
)
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
)
627 def generate_post_assignment_code(self
, code
):
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())
635 self
.generate_subexpr_disposal_code(code
)
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.
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.
649 def free_temps(self
, code
):
651 if not self
.type.is_void
:
652 self
.release_temp_result(code
)
654 self
.free_subexpr_temps(code
)
656 def free_subexpr_temps(self
, code
):
657 for sub
in self
.subexpr_nodes():
660 def generate_function_definitions(self
, env
, code
):
663 # ---------------- Annotation ---------------------
665 def annotate(self
, code
):
666 for node
in self
.subexpr_nodes():
669 # ----------------- Coercion ----------------------
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.
677 # This method is called during the analyse_expressions
678 # phase of the src_node's processing.
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.
690 if self
.check_for_coercion_error(dst_type
, env
):
693 if dst_type
.is_reference
and not src_type
.is_reference
:
694 dst_type
= dst_type
.ref_base_type
696 if src_type
.is_const
:
697 src_type
= src_type
.const_base_type
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
):
705 dst_type
= dst_type
.base_type
707 for signature
in src_type
.get_all_specialized_function_types():
708 if signature
.same_as(dst_type
):
710 src
.entry
= src
.type.entry
711 src
.entry
.used
= True
714 if src_type
.is_fused
:
715 error(self
.pos
, "Type is not specialized")
717 error(self
.pos
, "Cannot coerce to a type that is not specialized")
719 self
.type = error_type
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
)
727 if dst_type
.is_memoryviewslice
:
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(
735 elif not src_type
.is_error
:
737 "Cannot convert '%s' to memoryviewslice" %
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
745 msg
= "Different base types for memoryviews (%s, %s)"
746 tup
= src
.type.dtype
, dst_type
.dtype
748 error(self
.pos
, msg
% tup
)
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
)
755 src
= CoerceToPyTypeNode(src
, env
, type=dst_type
)
756 if not src
.type.subtype_of(dst_type
):
757 if src
.constant_result
is not None:
758 src
= PyTypeTestNode(src
, dst_type
, env
)
759 elif src
.type.is_pyobject
:
760 src
= CoerceFromPyTypeNode(dst_type
, src
, env
)
761 elif (dst_type
.is_complex
762 and src_type
!= dst_type
763 and dst_type
.assignable_from(src_type
)):
764 src
= CoerceToComplexNode(src
, dst_type
, env
)
765 else: # neither src nor dst are py types
766 # Added the string comparison, since for c types that
767 # is enough, but Cython gets confused when the types are
768 # in different pxi files.
769 if not (str(src
.type) == str(dst_type
) or dst_type
.assignable_from(src_type
)):
770 self
.fail_assignment(dst_type
)
773 def fail_assignment(self
, dst_type
):
774 error(self
.pos
, "Cannot assign type '%s' to '%s'" % (self
.type, dst_type
))
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
})
784 self
.fail_assignment(dst_type
)
788 def coerce_to_pyobject(self
, env
):
789 return self
.coerce_to(PyrexTypes
.py_object_type
, env
)
791 def coerce_to_boolean(self
, env
):
792 # Coerce result to something acceptable as
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
)
802 if type.is_enum
or type.is_error
:
804 elif type.is_pyobject
or type.is_int
or type.is_ptr
or type.is_float
:
805 return CoerceToBooleanNode(self
, env
)
807 error(self
.pos
, "Type '%s' not acceptable as a boolean" % type)
810 def coerce_to_integer(self
, env
):
811 # If not already some C integer type, coerce to longint.
815 return self
.coerce_to(PyrexTypes
.c_long_type
, env
)
817 def coerce_to_temp(self
, env
):
818 # Ensure that the result is in a temporary.
819 if self
.result_in_temp():
822 return CoerceToTempNode(self
, env
)
824 def coerce_to_simple(self
, env
):
825 # Ensure that the result is simple (see is_simple).
829 return self
.coerce_to_temp(env
)
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()
838 def may_be_none(self
):
839 if self
.type and not (self
.type.is_pyobject
or
840 self
.type.is_memoryviewslice
):
842 if self
.has_constant_result():
843 return self
.constant_result
is not None
846 def as_cython_attribute(self
):
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
)
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.
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
:
867 value
= getattr(node
, attr_name
)
868 except AttributeError:
871 kwargs
[attr_name
] = value
872 return cls(node
.pos
, **kwargs
)
875 class AtomicExprNode(ExprNode
):
876 # Abstract base class for expression nodes which have
877 # no sub-expressions.
881 # Override to optimize -- we know we have no children
882 def generate_subexpr_evaluation_code(self
, code
):
884 def generate_subexpr_disposal_code(self
, code
):
887 class PyConstNode(AtomicExprNode
):
888 # Abstract base class for constant Python values.
891 type = py_object_type
896 def may_be_none(self
):
899 def analyse_types(self
, env
):
902 def calculate_result_code(self
):
905 def generate_result_code(self
, code
):
909 class NoneNode(PyConstNode
):
910 # The constant value None
915 constant_result
= None
919 def compile_time_value(self
, denv
):
922 def may_be_none(self
):
926 class EllipsisNode(PyConstNode
):
927 # '...' in a subscript list.
929 value
= "Py_Ellipsis"
931 constant_result
= Ellipsis
933 def compile_time_value(self
, denv
):
937 class ConstNode(AtomicExprNode
):
938 # Abstract base type for literal constant nodes.
940 # value string C code fragment
948 def nonlocally_immutable(self
):
951 def may_be_none(self
):
954 def analyse_types(self
, env
):
955 return self
# Types are held in class variables
957 def check_const(self
):
960 def get_constant_c_result_code(self
):
961 return self
.calculate_result_code()
963 def calculate_result_code(self
):
964 return str(self
.value
)
966 def generate_result_code(self
, code
):
970 class BoolNode(ConstNode
):
971 type = PyrexTypes
.c_bint_type
972 # The constant value True or False
974 def calculate_constant_result(self
):
975 self
.constant_result
= self
.value
977 def compile_time_value(self
, denv
):
980 def calculate_result_code(self
):
981 if self
.type.is_pyobject
:
982 return self
.value
and 'Py_True' or 'Py_False'
984 return str(int(self
.value
))
986 def coerce_to(self
, dst_type
, env
):
987 if dst_type
.is_pyobject
and self
.type.is_int
:
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
:
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
)
1000 class NullNode(ConstNode
):
1001 type = PyrexTypes
.c_null_ptr_type
1005 def get_constant_c_result_code(self
):
1009 class CharNode(ConstNode
):
1010 type = PyrexTypes
.c_char_type
1012 def calculate_constant_result(self
):
1013 self
.constant_result
= ord(self
.value
)
1015 def compile_time_value(self
, denv
):
1016 return ord(self
.value
)
1018 def calculate_result_code(self
):
1019 return "'%s'" % StringEncoding
.escape_char(self
.value
)
1022 class IntNode(ConstNode
):
1024 # unsigned "" or "U"
1025 # longness "" or "L" or "LL"
1026 # is_c_literal True/False/None creator considers this a C integer literal
1030 is_c_literal
= None # unknown
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()
1037 def find_suitable_type_for_value(self
):
1038 if self
.constant_result
is constant_value_not_set
:
1040 self
.calculate_constant_result()
1043 # we ignore 'is_c_literal = True' and instead map signed 32bit
1044 # integers as C long values
1045 if self
.is_c_literal
or \
1046 self
.constant_result
in (constant_value_not_set
, not_a_constant
) or \
1047 self
.unsigned
or self
.longness
== 'LL':
1048 # clearly a C literal
1049 rank
= (self
.longness
== 'LL') and 2 or 1
1050 suitable_type
= PyrexTypes
.modifiers_and_name_to_type
[not self
.unsigned
, rank
, "int"]
1052 suitable_type
= PyrexTypes
.widest_numeric_type(suitable_type
, self
.type)
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
1059 suitable_type
= PyrexTypes
.c_long_type
1061 suitable_type
= PyrexTypes
.py_object_type
1062 return suitable_type
1064 def coerce_to(self
, dst_type
, env
):
1065 if self
.type is dst_type
:
1067 elif dst_type
.is_float
:
1068 if self
.has_constant_result():
1069 return FloatNode(self
.pos
, value
='%d.0' % int(self
.constant_result
), type=dst_type
,
1070 constant_result
=float(self
.constant_result
))
1072 return FloatNode(self
.pos
, value
=self
.value
, type=dst_type
,
1073 constant_result
=not_a_constant
)
1074 if dst_type
.is_numeric
and not dst_type
.is_complex
:
1075 node
= IntNode(self
.pos
, value
=self
.value
, constant_result
=self
.constant_result
,
1076 type = dst_type
, is_c_literal
= True,
1077 unsigned
=self
.unsigned
, longness
=self
.longness
)
1079 elif dst_type
.is_pyobject
:
1080 node
= IntNode(self
.pos
, value
=self
.value
, constant_result
=self
.constant_result
,
1081 type = PyrexTypes
.py_object_type
, is_c_literal
= False,
1082 unsigned
=self
.unsigned
, longness
=self
.longness
)
1084 # FIXME: not setting the type here to keep it working with
1085 # complex numbers. Should they be special cased?
1086 node
= IntNode(self
.pos
, value
=self
.value
, constant_result
=self
.constant_result
,
1087 unsigned
=self
.unsigned
, longness
=self
.longness
)
1088 # We still need to perform normal coerce_to processing on the
1089 # result, because we might be coercing to an extension type,
1090 # in which case a type test node will be needed.
1091 return ConstNode
.coerce_to(node
, dst_type
, env
)
1093 def coerce_to_boolean(self
, env
):
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
)
1100 def generate_evaluation_code(self
, code
):
1101 if self
.type.is_pyobject
:
1102 # pre-allocate a Python version of the number
1103 plain_integer_string
= str(Utils
.str_to_number(self
.value
))
1104 self
.result_code
= code
.get_py_int(plain_integer_string
, self
.longness
)
1106 self
.result_code
= self
.get_constant_c_result_code()
1108 def get_constant_c_result_code(self
):
1109 return self
.value_as_c_integer_string() + self
.unsigned
+ self
.longness
1111 def value_as_c_integer_string(self
):
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)
1121 def calculate_result_code(self
):
1122 return self
.result_code
1124 def calculate_constant_result(self
):
1125 self
.constant_result
= Utils
.str_to_number(self
.value
)
1127 def compile_time_value(self
, denv
):
1128 return Utils
.str_to_number(self
.value
)
1131 class FloatNode(ConstNode
):
1132 type = PyrexTypes
.c_double_type
1134 def calculate_constant_result(self
):
1135 self
.constant_result
= float(self
.value
)
1137 def compile_time_value(self
, denv
):
1138 return float(self
.value
)
1140 def coerce_to(self
, dst_type
, env
):
1141 if dst_type
.is_pyobject
and self
.type.is_float
:
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
:
1148 self
.pos
, value
=self
.value
,
1149 constant_result
=self
.constant_result
,
1151 return ConstNode
.coerce_to(self
, dst_type
, env
)
1153 def calculate_result_code(self
):
1154 return self
.result_code
1156 def get_constant_c_result_code(self
):
1158 assert isinstance(strval
, (str, unicode))
1159 cmpval
= repr(float(strval
))
1161 return "(Py_HUGE_VAL * 0)"
1162 elif cmpval
== 'inf':
1163 return "Py_HUGE_VAL"
1164 elif cmpval
== '-inf':
1165 return "(-Py_HUGE_VAL)"
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
)
1174 self
.result_code
= c_value
1177 class BytesNode(ConstNode
):
1178 # A char* or bytes literal
1180 # value BytesLiteral
1182 is_string_literal
= True
1183 # start off as Python 'bytes' to support len() in O(1)
1186 def calculate_constant_result(self
):
1187 self
.constant_result
= self
.value
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
1193 self
.pos
, value
=value
, constant_result
=value
)
1195 def compile_time_value(self
, denv
):
1198 def analyse_as_type(self
, env
):
1199 type = PyrexTypes
.parse_basic_type(self
.value
)
1200 if type is not None:
1202 from TreeFragment
import TreeFragment
1203 pos
= (self
.pos
[0], self
.pos
[1], self
.pos
[2]-7)
1204 declaration
= TreeFragment(u
"sizeof(%s)" % self
.value
, name
=pos
[0].filename
, initial_pos
=pos
)
1205 sizeof_node
= declaration
.root
.stats
[0].expr
1206 sizeof_node
= sizeof_node
.analyse_types(env
)
1207 if isinstance(sizeof_node
, SizeofTypeNode
):
1208 return sizeof_node
.arg_type
1210 def can_coerce_to_char_literal(self
):
1211 return len(self
.value
) == 1
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
)
1219 def coerce_to(self
, dst_type
, env
):
1220 if self
.type == dst_type
:
1223 if not self
.can_coerce_to_char_literal():
1224 error(self
.pos
, "Only single-character string literals can be coerced into ints.")
1226 if dst_type
.is_unicode_char
:
1227 error(self
.pos
, "Bytes literals cannot coerce to Py_UNICODE/Py_UCS4, use a unicode literal instead.")
1229 return CharNode(self
.pos
, value
=self
.value
,
1230 constant_result
=ord(self
.value
))
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
1238 self
.check_for_coercion_error(dst_type
, env
, fail
=True)
1240 elif dst_type
== PyrexTypes
.c_char_ptr_type
:
1241 node
.type = dst_type
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
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
)
1255 def generate_evaluation_code(self
, code
):
1256 if self
.type.is_pyobject
:
1257 self
.result_code
= code
.get_py_string_const(self
.value
)
1259 self
.result_code
= code
.get_string_const(self
.value
)
1261 def get_constant_c_result_code(self
):
1264 def calculate_result_code(self
):
1265 return self
.result_code
1268 class UnicodeNode(ConstNode
):
1269 # A Py_UNICODE* or unicode literal
1271 # value EncodedString
1272 # bytes_value BytesLiteral the literal parsed as bytes string
1273 # ('-3' unicode literals only)
1275 is_string_literal
= True
1279 def calculate_constant_result(self
):
1280 self
.constant_result
= self
.value
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
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
1296 self
.pos
, value
=value
, bytes_value
=bytes_value
,
1297 constant_result
=value
)
1299 def coerce_to(self
, dst_type
, env
):
1300 if dst_type
is self
.type:
1302 elif dst_type
.is_unicode_char
:
1303 if not self
.can_coerce_to_char_literal():
1305 "Only single-character Unicode string literals or "
1306 "surrogate pairs can be coerced into Py_UCS4/Py_UNICODE.")
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
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
1322 "Unicode literals do not support coercion to C types other "
1323 "than Py_UNICODE/Py_UCS4 (for characters) or Py_UNICODE* "
1325 elif dst_type
not in (py_object_type
, Builtin
.basestring_type
):
1326 self
.check_for_coercion_error(dst_type
, env
, fail
=True)
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))
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
)
1339 def contains_surrogates(self
):
1340 return StringEncoding
.string_contains_surrogates(self
.value
)
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
)
1352 "%s = PyUnicode_FromUnicode(%s, (sizeof(%s) / sizeof(Py_UNICODE))-1); %s" % (
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")
1362 self
.result_code
= code
.get_py_string_const(self
.value
)
1364 self
.result_code
= code
.get_pyunicode_ptr_const(self
.value
)
1366 def calculate_result_code(self
):
1367 return self
.result_code
1369 def compile_time_value(self
, env
):
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
1377 # value BytesLiteral (or EncodedString with ASCII content)
1378 # unicode_value EncodedString or None
1379 # is_identifier boolean
1382 is_string_literal
= True
1383 is_identifier
= None
1384 unicode_value
= None
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
1391 def as_sliced_node(self
, start
, stop
, step
=None):
1392 value
= type(self
.value
)(self
.value
[start
:stop
:step
])
1393 value
.encoding
= self
.value
.encoding
1394 if self
.unicode_value
is not None:
1395 if StringEncoding
.string_contains_surrogates(self
.unicode_value
[:stop
]):
1396 # this is unsafe as it may give different results in different runtimes
1398 unicode_value
= StringEncoding
.EncodedString(
1399 self
.unicode_value
[start
:stop
:step
])
1401 unicode_value
= None
1403 self
.pos
, value
=value
, unicode_value
=unicode_value
,
1404 constant_result
=value
, is_identifier
=self
.is_identifier
)
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)
1417 def can_coerce_to_char_literal(self
):
1418 return not self
.is_identifier
and len(self
.value
) == 1
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
)
1425 def get_constant_c_result_code(self
):
1428 def calculate_result_code(self
):
1429 return self
.result_code
1431 def compile_time_value(self
, env
):
1435 class IdentifierStringNode(StringNode
):
1436 # A special str value that represents an identifier (bytes in Py2,
1438 is_identifier
= True
1441 class ImagNode(AtomicExprNode
):
1442 # Imaginary number literal
1444 # value float imaginary part
1446 type = PyrexTypes
.c_double_complex_type
1448 def calculate_constant_result(self
):
1449 self
.constant_result
= complex(0.0, self
.value
)
1451 def compile_time_value(self
, denv
):
1452 return complex(0.0, self
.value
)
1454 def analyse_types(self
, env
):
1455 self
.type.create_declaration_utility_code(env
)
1458 def may_be_none(self
):
1461 def coerce_to(self
, dst_type
, env
):
1462 if self
.type is dst_type
:
1464 node
= ImagNode(self
.pos
, value
=self
.value
)
1465 if dst_type
.is_pyobject
:
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
)
1473 gil_message
= "Constructing complex number"
1475 def calculate_result_code(self
):
1476 if self
.type.is_pyobject
:
1477 return self
.result()
1479 return "%s(0, %r)" % (self
.type.from_parts
, float(self
.value
))
1481 def generate_result_code(self
, code
):
1482 if self
.type.is_pyobject
:
1484 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1487 code
.error_goto_if_null(self
.result(), self
.pos
)))
1488 code
.put_gotref(self
.py_result())
1491 class NewExprNode(AtomicExprNode
):
1495 # cppclass node c++ class to create
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
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
1516 def analyse_types(self
, env
):
1517 if self
.type is None:
1518 self
.infer_type(env
)
1521 def may_be_none(self
):
1524 def generate_result_code(self
, code
):
1527 def calculate_result_code(self
):
1528 return "new " + self
.class_type
.declaration_code("")
1531 class NameNode(AtomicExprNode
):
1532 # Reference to a local or global variable name.
1534 # name string Python name of the variable
1535 # entry Entry Symbol table entry
1536 # type_entry Entry For extension type names, the original type entry
1537 # cf_is_null boolean Is uninitialized before this node
1538 # cf_maybe_null boolean Maybe uninitialized before this node
1539 # allow_null boolean Don't raise UnboundLocalError
1540 # nogil boolean Whether it is used in a nogil context
1543 is_cython_module
= False
1544 cython_attribute
= None
1545 lhs_of_first_assignment
= False # TODO: remove me
1546 is_used_as_rvalue
= 0
1549 cf_maybe_null
= True
1553 inferred_type
= None
1555 def as_cython_attribute(self
):
1556 return self
.cython_attribute
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
:
1566 def infer_type(self
, env
):
1567 if self
.entry
is None:
1568 self
.entry
= env
.lookup(self
.name
)
1569 if self
.entry
is None or self
.entry
.type is unspecified_type
:
1570 if self
.inferred_type
is not None:
1571 return self
.inferred_type
1572 return py_object_type
1573 elif (self
.entry
.type.is_extension_type
or self
.entry
.type.is_builtin_type
) and \
1574 self
.name
== self
.entry
.type.name
:
1575 # Unfortunately the type attribute of type objects
1576 # is used for the pointer to the type they represent.
1578 elif self
.entry
.type.is_cfunction
:
1579 if self
.entry
.scope
.is_builtin_scope
:
1580 # special case: optimised builtin functions must be treated as Python objects
1581 return py_object_type
1583 # special case: referring to a C function must return its pointer
1584 return PyrexTypes
.CPtrType(self
.entry
.type)
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
1594 def compile_time_value(self
, denv
):
1596 return denv
.lookup(self
.name
)
1598 error(self
.pos
, "Compile-time name '%s' not defined" % self
.name
)
1600 def get_constant_c_result_code(self
):
1601 if not self
.entry
or self
.entry
.type.is_pyobject
:
1603 return self
.entry
.cname
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
:
1612 if entry
and entry
.is_cfunction
:
1613 var_entry
= entry
.as_variable
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
)
1622 return super(NameNode
, self
).coerce_to(dst_type
, env
)
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.
1629 entry
= env
.lookup(self
.name
)
1630 if entry
and entry
.as_module
:
1631 return entry
.as_module
1634 def analyse_as_type(self
, env
):
1635 if self
.cython_attribute
:
1636 type = PyrexTypes
.parse_basic_type(self
.cython_attribute
)
1638 type = PyrexTypes
.parse_basic_type(self
.name
)
1643 entry
= env
.lookup(self
.name
)
1644 if entry
and entry
.is_type
:
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.
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
:
1660 def analyse_target_declaration(self
, env
):
1662 self
.entry
= env
.lookup_here(self
.name
)
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
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
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
)
1679 self
.entry
= env
.declare_builtin(self
.name
, self
.pos
)
1681 self
.type = PyrexTypes
.error_type
1686 if entry
.type.is_buffer
:
1688 Buffer
.used_buffer_aux_vars(entry
)
1689 self
.analyse_rvalue_entry(env
)
1692 def analyse_target_types(self
, env
):
1693 self
.analyse_entry(env
, is_target
=True)
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
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'"
1708 self
.type = PyrexTypes
.error_type
1710 if self
.entry
.type.is_buffer
:
1712 Buffer
.used_buffer_aux_vars(self
.entry
)
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
)
1721 if entry
.is_declared_generic
:
1722 self
.result_ctype
= py_object_type
1724 if entry
.is_pyglobal
or entry
.is_builtin
:
1725 if entry
.is_builtin
and entry
.is_const
:
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
1737 def nogil_check(self
, env
):
1739 if self
.is_used_as_rvalue
:
1741 if entry
.is_builtin
:
1742 if not entry
.is_const
: # cached builtins are ok
1744 elif entry
.is_pyglobal
:
1746 elif self
.entry
.type.is_memoryviewslice
:
1747 if self
.cf_is_null
or self
.cf_maybe_null
:
1749 MemoryView
.err_if_nogil_initialized_check(self
.pos
, env
)
1751 gil_message
= "Accessing Python global or builtin"
1753 def analyse_entry(self
, env
, is_target
=False):
1754 #print "NameNode.analyse_entry:", self.name ###
1755 self
.check_identifier_kind()
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
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.
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
1778 "'%s' is not a constant, variable or function identifier" % self
.name
)
1780 def is_simple(self
):
1781 # If it's not a C variable, it'll be in a temp.
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"
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
1797 for assignment
in self
.cf_state
:
1798 if assignment
.rhs
.may_be_none():
1801 del self
._none
_checking
1803 return super(NameNode
, self
).may_be_none()
1805 def nonlocally_immutable(self
):
1806 if ExprNode
.nonlocally_immutable(self
):
1809 if not entry
or entry
.in_closure
:
1811 return entry
.is_local
or entry
.is_arg
or entry
.is_builtin
or entry
.is_readonly
1813 def calculate_target_results(self
, env
):
1816 def check_const(self
):
1818 if entry
is not None and not (entry
.is_const
or entry
.is_cfunction
or entry
.is_builtin
):
1823 def check_const_addr(self
):
1825 if not (entry
.is_cglobal
or entry
.is_cfunction
or entry
.is_builtin
):
1826 self
.addr_not_const()
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
1835 def is_addressable(self
):
1836 return self
.entry
.is_variable
and not self
.type.is_memoryviewslice
1838 def is_ephemeral(self
):
1839 # Name nodes are never ephemeral, even if the
1840 # result is in a temporary.
1843 def calculate_result_code(self
):
1846 return "<error>" # There was an error earlier
1849 def generate_result_code(self
, code
):
1850 assert hasattr(self
, 'entry')
1853 return # There was an error earlier
1854 if entry
.is_builtin
and entry
.is_const
:
1855 return # Lookup already cached
1856 elif entry
.is_pyclass_attr
:
1857 assert entry
.type.is_pyobject
, "Python global or builtin not a Python object"
1858 interned_cname
= code
.intern_identifier(self
.entry
.name
)
1859 if entry
.is_builtin
:
1860 namespace
= Naming
.builtins_cname
1861 else: # entry.is_pyglobal
1862 namespace
= entry
.scope
.namespace_cname
1863 if not self
.cf_is_null
:
1865 '%s = PyObject_GetItem(%s, %s);' % (
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"))
1874 '%s = __Pyx_GetModuleGlobalName(%s);' % (
1877 if not self
.cf_is_null
:
1879 code
.putln(code
.error_goto_if_null(self
.result(), self
.pos
))
1880 code
.put_gotref(self
.py_result())
1882 elif entry
.is_builtin
:
1883 assert entry
.type.is_pyobject
, "Python global or builtin not a Python object"
1884 interned_cname
= code
.intern_identifier(self
.entry
.name
)
1885 code
.globalstate
.use_utility_code(
1886 UtilityCode
.load_cached("GetBuiltinName", "ObjectHandling.c"))
1888 '%s = __Pyx_GetBuiltinName(%s); %s' % (
1891 code
.error_goto_if_null(self
.result(), self
.pos
)))
1892 code
.put_gotref(self
.py_result())
1894 elif entry
.is_pyglobal
:
1895 assert entry
.type.is_pyobject
, "Python global or builtin not a Python object"
1896 interned_cname
= code
.intern_identifier(self
.entry
.name
)
1897 if entry
.scope
.is_module_scope
:
1898 code
.globalstate
.use_utility_code(
1899 UtilityCode
.load_cached("GetModuleGlobalName", "ObjectHandling.c"))
1901 '%s = __Pyx_GetModuleGlobalName(%s); %s' % (
1904 code
.error_goto_if_null(self
.result(), self
.pos
)))
1906 # FIXME: is_pyglobal is also used for class namespace
1907 code
.globalstate
.use_utility_code(
1908 UtilityCode
.load_cached("GetNameInClass", "ObjectHandling.c"))
1910 '%s = __Pyx_GetNameInClass(%s, %s); %s' % (
1912 entry
.scope
.namespace_cname
,
1914 code
.error_goto_if_null(self
.result(), self
.pos
)))
1915 code
.put_gotref(self
.py_result())
1917 elif entry
.is_local
or entry
.in_closure
or entry
.from_closure
or entry
.type.is_memoryviewslice
:
1918 # Raise UnboundLocalError for objects and memoryviewslices
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
)
1923 memslice_check
= entry
.type.is_memoryviewslice
and self
.initialized_check
1925 if null_code
and raise_unbound
and (entry
.type.is_pyobject
or memslice_check
):
1926 code
.put_error_if_unbound(self
.pos
, entry
, self
.in_nogil_context
)
1928 def generate_assignment_code(self
, rhs
, code
):
1929 #print "NameNode.generate_assignment_code:", self.name ###
1932 return # There was an error earlier
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")
1938 # is_pyglobal seems to be True for module level-globals only.
1939 # We use this to access class->tp_dict if necessary.
1940 if entry
.is_pyglobal
:
1941 assert entry
.type.is_pyobject
, "Python global or builtin not a Python object"
1942 interned_cname
= code
.intern_identifier(self
.entry
.name
)
1943 namespace
= self
.entry
.scope
.namespace_cname
1945 # if the entry is a member we have to cheat: SetAttr does not work
1946 # on types, so we create a descriptor which is then added to tp_dict
1947 setter
= 'PyDict_SetItem'
1948 namespace
= '%s->tp_dict' % namespace
1949 elif entry
.scope
.is_module_scope
:
1950 setter
= 'PyDict_SetItem'
1951 namespace
= Naming
.moddict_cname
1952 elif entry
.is_pyclass_attr
:
1953 setter
= 'PyObject_SetItem'
1955 assert False, repr(entry
)
1956 code
.put_error_if_neg(
1958 '%s(%s, %s, %s)' % (
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
)
1969 # in Py2.6+, we need to invalidate the method cache
1970 code
.putln("PyType_Modified(%s);" %
1971 entry
.scope
.parent_type
.typeptr_cname
)
1973 if self
.type.is_memoryviewslice
:
1974 self
.generate_acquire_memoryviewslice(rhs
, code
)
1976 elif self
.type.is_buffer
:
1977 # Generate code for doing the buffer release/acquisition.
1978 # This might raise an exception in which case the assignment (done
1979 # below) will not happen.
1981 # The reason this is not in a typetest-like node is because the
1982 # variables that the acquired buffer info is stored to is allocated
1983 # per entry and coupled with it.
1984 self
.generate_acquire_buffer(rhs
, code
)
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
1995 if not self
.cf_is_null
:
1996 if self
.cf_maybe_null
:
1997 code
.put_xgotref(self
.py_result())
1999 code
.put_gotref(self
.py_result())
2001 if entry
.is_cglobal
:
2002 code
.put_decref_set(
2003 self
.result(), rhs
.result_as(self
.ctype()))
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()))
2010 code
.put_decref_set(
2011 self
.result(), rhs
.result_as(self
.ctype()))
2015 code
.put_giveref(rhs
.py_result())
2016 if not self
.type.is_memoryviewslice
:
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
)
2027 rhs
.free_temps(code
)
2029 def generate_acquire_memoryviewslice(self
, rhs
, code
):
2031 Slices, coercions from objects, return values etc are new references.
2032 We have a borrowed reference in case of dst = src
2036 MemoryView
.put_acquire_memoryviewslice(
2037 lhs_cname
=self
.result(),
2042 have_gil
=not self
.in_nogil_context
,
2043 first_assignment
=self
.cf_is_null
)
2045 def generate_acquire_buffer(self
, rhs
, code
):
2046 # rhstmp is only used in case the rhs is a complicated expression leading to
2047 # the object, to avoid repeating the same C expression for every reference
2048 # to the rhs. It does NOT hold a reference.
2049 pretty_rhs
= isinstance(rhs
, NameNode
) or rhs
.is_temp
2051 rhstmp
= rhs
.result_as(self
.ctype())
2053 rhstmp
= code
.funcstate
.allocate_temp(self
.entry
.type, manage_ref
=False)
2054 code
.putln('%s = %s;' % (rhstmp
, rhs
.result_as(self
.ctype())))
2057 Buffer
.put_assign_to_buffer(self
.result(), rhstmp
, self
.entry
,
2058 is_initialized
=not self
.lhs_of_first_assignment
,
2059 pos
=self
.pos
, code
=code
)
2062 code
.putln("%s = 0;" % rhstmp
)
2063 code
.funcstate
.release_temp(rhstmp
)
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'
2074 # minor hack: fake a NameError on KeyError
2076 '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' %
2079 'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {'
2080 ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s'
2082 '}' % (namespace
, interned_cname
,
2084 code
.error_goto(self
.pos
)))
2085 elif self
.entry
.is_pyglobal
:
2086 code
.globalstate
.use_utility_code(
2087 UtilityCode
.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"))
2088 interned_cname
= code
.intern_identifier(self
.entry
.name
)
2089 del_code
= '__Pyx_PyObject_DelAttrStr(%s, %s)' % (
2090 Naming
.module_cname
, interned_cname
)
2091 if ignore_nonexisting
:
2092 code
.putln('if (unlikely(%s < 0)) { if (likely(PyErr_ExceptionMatches(PyExc_AttributeError))) PyErr_Clear(); else %s }' % (
2094 code
.error_goto(self
.pos
)))
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
)
2102 if self
.entry
.type.is_pyobject
:
2103 if self
.entry
.in_closure
:
2105 if ignore_nonexisting
and self
.cf_maybe_null
:
2106 code
.put_xgotref(self
.result())
2108 code
.put_gotref(self
.result())
2109 if ignore_nonexisting
and self
.cf_maybe_null
:
2110 code
.put_xdecref(self
.result(), self
.ctype())
2112 code
.put_decref(self
.result(), self
.ctype())
2113 code
.putln('%s = NULL;' % self
.result())
2115 code
.put_xdecref_memoryviewslice(self
.entry
.cname
,
2116 have_gil
=not self
.nogil
)
2118 error(self
.pos
, "Deletion of C names not supported")
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)'
2126 style
, text
= 'c_call', 'c function (%s)'
2127 code
.annotate(pos
, AnnotationItem(style
, text
% self
.type, size
=len(self
.name
)))
2129 class BackquoteNode(ExprNode
):
2134 type = py_object_type
2138 def analyse_types(self
, env
):
2139 self
.arg
= self
.arg
.analyse_types(env
)
2140 self
.arg
= self
.arg
.coerce_to_pyobject(env
)
2144 gil_message
= "Backquote expression"
2146 def calculate_constant_result(self
):
2147 self
.constant_result
= repr(self
.arg
.constant_result
)
2149 def generate_result_code(self
, code
):
2151 "%s = PyObject_Repr(%s); %s" % (
2153 self
.arg
.py_result(),
2154 code
.error_goto_if_null(self
.result(), self
.pos
)))
2155 code
.put_gotref(self
.py_result())
2158 class ImportNode(ExprNode
):
2159 # Used as part of import statement implementation.
2160 # Implements result =
2161 # __import__(module_name, globals(), None, name_list, level)
2163 # module_name StringNode dotted name of module. Empty module
2164 # name means importing the parent package according
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
2175 type = py_object_type
2177 subexprs
= ['module_name', 'name_list']
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
):
2186 module_name
= self
.module_name
.analyse_types(env
)
2187 self
.module_name
= module_name
.coerce_to_pyobject(env
)
2189 name_list
= self
.name_list
.analyse_types(env
)
2190 self
.name_list
= name_list
.coerce_to_pyobject(env
)
2192 env
.use_utility_code(UtilityCode
.load_cached("Import", "ImportExport.c"))
2195 gil_message
= "Python import"
2197 def generate_result_code(self
, code
):
2199 name_list_code
= self
.name_list
.py_result()
2201 name_list_code
= "0"
2203 "%s = __Pyx_Import(%s, %s, %d); %s" % (
2205 self
.module_name
.py_result(),
2208 code
.error_goto_if_null(self
.result(), self
.pos
)))
2209 code
.put_gotref(self
.py_result())
2212 class IteratorNode(ExprNode
):
2213 # Used as part of for statement implementation.
2215 # Implements result = iter(sequence)
2219 type = py_object_type
2220 iter_func_ptr
= None
2221 counter_cname
= None
2222 cpp_iterator_cname
= None
2223 reversed = False # currently only used for list/tuple types (see Optimize.py)
2225 subexprs
= ['sequence']
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
)
2236 self
.sequence
= self
.sequence
.coerce_to_pyobject(env
)
2237 if self
.sequence
.type is list_type
or \
2238 self
.sequence
.type is tuple_type
:
2239 self
.sequence
= self
.sequence
.as_none_safe_node("'NoneType' object is not iterable")
2243 gil_message
= "Iterating over Python object"
2245 _func_iternext_type
= PyrexTypes
.CPtrType(PyrexTypes
.CFuncType(
2246 PyrexTypes
.py_object_type
, [
2247 PyrexTypes
.CFuncTypeArg("it", PyrexTypes
.py_object_type
, None),
2250 def type_dependencies(self
, env
):
2251 return self
.sequence
.type_dependencies(env
)
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
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")
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
2278 or not end
.type.is_cfunction
2280 error(self
.pos
, "missing end() on %s" % self
.sequence
.type)
2281 self
.type = error_type
2283 iter_type
= begin
.type.return_type
2284 if iter_type
.is_cpp_class
:
2285 if env
.lookup_operator_for_types(
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
2292 if env
.lookup_operator_for_types(self
.pos
, '++', [iter_type
]) is None:
2293 error(self
.pos
, "missing operator++ on result of begin() on %s" % self
.sequence
.type)
2294 self
.type = error_type
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
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
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
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()
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
))
2324 if sequence_type
.is_array
or sequence_type
.is_ptr
:
2325 raise InternalError("for in carray slice not transformed")
2326 is_builtin_sequence
= sequence_type
is list_type
or \
2327 sequence_type
is tuple_type
2328 if not is_builtin_sequence
:
2329 # reversed() not currently optimised (see Optimize.py)
2330 assert not self
.reversed, "internal error: reversed() only implemented for list/tuple objects"
2331 self
.may_be_a_sequence
= not sequence_type
.is_builtin_type
2332 if self
.may_be_a_sequence
:
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)
2341 if sequence_type
is list_type
:
2342 init_value
= 'PyList_GET_SIZE(%s) - 1' % self
.result()
2344 init_value
= 'PyTuple_GET_SIZE(%s) - 1' % self
.result()
2348 "%s = %s; __Pyx_INCREF(%s); %s = %s;" % (
2350 self
.sequence
.py_result(),
2355 if not is_builtin_sequence
:
2356 self
.iter_func_ptr
= code
.funcstate
.allocate_temp(self
._func
_iternext
_type
, manage_ref
=False)
2357 if self
.may_be_a_sequence
:
2358 code
.putln("%s = NULL;" % self
.iter_func_ptr
)
2359 code
.putln("} else {")
2360 code
.put("%s = -1; " % self
.counter_cname
)
2361 code
.putln("%s = PyObject_GetIter(%s); %s" % (
2363 self
.sequence
.py_result(),
2364 code
.error_goto_if_null(self
.result(), self
.pos
)))
2365 code
.put_gotref(self
.py_result())
2366 code
.putln("%s = Py_TYPE(%s)->tp_iternext;" % (self
.iter_func_ptr
, self
.py_result()))
2367 if self
.may_be_a_sequence
:
2370 def generate_next_sequence_item(self
, test_name
, result_name
, code
):
2371 assert self
.counter_cname
, "internal error: counter_cname temp not prepared"
2372 final_size
= 'Py%s_GET_SIZE(%s)' % (test_name
, self
.py_result())
2373 if self
.sequence
.is_sequence_constructor
:
2374 item_count
= len(self
.sequence
.args
)
2375 if self
.sequence
.mult_factor
is None:
2376 final_size
= item_count
2377 elif isinstance(self
.sequence
.mult_factor
.constant_result
, (int, long)):
2378 final_size
= item_count
* self
.sequence
.mult_factor
.constant_result
2379 code
.putln("if (%s >= %s) break;" % (self
.counter_cname
, final_size
))
2384 code
.putln("#if CYTHON_COMPILING_IN_CPYTHON")
2386 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s%s; %s" % (
2394 # use the error label to avoid C compiler warnings if we only use it below
2395 code
.error_goto_if_neg('0', self
.pos
)
2399 "%s = PySequence_ITEM(%s, %s); %s%s; %s" % (
2405 code
.error_goto_if_null(result_name
, self
.pos
)))
2406 code
.putln("#endif")
2408 def generate_iter_next_result_code(self
, result_name
, code
):
2409 sequence_type
= self
.sequence
.type
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
2416 end_func
= "%s.end" % self
.sequence
.result()
2417 # TODO: Cache end() call?
2418 code
.putln("if (!(%s != %s())) break;" % (
2421 code
.putln("%s = *%s;" % (
2424 code
.putln("++%s;" % self
.result())
2426 elif sequence_type
is list_type
:
2427 self
.generate_next_sequence_item('List', result_name
, code
)
2429 elif sequence_type
is tuple_type
:
2430 self
.generate_next_sequence_item('Tuple', result_name
, code
)
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
)
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
))
2453 code
.putln("break;")
2455 code
.put_gotref(result_name
)
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
)
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.
2475 # iterator IteratorNode
2477 def __init__(self
, iterator
):
2478 AtomicExprNode
.__init
__(self
, iterator
.pos
)
2479 self
.iterator
= iterator
2481 def type_dependencies(self
, env
):
2482 return self
.iterator
.type_dependencies(env
)
2484 def infer_type(self
, env
, iterator_type
= None):
2485 if iterator_type
is None:
2486 iterator_type
= self
.iterator
.infer_type(env
)
2487 if iterator_type
.is_ptr
or iterator_type
.is_array
:
2488 return iterator_type
.base_type
2489 elif iterator_type
.is_cpp_class
:
2490 item_type
= env
.lookup_operator_for_types(self
.pos
, "*", [iterator_type
]).type.return_type
2491 if item_type
.is_reference
:
2492 item_type
= item_type
.ref_base_type
2493 if item_type
.is_const
:
2494 item_type
= item_type
.const_base_type
2497 # Avoid duplication of complicated logic.
2498 fake_index_node
= IndexNode(
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
)
2505 def analyse_types(self
, env
):
2506 self
.type = self
.infer_type(env
, self
.iterator
.type)
2510 def generate_result_code(self
, code
):
2511 self
.iterator
.generate_iter_next_result_code(self
.result(), code
)
2514 class WithExitCallNode(ExprNode
):
2515 # The __exit__() call of a 'with' statement. Used in both the
2516 # except and finally clauses.
2518 # with_stat WithStatNode the surrounding 'with' statement
2519 # args TupleNode or ResultStatNode the exception info tuple
2524 def analyse_types(self
, env
):
2525 self
.args
= self
.args
.analyse_types(env
)
2526 self
.type = PyrexTypes
.c_bint_type
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
)
2535 self
.args
.generate_evaluation_code(code
)
2536 result_var
= code
.funcstate
.allocate_temp(py_object_type
, manage_ref
=False)
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);" % (
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
)
2549 code
.putln(code
.error_goto_if_null(result_var
, self
.pos
))
2550 code
.put_gotref(result_var
)
2551 if self
.result_is_used
:
2552 self
.allocate_temp_result(code
)
2553 code
.putln("%s = __Pyx_PyObject_IsTrue(%s);" % (self
.result(), result_var
))
2554 code
.put_decref_clear(result_var
, type=py_object_type
)
2555 if self
.result_is_used
:
2556 code
.put_error_if_neg(self
.pos
, self
.result())
2557 code
.funcstate
.release_temp(result_var
)
2558 if self
.test_if_run
:
2562 class ExcValueNode(AtomicExprNode
):
2563 # Node created during analyse_types phase
2564 # of an ExceptClauseNode to fetch the current
2567 type = py_object_type
2569 def __init__(self
, pos
):
2570 ExprNode
.__init
__(self
, pos
)
2572 def set_var(self
, var
):
2575 def calculate_result_code(self
):
2578 def generate_result_code(self
, code
):
2581 def analyse_types(self
, env
):
2585 class TempNode(ExprNode
):
2586 # Node created during analyse_types phase
2587 # of some nodes to hold a temporary value.
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.
2596 def __init__(self
, pos
, type, env
=None):
2597 ExprNode
.__init
__(self
, pos
)
2599 if type.is_pyobject
:
2600 self
.result_ctype
= py_object_type
2603 def analyse_types(self
, env
):
2606 def analyse_target_declaration(self
, env
):
2609 def generate_result_code(self
, code
):
2612 def allocate(self
, code
):
2613 self
.temp_cname
= code
.funcstate
.allocate_temp(self
.type, manage_ref
=True)
2615 def release(self
, code
):
2616 code
.funcstate
.release_temp(self
.temp_cname
)
2617 self
.temp_cname
= None
2621 return self
.temp_cname
2623 assert False, "Remember to call allocate/release on TempNode"
2626 # Do not participate in normal temp alloc/dealloc:
2627 def allocate_temp_result(self
, code
):
2630 def release_temp_result(self
, code
):
2633 class PyTempNode(TempNode
):
2634 # TempNode holding a Python value.
2636 def __init__(self
, pos
, env
):
2637 TempNode
.__init
__(self
, pos
, PyrexTypes
.py_object_type
, env
)
2639 class RawCNameExprNode(ExprNode
):
2642 def __init__(self
, pos
, type=None, cname
=None):
2643 ExprNode
.__init
__(self
, pos
, type=type)
2644 if cname
is not None:
2647 def analyse_types(self
, env
):
2650 def set_cname(self
, cname
):
2656 def generate_result_code(self
, code
):
2660 #-------------------------------------------------------------------
2662 # Parallel nodes (cython.parallel.thread(savailable|id))
2664 #-------------------------------------------------------------------
2666 class ParallelThreadsAvailableNode(AtomicExprNode
):
2668 Note: this is disabled and not a valid directive at this moment
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()
2675 type = PyrexTypes
.c_int_type
2677 def analyse_types(self
, env
):
2679 # env.add_include_file("omp.h")
2682 def generate_result_code(self
, code
):
2683 code
.putln("#ifdef _OPENMP")
2684 code
.putln("if (omp_in_parallel()) %s = omp_get_max_threads();" %
2686 code
.putln("else %s = omp_get_num_threads();" % self
.temp_code
)
2688 code
.putln("%s = 1;" % self
.temp_code
)
2689 code
.putln("#endif")
2692 return self
.temp_code
2695 class ParallelThreadIdNode(AtomicExprNode
): #, Nodes.ParallelNode):
2697 Implements cython.parallel.threadid()
2700 type = PyrexTypes
.c_int_type
2702 def analyse_types(self
, env
):
2704 # env.add_include_file("omp.h")
2707 def generate_result_code(self
, code
):
2708 code
.putln("#ifdef _OPENMP")
2709 code
.putln("%s = omp_get_thread_num();" % self
.temp_code
)
2711 code
.putln("%s = 0;" % self
.temp_code
)
2712 code
.putln("#endif")
2715 return self
.temp_code
2718 #-------------------------------------------------------------------
2722 #-------------------------------------------------------------------
2724 class IndexNode(ExprNode
):
2725 # Sequence indexing.
2729 # indices [ExprNode]
2730 # type_indices [PyrexType]
2731 # is_buffer_access boolean Whether this is a buffer access.
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.
2737 # is_fused_index boolean Whether the index is used to specialize a
2740 subexprs
= ['base', 'index', 'indices']
2745 is_fused_index
= False
2747 # Whether we're assigning to a buffer (in that case it needs to be
2749 writable_needed
= False
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
2760 def __init__(self
, pos
, index
, **kw
):
2761 ExprNode
.__init
__(self
, pos
, index
=index
, **kw
)
2764 def calculate_constant_result(self
):
2765 self
.constant_result
= \
2766 self
.base
.constant_result
[self
.index
.constant_result
]
2768 def compile_time_value(self
, denv
):
2769 base
= self
.base
.compile_time_value(denv
)
2770 index
= self
.index
.compile_time_value(denv
)
2773 except Exception, e
:
2774 self
.compile_time_value_error(e
)
2776 def is_ephemeral(self
):
2777 return self
.base
.is_ephemeral()
2779 def is_simple(self
):
2780 if self
.is_buffer_access
or self
.memslice_index
:
2782 elif self
.memslice_slice
:
2786 return (base
.is_simple() and self
.index
.is_simple()
2787 and base
.type and (base
.type.is_ptr
or base
.type.is_array
))
2789 def may_be_none(self
):
2790 base_type
= self
.base
.type
2792 if base_type
.is_string
:
2794 if isinstance(self
.index
, SliceNode
):
2796 if base_type
in (bytes_type
, str_type
, unicode_type
,
2797 basestring_type
, list_type
, tuple_type
):
2799 return ExprNode
.may_be_none(self
)
2801 def analyse_target_declaration(self
, env
):
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
2811 template_values
= [self
.index
]
2813 type_node
= Nodes
.TemplatedTypeNode(
2815 positional_args
= template_values
,
2816 keyword_args
= None)
2817 return type_node
.analyse(env
, base_type
= base_type
)
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")
2825 def type_dependencies(self
, env
):
2826 return self
.base
.type_dependencies(env
) + self
.index
.type_dependencies(env
)
2828 def infer_type(self
, env
):
2829 base_type
= self
.base
.infer_type(env
)
2830 if isinstance(self
.index
, SliceNode
):
2832 if base_type
.is_string
:
2833 # sliced C strings must coerce to Python
2835 elif base_type
.is_pyunicode_ptr
:
2836 # sliced Py_UNICODE* strings must coerce to Python
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
2843 # TODO: Handle buffers (hopefully without too much redundancy).
2844 return py_object_type
2846 index_type
= self
.index
.infer_type(env
)
2847 if index_type
and index_type
.is_int
or isinstance(self
.index
, IntNode
):
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
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:
2875 elif base_type
.is_ptr
or base_type
.is_array
:
2876 return base_type
.base_type
2878 if base_type
.is_cpp_class
:
2880 def __init__(self
, **kwds
):
2881 self
.__dict
__.update(kwds
)
2883 FakeOperand(pos
=self
.pos
, type=base_type
),
2884 FakeOperand(pos
=self
.pos
, type=index_type
),
2886 index_func
= env
.lookup_operator('[]', operands
)
2887 if index_func
is not None:
2888 return index_func
.type.return_type
2890 # may be slicing or indexing, we don't know
2891 if base_type
in (unicode_type
, str_type
):
2892 # these types always returns their own type on Python indexing/slicing
2895 # TODO: Handle buffers (hopefully without too much redundancy).
2896 return py_object_type
2898 def analyse_types(self
, env
):
2899 return self
.analyse_base_and_index_types(env
, getting
=True)
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)
2909 def analyse_base_and_index_types(self
, env
, getting
=False, setting
=False,
2911 # Note: This might be cleaned up by having IndexNode
2912 # parsed in a saner way and only construct the tuple if
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
2921 self
.is_memslice_copy
= False
2922 # incomplete indexing, Ellipsis indexing or slicing
2923 self
.memslice_slice
= False
2925 self
.memslice_index
= False
2928 self
.base
= self
.base
.analyse_types(env
)
2930 if self
.base
.type.is_error
:
2931 # Do not visit child tree if base is undeclared to avoid confusing
2933 self
.type = PyrexTypes
.error_type
2936 is_slice
= isinstance(self
.index
, SliceNode
)
2938 if not env
.directives
['wraparound']:
2940 check_negative_indices(self
.index
.start
, self
.index
.stop
)
2942 check_negative_indices(self
.index
)
2944 # Potentially overflowing index value.
2945 if not is_slice
and isinstance(self
.index
, IntNode
) and Utils
.long_literal(self
.index
.value
):
2946 self
.index
= self
.index
.coerce_to_pyobject(env
)
2948 is_memslice
= self
.base
.type.is_memoryviewslice
2950 # Handle the case where base is a literal char* (and we expect a string, not an int)
2951 if not is_memslice
and (isinstance(self
.base
, BytesNode
) or is_slice
):
2952 if self
.base
.type.is_string
or not (self
.base
.type.is_ptr
or self
.base
.type.is_array
):
2953 self
.base
= self
.base
.coerce_to_pyobject(env
)
2955 skip_child_analysis
= False
2956 buffer_access
= False
2959 indices
= self
.indices
2960 elif isinstance(self
.index
, TupleNode
):
2961 indices
= self
.index
.args
2963 indices
= [self
.index
]
2965 if (is_memslice
and not self
.indices
and
2966 isinstance(self
.index
, EllipsisNode
)):
2967 # Memoryviewslice copying
2968 self
.is_memslice_copy
= True
2971 # memoryviewslice indexing or slicing
2974 skip_child_analysis
= True
2975 newaxes
= [newaxis
for newaxis
in indices
if newaxis
.is_none
]
2976 have_slices
, indices
= MemoryView
.unellipsify(indices
,
2978 self
.base
.type.ndim
)
2980 self
.memslice_index
= (not newaxes
and
2981 len(indices
) == self
.base
.type.ndim
)
2984 index_type
= PyrexTypes
.c_py_ssize_t_type
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" %
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
]
3001 if isinstance(index
, SliceNode
):
3002 self
.memslice_slice
= True
3003 if index
.step
.is_none
:
3004 axes
.append((access
, packing
))
3006 axes
.append((access
, 'strided'))
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
)
3018 self
.memslice_slice
= True
3019 new_indices
.append(index
)
3020 axes
.append(('direct', 'strided'))
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
3028 self
.memslice_index
= True
3029 index
= index
.coerce_to(index_type
, env
)
3031 new_indices
.append(index
)
3034 self
.type = error_type
3035 error(index
.pos
, "Invalid index for memoryview specified")
3038 self
.memslice_index
= self
.memslice_index
and not self
.memslice_slice
3039 self
.original_indices
= indices
3040 # All indices with all start/stop/step for slices.
3041 # We need to keep this around
3042 self
.indices
= new_indices
3045 elif self
.base
.type.is_buffer
:
3047 if len(indices
) == self
.base
.type.ndim
:
3048 buffer_access
= True
3049 skip_child_analysis
= True
3051 x
= x
.analyse_types(env
)
3052 if not x
.type.is_int
:
3053 buffer_access
= False
3055 if buffer_access
and not self
.base
.type.is_memoryviewslice
:
3056 assert hasattr(self
.base
, "entry") # Must be a NameNode-like node
3058 # On cloning, indices is cloned. Otherwise, unpack index into indices
3059 assert not (buffer_access
and isinstance(self
.index
, CloneNode
))
3061 self
.nogil
= env
.nogil
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
)
3068 self
.indices
= indices
3070 self
.type = self
.base
.type.dtype
3071 self
.is_buffer_access
= True
3072 self
.buffer_type
= self
.base
.type #self.base.entry.type
3074 if getting
and self
.type.is_pyobject
:
3077 if setting
and self
.base
.type.is_memoryviewslice
:
3078 self
.base
.type.writable_needed
= True
3080 if not self
.base
.entry
.type.writable
:
3081 error(self
.pos
, "Writing to readonly buffer")
3083 self
.writable_needed
= True
3084 if self
.base
.type.is_buffer
:
3085 self
.base
.entry
.buffer_aux
.writable_needed
= True
3087 elif self
.is_memslice_copy
:
3088 self
.type = self
.base
.type
3090 self
.memslice_ellipsis_noop
= True
3092 self
.memslice_broadcast
= True
3094 elif self
.memslice_slice
:
3097 self
.use_managed_ref
= True
3099 if not MemoryView
.validate_axes(self
.pos
, axes
):
3100 self
.type = error_type
3103 self
.type = PyrexTypes
.MemoryViewSliceType(
3104 self
.base
.type.dtype
, axes
)
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
)
3112 self
.memslice_broadcast
= True
3115 base_type
= self
.base
.type
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
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
3129 warning(self
.pos
, "cannot assign to Unicode string index", level
=1)
3130 elif self
.index
.constant_result
in (0, -1):
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
:
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']):
3147 self
.index
= self
.index
.coerce_to(PyrexTypes
.c_py_ssize_t_type
, env
).coerce_to_simple(env
)
3148 self
.original_index_type
.create_to_py_utility_code(env
)
3150 self
.index
= self
.index
.coerce_to_pyobject(env
)
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
:
3158 self
.type = PyrexTypes
.c_uchar_type
3160 # not using 'uchar' to enable fast and safe error reporting as '-1'
3161 self
.type = PyrexTypes
.c_int_type
3162 elif is_slice
and base_type
in (bytes_type
, str_type
, unicode_type
, list_type
, tuple_type
):
3163 self
.type = base_type
3166 if base_type
in (list_type
, tuple_type
) and self
.index
.type.is_int
:
3167 item_type
= infer_sequence_item_type(
3168 env
, self
.base
, self
.index
, seq_type
=base_type
)
3169 if item_type
is None:
3170 item_type
= py_object_type
3171 self
.type = item_type
3172 if base_type
in (list_type
, tuple_type
, dict_type
):
3173 # do the None check explicitly (not in a helper) to allow optimising it away
3174 self
.base
= self
.base
.as_none_safe_node("'NoneType' object is not subscriptable")
3176 if base_type
.is_ptr
or base_type
.is_array
:
3177 self
.type = base_type
.base_type
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
:
3185 "Invalid index type '%s'" %
3187 elif base_type
.is_cpp_class
:
3188 function
= env
.lookup_operator("[]", [self
.base
, self
.index
])
3189 if function
is None:
3190 error(self
.pos
, "Indexing '%s' not supported for index type '%s'" % (base_type
, self
.index
.type))
3191 self
.type = PyrexTypes
.error_type
3192 self
.result_code
= "<error>"
3194 func_type
= function
.type
3195 if func_type
.is_ptr
:
3196 func_type
= func_type
.base_type
3197 self
.index
= self
.index
.coerce_to(func_type
.args
[0].type, env
)
3198 self
.type = func_type
.return_type
3199 if setting
and not func_type
.return_type
.is_reference
:
3200 error(self
.pos
, "Can't set non-reference result '%s'" % self
.type)
3201 elif base_type
.is_cfunction
:
3202 if base_type
.is_fused
:
3203 self
.parse_indexed_fused_cdef(env
)
3205 self
.type_indices
= self
.parse_index_as_types(env
)
3206 if base_type
.templates
is None:
3207 error(self
.pos
, "Can only parameterize template functions.")
3208 elif len(base_type
.templates
) != len(self
.type_indices
):
3209 error(self
.pos
, "Wrong number of template arguments: expected %s, got %s" % (
3210 (len(base_type
.templates
), len(self
.type_indices
))))
3211 self
.type = base_type
.specialize(dict(zip(base_type
.templates
, self
.type_indices
)))
3214 "Attempting to index non-array type '%s'" %
3216 self
.type = PyrexTypes
.error_type
3218 self
.wrap_in_nonecheck_node(env
, getting
)
3221 def wrap_in_nonecheck_node(self
, env
, getting
):
3222 if not env
.directives
['nonecheck'] or not self
.base
.may_be_none():
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"
3231 msg
= "Cannot index None memoryview slice"
3233 msg
= "'NoneType' object is not subscriptable"
3235 self
.base
= self
.base
.as_none_safe_node(msg
)
3237 def parse_index_as_types(self
, env
, required
=True):
3238 if isinstance(self
.index
, TupleNode
):
3239 indices
= self
.index
.args
3241 indices
= [self
.index
]
3243 for index
in indices
:
3244 type_indices
.append(index
.analyse_as_type(env
))
3245 if type_indices
[-1] is None:
3247 error(index
.pos
, "not parsable as a type")
3251 def parse_indexed_fused_cdef(self
, env
):
3253 Interpret fused_cdef_func[specific_type1, ...]
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.
3260 self
.type = PyrexTypes
.error_type
3262 self
.is_fused_index
= True
3264 base_type
= self
.base
.type
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)
3275 if specific_types
is None:
3276 self
.index
= self
.index
.analyse_types(env
)
3278 if not self
.base
.entry
.as_variable
:
3279 error(self
.pos
, "Can only index fused functions with types")
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
3285 self
.base
.is_temp
= True
3288 self
.entry
.used
= True
3290 self
.is_fused_index
= False
3293 for i
, type in enumerate(specific_types
):
3294 specific_types
[i
] = type.specialize_fused(env
)
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
)
3304 # See if our index types form valid specializations
3305 for pos
, specific_type
, fused_type
in zip(positions
,
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")
3312 if specific_type
is None or specific_type
.is_error
:
3315 fused_to_specific
= dict(zip(fused_types
, specific_types
))
3316 type = base_type
.specialize(fused_to_specific
)
3319 # Only partially specific, this is invalid
3321 "Index operation makes function only partially specific")
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
3328 if self
.base
.is_attribute
:
3329 # Pretend to be a normal attribute, for cdef extension
3331 self
.entry
= signature
.entry
3332 self
.is_attribute
= True
3333 self
.obj
= self
.base
.obj
3335 self
.type.entry
.used
= True
3336 self
.base
.type = signature
3337 self
.base
.entry
= signature
.entry
3342 raise InternalError("Couldn't find the right signature")
3344 gil_message
= "Indexing Python object"
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",
3353 if self
.type.is_pyobject
:
3354 error(self
.pos
, "Cannot access buffer with object dtype without gil")
3356 super(IndexNode
, self
).nogil_check(env
)
3359 def check_const_addr(self
):
3360 return self
.base
.check_const_addr() and self
.index
.check_const()
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
3370 elif self
.type.is_ptr
:
3371 # non-const pointers can always be reassigned
3373 elif self
.type.is_array
:
3374 # fixed-sized arrays aren't l-values
3376 # Just about everything else returned by the index operator
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]))"
3393 assert False, "unexpected base type in indexing: %s" % self
.base
.type
3394 elif self
.base
.type.is_cfunction
:
3397 ",".join([param
.declaration_code("") for param
in self
.type_indices
]))
3399 if (self
.type.is_ptr
or self
.type.is_array
) and self
.type == self
.base
.type:
3400 error(self
.pos
, "Invalid use of pointer slice")
3402 index_code
= "(%s[%s])"
3403 return index_code
% (self
.base
.result(), self
.index
.result())
3405 def extra_index_params(self
, code
):
3406 if self
.index
.type.is_int
:
3407 is_list
= self
.base
.type is list_type
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
)
3422 def generate_subexpr_evaluation_code(self
, code
):
3423 self
.base
.generate_evaluation_code(code
)
3424 if self
.type_indices
is not None:
3426 elif self
.indices
is None:
3427 self
.index
.generate_evaluation_code(code
)
3429 for i
in self
.indices
:
3430 i
.generate_evaluation_code(code
)
3432 def generate_subexpr_disposal_code(self
, code
):
3433 self
.base
.generate_disposal_code(code
)
3434 if self
.type_indices
is not None:
3436 elif self
.indices
is None:
3437 self
.index
.generate_disposal_code(code
)
3439 for i
in self
.indices
:
3440 i
.generate_disposal_code(code
)
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
)
3447 for i
in self
.indices
:
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
)
3461 elif self
.memslice_slice
:
3462 self
.put_memoryviewslice_slice_code(code
)
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"
3473 function
= "__Pyx_GetItemInt"
3474 code
.globalstate
.use_utility_code(
3475 TempitaUtilityCode
.load_cached("GetItemInt", "ObjectHandling.c"))
3477 if self
.base
.type is dict_type
:
3478 function
= "__Pyx_PyDict_GetItem"
3479 code
.globalstate
.use_utility_code(
3480 UtilityCode
.load_cached("DictGetItem", "ObjectHandling.c"))
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"
3494 code
.globalstate
.use_utility_code(
3495 UtilityCode
.load_cached("GetItemIntByteArray", "StringTools.c"))
3497 assert False, "unexpected type %s and base type %s for indexing" % (
3498 self
.type, self
.base
.type)
3500 if self
.index
.type.is_int
:
3501 index_code
= self
.index
.result()
3503 index_code
= self
.index
.py_result()
3506 "%s = %s(%s, %s%s); if (unlikely(%s == %s)) %s;" % (
3509 self
.base
.py_result(),
3511 self
.extra_index_params(code
),
3514 code
.error_goto(self
.pos
)))
3515 if self
.type.is_pyobject
:
3516 code
.put_gotref(self
.py_result())
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"
3525 code
.globalstate
.use_utility_code(
3526 UtilityCode
.load_cached("SetItemInt", "ObjectHandling.c"))
3527 function
= "__Pyx_SetItemInt"
3528 index_code
= self
.index
.result()
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).
3541 function
= "PyObject_SetItem"
3543 "if (unlikely(%s(%s, %s, %s%s) < 0)) %s" % (
3545 self
.base
.py_result(),
3548 self
.extra_index_params(code
),
3549 code
.error_goto(self
.pos
)))
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
)
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
,
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);" % (
3565 code
.putln("*%s %s= %s;" % (ptr
, op
, rhs_code
))
3566 code
.put_giveref("*%s" % ptr
)
3567 code
.funcstate
.release_temp(ptr
)
3570 code
.putln("*%s %s= %s;" % (ptrexpr
, op
, rhs
.result()))
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
)
3578 self
.generate_subexpr_evaluation_code(code
)
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
)
3594 self
.result(), rhs
.result()))
3596 if generate_evaluation_code
:
3597 self
.generate_disposal_code(code
)
3599 self
.generate_subexpr_disposal_code(code
)
3600 self
.free_subexpr_temps(code
)
3602 rhs
.generate_disposal_code(code
)
3603 rhs
.free_temps(code
)
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:
3612 needs_cast
= True # make at least the C compiler happy
3614 "value outside of range(0, 256)"
3615 " when assigning to byte: %s" % rhs
.constant_result
,
3618 needs_cast
= rhs
.type != PyrexTypes
.c_uchar_type
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
)
3630 code
.putln("if (unlikely(%s)) {" % ' || '.join(conditions
))
3632 'PyErr_SetString(PyExc_ValueError,'
3633 ' "byte must be in range(0, 256)"); %s' %
3634 code
.error_goto(self
.pos
))
3638 value_code
= '((unsigned char)%s)' % value_code
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"))
3650 index_code
= self
.index
.py_result()
3651 if self
.base
.type is dict_type
:
3652 function
= "PyDict_DelItem"
3654 function
= "PyObject_DelItem"
3656 "if (%s(%s, %s%s) < 0) %s" % (
3658 self
.base
.py_result(),
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
)
3665 def buffer_entry(self
):
3666 import Buffer
, MemoryView
3669 if self
.base
.is_nonecheck
:
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
)
3680 if entry
.type.is_buffer
:
3681 buffer_entry
= Buffer
.BufferEntry(entry
)
3683 buffer_entry
= MemoryView
.MemoryViewSliceBufferEntry(entry
)
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
]
3693 for temp
, index
in zip(index_temps
, self
.indices
):
3694 code
.putln("%s = %s;" % (temp
, index
.result()))
3696 # Generate buffer access code using these temps
3698 buffer_entry
= self
.buffer_entry()
3699 if buffer_entry
.type.is_buffer
:
3700 negative_indices
= buffer_entry
.type.negative_indices
3702 negative_indices
= Buffer
.buffer_defaults
['negative_indices']
3704 return buffer_entry
, Buffer
.put_buffer_lookup_code(
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
)
3713 def put_memoryviewslice_slice_code(self
, code
):
3715 buffer_entry
= self
.buffer_entry()
3716 have_gil
= not self
.in_nogil_context
3718 if sys
.version_info
< (3,):
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
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
)
3741 buffer_entry
.generate_buffer_slice_code(code
, self
.original_indices
,
3744 have_slices
=have_slices
,
3745 directives
=code
.globalstate
.directives
)
3747 def generate_memoryviewslice_setslice_code(self
, rhs
, code
):
3748 "memslice1[...] = memslice2 or memslice1[:] = memslice2"
3750 MemoryView
.copy_broadcast_memview_src_to_dst(rhs
, self
, code
)
3752 def generate_memoryviewslice_assign_scalar_code(self
, rhs
, code
):
3753 "memslice1[...] = 0.0 or memslice1[:] = 0.0"
3755 MemoryView
.assign_scalar(self
, rhs
, code
)
3758 class SliceIndexNode(ExprNode
):
3759 # 2-element slice indexing
3762 # start ExprNode or None
3763 # stop ExprNode or None
3764 # slice ExprNode or None constant slice object
3766 subexprs
= ['base', 'start', 'stop', 'slice']
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
:
3774 elif base_type
.is_pyunicode_ptr
:
3776 elif base_type
in (bytes_type
, str_type
, unicode_type
,
3777 basestring_type
, list_type
, tuple_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
3783 def may_be_none(self
):
3784 base_type
= self
.base
.type
3786 if base_type
.is_string
:
3788 if base_type
in (bytes_type
, str_type
, unicode_type
,
3789 basestring_type
, list_type
, tuple_type
):
3791 return ExprNode
.may_be_none(self
)
3793 def calculate_constant_result(self
):
3794 if self
.start
is None:
3797 start
= self
.start
.constant_result
3798 if self
.stop
is None:
3801 stop
= self
.stop
.constant_result
3802 self
.constant_result
= self
.base
.constant_result
[start
:stop
]
3804 def compile_time_value(self
, denv
):
3805 base
= self
.base
.compile_time_value(denv
)
3806 if self
.start
is None:
3809 start
= self
.start
.compile_time_value(denv
)
3810 if self
.stop
is None:
3813 stop
= self
.stop
.compile_time_value(denv
)
3815 return base
[start
:stop
]
3816 except Exception, e
:
3817 self
.compile_time_value_error(e
)
3819 def analyse_target_declaration(self
, env
):
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
3829 def analyse_types(self
, env
, getting
=True):
3830 self
.base
= self
.base
.analyse_types(env
)
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
,
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
,
3844 self
.start
= self
.start
.analyse_types(env
)
3846 self
.stop
= self
.stop
.analyse_types(env
)
3848 if not env
.directives
['wraparound']:
3849 check_negative_indices(self
.start
, self
.stop
)
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
3862 self
.type = PyrexTypes
.CPtrType(base_type
.base_type
)
3864 self
.base
= self
.base
.coerce_to_pyobject(env
)
3865 self
.type = py_object_type
3866 if base_type
.is_builtin_type
:
3867 # slicing builtin types returns something of the same type
3868 self
.type = base_type
3869 self
.base
= self
.base
.as_none_safe_node("'NoneType' object is not subscriptable")
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(
3878 start
=copy
.deepcopy(self
.start
or none_node
),
3879 stop
=copy
.deepcopy(self
.stop
or none_node
),
3881 ).analyse_types(env
)
3883 c_int
= PyrexTypes
.c_py_ssize_t_type
3885 self
.start
= self
.start
.coerce_to(c_int
, env
)
3887 self
.stop
= self
.stop
.coerce_to(c_int
, env
)
3891 nogil_check
= Node
.gil_error
3892 gil_message
= "Slicing Python object"
3894 get_slice_utility_code
= TempitaUtilityCode
.load(
3895 "SliceObject", "ObjectHandling.c", context
={'access': 'Get'})
3897 set_slice_utility_code
= TempitaUtilityCode
.load(
3898 "SliceObject", "ObjectHandling.c", context
={'access': 'Set'})
3900 def coerce_to(self
, dst_type
, env
):
3901 if ((self
.base
.type.is_string
or self
.base
.type.is_cpp_string
)
3902 and dst_type
in (bytes_type
, bytearray_type
, str_type
, unicode_type
)):
3903 if (dst_type
not in (bytes_type
, bytearray_type
)
3904 and not env
.directives
['c_string_encoding']):
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
)
3911 def generate_result_code(self
, code
):
3912 if not self
.type.is_pyobject
:
3914 "Slicing is not currently supported for '%s'." % self
.type)
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'
3928 type_name
= self
.type.name
.title()
3929 if self
.stop
is None:
3931 "%s = __Pyx_Py%s_FromString(%s + %s); %s" % (
3936 code
.error_goto_if_null(result
, self
.pos
)))
3939 "%s = __Pyx_Py%s_FromStringAndSize(%s + %s, %s - %s); %s" % (
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:
3953 "%s = __Pyx_PyUnicode_FromUnicode(%s + %s); %s" % (
3957 code
.error_goto_if_null(result
, self
.pos
)))
3960 "%s = __Pyx_PyUnicode_FromUnicodeAndLength(%s + %s, %s - %s); %s" % (
3966 code
.error_goto_if_null(result
, self
.pos
)))
3968 elif self
.base
.type is unicode_type
:
3969 code
.globalstate
.use_utility_code(
3970 UtilityCode
.load_cached("PyUnicode_Substring", "StringTools.c"))
3972 "%s = __Pyx_PyUnicode_Substring(%s, %s, %s); %s" % (
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()
3983 "%s = __Pyx_PyObject_GetSlice(%s, %s, %s, %s, %s, %s, %d, %d, %d); %s" % (
3985 self
.base
.py_result(),
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
)))
3992 if self
.base
.type is list_type
:
3993 code
.globalstate
.use_utility_code(
3994 TempitaUtilityCode
.load_cached("SliceTupleAndList", "ObjectHandling.c"))
3995 cfunc
= '__Pyx_PyList_GetSlice'
3996 elif self
.base
.type is tuple_type
:
3997 code
.globalstate
.use_utility_code(
3998 TempitaUtilityCode
.load_cached("SliceTupleAndList", "ObjectHandling.c"))
3999 cfunc
= '__Pyx_PyTuple_GetSlice'
4001 cfunc
= '__Pyx_PySequence_GetSlice'
4003 "%s = %s(%s, %s, %s); %s" % (
4006 self
.base
.py_result(),
4009 code
.error_goto_if_null(result
, self
.pos
)))
4010 code
.put_gotref(self
.py_result())
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(),
4023 py_start
, py_stop
, py_slice
,
4024 has_c_start
, has_c_stop
,
4025 bool(code
.globalstate
.directives
['wraparound'])))
4029 start_offset
= self
.start_code()
4030 if start_offset
== '0':
4034 if rhs
.type.is_array
:
4035 array_length
= rhs
.type.size
4036 self
.generate_slice_guard_code(code
, array_length
)
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
,
4046 self
.generate_subexpr_disposal_code(code
)
4047 self
.free_subexpr_temps(code
)
4048 rhs
.generate_disposal_code(code
)
4049 rhs
.free_temps(code
)
4051 def generate_deletion_code(self
, code
, ignore_nonexisting
=False):
4052 if not self
.base
.type.is_pyobject
:
4054 "Deleting slices is only supported for Python types, not '%s'." % self
.type)
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(),
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
)
4070 def get_slice_config(self
):
4071 has_c_start
, c_start
, py_start
= False, '0', 'NULL'
4073 has_c_start
= not self
.start
.type.is_pyobject
4075 c_start
= self
.start
.result()
4077 py_start
= '&%s' % self
.start
.py_result()
4078 has_c_stop
, c_stop
, py_stop
= False, '0', 'NULL'
4080 has_c_stop
= not self
.stop
.type.is_pyobject
4082 c_stop
= self
.stop
.result()
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
)
4089 def generate_slice_guard_code(self
, code
, target_size
):
4090 if not self
.base
.type.is_array
:
4092 slice_size
= self
.base
.type.size
4095 stop
= self
.stop
.result()
4099 slice_size
= self
.base
.type.size
+ stop
4106 start
= self
.start
.result()
4110 start
= self
.base
.type.size
+ start
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:
4127 check
= "(%s)-(%s)" % (stop
, start
)
4128 else: # stop is not None:
4131 code
.putln("if (unlikely((%s) != %d)) {" % (check
, target_size
))
4132 code
.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%" CYTHON_FORMAT_SSIZE_T "d, got %%" CYTHON_FORMAT_SSIZE_T "d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
4133 target_size
, check
))
4134 code
.putln(code
.error_goto(self
.pos
))
4137 def start_code(self
):
4139 return self
.start
.result()
4143 def stop_code(self
):
4145 return self
.stop
.result()
4146 elif self
.base
.type.is_array
:
4147 return self
.base
.type.size
4149 return "PY_SSIZE_T_MAX"
4151 def calculate_result_code(self
):
4152 # self.result() is not used, but this method must exist
4156 class SliceNode(ExprNode
):
4157 # start:stop:step in subscript list
4163 subexprs
= ['start', 'stop', 'step']
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
)
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
)
4179 return slice(start
, stop
, step
)
4180 except Exception, e
:
4181 self
.compile_time_value_error(e
)
4183 def may_be_none(self
):
4186 def analyse_types(self
, env
):
4187 start
= self
.start
.analyse_types(env
)
4188 stop
= self
.stop
.analyse_types(env
)
4189 step
= self
.step
.analyse_types(env
)
4190 self
.start
= start
.coerce_to_pyobject(env
)
4191 self
.stop
= stop
.coerce_to_pyobject(env
)
4192 self
.step
= step
.coerce_to_pyobject(env
)
4193 if self
.start
.is_literal
and self
.stop
.is_literal
and self
.step
.is_literal
:
4194 self
.is_literal
= True
4195 self
.is_temp
= False
4198 gil_message
= "Constructing Python slice object"
4200 def calculate_result_code(self
):
4201 return self
.result_code
4203 def generate_result_code(self
, code
):
4205 self
.result_code
= code
.get_py_const(py_object_type
, 'slice', cleanup_level
=2)
4206 code
= code
.get_cached_constants_writer()
4207 code
.mark_pos(self
.pos
)
4210 "%s = PySlice_New(%s, %s, %s); %s" % (
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())
4218 code
.put_giveref(self
.py_result())
4220 def __deepcopy__(self
, memo
):
4222 There is a copy bug in python 2.4 for slice objects.
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
)
4234 class CallNode(ExprNode
):
4236 # allow overriding the default 'may_be_none' behaviour
4237 may_return_none
= None
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
:
4259 elif result_type
.is_builtin_type
:
4260 if function
.entry
.name
== 'float':
4261 return PyrexTypes
.c_double_type
4262 elif function
.entry
.name
in Builtin
.types_that_construct_their_instance
:
4264 return py_object_type
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
)
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.
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
:
4286 if (entry
.type.is_builtin_type
and
4287 entry
.name
in Builtin
.types_that_construct_their_instance
):
4289 return ExprNode
.may_be_none(self
)
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()
4296 for arg
, member
in zip(args
, type.scope
.var_entries
):
4297 items
.append(DictItemNode(pos
=arg
.pos
, key
=StringNode(pos
=arg
.pos
, value
=member
.name
), value
=arg
))
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
)
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
)
4315 def is_lvalue(self
):
4316 return self
.type.is_reference
4318 def nogil_check(self
, env
):
4319 func_type
= self
.function_type()
4320 if func_type
.is_pyobject
:
4322 elif not getattr(func_type
, 'nogil', False):
4325 gil_message
= "Calling gil-requiring function"
4328 class SimpleCallNode(CallNode
):
4329 # Function call without keyword, * or ** args.
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
4340 subexprs
= ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
4345 wrapper_call
= False
4346 has_optional_args
= False
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
]
4354 return function(*args
)
4355 except Exception, e
:
4356 self
.compile_time_value_error(e
)
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.")
4364 type = self
.args
[0].analyse_as_type(env
)
4366 error(self
.args
[0].pos
, "Unknown type")
4368 return PyrexTypes
.CPtrType(type)
4370 def explicit_args_kwds(self
):
4371 return self
.args
, None
4373 def analyse_types(self
, env
):
4374 if self
.analyse_as_type_constructor(env
):
4378 self
.analysed
= True
4379 self
.function
.is_called
= 1
4380 self
.function
= self
.function
.analyse_types(env
)
4381 function
= self
.function
4383 if function
.is_attribute
and function
.entry
and function
.entry
.is_cmethod
:
4384 # Take ownership of the object from which the attribute
4385 # was obtained, because we need to pass it as 'self'.
4386 self
.self
= function
.obj
4387 function
.obj
= CloneNode(self
.self
)
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
)
4394 if func_type
is Builtin
.type_type
and function
.is_name
and \
4395 function
.entry
and \
4396 function
.entry
.is_builtin
and \
4397 function
.entry
.name
in Builtin
.types_that_construct_their_instance
:
4398 # calling a builtin type that returns a specific object type
4399 if function
.entry
.name
== 'float':
4400 # the following will come true later on in a transform
4401 self
.type = PyrexTypes
.c_double_type
4402 self
.result_ctype
= PyrexTypes
.c_double_type
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
4411 self
.type = function
.type_entry
.type
4412 self
.result_ctype
= py_object_type
4413 self
.may_return_none
= False
4415 self
.type = py_object_type
4418 self
.args
= [ arg
.analyse_types(env
) for arg
in self
.args
]
4419 self
.analyse_c_function_call(env
)
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
4428 if func_type
.is_ptr
:
4429 func_type
= func_type
.base_type
4433 def analyse_c_function_call(self
, env
):
4434 if self
.function
.type is error_type
:
4435 self
.type = error_type
4439 args
= [self
.self
] + self
.args
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>"
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
4455 overloaded_entry
= None
4457 if overloaded_entry
:
4458 if self
.function
.type.is_fused
:
4459 functypes
= self
.function
.type.get_all_specialized_function_types()
4460 alternatives
= [f
.entry
for f
in functypes
]
4462 alternatives
= overloaded_entry
.all_alternatives()
4464 entry
= PyrexTypes
.best_match(args
, alternatives
, self
.pos
, env
)
4467 self
.type = PyrexTypes
.error_type
4468 self
.result_code
= "<error>"
4472 self
.function
.entry
= entry
4473 self
.function
.type = entry
.type
4474 func_type
= self
.function_type()
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>"
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
4492 # check 'self' argument
4493 if entry
and entry
.is_cmethod
and func_type
.args
:
4494 formal_arg
= func_type
.args
[0]
4496 if formal_arg
.not_none
:
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
])
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
])
4508 if formal_arg
.accept_builtin_subtypes
:
4509 arg
= CMethodSelfCloneNode(self
.self
)
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
4521 some_args_in_temps
= False
4522 for i
in xrange(min(max_nargs
, actual_nargs
)):
4523 formal_arg
= func_type
.args
[i
]
4524 formal_type
= formal_arg
.type
4525 arg
= args
[i
].coerce_to(formal_type
, env
)
4526 if formal_arg
.not_none
:
4527 # C methods must do the None checks at *call* time
4528 arg
= arg
.as_none_safe_node(
4529 "cannot pass None into a C function argument that is declared 'not None'")
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
4538 elif arg
.nonlocally_immutable():
4539 # plain local variables are ok
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
)
4551 # handle additional varargs parameters
4552 for i
in xrange(max_nargs
, actual_nargs
):
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")
4560 args
[i
] = arg
= arg
.coerce_to(arg_ctype
, env
)
4561 if arg
.is_temp
and i
> 0:
4562 some_args_in_temps
= True
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
4570 for i
in xrange(actual_nargs
-1):
4571 if i
== 0 and self
.self
is not None:
4572 continue # self is ok
4574 if arg
.nonlocally_immutable():
4575 # locals, C functions, unassignable types are safe.
4577 elif arg
.type.is_cpp_class
:
4578 # Assignment has side effects, avoid.
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
4586 #self.args[i] = arg.coerce_to_temp(env)
4587 # instead: issue a warning
4588 if i
> 0 or i
== 1 and self
.self
is not None: # skip first arg
4589 warning(arg
.pos
, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
4594 # Calc result type and code fragment
4595 if isinstance(self
.function
, NewExprNode
):
4596 self
.type = PyrexTypes
.CPtrType(self
.function
.class_type
)
4598 self
.type = func_type
.return_type
4600 if self
.function
.is_name
or self
.function
.is_attribute
:
4601 if self
.function
.entry
and self
.function
.entry
.utility_code
:
4602 self
.is_temp
= 1 # currently doesn't work for self.calculate_result_code()
4604 if self
.type.is_pyobject
:
4605 self
.result_ctype
= py_object_type
4607 elif func_type
.exception_value
is not None \
4608 or func_type
.exception_check
:
4610 elif self
.type.is_memoryviewslice
:
4612 # func_type.exception_check = True
4614 # Called in 'nogil' context?
4615 self
.nogil
= env
.nogil
4617 func_type
.exception_check
and
4618 func_type
.exception_check
!= '+'):
4619 env
.use_utility_code(pyerr_occurred_withgil_utility_code
)
4620 # C++ exception handler
4621 if func_type
.exception_check
== '+':
4622 if func_type
.exception_value
is None:
4623 env
.use_utility_code(UtilityCode
.load_cached("CppExceptionConversion", "CppSupport.cpp"))
4625 def calculate_result_code(self
):
4626 return self
.c_call_code()
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
:
4632 formal_args
= func_type
.args
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
)
4642 if func_type
.is_overridable
:
4643 arg_list_code
.append(str(int(self
.wrapper_call
or self
.function
.entry
.is_unbound_cmethod
)))
4645 if func_type
.optional_arg_count
:
4646 if expected_nargs
== actual_nargs
:
4647 optional_args
= 'NULL'
4649 optional_args
= "&%s" % self
.opt_arg_struct
4650 arg_list_code
.append(optional_args
)
4652 for actual_arg
in self
.args
[len(formal_args
):]:
4653 arg_list_code
.append(actual_arg
.result())
4655 result
= "%s(%s)" % (self
.function
.result(), ', '.join(arg_list_code
))
4658 def generate_result_code(self
, code
):
4659 func_type
= self
.function_type()
4660 if self
.function
.is_name
or self
.function
.is_attribute
:
4661 if self
.function
.entry
and self
.function
.entry
.utility_code
:
4662 code
.globalstate
.use_utility_code(self
.function
.entry
.utility_code
)
4663 if func_type
.is_pyobject
:
4664 arg_code
= self
.arg_tuple
.py_result()
4665 code
.globalstate
.use_utility_code(UtilityCode
.load_cached(
4666 "PyObjectCall", "ObjectHandling.c"))
4668 "%s = __Pyx_PyObject_Call(%s, %s, NULL); %s" % (
4670 self
.function
.py_result(),
4672 code
.error_goto_if_null(self
.result(), self
.pos
)))
4673 code
.put_gotref(self
.py_result())
4674 elif func_type
.is_cfunction
:
4675 if self
.has_optional_args
:
4676 actual_nargs
= len(self
.args
)
4677 expected_nargs
= len(func_type
.args
) - func_type
.optional_arg_count
4678 self
.opt_arg_struct
= code
.funcstate
.allocate_temp(
4679 func_type
.op_arg_struct
.base_type
, manage_ref
=True)
4680 code
.putln("%s.%s = %s;" % (
4681 self
.opt_arg_struct
,
4682 Naming
.pyrex_prefix
+ "n",
4683 len(self
.args
) - expected_nargs
))
4684 args
= list(zip(func_type
.args
, self
.args
))
4685 for formal_arg
, actual_arg
in args
[expected_nargs
:actual_nargs
]:
4686 code
.putln("%s.%s = %s;" % (
4687 self
.opt_arg_struct
,
4688 func_type
.opt_arg_cname(formal_arg
.name
),
4689 actual_arg
.result_as(formal_arg
.type)))
4691 if self
.type.is_pyobject
and self
.is_temp
:
4692 exc_checks
.append("!%s" % self
.result())
4693 elif self
.type.is_memoryviewslice
:
4695 exc_checks
.append(self
.type.error_condition(self
.result()))
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
))
4703 exc_checks
.append("__Pyx_ErrOccurredWithGIL()")
4705 exc_checks
.append("PyErr_Occurred()")
4706 if self
.is_temp
or exc_checks
:
4707 rhs
= self
.c_call_code()
4709 lhs
= "%s = " % self
.result()
4710 if self
.is_temp
and self
.type.is_pyobject
:
4711 #return_type = self.type # func_type.return_type
4712 #print "SimpleCallNode.generate_result_code: casting", rhs, \
4713 # "from", return_type, "to pyobject" ###
4714 rhs
= typecast(py_object_type
, self
.type, rhs
)
4717 if func_type
.exception_check
== '+':
4718 if func_type
.exception_value
is None:
4719 raise_py_exception
= "__Pyx_CppExn2PyErr();"
4720 elif func_type
.exception_value
.type.is_pyobject
:
4721 raise_py_exception
= 'try { throw; } catch(const std::exception& exn) { PyErr_SetString(%s, exn.what()); } catch(...) { PyErr_SetNone(%s); }' % (
4722 func_type
.exception_value
.entry
.cname
,
4723 func_type
.exception_value
.entry
.cname
)
4725 raise_py_exception
= '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.");' % func_type
.exception_value
.entry
.cname
4727 code
.putln("%s%s;" % (lhs
, rhs
))
4728 code
.putln("} catch(...) {")
4730 code
.put_ensure_gil(declare_gilstate
=True)
4731 code
.putln(raise_py_exception
)
4733 code
.put_release_ensured_gil()
4734 code
.putln(code
.error_goto(self
.pos
))
4738 goto_error
= code
.error_goto_if(" && ".join(exc_checks
), self
.pos
)
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
)
4748 class InlinedDefNodeCallNode(CallNode
):
4749 # Inline call to defnode
4751 # function PyCFunctionNode
4752 # function_name NameNode
4755 subexprs
= ['args', 'function_name']
4757 type = py_object_type
4759 function_name
= None
4761 def can_be_inlined(self
):
4762 func_type
= self
.function
.def_node
4763 if func_type
.star_arg
or func_type
.starstar_arg
:
4765 if len(func_type
.args
) != len(self
.args
):
4769 def analyse_types(self
, env
):
4770 self
.function_name
= self
.function_name
.analyse_types(env
)
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
)
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
)
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
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
)
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
4805 for i
in xrange(actual_nargs
-1):
4807 if arg
.nonlocally_immutable():
4808 # locals, C functions, unassignable types are safe.
4810 elif arg
.type.is_cpp_class
:
4811 # Assignment has side effects, avoid.
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
4819 #self.args[i] = arg.coerce_to_temp(env)
4820 # instead: issue a warning
4822 warning(arg
.pos
, "Argument evaluation order in C function call is undefined and may not be as expected", 0)
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))
4833 arg_code
.append(arg
.result())
4834 arg_code
= ', '.join(arg_code
)
4836 "%s = %s(%s); %s" % (
4838 self
.function
.def_node
.entry
.pyfunc_cname
,
4840 code
.error_goto_if_null(self
.result(), self
.pos
)))
4841 code
.put_gotref(self
.py_result())
4844 class PythonCapiFunctionNode(ExprNode
):
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
)
4851 def analyse_types(self
, env
):
4854 def generate_result_code(self
, code
):
4855 if self
.utility_code
:
4856 code
.globalstate
.use_utility_code(self
.utility_code
)
4858 def calculate_result_code(self
):
4862 class PythonCapiCallNode(SimpleCallNode
):
4863 # Python C-API Function call (only created in transforms)
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
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
)
4883 class GeneralCallNode(CallNode
):
4884 # General Python function call, including keyword,
4885 # * and ** arguments.
4888 # positional_args ExprNode Tuple of positional arguments
4889 # keyword_args ExprNode or None Dict of keyword arguments
4891 type = py_object_type
4893 subexprs
= ['function', 'positional_args', 'keyword_args']
4895 nogil_check
= Node
.gil_error
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
)
4902 return function(*positional_args
, **keyword_args
)
4903 except Exception, e
:
4904 self
.compile_time_value_error(e
)
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
4913 def analyse_types(self
, env
):
4914 if self
.analyse_as_type_constructor(env
):
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
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
)
4929 "Non-trivial keyword arguments and starred "
4930 "arguments not allowed in cdef functions.")
4932 # error was already reported
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
4949 self
.type = py_object_type
4953 def map_to_simple_call_node(self
):
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.
4959 if not isinstance(self
.positional_args
, TupleNode
):
4960 # has starred argument
4962 if not isinstance(self
.keyword_args
, DictNode
):
4963 # keywords come from arbitrary expression => nothing to do here
4965 function
= self
.function
4966 entry
= getattr(function
, 'entry', None)
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
:
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'
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
),
4987 matched_args
= set([ arg
.name
for arg
in declared_args
[:len(pos_args
)]
4989 unmatched_args
= declared_args
[len(pos_args
):]
4990 matched_kwargs_count
= 0
4991 args
= list(pos_args
)
4993 # check for duplicate keywords
4994 seen
= set(matched_args
)
4996 for arg
in kwargs
.key_value_pairs
:
4997 name
= arg
.key
.value
4999 error(arg
.pos
, "argument '%s' passed twice" % name
)
5001 # continue to report more errors if there are any
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
)
5014 # match keyword arguments that are passed out-of-order, but keep
5015 # the evaluation of non-simple arguments in order by moving them
5017 from Cython
.Compiler
.UtilNodes
import EvalWithTempExprNode
, LetRefNode
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
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
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
)
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
)
5048 temp
= LetRefNode(arg
.value
)
5049 assert temp
.is_simple()
5051 temps
.append((pos
, temp
))
5054 # may have to move preceding non-simple args into temps
5057 first_temp_arg
= temps
[0][-1]
5058 for arg_value
in args
:
5059 if arg_value
is first_temp_arg
:
5061 if arg_value
.is_simple():
5062 final_args
.append(arg_value
)
5064 temp
= LetRefNode(arg_value
)
5065 new_temps
.append(temp
)
5066 final_args
.append(temp
)
5069 temps
= new_temps
+ [ arg
for i
,arg
in sorted(temps
) ]
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
:
5077 "C function got unexpected keyword argument '%s'" %
5081 # error was reported already
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
)
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()
5097 code
.globalstate
.use_utility_code(UtilityCode
.load_cached(
5098 "PyObjectCall", "ObjectHandling.c"))
5100 "%s = __Pyx_PyObject_Call(%s, %s, %s); %s" % (
5102 self
.function
.py_result(),
5103 self
.positional_args
.py_result(),
5105 code
.error_goto_if_null(self
.result(), self
.pos
)))
5106 code
.put_gotref(self
.py_result())
5109 class AsTupleNode(ExprNode
):
5110 # Convert argument to tuple. Used for normalising
5111 # the * argument of a function call.
5117 def calculate_constant_result(self
):
5118 self
.constant_result
= tuple(self
.arg
.constant_result
)
5120 def compile_time_value(self
, denv
):
5121 arg
= self
.arg
.compile_time_value(denv
)
5124 except Exception, e
:
5125 self
.compile_time_value_error(e
)
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
5134 def may_be_none(self
):
5137 nogil_check
= Node
.gil_error
5138 gil_message
= "Constructing Python tuple"
5140 def generate_result_code(self
, code
):
5142 "%s = PySequence_Tuple(%s); %s" % (
5144 self
.arg
.py_result(),
5145 code
.error_goto_if_null(self
.result(), self
.pos
)))
5146 code
.put_gotref(self
.py_result())
5149 class AttributeNode(ExprNode
):
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.
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
5167 type = PyrexTypes
.error_type
5170 needs_none_check
= True
5171 is_memslice_transpose
= False
5172 is_special_lookup
= False
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
5180 cy
= self
.obj
.as_cython_attribute()
5182 return "%s.%s" % (cy
, self
.attribute
)
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
:
5190 if entry
and entry
.is_cfunction
and entry
.as_variable
:
5191 # must be a cpdef function
5193 self
.entry
= entry
.as_variable
5194 self
.analyse_as_python_attribute(env
)
5196 return ExprNode
.coerce_to(self
, dst_type
, env
)
5198 def calculate_constant_result(self
):
5199 attr
= self
.attribute
5200 if attr
.startswith("__") and attr
.endswith("__"):
5202 self
.constant_result
= getattr(self
.obj
.constant_result
, attr
)
5204 def compile_time_value(self
, denv
):
5205 attr
= self
.attribute
5206 if attr
.startswith("__") and attr
.endswith("__"):
5208 "Invalid attribute name '%s' in compile-time expression" % attr
)
5210 obj
= self
.obj
.compile_time_value(denv
)
5212 return getattr(obj
, attr
)
5213 except Exception, e
:
5214 self
.compile_time_value_error(e
)
5216 def type_dependencies(self
, env
):
5217 return self
.obj
.type_dependencies(env
)
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
5236 def analyse_target_declaration(self
, env
):
5239 def analyse_target_types(self
, env
):
5240 node
= self
.analyse_types(env
, target
= 1)
5241 if node
.type.is_const
:
5242 error(self
.pos
, "Assignment to const attribute '%s'" % self
.attribute
)
5243 if not node
.is_lvalue():
5244 error(self
.pos
, "Assignment to non-lvalue of type '%s'" % self
.type)
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
)
5253 node
= self
.analyse_as_ordinary_attribute_node(env
, target
)
5254 assert node
is not None
5256 node
.entry
.used
= True
5257 if node
.is_attribute
:
5258 node
.wrap_obj_in_nonecheck(env
)
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
5266 module_scope
= self
.obj
.analyse_as_module(env
)
5268 entry
= module_scope
.lookup_here(self
.attribute
)
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
)
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
5280 type = self
.obj
.analyse_as_extension_type(env
)
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
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
),
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)
5301 def analyse_as_type(self
, env
):
5302 module_scope
= self
.obj
.analyse_as_module(env
)
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
)
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
)
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
:
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
)
5327 entry
= module_scope
.lookup_here(self
.attribute
)
5328 if entry
and entry
.as_module
:
5329 return entry
.as_module
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
)
5337 node
= node
.analyse_target_types(env
)
5339 node
= node
.analyse_rvalue_entry(env
)
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")
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()
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
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
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
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
5377 elif obj_type
.is_extension_type
or obj_type
.is_builtin_type
:
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
5388 self
.use_managed_ref
= True
5389 self
.type = self
.obj
.type
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
:
5398 "Cannot select attribute of incomplete type '%s'"
5400 self
.type = PyrexTypes
.error_type
5404 if obj_type
.is_extension_type
and entry
.name
== "__weakref__":
5405 error(self
.pos
, "Illegal use of special attribute __weakref__")
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
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
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
)
5427 def analyse_as_python_attribute(self
, env
, obj_type
=None, immutable_obj
=False):
5428 if obj_type
is None:
5429 obj_type
= self
.obj
.type
5430 # mangle private '__*' Python attributes used inside of a class
5431 self
.attribute
= env
.mangle_class_private_name(self
.attribute
)
5432 self
.member
= self
.attribute
5433 self
.type = py_object_type
5435 if not obj_type
.is_pyobject
and not obj_type
.is_error
:
5436 if obj_type
.can_coerce_to_pyobject(env
):
5437 if not immutable_obj
:
5438 self
.obj
= self
.obj
.coerce_to_pyobject(env
)
5439 elif (obj_type
.is_cfunction
and (self
.obj
.is_name
or self
.obj
.is_attribute
)
5440 and self
.obj
.entry
.as_variable
5441 and self
.obj
.entry
.as_variable
.type.is_pyobject
):
5442 # might be an optimised builtin function => unpack it
5443 if not immutable_obj
:
5444 self
.obj
= self
.obj
.coerce_to_pyobject(env
)
5447 "Object of type '%s' has no attribute '%s'" %
5448 (obj_type
, self
.attribute
))
5450 def wrap_obj_in_nonecheck(self
, env
):
5451 if not env
.directives
['nonecheck']:
5456 if (self
.obj
.type.is_extension_type
and self
.needs_none_check
and not
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"
5464 entry
= self
.obj
.type.scope
.lookup_here(self
.attribute
)
5466 # copy/is_c_contig/shape/strides etc
5467 msg
= "Cannot access '%s' attribute of None memoryview slice"
5468 format_args
= (entry
.name
,)
5471 self
.obj
= self
.obj
.as_none_safe_node(msg
, 'PyExc_AttributeError',
5472 format_args
=format_args
)
5475 def nogil_check(self
, env
):
5478 elif self
.type.is_memoryviewslice
:
5480 MemoryView
.err_if_nogil_initialized_check(self
.pos
, env
, 'attribute')
5482 gil_message
= "Accessing Python attribute"
5484 def is_simple(self
):
5486 return self
.result_in_temp() or self
.obj
.is_simple()
5488 return NameNode
.is_simple(self
)
5490 def is_lvalue(self
):
5492 return not self
.type.is_array
5494 return NameNode
.is_lvalue(self
)
5496 def is_ephemeral(self
):
5498 return self
.obj
.is_ephemeral()
5500 return NameNode
.is_ephemeral(self
)
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() ###
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
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
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
:
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.
5531 elif obj
.type.is_complex
:
5532 return "__Pyx_C%s(%s)" % (self
.member
.upper(), obj_code
)
5534 if obj
.type.is_builtin_type
and self
.entry
and self
.entry
.is_variable
:
5535 # accessing a field of a builtin type, need to cast better than result_as() does
5536 obj_code
= obj
.type.cast_code(obj
.result(), to_object_struct
= True)
5537 return "%s%s%s" % (obj_code
, self
.op
, self
.member
)
5539 def generate_result_code(self
, code
):
5541 if self
.is_special_lookup
:
5542 code
.globalstate
.use_utility_code(
5543 UtilityCode
.load_cached("PyObjectLookupSpecial", "ObjectHandling.c"))
5544 lookup_func_name
= '__Pyx_PyObject_LookupSpecial'
5546 code
.globalstate
.use_utility_code(
5547 UtilityCode
.load_cached("PyObjectGetAttrStr", "ObjectHandling.c"))
5548 lookup_func_name
= '__Pyx_PyObject_GetAttrStr'
5550 '%s = %s(%s, %s); %s' % (
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
:
5562 error(self
.pos
, "Transposing not supported for slices "
5563 "with indirect dimensions")
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)
5571 T
= "__pyx_memslice_transpose(&%s) == 0"
5572 code
.putln(code
.error_goto_if(T
% self
.result(), self
.pos
))
5573 elif self
.initialized_check
:
5575 'if (unlikely(!%s.memview)) {'
5576 'PyErr_SetString(PyExc_AttributeError,'
5577 '"Memoryview is not initialized");'
5579 '}' % (self
.result(), code
.error_goto(self
.pos
)))
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
:
5585 elif self
.entry
and self
.entry
.is_cmethod
and self
.entry
.utility_code
:
5586 # C method implemented as function call with utility code
5587 code
.globalstate
.use_utility_code(self
.entry
.utility_code
)
5589 def generate_disposal_code(self
, code
):
5590 if self
.is_temp
and self
.type.is_memoryviewslice
and self
.is_memslice_transpose
:
5591 # mirror condition for putting the memview incref here:
5592 if self
.obj
.is_name
or (self
.obj
.is_attribute
and
5593 self
.obj
.is_memslice_transpose
):
5594 code
.put_xdecref_memoryviewslice(
5595 self
.result(), have_gil
=True)
5597 ExprNode
.generate_disposal_code(self
, code
)
5599 def generate_assignment_code(self
, rhs
, code
):
5600 self
.obj
.generate_evaluation_code(code
)
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
),
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())))
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
:
5625 MemoryView
.put_assign_to_memviewslice(
5626 select_code
, rhs
, rhs
.result(), self
.type, code
)
5628 if not self
.type.is_memoryviewslice
:
5632 rhs
.result_as(self
.ctype())))
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
)
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
)))
5650 error(self
.pos
, "Cannot delete C attribute of extension type")
5651 self
.obj
.generate_disposal_code(code
)
5652 self
.obj
.free_temps(code
)
5654 def annotate(self
, code
):
5656 style
, text
= 'py_attr', 'python attribute (%s)'
5658 style
, text
= 'c_attr', 'c attribute (%s)'
5659 code
.annotate(self
.pos
, AnnotationItem(style
, text
% self
.type, size
=len(self
.attribute
)))
5662 #-------------------------------------------------------------------
5666 #-------------------------------------------------------------------
5668 class StarredTargetNode(ExprNode
):
5669 # A starred expression like "*a"
5671 # This is only allowed in sequence assignment targets such as
5673 # a, *b = (1,2,3,4) => a = 1 ; b = [2,3,4]
5675 # and will be removed during type analysis (or generate an error
5676 # if it's found at unexpected places).
5680 subexprs
= ['target']
5682 type = py_object_type
5685 def __init__(self
, pos
, target
):
5686 ExprNode
.__init
__(self
, pos
)
5687 self
.target
= target
5689 def analyse_declarations(self
, env
):
5690 error(self
.pos
, "can use starred expression only as assignment target")
5691 self
.target
.analyse_declarations(env
)
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
5699 def analyse_target_declaration(self
, env
):
5700 self
.target
.analyse_target_declaration(env
)
5702 def analyse_target_types(self
, env
):
5703 self
.target
= self
.target
.analyse_target_types(env
)
5704 self
.type = self
.target
.type
5707 def calculate_result_code(self
):
5710 def generate_result_code(self
, code
):
5714 class SequenceNode(ExprNode
):
5715 # Base class for list and tuple constructor nodes.
5716 # Contains common code for performing sequence unpacking.
5719 # unpacked_items [ExprNode] or None
5720 # coerced_unpacked_items [ExprNode] or None
5721 # mult_factor ExprNode the integer number of content repetitions ([1,2]*3)
5723 subexprs
= ['args', 'mult_factor']
5725 is_sequence_constructor
= 1
5726 unpacked_items
= None
5728 slow
= False # trade speed for code size (e.g. use PyTuple_Pack())
5730 def compile_time_value_list(self
, denv
):
5731 return [arg
.compile_time_value(denv
) for arg
in self
.args
]
5733 def replace_starred_target_node(self
):
5734 # replace a starred node in the targets by the contained expression
5735 self
.starred_assignment
= False
5737 for arg
in self
.args
:
5739 if self
.starred_assignment
:
5740 error(arg
.pos
, "more than 1 starred expression in assignment")
5741 self
.starred_assignment
= True
5743 arg
.is_starred
= True
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
)
5752 def analyse_types(self
, env
, skip_children
=False):
5753 for i
in range(len(self
.args
)):
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
)
5762 # not setting self.type here, subtypes do this
5765 def may_be_none(self
):
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
)
5777 if not arg
.type.assignable_from(Builtin
.list_type
):
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
5791 def generate_result_code(self
, code
):
5792 self
.generate_operation_code(code
)
5794 def generate_sequence_packing_code(self
, code
, target
=None, plain
=False):
5796 target
= self
.result()
5797 size_factor
= c_mult
= ''
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
5808 size_factor
= ' * ((%s<0) ? 0:%s)' % (c_mult
, c_mult
)
5810 if self
.type is Builtin
.tuple_type
and (self
.is_literal
or self
.slow
) and not c_mult
:
5811 # use PyTuple_Pack() to avoid generating huge amounts of one-time code
5812 code
.putln('%s = PyTuple_Pack(%d, %s); %s' % (
5815 ', '.join([ arg
.py_result() for arg
in self
.args
]),
5816 code
.error_goto_if_null(target
, self
.pos
)))
5817 code
.put_gotref(target
)
5819 # build the tuple/list step by step, potentially multiplying it as we go
5820 if self
.type is Builtin
.list_type
:
5821 create_func
, set_item_func
= 'PyList_New', 'PyList_SET_ITEM'
5822 elif self
.type is Builtin
.tuple_type
:
5823 create_func
, set_item_func
= 'PyTuple_New', 'PyTuple_SET_ITEM'
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
)
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.
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
)
5843 offset
= '%s * %s' % (counter
, arg_count
)
5844 code
.putln('for (%s=0; %s < %s; %s++) {' % (
5845 counter
, counter
, c_mult
, counter
5850 for i
in xrange(arg_count
):
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);" % (
5857 (offset
and i
) and ('%s + %s' % (offset
, i
)) or (offset
or i
),
5859 code
.put_giveref(arg
.py_result())
5863 #code.funcstate.release_temp(counter)
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
)
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
))
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
)
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
)
5892 def generate_assignment_code(self
, rhs
, code
):
5893 if self
.starred_assignment
:
5894 self
.generate_starred_assignment_code(rhs
, code
)
5896 self
.generate_parallel_assignment_code(rhs
, code
)
5898 for item
in self
.unpacked_items
:
5900 rhs
.free_temps(code
)
5902 _func_iternext_type
= PyrexTypes
.CPtrType(PyrexTypes
.CFuncType(
5903 PyrexTypes
.py_object_type
, [
5904 PyrexTypes
.CFuncTypeArg("it", PyrexTypes
.py_object_type
, None),
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
:
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
5919 self
.generate_special_parallel_unpacking_code(
5920 code
, rhs
, use_loop
=long_enough_for_a_loop
)
5923 self
.generate_generic_parallel_unpacking_code(
5924 code
, rhs
, self
.unpacked_items
, use_loop
=long_enough_for_a_loop
)
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
)
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
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
)
5950 code
.putln("if (%s) {" % sequence_type_test
)
5951 code
.putln("PyObject* sequence = %s;" % rhs
.py_result())
5953 # list/tuple => check size
5954 code
.putln("#if CYTHON_COMPILING_IN_CPYTHON")
5955 code
.putln("Py_ssize_t size = Py_SIZE(sequence);")
5957 code
.putln("Py_ssize_t size = PySequence_Size(sequence);") # < 0 => exception
5958 code
.putln("#endif")
5959 code
.putln("if (unlikely(size != %d)) {" % len(self
.args
))
5960 code
.globalstate
.use_utility_code(raise_too_many_values_to_unpack
)
5961 code
.putln("if (size > %d) __Pyx_RaiseTooManyValuesError(%d);" % (
5962 len(self
.args
), len(self
.args
)))
5963 code
.globalstate
.use_utility_code(raise_need_more_values_to_unpack
)
5964 code
.putln("else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);")
5965 code
.putln(code
.error_goto(self
.pos
))
5968 code
.putln("#if CYTHON_COMPILING_IN_CPYTHON")
5969 # unpack items from list/tuple in unrolled loop (can't fail)
5970 if len(sequence_types
) == 2:
5971 code
.putln("if (likely(Py%s_CheckExact(sequence))) {" % sequence_types
[0])
5972 for i
, item
in enumerate(self
.unpacked_items
):
5973 code
.putln("%s = Py%s_GET_ITEM(sequence, %d); " % (
5974 item
.result(), sequence_types
[0], i
))
5975 if len(sequence_types
) == 2:
5976 code
.putln("} else {")
5977 for i
, item
in enumerate(self
.unpacked_items
):
5978 code
.putln("%s = Py%s_GET_ITEM(sequence, %d); " % (
5979 item
.result(), sequence_types
[1], i
))
5981 for item
in self
.unpacked_items
:
5982 code
.put_incref(item
.result(), item
.ctype())
5985 # in non-CPython, use the PySequence protocol (which can fail)
5987 for i
, item
in enumerate(self
.unpacked_items
):
5988 code
.putln("%s = PySequence_ITEM(sequence, %d); %s" % (
5990 code
.error_goto_if_null(item
.result(), self
.pos
)))
5991 code
.put_gotref(item
.result())
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;")
6006 code
.putln("#endif")
6007 rhs
.generate_disposal_code(code
)
6009 if sequence_type_test
== '1':
6010 code
.putln("}") # all done
6011 elif sequence_type_test
== none_check
:
6012 # either tuple/list or None => save some code by generating the error directly
6013 code
.putln("} else {")
6014 code
.globalstate
.use_utility_code(
6015 UtilityCode
.load_cached("RaiseNoneIterError", "ObjectHandling.c"))
6016 code
.putln("__Pyx_RaiseNoneNotIterableError(); %s" % code
.error_goto(self
.pos
))
6017 code
.putln("}") # all done
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
)
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!
6030 code
.putln("PyObject** temps[%s] = {%s};" % (
6031 len(self
.unpacked_items
),
6032 ','.join(['&%s' % item
.result() for item
in unpacked_items
])))
6034 iterator_temp
= code
.funcstate
.allocate_temp(py_object_type
, manage_ref
=True)
6036 "%s = PyObject_GetIter(%s); %s" % (
6039 code
.error_goto_if_null(iterator_temp
, self
.pos
)))
6040 code
.put_gotref(iterator_temp
)
6041 rhs
.generate_disposal_code(code
)
6043 iternext_func
= code
.funcstate
.allocate_temp(self
._func
_iternext
_type
, manage_ref
=False)
6044 code
.putln("%s = Py_TYPE(%s)->tp_iternext;" % (
6045 iternext_func
, iterator_temp
))
6047 unpacking_error_label
= code
.new_label('unpacking_failed')
6048 unpack_code
= "%s(%s)" % (iternext_func
, iterator_temp
)
6050 code
.putln("for (index=0; index < %s; index++) {" % len(unpacked_items
))
6051 code
.put("PyObject* item = %s; if (unlikely(!item)) " % unpack_code
)
6052 code
.put_goto(unpacking_error_label
)
6053 code
.put_gotref("item")
6054 code
.putln("*(temps[index]) = item;")
6057 for i
, item
in enumerate(unpacked_items
):
6059 "index = %d; %s = %s; if (unlikely(!%s)) " % (
6064 code
.put_goto(unpacking_error_label
)
6065 code
.put_gotref(item
.py_result())
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)" % (
6072 len(unpacked_items
)))
6073 code
.putln("%s = NULL;" % iternext_func
)
6074 code
.put_decref_clear(iterator_temp
, py_object_type
)
6076 unpacking_done_label
= code
.new_label('unpacking_done')
6077 code
.put_goto(unpacking_done_label
)
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
)
6086 code
.funcstate
.release_temp(iternext_func
)
6088 code
.funcstate
.release_temp(iterator_temp
)
6089 iterator_temp
= None
6091 return iterator_temp
6093 def generate_starred_assignment_code(self
, rhs
, code
):
6094 for i
, arg
in enumerate(self
.args
):
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:]
6103 iterator_temp
= None
6104 if unpacked_fixed_items_left
:
6105 for item
in unpacked_fixed_items_left
:
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
)
6116 starred_target
.allocate(code
)
6117 target_list
= starred_target
.result()
6118 code
.putln("%s = PySequence_List(%s); %s" % (
6120 iterator_temp
or rhs
.py_result(),
6121 code
.error_goto_if_null(target_list
, self
.pos
)))
6122 code
.put_gotref(target_list
)
6125 code
.put_decref_clear(iterator_temp
, py_object_type
)
6126 code
.funcstate
.release_temp(iterator_temp
)
6128 rhs
.generate_disposal_code(code
)
6130 if unpacked_fixed_items_right
:
6131 code
.globalstate
.use_utility_code(raise_need_more_values_to_unpack
)
6132 length_temp
= code
.funcstate
.allocate_temp(PyrexTypes
.c_py_ssize_t_type
, manage_ref
=False)
6133 code
.putln('%s = PyList_GET_SIZE(%s);' % (length_temp
, target_list
))
6134 code
.putln("if (unlikely(%s < %d)) {" % (length_temp
, len(unpacked_fixed_items_right
)))
6135 code
.putln("__Pyx_RaiseNeedMoreValuesError(%d+%s); %s" % (
6136 len(unpacked_fixed_items_left
), length_temp
,
6137 code
.error_goto(self
.pos
)))
6140 for item
in unpacked_fixed_items_right
[::-1]:
6142 for i
, (item
, coerced_arg
) in enumerate(zip(unpacked_fixed_items_right
[::-1],
6143 self
.coerced_unpacked_items
[::-1])):
6144 code
.putln('#if CYTHON_COMPILING_IN_CPYTHON')
6145 code
.putln("%s = PyList_GET_ITEM(%s, %s-%d); " % (
6146 item
.py_result(), target_list
, length_temp
, i
+1))
6147 # resize the list the hard way
6148 code
.putln("((PyVarObject*)%s)->ob_size--;" % target_list
)
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
)
6156 code
.putln('#if !CYTHON_COMPILING_IN_CPYTHON')
6157 sublist_temp
= code
.funcstate
.allocate_temp(py_object_type
, manage_ref
=True)
6158 code
.putln('%s = PySequence_GetSlice(%s, 0, %s-%d); %s' % (
6159 sublist_temp
, target_list
, length_temp
, len(unpacked_fixed_items_right
),
6160 code
.error_goto_if_null(sublist_temp
, self
.pos
)))
6161 code
.put_gotref(sublist_temp
)
6162 code
.funcstate
.release_temp(length_temp
)
6163 code
.put_decref(target_list
, py_object_type
)
6164 code
.putln('%s = %s; %s = NULL;' % (target_list
, sublist_temp
, sublist_temp
))
6166 code
.putln('%s = %s;' % (sublist_temp
, sublist_temp
)) # avoid warning about unused variable
6167 code
.funcstate
.release_temp(sublist_temp
)
6168 code
.putln('#endif')
6170 for i
, arg
in enumerate(self
.args
):
6171 arg
.generate_assignment_code(self
.coerced_unpacked_items
[i
], code
)
6173 def annotate(self
, code
):
6174 for arg
in self
.args
:
6176 if self
.unpacked_items
:
6177 for arg
in self
.unpacked_items
:
6179 for arg
in self
.coerced_unpacked_items
:
6183 class TupleNode(SequenceNode
):
6184 # Tuple constructor.
6187 is_partly_literal
= False
6189 gil_message
= "Constructing Python tuple"
6191 def analyse_types(self
, env
, skip_children
=False):
6192 if len(self
.args
) == 0:
6194 node
.is_temp
= False
6195 node
.is_literal
= True
6197 node
= SequenceNode
.analyse_types(self
, env
, skip_children
)
6198 for child
in node
.args
:
6199 if not child
.is_literal
:
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
6207 if not node
.mult_factor
.type.is_pyobject
:
6208 node
.mult_factor
= node
.mult_factor
.coerce_to_pyobject(env
)
6210 node
.is_partly_literal
= True
6213 def is_simple(self
):
6214 # either temp or constant => always simple
6217 def nonlocally_immutable(self
):
6218 # either temp or constant => always safe
6221 def calculate_result_code(self
):
6222 if len(self
.args
) > 0:
6223 return self
.result_code
6225 return Naming
.empty_tuple
6227 def calculate_constant_result(self
):
6228 self
.constant_result
= tuple([
6229 arg
.constant_result
for arg
in self
.args
])
6231 def compile_time_value(self
, denv
):
6232 values
= self
.compile_time_value_list(denv
)
6234 return tuple(values
)
6235 except Exception, e
:
6236 self
.compile_time_value_error(e
)
6238 def generate_operation_code(self
, code
):
6239 if len(self
.args
) == 0:
6240 # result_code is Naming.empty_tuple
6242 if self
.is_partly_literal
:
6243 # underlying tuple is const, but factor is not
6244 tuple_target
= code
.get_py_const(py_object_type
, 'tuple', cleanup_level
=2)
6245 const_code
= code
.get_cached_constants_writer()
6246 const_code
.mark_pos(self
.pos
)
6247 self
.generate_sequence_packing_code(const_code
, tuple_target
, plain
=True)
6248 const_code
.put_giveref(tuple_target
)
6249 code
.putln('%s = PyNumber_Multiply(%s, %s); %s' % (
6250 self
.result(), tuple_target
, self
.mult_factor
.py_result(),
6251 code
.error_goto_if_null(self
.result(), self
.pos
)
6253 code
.put_gotref(self
.py_result())
6254 elif self
.is_literal
:
6255 # non-empty cached tuple => result is global constant,
6256 # creation code goes into separate code writer
6257 self
.result_code
= code
.get_py_const(py_object_type
, 'tuple', cleanup_level
=2)
6258 code
= code
.get_cached_constants_writer()
6259 code
.mark_pos(self
.pos
)
6260 self
.generate_sequence_packing_code(code
)
6261 code
.put_giveref(self
.py_result())
6263 self
.generate_sequence_packing_code(code
)
6266 class ListNode(SequenceNode
):
6269 # obj_conversion_errors [PyrexError] used internally
6270 # orignial_args [ExprNode] used internally
6272 obj_conversion_errors
= []
6274 in_module_scope
= False
6276 gil_message
= "Constructing Python list"
6278 def type_dependencies(self
, env
):
6281 def infer_type(self
, env
):
6282 # TOOD: Infer non-object list arrays.
6285 def analyse_expressions(self
, env
):
6286 node
= SequenceNode
.analyse_expressions(self
, env
)
6287 return node
.coerce_to_pyobject(env
)
6289 def analyse_types(self
, env
):
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
6299 def coerce_to(self
, dst_type
, env
):
6300 if dst_type
.is_pyobject
:
6301 for err
in self
.obj_conversion_errors
:
6303 self
.obj_conversion_errors
= []
6304 if not self
.type.subtype_of(dst_type
):
6305 error(self
.pos
, "Cannot coerce list to type '%s'" % dst_type
)
6306 elif self
.mult_factor
:
6307 error(self
.pos
, "Cannot coerce multiplied list to '%s'" % dst_type
)
6308 elif dst_type
.is_ptr
and dst_type
.base_type
is not PyrexTypes
.c_void_type
:
6309 base_type
= dst_type
.base_type
6310 self
.type = PyrexTypes
.CArrayType(base_type
, len(self
.args
))
6311 for i
in range(len(self
.original_args
)):
6313 if isinstance(arg
, CoerceToPyTypeNode
):
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
)
6320 if len(self
.args
) < len(dst_type
.scope
.var_entries
):
6321 warning(self
.pos
, "Too few members for '%s'" % dst_type
, 1)
6322 for i
, (arg
, member
) in enumerate(zip(self
.original_args
, dst_type
.scope
.var_entries
)):
6323 if isinstance(arg
, CoerceToPyTypeNode
):
6325 self
.args
[i
] = arg
.coerce_to(member
.type, env
)
6326 self
.type = dst_type
6328 self
.type = error_type
6329 error(self
.pos
, "Cannot coerce list to type '%s'" % dst_type
)
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
)
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)
6343 SequenceNode
.allocate_temp_result(self
, code
)
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.
6351 SequenceNode
.release_temp_result(self
, env
)
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
]
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
)
6365 def generate_operation_code(self
, code
):
6366 if self
.type.is_pyobject
:
6367 for err
in self
.obj_conversion_errors
:
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;" % (
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;" % (
6383 raise InternalError("List type never specified")
6386 class ScopedExprNode(ExprNode
):
6387 # Abstract base class for ExprNodes that have their own local
6388 # scope, such as generator expressions.
6390 # expr_scope Scope the inner scope of the expression
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
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
)
6407 self
.expr_scope
= None
6409 def analyse_declarations(self
, env
):
6410 self
.init_scope(env
)
6412 def analyse_scoped_declarations(self
, env
):
6413 # this is called with the expr_scope as env
6416 def analyse_types(self
, env
):
6417 # no recursion here, the children will be analysed separately below
6420 def analyse_scoped_expressions(self
, env
):
6421 # this is called with the expr_scope as env
6424 def generate_evaluation_code(self
, code
):
6425 # set up local variables and free their references on exit
6426 generate_inner_evaluation_code
= super(ScopedExprNode
, self
).generate_evaluation_code
6427 if not self
.has_local_scope
or not self
.expr_scope
.var_entries
:
6428 # no local variables => delegate, done
6429 generate_inner_evaluation_code(code
)
6432 code
.putln('{ /* enter inner scope */')
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
)
6440 # no local Python references => no cleanup required
6441 generate_inner_evaluation_code(code
)
6442 code
.putln('} /* exit inner scope */')
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()
6449 generate_inner_evaluation_code(code
)
6451 # normal (non-error) exit
6452 for entry
in py_entries
:
6453 code
.put_var_decref(entry
)
6455 # error/loop body exit points
6456 exit_scope
= code
.new_label('exit_scope')
6457 code
.put_goto(exit_scope
)
6458 for label
, old_label
in ([(code
.error_label
, old_error_label
)] +
6459 list(zip(code
.get_loop_labels(), old_loop_labels
))):
6460 if code
.label_used(label
):
6461 code
.put_label(label
)
6462 for entry
in py_entries
:
6463 code
.put_var_decref(entry
)
6464 code
.put_goto(old_label
)
6465 code
.put_label(exit_scope
)
6466 code
.putln('} /* exit inner scope */')
6468 code
.set_loop_labels(old_loop_labels
)
6469 code
.error_label
= old_error_label
6472 class ComprehensionNode(ScopedExprNode
):
6473 # A list/set/dict comprehension
6475 child_attrs
= ["loop"]
6479 def infer_type(self
, env
):
6482 def analyse_declarations(self
, env
):
6483 self
.append
.target
= self
# this is used in the PyList_Append of the inner loop
6484 self
.init_scope(env
)
6486 def analyse_scoped_declarations(self
, env
):
6487 self
.loop
.analyse_declarations(env
)
6489 def analyse_types(self
, env
):
6490 if not self
.has_local_scope
:
6491 self
.loop
= self
.loop
.analyse_expressions(env
)
6494 def analyse_scoped_expressions(self
, env
):
6495 if self
.has_local_scope
:
6496 self
.loop
= self
.loop
.analyse_expressions(env
)
6499 def may_be_none(self
):
6502 def generate_result_code(self
, code
):
6503 self
.generate_operation_code(code
)
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()'
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
)))
6518 code
.put_gotref(self
.result())
6519 self
.loop
.generate_execution_code(code
)
6521 def annotate(self
, code
):
6522 self
.loop
.annotate(code
)
6525 class ComprehensionAppendNode(Node
):
6526 # Need to be careful to avoid infinite recursion:
6527 # target must not be in child_attrs/subexprs
6529 child_attrs
= ['expr']
6532 type = PyrexTypes
.c_int_type
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
)
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"
6548 raise InternalError(
6549 "Invalid type for comprehension node: %s" % self
.target
.type)
6551 self
.expr
.generate_evaluation_code(code
)
6552 code
.putln(code
.error_goto_if("%s(%s, (PyObject*)%s)" % (
6554 self
.target
.result(),
6557 self
.expr
.generate_disposal_code(code
)
6558 self
.expr
.free_temps(code
)
6560 def generate_function_definitions(self
, env
, code
):
6561 self
.expr
.generate_function_definitions(env
, code
)
6563 def annotate(self
, code
):
6564 self
.expr
.annotate(code
)
6566 class DictComprehensionAppendNode(ComprehensionAppendNode
):
6567 child_attrs
= ['key_expr', 'value_expr']
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
)
6578 def generate_execution_code(self
, code
):
6579 self
.key_expr
.generate_evaluation_code(code
)
6580 self
.value_expr
.generate_evaluation_code(code
)
6581 code
.putln(code
.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % (
6582 self
.target
.result(),
6583 self
.key_expr
.result(),
6584 self
.value_expr
.result()
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
)
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
)
6595 def annotate(self
, code
):
6596 self
.key_expr
.annotate(code
)
6597 self
.value_expr
.annotate(code
)
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
6606 # loop ForStatNode the for-loop, not containing any YieldExprNodes
6607 # result_node ResultRefNode the reference to the result value temp
6608 # orig_func String the name of the builtin function this node replaces
6610 child_attrs
= ["loop"]
6611 loop_analysed
= False
6612 type = py_object_type
6614 def analyse_scoped_declarations(self
, env
):
6615 self
.loop
.analyse_declarations(env
)
6617 def may_be_none(self
):
6620 def annotate(self
, code
):
6621 self
.loop
.annotate(code
)
6623 def infer_type(self
, env
):
6624 return self
.result_node
.infer_type(env
)
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
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
)
6640 def coerce_to(self
, dst_type
, env
):
6641 if self
.orig_func
== 'sum' and dst_type
.is_numeric
and not self
.loop_analysed
:
6642 # We can optimise by dropping the aggregation variable and
6643 # the add operations into C. This can only be done safely
6644 # before analysing the loop body, after that, the result
6645 # reference type will have infected expressions and
6647 self
.result_node
.type = self
.type = dst_type
6649 return super(InlinedGeneratorExpressionNode
, self
).coerce_to(dst_type
, env
)
6651 def generate_result_code(self
, code
):
6652 self
.result_node
.result_code
= self
.result()
6653 self
.loop
.generate_execution_code(code
)
6656 class SetNode(ExprNode
):
6663 gil_message
= "Constructing Python set"
6665 def analyse_types(self
, env
):
6666 for i
in range(len(self
.args
)):
6668 arg
= arg
.analyse_types(env
)
6669 self
.args
[i
] = arg
.coerce_to_pyobject(env
)
6670 self
.type = set_type
6674 def may_be_none(self
):
6677 def calculate_constant_result(self
):
6678 self
.constant_result
= set([
6679 arg
.constant_result
for arg
in self
.args
])
6681 def compile_time_value(self
, denv
):
6682 values
= [arg
.compile_time_value(denv
) for arg
in self
.args
]
6685 except Exception, e
:
6686 self
.compile_time_value_error(e
)
6688 def generate_evaluation_code(self
, code
):
6689 code
.globalstate
.use_utility_code(Builtin
.py_set_utility_code
)
6690 self
.allocate_temp_result(code
)
6692 "%s = PySet_New(0); %s" % (
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(
6700 "PySet_Add(%s, %s)" % (self
.result(), arg
.py_result()))
6701 arg
.generate_disposal_code(code
)
6702 arg
.free_temps(code
)
6705 class DictNode(ExprNode
):
6706 # Dictionary constructor.
6708 # key_value_pairs [DictItemNode]
6709 # exclude_null_values [boolean] Do not add NULL values to dict
6711 # obj_conversion_errors [PyrexError] used internally
6713 subexprs
= ['key_value_pairs']
6715 exclude_null_values
= False
6718 obj_conversion_errors
= []
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
])
6725 def calculate_constant_result(self
):
6726 self
.constant_result
= dict([
6727 item
.constant_result
for item
in self
.key_value_pairs
])
6729 def compile_time_value(self
, denv
):
6730 pairs
= [(item
.key
.compile_time_value(denv
), item
.value
.compile_time_value(denv
))
6731 for item
in self
.key_value_pairs
]
6734 except Exception, e
:
6735 self
.compile_time_value_error(e
)
6737 def type_dependencies(self
, env
):
6740 def infer_type(self
, env
):
6741 # TOOD: Infer struct constructors.
6744 def analyse_types(self
, env
):
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)
6752 def may_be_none(self
):
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>")
6773 key
= str(item
.key
.value
) # converts string literals to unicode in Py3
6774 member
= dst_type
.scope
.lookup_here(key
)
6776 error(item
.key
.pos
, "struct '%s' has no field '%s'" % (dst_type
, key
))
6779 if isinstance(value
, CoerceToPyTypeNode
):
6781 item
.value
= value
.coerce_to(member
.type, env
)
6783 self
.type = error_type
6784 error(self
.pos
, "Cannot interpret dict as type '%s'" % dst_type
)
6787 def release_errors(self
):
6788 for err
in self
.obj_conversion_errors
:
6790 self
.obj_conversion_errors
= []
6792 gil_message
= "Constructing Python dict"
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()
6802 "%s = PyDict_New(); %s" % (
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)" % (
6814 item
.key
.py_result(),
6815 item
.value
.py_result()))
6816 if self
.exclude_null_values
:
6819 code
.putln("%s.%s = %s;" % (
6822 item
.value
.result()))
6823 item
.generate_disposal_code(code
)
6824 item
.free_temps(code
)
6826 def annotate(self
, code
):
6827 for item
in self
.key_value_pairs
:
6830 class DictItemNode(ExprNode
):
6831 # Represents a single item in a DictNode
6835 subexprs
= ['key', 'value']
6837 nogil_check
= None # Parent DictNode takes care of it
6839 def calculate_constant_result(self
):
6840 self
.constant_result
= (
6841 self
.key
.constant_result
, self
.value
.constant_result
)
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
)
6850 def generate_evaluation_code(self
, code
):
6851 self
.key
.generate_evaluation_code(code
)
6852 self
.value
.generate_evaluation_code(code
)
6854 def generate_disposal_code(self
, code
):
6855 self
.key
.generate_disposal_code(code
)
6856 self
.value
.generate_disposal_code(code
)
6858 def free_temps(self
, code
):
6859 self
.key
.free_temps(code
)
6860 self
.value
.free_temps(code
)
6863 return iter([self
.key
, self
.value
])
6866 class SortedDictKeysNode(ExprNode
):
6867 # build sorted list of dict keys, e.g. for dir()
6872 def __init__(self
, arg
):
6873 ExprNode
.__init
__(self
, arg
.pos
, arg
=arg
)
6874 self
.type = Builtin
.list_type
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")
6884 def may_be_none(self
):
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'
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())
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)
6906 def get_py_qualified_name(self
, code
):
6907 return code
.get_py_string_const(
6908 self
.qualname
, identifier
=True)
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.
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
6922 subexprs
= ['bases', 'doc']
6924 def analyse_types(self
, env
):
6925 self
.bases
= self
.bases
.analyse_types(env
)
6927 self
.doc
= self
.doc
.analyse_types(env
)
6928 self
.doc
= self
.doc
.coerce_to_pyobject(env
)
6929 self
.type = py_object_type
6931 env
.use_utility_code(UtilityCode
.load_cached("CreateClass", "ObjectHandling.c"))
6934 def may_be_none(self
):
6937 gil_message
= "Constructing Python class"
6939 def generate_result_code(self
, code
):
6940 cname
= code
.intern_identifier(self
.name
)
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
)
6952 '%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s' % (
6954 self
.bases
.py_result(),
6955 self
.dict.py_result(),
6959 code
.error_goto_if_null(self
.result(), self
.pos
)))
6960 code
.put_gotref(self
.py_result())
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.
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
6976 def analyse_types(self
, env
):
6977 self
.type = py_object_type
6981 def may_be_none(self
):
6984 gil_message
= "Constructing Python class"
6986 def generate_result_code(self
, code
):
6987 code
.globalstate
.use_utility_code(UtilityCode
.load_cached("Py3ClassCreate", "ObjectHandling.c"))
6988 cname
= code
.intern_identifier(self
.name
)
6990 mkw
= self
.mkw
.py_result()
6994 metaclass
= self
.metaclass
.result()
6996 metaclass
= "((PyObject*)&__Pyx_DefaultClassType)"
6998 '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s, %d, %d); %s' % (
7002 self
.bases
.py_result(),
7003 self
.dict.py_result(),
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())
7010 class KeywordArgsNode(ExprNode
):
7011 # Helper class for keyword arguments.
7013 # starstar_arg DictNode
7014 # keyword_args [DictItemNode]
7016 subexprs
= ['starstar_arg', 'keyword_args']
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
7025 raise ValueError("duplicate keyword argument found: %s" % key
)
7027 self
.constant_result
= result
7029 def compile_time_value(self
, denv
):
7030 result
= self
.starstar_arg
.compile_time_value(denv
)
7031 pairs
= [ (item
.key
.compile_time_value(denv
), item
.value
.compile_time_value(denv
))
7032 for item
in self
.keyword_args
]
7034 result
= dict(result
)
7035 for key
, value
in pairs
:
7037 raise ValueError("duplicate keyword argument found: %s" % key
)
7039 except Exception, e
:
7040 self
.compile_time_value_error(e
)
7043 def type_dependencies(self
, env
):
7046 def infer_type(self
, env
):
7049 def analyse_types(self
, env
):
7050 arg
= self
.starstar_arg
.analyse_types(env
)
7051 arg
= arg
.coerce_to_pyobject(env
)
7052 self
.starstar_arg
= arg
.as_none_safe_node(
7053 # FIXME: CPython's error message starts with the runtime function name
7054 'argument after ** must be a mapping, not NoneType')
7055 self
.keyword_args
= [ item
.analyse_types(env
)
7056 for item
in self
.keyword_args
]
7059 def may_be_none(self
):
7062 gil_message
= "Constructing Python dict"
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
:
7074 "%s = PyDict_Copy(%s); %s" % (
7076 self
.starstar_arg
.py_result(),
7077 code
.error_goto_if_null(self
.result(), self
.pos
)))
7078 code
.put_gotref(self
.py_result())
7080 code
.putln("%s = %s;" % (
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 {')
7087 "%s = PyObject_CallFunctionObjArgs("
7088 "(PyObject*)&PyDict_Type, %s, NULL); %s" % (
7090 self
.starstar_arg
.py_result(),
7091 code
.error_goto_if_null(self
.result(), self
.pos
)))
7092 code
.put_gotref(self
.py_result())
7094 self
.starstar_arg
.generate_disposal_code(code
)
7095 self
.starstar_arg
.free_temps(code
)
7097 if not self
.keyword_args
:
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))) {" % (
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
)))
7112 code
.put_error_if_neg(self
.pos
,
7113 "PyDict_SetItem(%s, %s, %s)" % (
7115 item
.key
.py_result(),
7116 item
.value
.py_result()))
7117 item
.generate_disposal_code(code
)
7118 item
.free_temps(code
)
7120 def annotate(self
, code
):
7121 self
.starstar_arg
.annotate(code
)
7122 for item
in self
.keyword_args
:
7125 class PyClassMetaclassNode(ExprNode
):
7126 # Helper class holds Python3 metaclass object
7128 # bases ExprNode Base class tuple (not owned by this node)
7129 # mkw ExprNode Class keyword arguments (not owned by this node)
7133 def analyse_types(self
, env
):
7134 self
.type = py_object_type
7138 def may_be_none(self
):
7141 def generate_result_code(self
, code
):
7143 code
.globalstate
.use_utility_code(
7144 UtilityCode
.load_cached("Py3MetaclassGet", "ObjectHandling.c"))
7145 call
= "__Pyx_Py3MetaclassGet(%s, %s)" % (
7146 self
.bases
.result(),
7149 code
.globalstate
.use_utility_code(
7150 UtilityCode
.load_cached("CalculateMetaclass", "ObjectHandling.c"))
7151 call
= "__Pyx_CalculateMetaclass(NULL, %s)" % (
7152 self
.bases
.result())
7155 self
.result(), call
,
7156 code
.error_goto_if_null(self
.result(), self
.pos
)))
7157 code
.put_gotref(self
.py_result())
7159 class PyClassNamespaceNode(ExprNode
, ModuleNameMixin
):
7160 # Helper class holds Python3 namespace object
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)
7170 def analyse_types(self
, env
):
7172 self
.doc
= self
.doc
.analyse_types(env
)
7173 self
.doc
= self
.doc
.coerce_to_pyobject(env
)
7174 self
.type = py_object_type
7178 def may_be_none(self
):
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
)
7186 doc_code
= self
.doc
.result()
7188 doc_code
= '(PyObject *) NULL'
7190 mkw
= self
.mkw
.py_result()
7192 mkw
= '(PyObject *) NULL'
7194 metaclass
= self
.metaclass
.result()
7196 metaclass
= "(PyObject *) NULL"
7198 "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s" % (
7201 self
.bases
.result(),
7207 code
.error_goto_if_null(self
.result(), self
.pos
)))
7208 code
.put_gotref(self
.py_result())
7211 class ClassCellInjectorNode(ExprNode
):
7212 # Initialize CyFunction.func_classobj
7214 type = py_object_type
7218 def analyse_expressions(self
, env
):
7220 env
.use_utility_code(
7221 UtilityCode
.load_cached("CyFunctionClassCell", "CythonFunction.c"))
7224 def generate_evaluation_code(self
, code
):
7226 self
.allocate_temp_result(code
)
7228 '%s = PyList_New(0); %s' % (
7230 code
.error_goto_if_null(self
.result(), self
.pos
)))
7231 code
.put_gotref(self
.result())
7233 def generate_injection_code(self
, code
, classobj_cname
):
7235 code
.putln('__Pyx_CyFunction_InitClassCell(%s, %s);' % (
7236 self
.result(), classobj_cname
))
7239 class ClassCellNode(ExprNode
):
7240 # Class Cell for noargs super()
7243 is_generator
= False
7244 type = py_object_type
7246 def analyse_types(self
, env
):
7249 def generate_result_code(self
, code
):
7250 if not self
.is_generator
:
7251 code
.putln('%s = __Pyx_CyFunction_GetClassObj(%s);' % (
7255 code
.putln('%s = %s->classobj;' % (
7256 self
.result(), Naming
.generator_cname
))
7258 'if (!%s) { PyErr_SetString(PyExc_SystemError, '
7259 '"super(): empty __class__ cell"); %s }' % (
7261 code
.error_goto(self
.pos
)))
7262 code
.put_incref(self
.result(), py_object_type
)
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.
7270 # function ExprNode Function object
7271 # self_object ExprNode self object
7273 subexprs
= ['function']
7275 def analyse_types(self
, env
):
7276 self
.function
= self
.function
.analyse_types(env
)
7277 self
.type = py_object_type
7281 gil_message
= "Constructing a bound method"
7283 def generate_result_code(self
, code
):
7285 "%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
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())
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.
7298 # function ExprNode Function object
7300 type = py_object_type
7303 subexprs
= ['function']
7305 def analyse_types(self
, env
):
7306 self
.function
= self
.function
.analyse_types(env
)
7309 def may_be_none(self
):
7312 gil_message
= "Constructing an unbound method"
7314 def generate_result_code(self
, code
):
7315 class_cname
= code
.pyclass_stack
[-1].classobj
.result()
7317 "%s = PyMethod_New(%s, 0, %s); %s" % (
7319 self
.function
.py_result(),
7321 code
.error_goto_if_null(self
.result(), self
.pos
)))
7322 code
.put_gotref(self
.py_result())
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.
7330 # pymethdef_cname string PyMethodDef structure
7331 # self_object ExprNode or None
7333 # def_node DefNode the Python function node
7334 # module_name EncodedString Name of defining module
7335 # code_object CodeObjectNode the PyCodeObject creator node
7337 subexprs
= ['code_object', 'defaults_tuple', 'defaults_kwdict',
7345 defaults_struct
= None
7346 defaults_pyobjects
= 0
7347 defaults_tuple
= None
7348 defaults_kwdict
= None
7349 annotations_dict
= None
7351 type = py_object_type
7354 specialized_cpdefs
= None
7355 is_specialization
= False
7358 def from_defnode(cls
, node
, binding
):
7359 return cls(node
.pos
,
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
))
7366 def analyse_types(self
, env
):
7368 self
.analyse_default_args(env
)
7371 def analyse_default_args(self
, env
):
7373 Handle non-literal function's default arguments.
7375 nonliteral_objects
= []
7376 nonliteral_other
= []
7380 for arg
in self
.def_node
.args
:
7382 if not arg
.default
.is_literal
:
7383 arg
.is_dynamic
= True
7384 if arg
.type.is_pyobject
:
7385 nonliteral_objects
.append(arg
)
7387 nonliteral_other
.append(arg
)
7389 arg
.default
= DefaultLiteralArgNode(arg
.pos
, arg
.default
)
7391 default_kwargs
.append(arg
)
7393 default_args
.append(arg
)
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
))
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
)
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
7428 if default_args
or default_kwargs
:
7429 if self
.defaults_struct
is None:
7431 defaults_tuple
= TupleNode(self
.pos
, args
=[
7432 arg
.default
for arg
in default_args
])
7433 self
.defaults_tuple
= defaults_tuple
.analyse_types(env
)
7435 defaults_kwdict
= DictNode(self
.pos
, key_value_pairs
=[
7438 key
=IdentifierStringNode(arg
.pos
, value
=arg
.name
),
7440 for arg
in default_kwargs
])
7441 self
.defaults_kwdict
= defaults_kwdict
.analyse_types(env
)
7444 defaults_tuple
= DefaultsTupleNode(
7445 self
.pos
, default_args
, self
.defaults_struct
)
7447 defaults_tuple
= NoneNode(self
.pos
)
7449 defaults_kwdict
= DefaultsKwDictNode(
7450 self
.pos
, default_kwargs
, self
.defaults_struct
)
7452 defaults_kwdict
= NoneNode(self
.pos
)
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
,
7459 self
.pos
, args
=[defaults_tuple
, defaults_kwdict
])),
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
7470 annotations_dict
= DictNode(self
.pos
, key_value_pairs
=[
7472 pos
, key
=IdentifierStringNode(pos
, value
=name
),
7474 for pos
, name
, value
in annotations
])
7475 self
.annotations_dict
= annotations_dict
.analyse_types(env
)
7477 def may_be_none(self
):
7480 gil_message
= "Constructing Python function"
7482 def self_result_code(self
):
7483 if self
.self_object
is None:
7484 self_result
= "NULL"
7486 self_result
= self
.self_object
.py_result()
7489 def generate_result_code(self
, code
):
7491 self
.generate_cyfunction_code(code
)
7493 self
.generate_pycfunction_code(code
)
7495 def generate_pycfunction_code(self
, code
):
7496 py_mod_name
= self
.get_py_mod_name(code
)
7498 '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % (
7500 self
.pymethdef_cname
,
7501 self
.self_result_code(),
7503 code
.error_goto_if_null(self
.result(), self
.pos
)))
7505 code
.put_gotref(self
.py_result())
7507 def generate_cyfunction_code(self
, code
):
7508 if self
.specialized_cpdefs
:
7509 def_node
= self
.specialized_cpdefs
[0]
7511 def_node
= self
.def_node
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"
7518 code
.globalstate
.use_utility_code(
7519 UtilityCode
.load_cached("CythonFunction", "CythonFunction.c"))
7520 constructor
= "__Pyx_CyFunction_NewEx"
7522 if self
.code_object
:
7523 code_object_result
= self
.code_object
.py_result()
7525 code_object_result
= 'NULL'
7528 if def_node
.is_staticmethod
:
7529 flags
.append('__Pyx_CYFUNCTION_STATICMETHOD')
7530 elif def_node
.is_classmethod
:
7531 flags
.append('__Pyx_CYFUNCTION_CLASSMETHOD')
7533 if def_node
.local_scope
.parent_scope
.is_c_class_scope
:
7534 flags
.append('__Pyx_CYFUNCTION_CCLASS')
7537 flags
= ' | '.join(flags
)
7542 '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % (
7545 self
.pymethdef_cname
,
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
,
7552 code
.error_goto_if_null(self
.result(), self
.pos
)))
7554 code
.put_gotref(self
.py_result())
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
)
7561 'PyList_Append(%s, %s);' % (
7562 class_node
.class_cell
.result(),
7564 code
.put_giveref(self
.py_result())
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
))
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()))
7591 class InnerFunctionNode(PyCFunctionNode
):
7592 # Special PyCFunctionNode that depends on a closure class
7596 needs_self_code
= True
7598 def self_result_code(self
):
7599 if self
.needs_self_code
:
7600 return "((PyObject*)%s)" % Naming
.cur_scope_cname
7604 class CodeObjectNode(ExprNode
):
7605 # Create a PyCodeObject for a CyFunction instance.
7607 # def_node DefNode the Python function node
7608 # varnames TupleNode a tuple with all local variable names
7610 subexprs
= ['varnames']
7613 def __init__(self
, def_node
):
7614 ExprNode
.__init
__(self
, def_node
.pos
, def_node
=def_node
)
7615 args
= list(def_node
.args
)
7616 # if we have args/kwargs, then the first two in var_entries are those
7617 local_vars
= [arg
for arg
in def_node
.local_scope
.var_entries
if arg
.name
]
7618 self
.varnames
= TupleNode(
7620 args
=[IdentifierStringNode(arg
.pos
, value
=arg
.name
)
7621 for arg
in args
+ local_vars
],
7625 def may_be_none(self
):
7628 def calculate_result_code(self
):
7629 return self
.result_code
7631 def generate_result_code(self
, code
):
7632 self
.result_code
= code
.get_py_const(py_object_type
, 'codeobj', cleanup_level
=2)
7634 code
= code
.get_cached_constants_writer()
7635 code
.mark_pos(self
.pos
)
7636 func
= self
.def_node
7637 func_name
= code
.get_py_string_const(
7638 func
.name
, identifier
=True, is_str
=False, unicode_value
=func
.name
)
7639 # FIXME: better way to get the module file path at module init time? Encoding to use?
7640 file_path
= StringEncoding
.BytesLiteral(func
.pos
[0].get_filenametable_entry().encode('utf8'))
7641 file_path_const
= code
.get_py_string_const(file_path
, identifier
=False, is_str
=True)
7644 if self
.def_node
.star_arg
:
7645 flags
.append('CO_VARARGS')
7646 if self
.def_node
.starstar_arg
:
7647 flags
.append('CO_VARKEYWORDS')
7649 code
.putln("%s = (PyObject*)__Pyx_PyCode_New(%d, %d, %d, 0, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %s); %s" % (
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
7663 self
.pos
[1], # firstlineno
7664 Naming
.empty_bytes
, # lnotab
7665 code
.error_goto_if_null(self
.result_code
, self
.pos
),
7669 class DefaultLiteralArgNode(ExprNode
):
7670 # CyFunction's literal argument default value
7672 # Evaluate literal only once.
7678 def __init__(self
, pos
, arg
):
7679 super(DefaultLiteralArgNode
, self
).__init
__(pos
)
7681 self
.type = self
.arg
.type
7682 self
.evaluated
= False
7684 def analyse_types(self
, env
):
7687 def generate_result_code(self
, code
):
7690 def generate_evaluation_code(self
, code
):
7691 if not self
.evaluated
:
7692 self
.arg
.generate_evaluation_code(code
)
7693 self
.evaluated
= True
7696 return self
.type.cast_code(self
.arg
.result())
7699 class DefaultNonLiteralArgNode(ExprNode
):
7700 # CyFunction's non-literal argument default value
7704 def __init__(self
, pos
, arg
, defaults_struct
):
7705 super(DefaultNonLiteralArgNode
, self
).__init
__(pos
)
7707 self
.defaults_struct
= defaults_struct
7709 def analyse_types(self
, env
):
7710 self
.type = self
.arg
.type
7711 self
.is_temp
= False
7714 def generate_result_code(self
, code
):
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
)
7723 class DefaultsTupleNode(TupleNode
):
7724 # CyFunction's __defaults__ tuple
7726 def __init__(self
, pos
, defaults
, defaults_struct
):
7728 for arg
in defaults
:
7729 if not arg
.default
.is_literal
:
7730 arg
= DefaultNonLiteralArgNode(pos
, arg
, defaults_struct
)
7734 super(DefaultsTupleNode
, self
).__init
__(pos
, args
=args
)
7737 class DefaultsKwDictNode(DictNode
):
7738 # CyFunction's __kwdefaults__ dict
7740 def __init__(self
, pos
, defaults
, defaults_struct
):
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
)
7748 items
.append(DictItemNode(arg
.pos
, key
=name
, value
=arg
))
7749 super(DefaultsKwDictNode
, self
).__init
__(pos
, key_value_pairs
=items
)
7752 class LambdaNode(InnerFunctionNode
):
7753 # Lambda expression node (only used as a function reference)
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
7762 child_attrs
= ['def_node']
7764 name
= StringEncoding
.EncodedString('<lambda>')
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
)
7774 def analyse_types(self
, env
):
7775 self
.def_node
= self
.def_node
.analyse_expressions(env
)
7776 return super(LambdaNode
, self
).analyse_types(env
)
7778 def generate_result_code(self
, code
):
7779 self
.def_node
.generate_execution_code(code
)
7780 super(LambdaNode
, self
).generate_result_code(code
)
7783 class GeneratorExpressionNode(LambdaNode
):
7784 # A generator expression, e.g. (i for i in range(10))
7786 # Result is a generator.
7788 # loop ForStatNode the for-loop, containing a YieldExprNode
7789 # def_node DefNode the underlying generator 'def' node
7791 name
= StringEncoding
.EncodedString('genexpr')
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
7803 def generate_result_code(self
, code
):
7805 '%s = %s(%s); %s' % (
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())
7813 class YieldExprNode(ExprNode
):
7814 # Yield expression node
7816 # arg ExprNode the value to return from the generator
7817 # label_num integer yield label number
7818 # is_yield_from boolean is a YieldFromExprNode to delegate to another generator
7821 type = py_object_type
7823 is_yield_from
= False
7825 def analyse_types(self
, env
):
7826 if not self
.label_num
:
7827 error(self
.pos
, "'yield' not supported here")
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
)
7835 def coerce_yield_argument(self
, env
):
7836 self
.arg
= self
.arg
.coerce_to_pyobject(env
)
7838 def generate_evaluation_code(self
, code
):
7840 self
.arg
.generate_evaluation_code(code
)
7841 self
.arg
.make_owned_reference(code
)
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
)
7849 code
.put_init_to_py_none(Naming
.retval_cname
, py_object_type
)
7850 self
.generate_yield_code(code
)
7852 def generate_yield_code(self
, code
):
7854 Generate the code to return the argument in 'Naming.retval_cname'
7855 and to continue at the yield label.
7857 label_num
, label_name
= code
.new_yield_label()
7858 code
.use_label(label_name
)
7861 code
.funcstate
.closure_temps
.reset()
7862 for cname
, type, manage_ref
in code
.funcstate
.temps_in_use():
7863 save_cname
= code
.funcstate
.closure_temps
.allocate_temp(type)
7864 saved
.append((cname
, save_cname
, type))
7865 if type.is_pyobject
:
7866 code
.put_xgiveref(cname
)
7867 code
.putln('%s->%s = %s;' % (Naming
.cur_scope_cname
, save_cname
, cname
))
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
)
7876 code
.put_label(label_name
)
7877 for cname
, save_cname
, type in saved
:
7878 code
.putln('%s = %s->%s;' % (cname
, Naming
.cur_scope_cname
, save_cname
))
7879 if type.is_pyobject
:
7880 code
.putln('%s->%s = 0;' % (Naming
.cur_scope_cname
, save_cname
))
7881 code
.put_xgotref(cname
)
7882 code
.putln(code
.error_goto_if_null(Naming
.sent_value_cname
, self
.pos
))
7883 if self
.result_is_used
:
7884 self
.allocate_temp_result(code
)
7885 code
.put('%s = %s; ' % (self
.result(), Naming
.sent_value_cname
))
7886 code
.put_incref(self
.result(), py_object_type
)
7889 class YieldFromExprNode(YieldExprNode
):
7890 # "yield from GEN" expression
7891 is_yield_from
= True
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
)
7899 def generate_evaluation_code(self
, code
):
7900 code
.globalstate
.use_utility_code(UtilityCode
.load_cached("YieldFrom", "Generator.c"))
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
)
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" % (
7920 code
.error_goto(self
.pos
)))
7921 code
.put_gotref(self
.result())
7923 code
.putln("PyObject* exc_type = PyErr_Occurred();")
7924 code
.putln("if (exc_type) {")
7925 code
.putln("if (likely(exc_type == PyExc_StopIteration ||"
7926 " PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();")
7927 code
.putln("else %s" % code
.error_goto(self
.pos
))
7931 class GlobalsExprNode(AtomicExprNode
):
7935 def analyse_types(self
, env
):
7936 env
.use_utility_code(Builtin
.globals_utility_code
)
7939 gil_message
= "Constructing globals dict"
7941 def may_be_none(self
):
7944 def generate_result_code(self
, code
):
7945 code
.putln('%s = __Pyx_Globals(); %s' % (
7947 code
.error_goto_if_null(self
.result(), self
.pos
)))
7948 code
.put_gotref(self
.result())
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
)
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)
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 ]
7981 class PyClassLocalsExprNode(AtomicExprNode
):
7982 def __init__(self
, pos
, pyclass_dict
):
7983 AtomicExprNode
.__init
__(self
, pos
)
7984 self
.pyclass_dict
= pyclass_dict
7986 def analyse_types(self
, env
):
7987 self
.type = self
.pyclass_dict
.type
7988 self
.is_temp
= False
7991 def may_be_none(self
):
7995 return self
.pyclass_dict
.result()
7997 def generate_result_code(self
, code
):
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
)
8009 #-------------------------------------------------------------------
8011 # Unary operator nodes
8013 #-------------------------------------------------------------------
8015 compile_time_unary_operators
= {
8016 'not': operator
.not_
,
8022 class UnopNode(ExprNode
):
8026 # Processing during analyse_expressions phase:
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.
8034 subexprs
= ['operand']
8037 def calculate_constant_result(self
):
8038 func
= compile_time_unary_operators
[self
.operator
]
8039 self
.constant_result
= func(self
.operand
.constant_result
)
8041 def compile_time_value(self
, denv
):
8042 func
= compile_time_unary_operators
.get(self
.operator
)
8045 "Unary '%s' not supported in compile-time expression"
8047 operand
= self
.operand
.compile_time_value(denv
)
8049 return func(operand
)
8050 except Exception, e
:
8051 self
.compile_time_value_error(e
)
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:
8059 return self
.infer_unop_type(env
, operand_type
)
8061 def infer_unop_type(self
, env
, operand_type
):
8062 if operand_type
.is_pyobject
:
8063 return py_object_type
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
:
8071 return ExprNode
.may_be_none(self
)
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
8079 elif self
.is_cpp_operation():
8080 self
.analyse_cpp_operation(env
)
8082 self
.analyse_c_operation(env
)
8085 def check_const(self
):
8086 return self
.operand
.check_const()
8088 def is_py_operation(self
):
8089 return self
.operand
.type.is_pyobject
8091 def nogil_check(self
, env
):
8092 if self
.is_py_operation():
8095 def is_cpp_operation(self
):
8096 type = self
.operand
.type
8097 return type.is_cpp_class
8099 def coerce_operand_to_pyobject(self
, env
):
8100 self
.operand
= self
.operand
.coerce_to_pyobject(env
)
8102 def generate_result_code(self
, code
):
8103 if self
.operand
.type.is_pyobject
:
8104 self
.generate_py_operation_code(code
)
8106 def generate_py_operation_code(self
, code
):
8107 function
= self
.py_operation_function()
8109 "%s = %s(%s); %s" % (
8112 self
.operand
.py_result(),
8113 code
.error_goto_if_null(self
.result(), self
.pos
)))
8114 code
.put_gotref(self
.py_result())
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
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))
8129 self
.type = cpp_type
8132 class NotNode(UnopNode
):
8138 type = PyrexTypes
.c_bint_type
8140 def calculate_constant_result(self
):
8141 self
.constant_result
= not self
.operand
.constant_result
8143 def compile_time_value(self
, denv
):
8144 operand
= self
.operand
.compile_time_value(denv
)
8147 except Exception, e
:
8148 self
.compile_time_value_error(e
)
8150 def infer_unop_type(self
, env
, operand_type
):
8151 return PyrexTypes
.c_bint_type
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
)
8159 error(self
.pos
, "'!' operator not defined for %s" % operand_type
)
8160 self
.type = PyrexTypes
.error_type
8162 self
.type = cpp_type
8164 self
.operand
= self
.operand
.coerce_to_boolean(env
)
8167 def calculate_result_code(self
):
8168 return "(!%s)" % self
.operand
.result()
8170 def generate_result_code(self
, code
):
8174 class UnaryPlusNode(UnopNode
):
8175 # unary '+' operator
8179 def analyse_c_operation(self
, env
):
8180 self
.type = PyrexTypes
.widest_numeric_type(
8181 self
.operand
.type, PyrexTypes
.c_int_type
)
8183 def py_operation_function(self
):
8184 return "PyNumber_Positive"
8186 def calculate_result_code(self
):
8187 if self
.is_cpp_operation():
8188 return "(+%s)" % self
.operand
.result()
8190 return self
.operand
.result()
8193 class UnaryMinusNode(UnopNode
):
8194 # unary '-' operator
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
8206 if self
.type.is_complex
:
8209 def py_operation_function(self
):
8210 return "PyNumber_Negative"
8212 def calculate_result_code(self
):
8214 return "(-%s)" % self
.operand
.result()
8216 return "%s(%s)" % (self
.operand
.type.unary_op('-'), self
.operand
.result())
8218 def get_constant_c_result_code(self
):
8219 value
= self
.operand
.get_constant_c_result_code()
8221 return "(-%s)" % value
8223 class TildeNode(UnopNode
):
8224 # unary '~' operator
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
8235 def py_operation_function(self
):
8236 return "PyNumber_Invert"
8238 def calculate_result_code(self
):
8239 return "(~%s)" % self
.operand
.result()
8242 class CUnopNode(UnopNode
):
8244 def is_py_operation(self
):
8247 class DereferenceNode(CUnopNode
):
8252 def infer_unop_type(self
, env
, operand_type
):
8253 if operand_type
.is_ptr
:
8254 return operand_type
.base_type
8256 return PyrexTypes
.error_type
8258 def analyse_c_operation(self
, env
):
8259 if self
.operand
.type.is_ptr
:
8260 self
.type = self
.operand
.type.base_type
8264 def calculate_result_code(self
):
8265 return "(*%s)" % self
.operand
.result()
8268 class DecrementIncrementNode(CUnopNode
):
8269 # unary ++/-- operator
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
8280 def calculate_result_code(self
):
8282 return "(%s%s)" % (self
.operator
, self
.operand
.result())
8284 return "(%s%s)" % (self
.operand
.result(), self
.operator
)
8286 def inc_dec_constructor(is_prefix
, operator
):
8287 return lambda pos
, **kwds
: DecrementIncrementNode(pos
, is_prefix
=is_prefix
, operator
=operator
, **kwds
)
8290 class AmpersandNode(CUnopNode
):
8291 # The C address-of operator.
8296 def infer_unop_type(self
, env
, operand_type
):
8297 return PyrexTypes
.c_ptr_type(operand_type
)
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
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")
8311 self
.error("Taking address of non-lvalue")
8313 if argtype
.is_pyobject
:
8314 self
.error("Cannot take address of Python variable")
8316 self
.type = PyrexTypes
.c_ptr_type(argtype
)
8319 def check_const(self
):
8320 return self
.operand
.check_const_addr()
8322 def error(self
, mess
):
8323 error(self
.pos
, mess
)
8324 self
.type = PyrexTypes
.error_type
8325 self
.result_code
= "<error>"
8327 def calculate_result_code(self
):
8328 return "(&%s)" % self
.operand
.result()
8330 def generate_result_code(self
, code
):
8334 unop_node_classes
= {
8336 "-": UnaryMinusNode
,
8340 def unop_node(pos
, operator
, operand
):
8341 # Construct unnop node of appropriate class for
8343 if isinstance(operand
, IntNode
) and operator
== '-':
8344 return IntNode(pos
= operand
.pos
, value
= str(-Utils
.str_to_number(operand
.value
)),
8345 longness
=operand
.longness
, unsigned
=operand
.unsigned
)
8346 elif isinstance(operand
, UnopNode
) and operand
.operator
== operator
in '+-':
8347 warning(pos
, "Python has no increment/decrement operator: %s%sx == %s(%sx) == x" % ((operator
,)*4), 5)
8348 return unop_node_classes
[operator
](pos
,
8349 operator
= operator
,
8353 class TypecastNode(ExprNode
):
8357 # base_type CBaseTypeNode
8358 # declarator CDeclaratorNode
8361 # If used from a transform, one can if wanted specify the attribute
8362 # "type" directly and leave base_type and declarator to None
8364 subexprs
= ['operand']
8365 base_type
= declarator
= type = None
8367 def type_dependencies(self
, env
):
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
)
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
:
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
)
8404 if self
.operand
.type.is_ptr
:
8405 if not (self
.operand
.type.base_type
.is_void
or self
.operand
.type.base_type
.is_struct
):
8406 error(self
.pos
, "Python objects cannot be cast from pointers of primitive types")
8408 # Should this be an error?
8409 warning(self
.pos
, "No conversion from %s to %s, python object pointer used." % (self
.operand
.type, self
.type))
8410 self
.operand
= self
.operand
.coerce_to_simple(env
)
8411 elif from_py
and not to_py
:
8412 if self
.type.create_from_py_utility_code(env
):
8413 self
.operand
= self
.operand
.coerce_to(self
.type, env
)
8414 elif self
.type.is_ptr
:
8415 if not (self
.type.base_type
.is_void
or self
.type.base_type
.is_struct
):
8416 error(self
.pos
, "Python objects cannot be cast to pointers of primitive types")
8418 warning(self
.pos
, "No conversion from %s to %s, python object pointer used." % (self
.type, self
.operand
.type))
8419 elif from_py
and to_py
:
8421 self
.operand
= PyTypeTestNode(self
.operand
, self
.type, env
, notnone
=True)
8422 elif isinstance(self
.operand
, SliceIndexNode
):
8423 # This cast can influence the created type of string slices.
8424 self
.operand
= self
.operand
.coerce_to(self
.type, env
)
8425 elif self
.type.is_complex
and self
.operand
.type.is_complex
:
8426 self
.operand
= self
.operand
.coerce_to_simple(env
)
8427 elif self
.operand
.type.is_fused
:
8428 self
.operand
= self
.operand
.coerce_to(self
.type, env
)
8429 #self.type = self.operand.type
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()
8436 def nonlocally_immutable(self
):
8437 return self
.is_temp
or self
.operand
.nonlocally_immutable()
8439 def nogil_check(self
, env
):
8440 if self
.type and self
.type.is_pyobject
and self
.is_temp
:
8443 def check_const(self
):
8444 return self
.operand
.check_const()
8446 def calculate_constant_result(self
):
8447 self
.constant_result
= self
.calculate_result_code(self
.operand
.constant_result
)
8449 def calculate_result_code(self
, operand_result
= None):
8450 if operand_result
is None:
8451 operand_result
= self
.operand
.result()
8452 if self
.type.is_complex
:
8453 operand_result
= self
.operand
.result()
8454 if self
.operand
.type.is_complex
:
8455 real_part
= self
.type.real_type
.cast_code("__Pyx_CREAL(%s)" % operand_result
)
8456 imag_part
= self
.type.real_type
.cast_code("__Pyx_CIMAG(%s)" % operand_result
)
8458 real_part
= self
.type.real_type
.cast_code(operand_result
)
8460 return "%s(%s, %s)" % (
8461 self
.type.from_parts
,
8465 return self
.type.cast_code(operand_result
)
8467 def get_constant_c_result_code(self
):
8468 operand_result
= self
.operand
.get_constant_c_result_code()
8470 return self
.type.cast_code(operand_result
)
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)
8477 return ExprNode
.result_as(self
, type)
8479 def generate_result_code(self
, code
):
8482 "%s = (PyObject *)%s;" % (
8484 self
.operand
.result()))
8485 code
.put_incref(self
.result(), self
.ctype())
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"
8495 class CythonArrayNode(ExprNode
):
8497 Used when a pointer of base_type is cast to a memoryviewslice with that
8502 creates a fortran-contiguous cython.array.
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
8509 This also handles <int[:, :]> my_c_array
8512 operand ExprNode the thing we're casting
8513 base_type_node MemoryViewSliceTypeNode the cast expression node
8516 subexprs
= ['operand', 'shapes']
8523 shape_type
= PyrexTypes
.c_py_ssize_t_type
8525 def analyse_types(self
, env
):
8528 self
.operand
= self
.operand
.analyse_types(env
)
8529 if self
.array_dtype
:
8530 array_dtype
= self
.array_dtype
8532 array_dtype
= self
.base_type_node
.base_type_node
.analyse(env
)
8533 axes
= self
.base_type_node
.axes
8535 MemoryView
.validate_memslice_dtype(self
.pos
, array_dtype
)
8537 self
.type = error_type
8541 # Base type of the pointer or C array we are converting
8542 base_type
= self
.operand
.type
8544 if not self
.operand
.type.is_ptr
and not self
.operand
.type.is_array
:
8545 error(self
.operand
.pos
, ERR_NOT_POINTER
)
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
8557 error(self
.pos
, "unexpected base type %s found" % base_type
)
8560 if not (base_type
.same_as(array_dtype
) or base_type
.is_void
):
8561 error(self
.operand
.pos
, ERR_BASE_TYPE
)
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
)))
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
)
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
)
8584 error(axis
.pos
, ERR_NOT_STOP
)
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
)
8592 self
.shapes
.append(shape
)
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")
8603 if axis
.step
.compile_time_value(env
) != 1:
8604 error(axis
.step
.pos
, ERR_STEPS
)
8608 self
.mode
= "fortran"
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
)
8615 if not self
.operand
.is_name
:
8616 self
.operand
= self
.operand
.coerce_to_temp(env
)
8618 axes
= [('direct', 'follow')] * len(axes
)
8619 if self
.mode
== "fortran":
8620 axes
[0] = ('direct', 'contig')
8622 axes
[-1] = ('direct', 'contig')
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
)
8630 def allocate_temp_result(self
, code
):
8632 raise RuntimeError("temp allocated mulitple times")
8634 self
.temp_code
= code
.funcstate
.allocate_temp(self
.type, True)
8636 def infer_type(self
, env
):
8637 return self
.get_cython_array_type(env
)
8639 def get_cython_array_type(self
, env
):
8640 return env
.global_scope().context
.cython_scope
.viewscope
.lookup("array").type
8642 def generate_result_code(self
, code
):
8645 shapes
= [self
.shape_type
.cast_code(shape
.result())
8646 for shape
in self
.shapes
]
8647 dtype
= self
.coercion_type
.dtype
8649 shapes_temp
= code
.funcstate
.allocate_temp(py_object_type
, True)
8650 format_temp
= code
.funcstate
.allocate_temp(py_object_type
, True)
8652 itemsize
= "sizeof(%s)" % dtype
.declaration_code("")
8653 type_info
= Buffer
.get_type_information_cname(code
, dtype
)
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
))
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
)))
8668 err
= "!%s || !%s || !PyBytes_AsString(%s)" % (format_temp
,
8671 code
.putln(code
.error_goto_if(err
, self
.pos
))
8672 code
.put_gotref(format_temp
)
8673 code
.put_gotref(shapes_temp
)
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())
8684 code
.put_decref_clear(temp
, py_object_type
)
8685 code
.funcstate
.release_temp(temp
)
8687 dispose(shapes_temp
)
8688 dispose(format_temp
)
8691 def from_carray(cls
, src_node
, env
):
8693 Given a C array type, return a CythonArrayNode
8696 base_type
= src_node
.type
8698 none_node
= NoneNode(pos
)
8701 while base_type
.is_array
:
8702 axes
.append(SliceNode(pos
, start
=none_node
, stop
=none_node
,
8704 base_type
= base_type
.base_type
8705 axes
[-1].step
= IntNode(pos
, value
="1", is_c_literal
=True)
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
)
8714 class SizeofNode(ExprNode
):
8715 # Abstract base class for sizeof(x) expression nodes.
8717 type = PyrexTypes
.c_size_t_type
8719 def check_const(self
):
8722 def generate_result_code(self
, code
):
8726 class SizeofTypeNode(SizeofNode
):
8727 # C sizeof function applied to a type
8729 # base_type CBaseTypeNode
8730 # declarator CDeclaratorNode
8735 def analyse_types(self
, env
):
8736 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
8737 # this could be better handled by more uniformly treating types as runtime-available objects
8738 if 0 and self
.base_type
.module_path
:
8739 path
= self
.base_type
.module_path
8740 obj
= env
.lookup(path
[0])
8741 if obj
.as_module
is None:
8742 operand
= NameNode(pos
=self
.pos
, name
=path
[0])
8743 for attr
in path
[1:]:
8744 operand
= AttributeNode(pos
=self
.pos
, obj
=operand
, attribute
=attr
)
8745 operand
= AttributeNode(pos
=self
.pos
, obj
=operand
, attribute
=self
.base_type
.name
)
8746 self
.operand
= operand
8747 self
.__class
__ = SizeofVarNode
8748 node
= self
.analyse_types(env
)
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
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
)
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)
8772 arg_code
= self
.arg_type
.declaration_code("")
8773 return "(sizeof(%s))" % arg_code
8776 class SizeofVarNode(SizeofNode
):
8777 # C sizeof function applied to a variable
8781 subexprs
= ['operand']
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
)
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
8794 self
.operand
= self
.operand
.analyse_types(env
)
8797 def calculate_result_code(self
):
8798 return "(sizeof(%s))" % self
.operand
.result()
8800 def generate_result_code(self
, code
):
8803 class TypeofNode(ExprNode
):
8804 # Compile-time type of an expression, as a string.
8807 # literal StringNode # internal
8810 type = py_object_type
8812 subexprs
= ['literal'] # 'operand' will be ignored after type analysis!
8814 def analyse_types(self
, env
):
8815 self
.operand
= self
.operand
.analyse_types(env
)
8816 value
= StringEncoding
.EncodedString(str(self
.operand
.type)) #self.operand.type.typeof_name())
8817 literal
= StringNode(self
.pos
, value
=value
)
8818 literal
= literal
.analyse_types(env
)
8819 self
.literal
= literal
.coerce_to_pyobject(env
)
8822 def may_be_none(self
):
8825 def generate_evaluation_code(self
, code
):
8826 self
.literal
.generate_evaluation_code(code
)
8828 def calculate_result_code(self
):
8829 return self
.literal
.calculate_result_code()
8831 #-------------------------------------------------------------------
8833 # Binary operator nodes
8835 #-------------------------------------------------------------------
8837 compile_time_binary_operators
= {
8845 'is_not': operator
.is_not
,
8848 '/': operator
.truediv
,
8849 '//': operator
.floordiv
,
8850 '<<': operator
.lshift
,
8855 '>>': operator
.rshift
,
8858 'in': lambda x
, seq
: x
in seq
,
8859 'not_in': lambda x
, seq
: x
not in seq
,
8862 def get_compile_time_binop(node
):
8863 func
= compile_time_binary_operators
.get(node
.operator
)
8866 "Binary '%s' not supported in compile-time expression"
8870 class BinopNode(ExprNode
):
8875 # Processing during analyse_expressions phase:
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.
8883 subexprs
= ['operand1', 'operand2']
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
)
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
)
8897 return func(operand1
, operand2
)
8898 except Exception, e
:
8899 self
.compile_time_value_error(e
)
8901 def infer_type(self
, env
):
8902 return self
.result_type(self
.operand1
.infer_type(env
),
8903 self
.operand2
.infer_type(env
))
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
)
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,
8916 assert self
.type.is_pyobject
8918 elif self
.is_cpp_operation():
8919 self
.analyse_cpp_operation(env
)
8921 self
.analyse_c_operation(env
)
8923 def is_py_operation(self
):
8924 return self
.is_py_operation_types(self
.operand1
.type, self
.operand2
.type)
8926 def is_py_operation_types(self
, type1
, type2
):
8927 return type1
.is_pyobject
or type2
.is_pyobject
8929 def is_cpp_operation(self
):
8930 return (self
.operand1
.type.is_cpp_class
8931 or self
.operand2
.type.is_cpp_class
)
8933 def analyse_cpp_operation(self
, env
):
8934 entry
= env
.lookup_operator(self
.operator
, [self
.operand1
, self
.operand2
])
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
)
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
8948 def result_type(self
, type1
, type2
):
8949 if self
.is_py_operation_types(type1
, type2
):
8951 type2
= Builtin
.bytes_type
8952 elif type2
.is_pyunicode_ptr
:
8953 type2
= Builtin
.unicode_type
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?
8962 result_type
= self
.infer_builtin_types_operation(type1
, type2
)
8963 if result_type
is not None:
8965 return py_object_type
8967 return self
.compute_c_result_type(type1
, type2
)
8969 def infer_builtin_types_operation(self
, type1
, type2
):
8972 def nogil_check(self
, env
):
8973 if self
.is_py_operation():
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
)
8980 def check_const(self
):
8981 return self
.operand1
.check_const() and self
.operand2
.check_const()
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"
8992 "%s = %s(%s, %s%s); %s" % (
8995 self
.operand1
.py_result(),
8996 self
.operand2
.py_result(),
8998 code
.error_goto_if_null(self
.result(), self
.pos
)))
8999 code
.put_gotref(self
.py_result())
9001 code
.putln("%s = %s;" % (self
.result(), self
.calculate_result_code()))
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
9012 class CBinopNode(BinopNode
):
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
9020 def py_operation_function(self
):
9023 def calculate_result_code(self
):
9024 return "(%s %s %s)" % (
9025 self
.operand1
.result(),
9027 self
.operand2
.result())
9029 def compute_c_result_type(self
, type1
, type2
):
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?
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
9045 class NumBinopNode(BinopNode
):
9046 # Binary operation taking numeric arguments.
9049 overflow_check
= False
9050 overflow_bit_node
= None
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
)
9059 if self
.type.is_complex
:
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
],
9073 const_rhs
= self
.operand2
.has_constant_result())
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
)
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
9087 widest_type
= PyrexTypes
.widest_numeric_type(
9088 widest_type
, PyrexTypes
.c_int_type
)
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
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.
9104 return super(NumBinopNode
, self
).may_be_none()
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
)
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
)
9119 def generate_evaluation_code(self
, code
):
9120 if self
.overflow_check
:
9121 self
.overflow_bit_node
= self
9122 self
.overflow_bit
= code
.funcstate
.allocate_temp(PyrexTypes
.c_int_type
, manage_ref
=False)
9123 code
.putln("%s = 0;" % self
.overflow_bit
)
9124 super(NumBinopNode
, self
).generate_evaluation_code(code
)
9125 if self
.overflow_check
:
9126 code
.putln("if (unlikely(%s)) {" % self
.overflow_bit
)
9127 code
.putln('PyErr_SetString(PyExc_OverflowError, "value too large");')
9128 code
.putln(code
.error_goto(self
.pos
))
9130 code
.funcstate
.release_temp(self
.overflow_bit
)
9132 def calculate_result_code(self
):
9133 if self
.overflow_bit_node
is not None:
9134 return "%s(%s, %s, &%s)" % (
9136 self
.operand1
.result(),
9137 self
.operand2
.result(),
9138 self
.overflow_bit_node
.overflow_bit
)
9140 return "(%s %s %s)" % (
9141 self
.operand1
.result(),
9143 self
.operand2
.result())
9145 func
= self
.type.binary_op(self
.operator
)
9147 error(self
.pos
, "binary operator %s not supported for %s" % (self
.operator
, self
.type))
9148 return "%s(%s, %s)" % (
9150 self
.operand1
.result(),
9151 self
.operand2
.result())
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
))
9158 def py_operation_function(self
):
9159 function_name
= self
.py_functions
[self
.operator
]
9161 function_name
= function_name
.replace('PyNumber_', 'PyNumber_InPlace')
9162 return function_name
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"
9179 overflow_op_names
= {
9187 class IntBinopNode(NumBinopNode
):
9188 # Binary operation taking integer arguments.
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
)
9196 class AddNode(NumBinopNode
):
9199 def is_py_operation_types(self
, type1
, type2
):
9200 if type1
.is_string
and type2
.is_string
or type1
.is_pyunicode_ptr
and type2
.is_pyunicode_ptr
:
9203 return NumBinopNode
.is_py_operation_types(self
, type1
, type2
)
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
))]
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
):
9218 elif (type2
.is_ptr
or type2
.is_array
) and (type1
.is_int
or type1
.is_enum
):
9221 return NumBinopNode
.compute_c_result_type(
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'
9231 return '__Pyx_PyUnicode_Concat'
9232 return super(AddNode
, self
).py_operation_function()
9235 class SubNode(NumBinopNode
):
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
):
9241 elif (type1
.is_ptr
or type1
.is_array
) and (type2
.is_ptr
or type2
.is_array
):
9242 return PyrexTypes
.c_ptrdiff_t_type
9244 return NumBinopNode
.compute_c_result_type(
9248 class MulNode(NumBinopNode
):
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
)):
9256 return NumBinopNode
.is_py_operation_types(self
, type1
, type2
)
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
:
9264 if type2
in string_types
and type1
.is_builtin_type
:
9266 # multiplication of containers/numbers with an integer value
9267 # always (?) returns the same type
9275 class DivNode(NumBinopNode
):
9276 # '/' or '//' operator.
9279 truedivision
= None # == "unknown" if operator == '/'
9280 ctruedivision
= False
9281 cdivision_warnings
= False
9282 zerodivision_check
= None
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
['//']
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
)
9300 def compile_time_value(self
, denv
):
9301 operand1
= self
.operand1
.compile_time_value(denv
)
9302 operand2
= self
.operand2
.compile_time_value(denv
)
9304 func
= self
.find_compile_time_binary_operator(
9306 return func(operand1
, operand2
)
9307 except Exception, e
:
9308 self
.compile_time_value_error(e
)
9310 def analyse_operation(self
, env
):
9311 if self
.cdivision
or env
.directives
['cdivision']:
9312 self
.ctruedivision
= False
9314 self
.ctruedivision
= self
.truedivision
9315 NumBinopNode
.analyse_operation(self
, env
)
9316 if self
.is_cpp_operation():
9317 self
.cdivision
= True
9318 if not self
.type.is_pyobject
:
9319 self
.zerodivision_check
= (
9320 self
.cdivision
is None and not env
.directives
['cdivision']
9321 and (not self
.operand2
.has_constant_result() or
9322 self
.operand2
.constant_result
== 0))
9323 if self
.zerodivision_check
or env
.directives
['cdivision_warnings']:
9324 # Need to check ahead of time to warn or raise zero division error
9325 self
.operand1
= self
.operand1
.coerce_to_simple(env
)
9326 self
.operand2
= self
.operand2
.coerce_to_simple(env
)
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
)
9334 return NumBinopNode
.compute_c_result_type(self
, type1
, type2
)
9336 def zero_division_message(self
):
9337 if self
.type.is_int
:
9338 return "integer division or modulo by zero"
9340 return "float division"
9342 def generate_evaluation_code(self
, code
):
9343 if not self
.type.is_pyobject
and not self
.type.is_complex
:
9344 if self
.cdivision
is None:
9345 self
.cdivision
= (code
.globalstate
.directives
['cdivision']
9346 or not self
.type.signed
9347 or self
.type.is_float
)
9348 if not self
.cdivision
:
9349 code
.globalstate
.use_utility_code(div_int_utility_code
.specialize(self
.type))
9350 NumBinopNode
.generate_evaluation_code(self
, code
)
9351 self
.generate_div_warning_code(code
)
9353 def generate_div_warning_code(self
, code
):
9354 if not self
.type.is_pyobject
:
9355 if self
.zerodivision_check
:
9357 zero_test
= "%s(%s)" % (self
.type.unary_op('zero'), self
.operand2
.result())
9359 zero_test
= "%s == 0" % self
.operand2
.result()
9360 code
.putln("if (unlikely(%s)) {" % zero_test
)
9361 code
.put_ensure_gil()
9362 code
.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self
.zero_division_message())
9363 code
.put_release_ensured_gil()
9364 code
.putln(code
.error_goto(self
.pos
))
9366 if self
.type.is_int
and self
.type.signed
and self
.operator
!= '%':
9367 code
.globalstate
.use_utility_code(division_overflow_test_code
)
9368 if self
.operand2
.type.signed
== 2:
9369 # explicitly signed, no runtime check needed
9370 minus1_check
= 'unlikely(%s == -1)' % self
.operand2
.result()
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(''),
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
))
9385 if code
.globalstate
.directives
['cdivision_warnings'] and self
.operator
!= '/':
9386 code
.globalstate
.use_utility_code(cdivision_warning_utility_code
)
9387 code
.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % (
9388 self
.operand1
.result(),
9389 self
.operand2
.result()))
9390 code
.put_ensure_gil()
9391 code
.putln(code
.set_error_info(self
.pos
, used
=True))
9392 code
.putln("if (__Pyx_cdivision_warning(%(FILENAME)s, "
9393 "%(LINENO)s)) {" % {
9394 'FILENAME': Naming
.filename_cname
,
9395 'LINENO': Naming
.lineno_cname
,
9397 code
.put_release_ensured_gil()
9398 code
.put_goto(code
.error_label
)
9400 code
.put_release_ensured_gil()
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
)
9420 return "__Pyx_div_%s(%s, %s)" % (
9421 self
.type.specialization_name(),
9422 self
.operand1
.result(),
9423 self
.operand2
.result())
9426 class ModNode(DivNode
):
9429 def is_py_operation_types(self
, type1
, type2
):
9430 return (type1
.is_string
9432 or NumBinopNode
.is_py_operation_types(self
, type1
, type2
))
9434 def infer_builtin_types_operation(self
, type1
, type2
):
9435 # b'%s' % xyz raises an exception in Py3, so it's safe to infer the type for Py2
9436 if type1
is unicode_type
:
9437 # None + xyz may be implemented by RHS
9438 if type2
.is_builtin_type
or not self
.operand1
.may_be_none():
9440 elif type1
in (bytes_type
, str_type
, basestring_type
):
9441 if type2
is unicode_type
:
9443 elif type2
.is_numeric
:
9445 elif type1
is bytes_type
and not type2
.is_builtin_type
:
9446 return None # RHS might implement '% operator differently in Py3
9448 return basestring_type
# either str or unicode, can't tell
9451 def zero_division_message(self
):
9452 if self
.type.is_int
:
9453 return "integer division or modulo by zero"
9455 return "float divmod()"
9457 def analyse_operation(self
, env
):
9458 DivNode
.analyse_operation(self
, env
)
9459 if not self
.type.is_pyobject
:
9460 if self
.cdivision
is None:
9461 self
.cdivision
= env
.directives
['cdivision'] or not self
.type.signed
9462 if not self
.cdivision
and not self
.type.is_int
and not self
.type.is_float
:
9463 error(self
.pos
, "mod operator not supported for type '%s'" % self
.type)
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))
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
)
9478 def calculate_result_code(self
):
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())
9486 return "(%s %% %s)" % (
9487 self
.operand1
.result(),
9488 self
.operand2
.result())
9490 return "__Pyx_mod_%s(%s, %s)" % (
9491 self
.type.specialization_name(),
9492 self
.operand1
.result(),
9493 self
.operand2
.result())
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'
9500 return 'PyUnicode_Format'
9501 elif self
.operand1
.type is str_type
:
9502 if self
.operand1
.may_be_none():
9503 return '__Pyx_PyString_FormatSafe'
9505 return '__Pyx_PyString_Format'
9506 return super(ModNode
, self
).py_operation_function()
9509 class PowNode(NumBinopNode
):
9512 def analyse_c_operation(self
, env
):
9513 NumBinopNode
.analyse_c_operation(self
, env
)
9514 if self
.type.is_complex
:
9515 if self
.type.real_type
.is_float
:
9516 self
.operand1
= self
.operand1
.coerce_to(self
.type, env
)
9517 self
.operand2
= self
.operand2
.coerce_to(self
.type, env
)
9518 self
.pow_func
= "__Pyx_c_pow" + self
.type.real_type
.math_h_modifier
9520 error(self
.pos
, "complex int powers not supported")
9521 self
.pow_func
= "<error>"
9522 elif self
.type.is_float
:
9523 self
.pow_func
= "pow" + self
.type.math_h_modifier
9524 elif self
.type.is_int
:
9525 self
.pow_func
= "__Pyx_pow_%s" % self
.type.declaration_code('').replace(' ', '_')
9526 env
.use_utility_code(
9527 int_pow_utility_code
.specialize(
9528 func_name
=self
.pow_func
,
9529 type=self
.type.declaration_code(''),
9530 signed
=self
.type.signed
and 1 or 0))
9531 elif not self
.type.is_error
:
9532 error(self
.pos
, "got unexpected types for C power operator: %s, %s" %
9533 (self
.operand1
.type, self
.operand2
.type))
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()
9541 return self
.type.cast_code(operand
.result())
9542 return "%s(%s, %s)" % (
9544 typecast(self
.operand1
),
9545 typecast(self
.operand2
))
9548 # Note: This class is temporarily "shut down" into an ineffective temp
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.
9561 subexprs
= ['operand1', 'operand2']
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
)
9568 def may_be_none(self
):
9569 if self
.operator
== 'or':
9570 return self
.operand2
.may_be_none()
9572 return self
.operand1
.may_be_none() or self
.operand2
.may_be_none()
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
9580 self
.constant_result
= \
9581 self
.operand1
.constant_result
or \
9582 self
.operand2
.constant_result
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
)
9589 return self
.operand1
.compile_time_value(denv
) \
9590 or self
.operand2
.compile_time_value(denv
)
9592 def coerce_to_boolean(self
, env
):
9593 return BoolBinopNode(
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
)
9601 def analyse_types(self
, env
):
9602 self
.operand1
= self
.operand1
.analyse_types(env
)
9603 self
.operand2
= self
.operand2
.analyse_types(env
)
9604 self
.type = PyrexTypes
.independent_spanning_type(self
.operand1
.type, self
.operand2
.type)
9605 self
.operand1
= self
.operand1
.coerce_to(self
.type, env
)
9606 self
.operand2
= self
.operand2
.coerce_to(self
.type, env
)
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
)
9615 gil_message
= "Truth-testing Python object"
9617 def check_const(self
):
9618 return self
.operand1
.check_const() and self
.operand2
.check_const()
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':
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
)
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
,
9654 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
9656 self
.operand1
.py_result(),
9657 code
.error_goto_if_neg(test_result
, self
.pos
)))
9659 test_result
= self
.operand1
.result()
9660 return (test_result
, self
.type.is_pyobject
)
9663 class CondExprNode(ExprNode
):
9664 # Short-circuiting conditional expression.
9668 # false_val ExprNode
9673 subexprs
= ['test', 'true_val', 'false_val']
9675 def type_dependencies(self
, env
):
9676 return self
.true_val
.type_dependencies(env
) + self
.false_val
.type_dependencies(env
)
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
))
9683 def calculate_constant_result(self
):
9684 if self
.test
.constant_result
:
9685 self
.constant_result
= self
.true_val
.constant_result
9687 self
.constant_result
= self
.false_val
.constant_result
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
)
9694 return self
.analyse_result_type(env
)
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
:
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
)
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
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())
9725 def generate_evaluation_code(self
, code
):
9726 # Because subexprs may not be evaluated we can use a more optimal
9727 # subexpr allocation strategy than the default, so override evaluation_code.
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
)
9737 self
.test
.generate_disposal_code(code
)
9738 self
.test
.free_temps(code
)
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
)
9747 richcmp_constants
= {
9755 # the following are faked by special compare functions
9760 class CmpNode(object):
9761 # Mixin class containing code common to PrimaryCmpNodes
9762 # and CascadedCmpNodes.
9764 special_bool_cmp_function
= None
9765 special_bool_cmp_utility_code
= None
9767 def infer_type(self
, env
):
9768 # TODO: Actually implement this (after merging with -unstable).
9769 return py_object_type
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
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'
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'
9793 self
.constant_result
= func(operand1_result
, operand2_result
)
9795 def cascaded_compile_time_value(self
, operand1
, denv
):
9796 func
= get_compile_time_binop(self
)
9797 operand2
= self
.operand2
.compile_time_value(denv
)
9799 result
= func(operand1
, operand2
)
9800 except Exception, e
:
9801 self
.compile_time_value_error(e
)
9804 cascade
= self
.cascade
9806 result
= result
and cascade
.cascaded_compile_time_value(operand2
, denv
)
9809 def is_cpp_comparison(self
):
9810 return self
.operand1
.type.is_cpp_class
or self
.operand2
.type.is_cpp_class
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
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
9825 if type2_can_be_int
:
9828 if type1_can_be_int
:
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
9835 return PyrexTypes
.c_uchar_type
9839 def find_common_type(self
, env
, op
, operand1
, common_type
=None):
9840 operand2
= self
.operand2
9841 type1
= operand1
.type
9842 type2
= operand2
.type
9844 new_common_type
= None
9846 # catch general errors
9847 if type1
== str_type
and (type2
.is_string
or type2
in (bytes_type
, unicode_type
)) or \
9848 type2
== str_type
and (type1
.is_string
or type1
in (bytes_type
, unicode_type
)):
9849 error(self
.pos
, "Comparisons between bytes/unicode and str are not portable to Python 3")
9850 new_common_type
= error_type
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
9864 new_common_type
= PyrexTypes
.widest_numeric_type(type1
, type2
)
9865 elif type1
.is_numeric
and type2
.is_numeric
:
9866 new_common_type
= PyrexTypes
.widest_numeric_type(type1
, type2
)
9867 elif common_type
is None or not common_type
.is_pyobject
:
9868 new_common_type
= self
.find_common_int_type(env
, op
, operand1
, operand2
)
9870 if new_common_type
is None:
9871 # fall back to generic type compatibility tests
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
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
9884 new_common_type
= py_object_type
9885 elif py_object_type
.assignable_from(type1
) and py_object_type
.assignable_from(type2
):
9886 new_common_type
= py_object_type
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
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
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
9906 # recursively merge types
9907 if common_type
is None or new_common_type
.is_error
:
9908 common_type
= new_common_type
9910 # we could do a lot better by splitting the comparison
9911 # into a non-Python part and a Python part, but this is
9913 common_type
= PyrexTypes
.spanning_type(common_type
, new_common_type
)
9916 common_type
= self
.cascade
.find_common_type(env
, self
.operator
, operand2
, common_type
)
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))
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')))
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
)
9936 self
.cascade
.coerce_operands_to(dst_type
, env
)
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()))
9946 def is_c_string_contains(self
):
9947 return self
.operator
in ('in', 'not_in') and \
9948 ((self
.operand1
.type.is_int
9949 and (self
.operand2
.type.is_string
or self
.operand2
.type is bytes_type
)) or
9950 (self
.operand1
.type.is_unicode_char
9951 and self
.operand2
.type is unicode_type
))
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
9959 def find_special_bool_compare_function(self
, env
, operand1
, result_is_bool
=False):
9960 # note: currently operand1 must get coerced to a Python object if we succeed here!
9961 if self
.operator
in ('==', '!='):
9962 type1
, type2
= operand1
.type, self
.operand2
.type
9963 if result_is_bool
or (type1
.is_builtin_type
and type2
.is_builtin_type
):
9964 if type1
is Builtin
.unicode_type
or type2
is Builtin
.unicode_type
:
9965 self
.special_bool_cmp_utility_code
= UtilityCode
.load_cached("UnicodeEquals", "StringTools.c")
9966 self
.special_bool_cmp_function
= "__Pyx_PyUnicode_Equals"
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"
9972 elif type1
is Builtin
.basestring_type
or type2
is Builtin
.basestring_type
:
9973 self
.special_bool_cmp_utility_code
= UtilityCode
.load_cached("UnicodeEquals", "StringTools.c")
9974 self
.special_bool_cmp_function
= "__Pyx_PyUnicode_Equals"
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"
9980 elif self
.operator
in ('in', 'not_in'):
9981 if self
.operand2
.type is Builtin
.dict_type
:
9982 self
.operand2
= self
.operand2
.as_none_safe_node("'NoneType' object is not iterable")
9983 self
.special_bool_cmp_utility_code
= UtilityCode
.load_cached("PyDictContains", "ObjectHandling.c")
9984 self
.special_bool_cmp_function
= "__Pyx_PyDict_Contains"
9986 elif self
.operand2
.type is Builtin
.unicode_type
:
9987 self
.operand2
= self
.operand2
.as_none_safe_node("'NoneType' object is not iterable")
9988 self
.special_bool_cmp_utility_code
= UtilityCode
.load_cached("PyUnicodeContains", "StringTools.c")
9989 self
.special_bool_cmp_function
= "__Pyx_PyUnicode_Contains"
9992 if not self
.operand2
.type.is_pyobject
:
9993 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
9994 self
.special_bool_cmp_utility_code
= UtilityCode
.load_cached("PySequenceContains", "ObjectHandling.c")
9995 self
.special_bool_cmp_function
= "__Pyx_PySequence_Contains"
9999 def generate_operation_code(self
, code
, result_code
,
10000 operand1
, op
, operand2
):
10001 if self
.type.is_pyobject
:
10002 error_clause
= code
.error_goto_if_null
10003 got_ref
= "__Pyx_XGOTREF(%s); " % result_code
10004 if self
.special_bool_cmp_function
:
10005 code
.globalstate
.use_utility_code(
10006 UtilityCode
.load_cached("PyBoolOrNullFromLong", "ObjectHandling.c"))
10007 coerce_result
= "__Pyx_PyBoolOrNull_FromLong"
10009 coerce_result
= "__Pyx_PyBool_FromLong"
10011 error_clause
= code
.error_goto_if_neg
10015 if self
.special_bool_cmp_function
:
10016 if operand1
.type.is_pyobject
:
10017 result1
= operand1
.py_result()
10019 result1
= operand1
.result()
10020 if operand2
.type.is_pyobject
:
10021 result2
= operand2
.py_result()
10023 result2
= operand2
.result()
10024 if self
.special_bool_cmp_utility_code
:
10025 code
.globalstate
.use_utility_code(self
.special_bool_cmp_utility_code
)
10027 "%s = %s(%s(%s, %s, %s)); %s%s" % (
10030 self
.special_bool_cmp_function
,
10031 result1
, result2
, richcmp_constants
[op
],
10033 error_clause(result_code
, self
.pos
)))
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" % (
10039 operand1
.py_result(),
10040 operand2
.py_result(),
10041 richcmp_constants
[op
],
10043 error_clause(result_code
, self
.pos
)))
10045 elif operand1
.type.is_complex
:
10046 code
.putln("%s = %s(%s%s(%s, %s));" % (
10049 op
== "!=" and "!" or "",
10050 operand1
.type.unary_op('eq'),
10052 operand2
.result()))
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
)
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);" % (
10070 self
.c_operator(op
),
10073 def c_operator(self
, op
):
10076 elif op
== 'is_not':
10081 class PrimaryCmpNode(ExprNode
, CmpNode
):
10082 # Non-cascaded comparison or first comparison of
10083 # a cascaded sequence.
10086 # operand1 ExprNode
10087 # operand2 ExprNode
10088 # cascade CascadedCmpNode
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
10095 child_attrs
= ['operand1', 'operand2', 'coerced_operand2', 'cascade']
10098 coerced_operand2
= None
10099 is_memslice_nonecheck
= False
10101 def infer_type(self
, env
):
10102 # TODO: Actually implement this (after merging with -unstable).
10103 return py_object_type
10105 def type_dependencies(self
, env
):
10108 def calculate_constant_result(self
):
10109 assert not self
.cascade
10110 self
.calculate_cascaded_constant_result(self
.operand1
.constant_result
)
10112 def compile_time_value(self
, denv
):
10113 operand1
= self
.operand1
.compile_time_value(denv
)
10114 return self
.cascaded_compile_time_value(operand1
, denv
)
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
)
10122 error(self
.pos
, "Cascading comparison not yet supported for cpp types.")
10125 if self
.analyse_memoryviewslice_comparison(env
):
10129 self
.cascade
= self
.cascade
.analyse_types(env
)
10131 if self
.operator
in ('in', 'not_in'):
10132 if self
.is_c_string_contains():
10133 self
.is_pycmp
= False
10136 error(self
.pos
, "Cascading comparison not yet supported for 'int_val in string'.")
10138 if self
.operand2
.type is unicode_type
:
10139 env
.use_utility_code(UtilityCode
.load_cached("PyUCS4InUnicode", "StringTools.c"))
10141 if self
.operand1
.type is PyrexTypes
.c_uchar_type
:
10142 self
.operand1
= self
.operand1
.coerce_to(PyrexTypes
.c_char_type
, env
)
10143 if self
.operand2
.type is not bytes_type
:
10144 self
.operand2
= self
.operand2
.coerce_to(bytes_type
, env
)
10145 env
.use_utility_code(UtilityCode
.load_cached("BytesContains", "StringTools.c"))
10146 self
.operand2
= self
.operand2
.as_none_safe_node(
10147 "argument of type 'NoneType' is not iterable")
10148 elif self
.is_ptr_contains():
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
10154 elif self
.find_special_bool_compare_function(env
, self
.operand1
):
10155 if not self
.operand1
.type.is_pyobject
:
10156 self
.operand1
= self
.operand1
.coerce_to_pyobject(env
)
10157 common_type
= None # if coercion needed, the method call above has already done it
10158 self
.is_pycmp
= False # result is bint
10160 common_type
= py_object_type
10161 self
.is_pycmp
= True
10162 elif self
.find_special_bool_compare_function(env
, self
.operand1
):
10163 if not self
.operand1
.type.is_pyobject
:
10164 self
.operand1
= self
.operand1
.coerce_to_pyobject(env
)
10165 common_type
= None # if coercion needed, the method call above has already done it
10166 self
.is_pycmp
= False # result is bint
10168 common_type
= self
.find_common_type(env
, self
.operator
, self
.operand1
)
10169 self
.is_pycmp
= common_type
.is_pyobject
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
)
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
10185 self
.type = PyrexTypes
.c_bint_type
10188 cdr
.type = self
.type
10190 if self
.is_pycmp
or self
.cascade
or self
.special_bool_cmp_function
:
10191 # 1) owned reference, 2) reused value, 3) potential function error return value
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
])
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>"
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
)
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
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
10229 def coerce_to_boolean(self
, env
):
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
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
10243 # TODO: check if we can optimise parts of the cascade here
10244 return ExprNode
.coerce_to_boolean(self
, env
)
10246 def has_python_operands(self
):
10247 return (self
.operand1
.type.is_pyobject
10248 or self
.operand2
.type.is_pyobject
)
10250 def check_const(self
):
10255 return self
.operand1
.check_const() and self
.operand2
.check_const()
10257 def calculate_result_code(self
):
10258 if self
.operand1
.type.is_complex
:
10259 if self
.operator
== "!=":
10263 return "(%s%s(%s, %s))" % (
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"
10272 method
= "__Pyx_BytesContains"
10273 if self
.operator
== "not_in":
10277 return "(%s%s(%s, %s))" % (
10280 self
.operand2
.result(),
10281 self
.operand1
.result())
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
10289 result2
= "((PyObject *) %s.memview)" % result2
10291 return "(%s %s %s)" % (
10293 self
.c_operator(self
.operator
),
10296 def generate_evaluation_code(self
, code
):
10297 self
.operand1
.generate_evaluation_code(code
)
10298 self
.operand2
.generate_evaluation_code(code
)
10300 self
.allocate_temp_result(code
)
10301 self
.generate_operation_code(code
, self
.result(),
10302 self
.operand1
, self
.operator
, self
.operand2
)
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
)
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
)
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
)
10324 def annotate(self
, code
):
10325 self
.operand1
.annotate(code
)
10326 self
.operand2
.annotate(code
)
10328 self
.cascade
.annotate(code
)
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.
10338 # operand2 ExprNode
10339 # cascade CascadedCmpNode
10341 child_attrs
= ['operand2', 'coerced_operand2', 'cascade']
10344 coerced_operand2
= None
10345 constant_result
= constant_value_not_set
# FIXME: where to calculate this?
10347 def infer_type(self
, env
):
10348 # TODO: Actually implement this (after merging with -unstable).
10349 return py_object_type
10351 def type_dependencies(self
, env
):
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
10358 def analyse_types(self
, env
):
10359 self
.operand2
= self
.operand2
.analyse_types(env
)
10361 self
.cascade
= self
.cascade
.analyse_types(env
)
10364 def has_python_operands(self
):
10365 return self
.operand2
.type.is_pyobject
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
)
10374 operand2
= self
.cascade
.optimise_comparison(self
.operand2
, env
, result_is_bool
)
10375 if operand2
is not self
.operand2
:
10376 self
.coerced_operand2
= operand2
10379 def coerce_operands_to_pyobjects(self
, env
):
10380 self
.operand2
= self
.operand2
.coerce_to_pyobject(env
)
10381 if self
.operand2
.type is dict_type
and self
.operator
in ('in', 'not_in'):
10382 self
.operand2
= self
.operand2
.as_none_safe_node("'NoneType' object is not iterable")
10384 self
.cascade
.coerce_operands_to_pyobjects(env
)
10386 def coerce_cascaded_operands_to_temp(self
, env
):
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
)
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)
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
)
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
)
10415 def annotate(self
, code
):
10416 self
.operand2
.annotate(code
)
10418 self
.cascade
.annotate(code
)
10421 binop_node_classes
= {
10422 "or": BoolBinopNode
,
10423 "and": BoolBinopNode
,
10427 "<<": IntBinopNode
,
10428 ">>": IntBinopNode
,
10438 def binop_node(pos
, operator
, operand1
, operand2
, inplace
=False):
10439 # Construct binop node of appropriate class for
10441 return binop_node_classes
[operator
](pos
,
10442 operator
= operator
,
10443 operand1
= operand1
,
10444 operand2
= operand2
,
10447 #-------------------------------------------------------------------
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
10456 #-------------------------------------------------------------------
10458 class CoercionNode(ExprNode
):
10459 # Abstract base class for coercion nodes.
10461 # arg ExprNode node being coerced
10464 constant_result
= not_a_constant
10466 def __init__(self
, arg
):
10467 super(CoercionNode
, self
).__init
__(arg
.pos
)
10470 print("%s Coercing %s" % (self
, self
.arg
))
10472 def calculate_constant_result(self
):
10473 # constant folding can break type coercion, so this is disabled
10476 def annotate(self
, code
):
10477 self
.arg
.annotate(code
)
10478 if self
.arg
.type != self
.type:
10479 file, line
, col
= self
.pos
10480 code
.annotate((file, line
, col
-1), AnnotationItem(
10481 style
='coerce', tag
='coerce', text
='[%s] to [%s]' % (self
.arg
.type, self
.type)))
10483 class CoerceToMemViewSliceNode(CoercionNode
):
10485 Coerce an object to a memoryview slice. This holds a new reference in
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
10496 self
.use_managed_ref
= True
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()))
10505 error_cond
= self
.type.error_condition(self
.result())
10506 code
.putln(code
.error_goto_if(error_cond
, self
.pos
))
10509 class CastNode(CoercionNode
):
10510 # Wrap a node in a C type cast.
10512 def __init__(self
, arg
, new_type
):
10513 CoercionNode
.__init
__(self
, arg
)
10514 self
.type = new_type
10516 def may_be_none(self
):
10517 return self
.arg
.may_be_none()
10519 def calculate_result_code(self
):
10520 return self
.arg
.result_as(self
.type)
10522 def generate_result_code(self
, code
):
10523 self
.arg
.generate_result_code(code
)
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.
10531 exact_builtin_type
= True
10533 def __init__(self
, arg
, dst_type
, env
, notnone
=False):
10534 # The arg is know to be a Python object, and
10535 # the dst_type is known to be an extension type.
10536 assert dst_type
.is_extension_type
or dst_type
.is_builtin_type
, "PyTypeTest on non extension type"
10537 CoercionNode
.__init
__(self
, arg
)
10538 self
.type = dst_type
10539 self
.result_ctype
= arg
.ctype()
10540 self
.notnone
= notnone
10542 nogil_check
= Node
.gil_error
10543 gil_message
= "Python type test"
10545 def analyse_types(self
, env
):
10548 def may_be_none(self
):
10551 return self
.arg
.may_be_none()
10553 def is_simple(self
):
10554 return self
.arg
.is_simple()
10556 def result_in_temp(self
):
10557 return self
.arg
.result_in_temp()
10559 def is_ephemeral(self
):
10560 return self
.arg
.is_ephemeral()
10562 def nonlocally_immutable(self
):
10563 return self
.arg
.nonlocally_immutable()
10565 def calculate_constant_result(self
):
10569 def calculate_result_code(self
):
10570 return self
.arg
.result()
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
)
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
)))
10586 error(self
.pos
, "Cannot test type of extern C class "
10587 "without type object name specification")
10589 def generate_post_assignment_code(self
, code
):
10590 self
.arg
.generate_post_assignment_code(code
)
10592 def free_temps(self
, code
):
10593 self
.arg
.free_temps(code
)
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
10601 is_nonecheck
= True
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 ())
10612 nogil_check
= None # this node only guards an operation that would fail already
10614 def analyse_types(self
, env
):
10617 def may_be_none(self
):
10620 def is_simple(self
):
10621 return self
.arg
.is_simple()
10623 def result_in_temp(self
):
10624 return self
.arg
.result_in_temp()
10626 def nonlocally_immutable(self
):
10627 return self
.arg
.nonlocally_immutable()
10629 def calculate_result_code(self
):
10630 return self
.arg
.result()
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()
10638 raise Exception("unsupported type")
10640 def put_nonecheck(self
, code
):
10642 "if (unlikely(%s == Py_None)) {" % self
.condition())
10644 if self
.in_nogil_context
:
10645 code
.put_ensure_gil()
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
])))
10656 code
.putln('PyErr_SetString(%s, "%s");' % (
10657 self
.exception_type_cname
,
10658 escape(self
.exception_message
.encode('UTF-8'))))
10660 if self
.in_nogil_context
:
10661 code
.put_release_ensured_gil()
10663 code
.putln(code
.error_goto(self
.pos
))
10666 def generate_result_code(self
, code
):
10667 self
.put_nonecheck(code
)
10669 def generate_post_assignment_code(self
, code
):
10670 self
.arg
.generate_post_assignment_code(code
)
10672 def free_temps(self
, code
):
10673 self
.arg
.free_temps(code
)
10676 class CoerceToPyTypeNode(CoercionNode
):
10677 # This node is used to convert a C data type
10678 # to a Python object.
10680 type = py_object_type
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']):
10704 "default encoding required for conversion from '%s' to '%s'" %
10708 # FIXME: check that the target type and the resulting type are compatible
10711 if arg
.type.is_memoryviewslice
:
10712 # Register utility codes at this point
10713 arg
.type.get_to_py_function(env
, arg
)
10717 gil_message
= "Converting to Python object"
10719 def may_be_none(self
):
10720 # FIXME: is this always safe?
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
)
10729 return CoerceToBooleanNode(self
, env
)
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
:
10736 return self
.arg
.coerce_to(PyrexTypes
.c_long_type
, env
)
10738 def analyse_types(self
, env
):
10739 # The arg is always already analysed
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
)
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())
10755 code
.putln('%s = %s; %s' % (
10758 code
.error_goto_if_null(self
.result(), self
.pos
)))
10760 code
.put_gotref(self
.py_result())
10763 class CoerceIntToBytesNode(CoerceToPyTypeNode
):
10764 # This node is used to convert a C int type to a Python bytes
10769 def __init__(self
, arg
, env
):
10770 arg
= arg
.coerce_to_simple(env
)
10771 CoercionNode
.__init
__(self
, arg
)
10772 self
.type = Builtin
.bytes_type
10774 def generate_result_code(self
, code
):
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
))
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
)))
10790 if arg
.type is not PyrexTypes
.c_char_type
:
10791 temp
= code
.funcstate
.allocate_temp(PyrexTypes
.c_char_type
, manage_ref
=False)
10792 code
.putln("%s = (char)%s;" % (temp
, arg_result
))
10794 code
.putln('%s = PyBytes_FromStringAndSize(&%s, 1); %s' % (
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())
10803 class CoerceFromPyTypeNode(CoercionNode
):
10804 # This node is used to convert a Python object
10805 # to a C data type.
10807 def __init__(self
, result_type
, arg
, env
):
10808 CoercionNode
.__init
__(self
, arg
)
10809 self
.type = result_type
10811 if not result_type
.create_from_py_utility_code(env
):
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():
10817 "Obtaining '%s' from temporary Python value" % result_type
)
10818 elif self
.arg
.is_name
and self
.arg
.entry
and self
.arg
.entry
.is_pyglobal
:
10820 "Obtaining '%s' from externally modifiable global Python value" % result_type
,
10823 def analyse_types(self
, env
):
10824 # The arg is always already analysed
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' % (
10836 code
.error_goto_if(self
.type.error_condition(self
.result()), self
.pos
)))
10837 if self
.type.is_pyobject
:
10838 code
.put_gotref(self
.py_result())
10840 def nogil_check(self
, env
):
10841 error(self
.pos
, "Coercion from Python not allowed without the GIL")
10844 class CoerceToBooleanNode(CoercionNode
):
10845 # This node is used when a result needs to be used
10846 # in a boolean context.
10848 type = PyrexTypes
.c_bint_type
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',
10857 def __init__(self
, arg
, env
):
10858 CoercionNode
.__init
__(self
, arg
)
10859 if arg
.type.is_pyobject
:
10862 def nogil_check(self
, env
):
10863 if self
.arg
.type.is_pyobject
and self
._special
_builtins
.get(self
.arg
.type) is None:
10866 gil_message
= "Truth-testing Python object"
10868 def check_const(self
):
10872 return self
.arg
.check_const()
10874 def calculate_result_code(self
):
10875 return "(%s != 0)" % self
.arg
.result()
10877 def generate_result_code(self
, code
):
10878 if not self
.is_temp
:
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);" % (
10884 self
.arg
.py_result(),
10886 self
.arg
.py_result()))
10889 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
10891 self
.arg
.py_result(),
10892 code
.error_goto_if_neg(self
.result(), self
.pos
)))
10894 class CoerceToComplexNode(CoercionNode
):
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
)
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()
10908 real_part
= self
.arg
.result()
10910 return "%s(%s, %s)" % (
10911 self
.type.from_parts
,
10915 def generate_result_code(self
, code
):
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.
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
10928 if self
.type.is_pyobject
:
10929 self
.result_ctype
= py_object_type
10931 gil_message
= "Creating temporary Python reference"
10933 def analyse_types(self
, env
):
10934 # The arg is always already analysed
10937 def coerce_to_boolean(self
, env
):
10938 self
.arg
= self
.arg
.coerce_to_boolean(env
)
10939 if self
.arg
.is_simple():
10941 self
.type = self
.arg
.type
10942 self
.result_ctype
= self
.type
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
)
10957 class ProxyNode(CoercionNode
):
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
10962 MyNode -> ProxyNode -> ArgNode
10968 def __init__(self
, arg
):
10969 super(ProxyNode
, self
).__init
__(arg
)
10970 self
.constant_result
= arg
.constant_result
10973 def analyse_expressions(self
, env
):
10974 self
.arg
= self
.arg
.analyse_expressions(env
)
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
10985 def generate_result_code(self
, code
):
10986 self
.arg
.generate_result_code(code
)
10989 return self
.arg
.result()
10991 def is_simple(self
):
10992 return self
.arg
.is_simple()
10994 def may_be_none(self
):
10995 return self
.arg
.may_be_none()
10997 def generate_evaluation_code(self
, code
):
10998 self
.arg
.generate_evaluation_code(code
)
11000 def generate_result_code(self
, code
):
11001 self
.arg
.generate_result_code(code
)
11003 def generate_disposal_code(self
, code
):
11004 self
.arg
.generate_disposal_code(code
)
11006 def free_temps(self
, code
):
11007 self
.arg
.free_temps(code
)
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.
11017 subexprs
= [] # Arg is not considered a subexpr
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
11030 return self
.arg
.result()
11032 def may_be_none(self
):
11033 return self
.arg
.may_be_none()
11035 def type_dependencies(self
, env
):
11036 return self
.arg
.type_dependencies(env
)
11038 def infer_type(self
, env
):
11039 return self
.arg
.infer_type(env
)
11041 def analyse_types(self
, env
):
11042 self
.type = self
.arg
.type
11043 self
.result_ctype
= self
.arg
.result_ctype
11045 if hasattr(self
.arg
, 'entry'):
11046 self
.entry
= self
.arg
.entry
11049 def is_simple(self
):
11050 return True # result is always in a temp (or a name)
11052 def generate_evaluation_code(self
, code
):
11055 def generate_result_code(self
, code
):
11058 def generate_disposal_code(self
, code
):
11061 def free_temps(self
, code
):
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.
11071 def coerce_to(self
, dst_type
, env
):
11072 if dst_type
.is_builtin_type
and self
.type.subtype_of(dst_type
):
11074 return CloneNode
.coerce_to(self
, dst_type
, env
)
11077 class ModuleRefNode(ExprNode
):
11078 # Simple returns the module object
11080 type = py_object_type
11084 def analyse_types(self
, env
):
11087 def may_be_none(self
):
11090 def calculate_result_code(self
):
11091 return Naming
.module_cname
11093 def generate_result_code(self
, code
):
11096 class DocstringRefNode(ExprNode
):
11097 # Extracts the docstring of the body element
11099 subexprs
= ['body']
11100 type = py_object_type
11103 def __init__(self
, pos
, body
):
11104 ExprNode
.__init
__(self
, pos
)
11105 assert body
.type.is_pyobject
11108 def analyse_types(self
, env
):
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())
11120 #------------------------------------------------------------------------------------
11122 # Runtime support code
11124 #------------------------------------------------------------------------------------
11126 pyerr_occurred_withgil_utility_code
= UtilityCode(
11128 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
11131 static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
11134 PyGILState_STATE _save = PyGILState_Ensure();
11136 err = !!PyErr_Occurred();
11138 PyGILState_Release(_save);
11145 #------------------------------------------------------------------------------------
11147 raise_unbound_local_error_utility_code
= UtilityCode(
11149 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);
11152 static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) {
11153 PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname);
11157 raise_closure_name_error_utility_code
= UtilityCode(
11159 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);
11162 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
11163 PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname);
11167 # Don't inline the function, it should really never be called in production
11168 raise_unbound_memoryview_utility_code_nogil
= UtilityCode(
11170 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname);
11173 static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) {
11175 PyGILState_STATE gilstate = PyGILState_Ensure();
11177 __Pyx_RaiseUnboundLocalError(varname);
11179 PyGILState_Release(gilstate);
11183 requires
= [raise_unbound_local_error_utility_code
])
11185 #------------------------------------------------------------------------------------
11187 raise_too_many_values_to_unpack
= UtilityCode
.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c")
11188 raise_need_more_values_to_unpack
= UtilityCode
.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")
11189 tuple_unpacking_error_code
= UtilityCode
.load_cached("UnpackTupleError", "ObjectHandling.c")
11191 #------------------------------------------------------------------------------------
11193 int_pow_utility_code
= UtilityCode(
11195 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
11198 static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
11211 if (unlikely(e<0)) return 0;
11214 while (likely(e)) {
11215 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
11223 # ------------------------------ Division ------------------------------------
11225 div_int_utility_code
= UtilityCode(
11227 static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
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));
11238 mod_int_utility_code
= UtilityCode(
11240 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
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;
11250 mod_float_utility_code
= UtilityCode(
11252 static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
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;
11262 cdivision_warning_utility_code
= UtilityCode(
11264 static int __Pyx_cdivision_warning(const char *, int); /* proto */
11267 static int __Pyx_cdivision_warning(const char *filename, int lineno) {
11268 #if CYTHON_COMPILING_IN_PYPY
11269 filename++; // avoid compiler warnings
11271 return PyErr_Warn(PyExc_RuntimeWarning,
11272 "division with oppositely signed operands, C and Python semantics differ");
11274 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
11275 "division with oppositely signed operands, C and Python semantics differ",
11285 division_overflow_test_code
= UtilityCode(
11287 #define UNARY_NEG_WOULD_OVERFLOW(x) \
11288 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))