2 # Pyrex - Parse tree nodes for expressions
7 from Errors import error, warning, InternalError
8 from Errors import hold_errors, release_errors, held_errors, report_error
9 from Cython.Utils import UtilityCode
13 from Nodes import Node
15 from PyrexTypes import py_object_type, c_long_type, typecast, error_type
16 from Builtin import list_type, tuple_type, set_type, dict_type, unicode_type, bytes_type
20 from Annotate import AnnotationItem
22 from Cython.Debugging import print_call_chain
23 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
29 from sets import Set as set
31 class NotConstant(object): pass # just for the name
32 not_a_constant = NotConstant()
33 constant_value_not_set = object()
36 # subexprs [string] Class var holding names of subexpr node attrs
37 # type PyrexType Type of the result
38 # result_code string Code fragment
39 # result_ctype string C type of result_code if different from type
40 # is_temp boolean Result is in a temporary variable
41 # is_sequence_constructor
42 # boolean Is a list or tuple constructor expression
44 # [ExprNode or [ExprNode or None] or None]
45 # Cached result of subexpr_nodes()
50 # The Analyse Expressions phase for expressions is split
51 # into two sub-phases:
54 # Determines the result type of the expression based
55 # on the types of its sub-expressions, and inserts
56 # coercion nodes into the expression tree where needed.
57 # Marks nodes which will need to have temporary variables
61 # Allocates temporary variables where needed, and fills
62 # in the result_code field of each node.
64 # ExprNode provides some convenience routines which
65 # perform both of the above phases. These should only
66 # be called from statement nodes, and only when no
67 # coercion nodes need to be added around the expression
68 # being analysed. In that case, the above two phases
69 # should be invoked separately.
71 # Framework code in ExprNode provides much of the common
72 # processing for the various phases. It makes use of the
73 # 'subexprs' class attribute of ExprNodes, which should
74 # contain a list of the names of attributes which can
75 # hold sub-nodes or sequences of sub-nodes.
77 # The framework makes use of a number of abstract methods.
78 # Their responsibilities are as follows.
80 # Declaration Analysis phase
82 # analyse_target_declaration
83 # Called during the Analyse Declarations phase to analyse
84 # the LHS of an assignment or argument of a del statement.
85 # Nodes which cannot be the LHS of an assignment need not
88 # Expression Analysis phase
91 # - Call analyse_types on all sub-expressions.
92 # - Check operand types, and wrap coercion nodes around
93 # sub-expressions where needed.
94 # - Set the type of this node.
95 # - If a temporary variable will be required for the
96 # result, set the is_temp flag of this node.
98 # analyse_target_types
99 # Called during the Analyse Types phase to analyse
100 # the LHS of an assignment or argument of a del
101 # statement. Similar responsibilities to analyse_types.
104 # - Call allocate_temps for all sub-nodes.
105 # - Call allocate_temp for this node.
106 # - If a temporary was allocated, call release_temp on
107 # all sub-expressions.
109 # allocate_target_temps
110 # - Call allocate_temps on sub-nodes and allocate any other
111 # temps used during assignment.
112 # - Fill in result_code with a C lvalue if needed.
113 # - If a rhs node is supplied, call release_temp on it.
114 # - Call release_temp on sub-nodes and release any other
115 # temps used during assignment.
118 # Called by the default implementation of allocate_target_temps.
119 # Should return a C lvalue for assigning to the node. The default
120 # implementation calls calculate_result_code.
123 # - Check that this node and its subnodes form a
124 # legal constant expression. If so, do nothing,
125 # otherwise call not_const.
127 # The default implementation of check_const
128 # assumes that the expression is not constant.
131 # - Same as check_const, except check that the
132 # expression is a C lvalue whose address is
133 # constant. Otherwise, call addr_not_const.
135 # The default implementation of calc_const_addr
136 # assumes that the expression is not a constant
139 # Code Generation phase
141 # generate_evaluation_code
142 # - Call generate_evaluation_code for sub-expressions.
143 # - Perform the functions of generate_result_code
145 # - If result is temporary, call generate_disposal_code
146 # on all sub-expressions.
148 # A default implementation of generate_evaluation_code
149 # is provided which uses the following abstract methods:
151 # generate_result_code
152 # - Generate any C statements necessary to calculate
153 # the result of this node from the results of its
156 # calculate_result_code
157 # - Should return a C code fragment evaluating to the
158 # result. This is only called when the result is not
161 # generate_assignment_code
162 # Called on the LHS of an assignment.
163 # - Call generate_evaluation_code for sub-expressions.
164 # - Generate code to perform the assignment.
165 # - If the assignment absorbed a reference, call
166 # generate_post_assignment_code on the RHS,
167 # otherwise call generate_disposal_code on it.
169 # generate_deletion_code
170 # Called on an argument of a del statement.
171 # - Call generate_evaluation_code for sub-expressions.
172 # - Generate code to perform the deletion.
173 # - Call generate_disposal_code on all sub-expressions.
177 is_sequence_constructor = 0
180 saved_subexpr_nodes = None
184 constant_result = constant_value_not_set
187 _get_child_attrs = operator.attrgetter('subexprs')
188 except AttributeError:
190 def _get_child_attrs(self):
192 child_attrs = property(fget=_get_child_attrs)
194 def not_implemented(self, method_name):
195 print_call_chain(method_name, "not implemented") ###
197 "%s.%s not implemented" %
198 (self.__class__.__name__, method_name))
203 def is_ephemeral(self):
204 # An ephemeral node is one whose result is in
205 # a Python temporary and we suspect there are no
206 # other references to it. Certain operations are
207 # disallowed on such values, since they are
208 # likely to result in a dangling pointer.
209 return self.type.is_pyobject and self.is_temp
211 def subexpr_nodes(self):
212 # Extract a list of subexpression nodes based
213 # on the contents of the subexprs class attribute.
215 for name in self.subexprs:
216 item = getattr(self, name)
218 if type(item) is list:
225 if not self.is_temp or self.is_target:
226 return self.calculate_result_code()
227 else: # i.e. self.is_temp:
228 return self.result_code
230 def result_as(self, type = None):
231 # Return the result code cast to the specified C type.
232 return typecast(type, self.ctype(), self.result())
235 # Return the result code cast to PyObject *.
236 return self.result_as(py_object_type)
239 # Return the native C type of the result (i.e. the
240 # C type of the result_code expression).
241 return self.result_ctype or self.type
243 def calculate_constant_result(self):
244 # Calculate the constant result of this expression and store
245 # it in ``self.constant_result``. Does nothing by default,
246 # thus leaving ``self.constant_result`` unknown.
248 # This must only be called when it is assured that all
249 # sub-expressions have a valid constant_result value. The
250 # ConstantFolding transform will do this.
253 def compile_time_value(self, denv):
254 # Return value of compile-time expression, or report error.
255 error(self.pos, "Invalid compile-time expression")
257 def compile_time_value_error(self, e):
258 error(self.pos, "Error in compile-time expression: %s: %s" % (
259 e.__class__.__name__, e))
261 # ------------- Declaration Analysis ----------------
263 def analyse_target_declaration(self, env):
264 error(self.pos, "Cannot assign to or delete this")
266 # ------------- Expression Analysis ----------------
268 def analyse_const_expression(self, env):
269 # Called during the analyse_declarations phase of a
270 # constant expression. Analyses the expression's type,
271 # checks whether it is a legal const expression,
272 # and determines its value.
273 self.analyse_types(env)
274 self.allocate_temps(env)
277 def analyse_expressions(self, env):
278 # Convenience routine performing both the Type
279 # Analysis and Temp Allocation phases for a whole
281 self.analyse_types(env)
282 self.allocate_temps(env)
284 def analyse_target_expression(self, env, rhs):
285 # Convenience routine performing both the Type
286 # Analysis and Temp Allocation phases for the LHS of
288 self.analyse_target_types(env)
289 self.allocate_target_temps(env, rhs)
291 def analyse_boolean_expression(self, env):
292 # Analyse expression and coerce to a boolean.
293 self.analyse_types(env)
294 bool = self.coerce_to_boolean(env)
295 bool.allocate_temps(env)
298 def analyse_temp_boolean_expression(self, env):
299 # Analyse boolean expression and coerce result into
300 # a temporary. This is used when a branch is to be
301 # performed on the result and we won't have an
302 # opportunity to ensure disposal code is executed
303 # afterwards. By forcing the result into a temporary,
304 # we ensure that all disposal has been done by the
305 # time we get the result.
306 self.analyse_types(env)
307 bool = self.coerce_to_boolean(env)
308 temp_bool = bool.coerce_to_temp(env)
309 temp_bool.allocate_temps(env)
312 # --------------- Type Analysis ------------------
314 def analyse_as_module(self, env):
315 # If this node can be interpreted as a reference to a
316 # cimported module, return its scope, else None.
319 def analyse_as_type(self, env):
320 # If this node can be interpreted as a reference to a
321 # type, return that type, else None.
324 def analyse_as_extension_type(self, env):
325 # If this node can be interpreted as a reference to an
326 # extension type, return its type, else None.
329 def analyse_types(self, env):
330 self.not_implemented("analyse_types")
332 def analyse_target_types(self, env):
333 self.analyse_types(env)
335 def gil_assignment_check(self, env):
336 if env.nogil and self.type.is_pyobject:
337 error(self.pos, "Assignment of Python object not allowed without gil")
339 def check_const(self):
343 error(self.pos, "Not allowed in a constant expression")
345 def check_const_addr(self):
346 self.addr_not_const()
348 def addr_not_const(self):
349 error(self.pos, "Address is not constant")
351 def gil_check(self, env):
352 if env is not None and env.nogil and self.type.is_pyobject:
355 # ----------------- Result Allocation -----------------
357 def result_in_temp(self):
358 # Return true if result is in a temporary owned by
359 # this node or one of its subexpressions. Overridden
360 # by certain nodes which can share the result of
364 def allocate_target_temps(self, env, rhs):
365 # Perform temp allocation for the LHS of an assignment.
367 print("%s Allocating target temps" % self)
368 self.allocate_subexpr_temps(env)
369 self.is_target = True
371 rhs.release_temp(env)
372 self.release_subexpr_temps(env)
374 def allocate_temps(self, env, result = None):
375 # Allocate temporary variables for this node and
376 # all its sub-expressions. If a result is specified,
377 # this must be a temp node and the specified variable
378 # is used as the result instead of allocating a new
380 assert result is None, "deprecated, contact dagss if this triggers"
382 print("%s Allocating temps" % self)
383 self.allocate_subexpr_temps(env)
384 self.allocate_temp(env, result)
386 self.release_subexpr_temps(env)
388 def allocate_subexpr_temps(self, env):
389 # Allocate temporary variables for all sub-expressions
392 print("%s Allocating temps for: %s" % (self, self.subexprs))
393 for node in self.subexpr_nodes():
396 print("%s Allocating temps for %s" % (self, node))
397 node.allocate_temps(env)
399 def allocate_temp(self, env, result = None):
400 # If this node requires a temporary variable for its
401 # result, allocate one, otherwise set the result to
402 # a C code fragment. If a result is specified,
403 # this must be a temp node and the specified variable
404 # is used as the result instead of allocating a new
407 print("%s Allocating temp" % self)
410 raise InternalError("Result forced on non-temp node")
411 self.result_code = result
416 type = PyrexTypes.py_object_type
417 self.result_code = env.allocate_temp(type)
419 self.result_code = None
421 print("%s Allocated result %s" % (self, self.result_code))
423 def target_code(self):
424 # Return code fragment for use as LHS of a C assignment.
425 return self.calculate_result_code()
427 def calculate_result_code(self):
428 self.not_implemented("calculate_result_code")
430 # def release_target_temp(self, env):
431 # # Release temporaries used by LHS of an assignment.
432 # self.release_subexpr_temps(env)
434 def release_temp(self, env):
435 # If this node owns a temporary result, release it,
436 # otherwise release results of its sub-expressions.
439 print("%s Releasing result %s" % (self, self.result_code))
440 env.release_temp(self.result_code)
442 self.release_subexpr_temps(env)
444 def release_subexpr_temps(self, env):
445 # Release the results of all sub-expressions of
447 for node in self.subexpr_nodes():
449 node.release_temp(env)
451 # ---------------- Code Generation -----------------
453 def make_owned_reference(self, code):
454 # If result is a pyobject, make sure we own
456 if self.type.is_pyobject and not self.result_in_temp():
457 code.put_incref(self.result(), self.ctype())
459 def generate_evaluation_code(self, code):
460 code.mark_pos(self.pos)
461 # Generate code to evaluate this node and
462 # its sub-expressions, and dispose of any
463 # temporary results of its sub-expressions.
464 self.generate_subexpr_evaluation_code(code)
465 self.generate_result_code(code)
467 self.generate_subexpr_disposal_code(code)
468 self.free_subexpr_temps(code)
470 def generate_subexpr_evaluation_code(self, code):
471 for node in self.subexpr_nodes():
472 node.generate_evaluation_code(code)
474 def generate_result_code(self, code):
475 self.not_implemented("generate_result_code")
477 def generate_disposal_code(self, code):
478 # If necessary, generate code to dispose of
479 # temporary Python reference.
481 if self.type.is_pyobject:
482 code.put_decref_clear(self.result(), self.ctype())
484 self.generate_subexpr_disposal_code(code)
486 def generate_subexpr_disposal_code(self, code):
487 # Generate code to dispose of temporary results
488 # of all sub-expressions.
489 for node in self.subexpr_nodes():
490 node.generate_disposal_code(code)
492 def generate_post_assignment_code(self, code):
493 # Same as generate_disposal_code except that
494 # assignment will have absorbed a reference to
495 # the result if it is a Python object.
497 if self.type.is_pyobject:
498 code.putln("%s = 0;" % self.result())
500 self.generate_subexpr_disposal_code(code)
502 def generate_assignment_code(self, rhs, code):
503 # Stub method for nodes which are not legal as
504 # the LHS of an assignment. An error will have
505 # been reported earlier.
508 def generate_deletion_code(self, code):
509 # Stub method for nodes that are not legal as
510 # the argument of a del statement. An error
511 # will have been reported earlier.
514 def free_temps(self, code):
516 self.free_subexpr_temps(code)
517 # otherwise, already freed in generate_evaluation_code
519 def free_subexpr_temps(self, code):
520 for sub in self.subexpr_nodes():
523 # ---------------- Annotation ---------------------
525 def annotate(self, code):
526 for node in self.subexpr_nodes():
529 # ----------------- Coercion ----------------------
531 def coerce_to(self, dst_type, env):
532 # Coerce the result so that it can be assigned to
533 # something of type dst_type. If processing is necessary,
534 # wraps this node in a coercion node and returns that.
535 # Otherwise, returns this node unchanged.
537 # This method is called during the analyse_expressions
538 # phase of the src_node's processing.
541 src_is_py_type = src_type.is_pyobject
542 dst_is_py_type = dst_type.is_pyobject
544 if dst_type.is_pyobject:
545 if not src.type.is_pyobject:
546 src = CoerceToPyTypeNode(src, env)
547 if not src.type.subtype_of(dst_type):
548 if not isinstance(src, NoneNode):
549 src = PyTypeTestNode(src, dst_type, env)
550 elif src.type.is_pyobject:
551 src = CoerceFromPyTypeNode(dst_type, src, env)
552 elif (dst_type.is_complex
553 and src_type != dst_type
554 and dst_type.assignable_from(src_type)
555 and not env.directives['c99_complex']):
556 src = CoerceToComplexNode(src, dst_type, env)
557 else: # neither src nor dst are py types
558 # Added the string comparison, since for c types that
559 # is enough, but Cython gets confused when the types are
560 # in different pxi files.
561 if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
562 error(self.pos, "Cannot assign type '%s' to '%s'" %
563 (src.type, dst_type))
566 def coerce_to_pyobject(self, env):
567 return self.coerce_to(PyrexTypes.py_object_type, env)
569 def coerce_to_boolean(self, env):
570 # Coerce result to something acceptable as
573 if type.is_pyobject or type.is_ptr or type.is_float:
574 return CoerceToBooleanNode(self, env)
576 if not type.is_int and not type.is_error:
578 "Type '%s' not acceptable as a boolean" % type)
581 def coerce_to_integer(self, env):
582 # If not already some C integer type, coerce to longint.
586 return self.coerce_to(PyrexTypes.c_long_type, env)
588 def coerce_to_temp(self, env):
589 # Ensure that the result is in a temporary.
590 if self.result_in_temp():
593 return CoerceToTempNode(self, env)
595 def coerce_to_simple(self, env):
596 # Ensure that the result is simple (see is_simple).
600 return self.coerce_to_temp(env)
603 # A node is simple if its result is something that can
604 # be referred to without performing any operations, e.g.
605 # a constant, local var, C global var, struct member
606 # reference, or temporary.
607 return self.result_in_temp()
609 def as_cython_attribute(self):
613 class RemoveAllocateTemps(type):
614 def __init__(cls, name, bases, dct):
615 super(RemoveAllocateTemps, cls).__init__(name, bases, dct)
616 def noop(self, env): pass
617 setattr(cls, 'allocate_temps', noop)
618 setattr(cls, 'allocate_temp', noop)
619 setattr(cls, 'release_temp', noop)
621 class NewTempExprNode(ExprNode):
623 old_temp = None # error checker for multiple frees etc.
625 # Do not enable this unless you are trying to make all ExprNodes
626 # NewTempExprNodes (child nodes reached via recursion may not have
628 # __metaclass__ = RemoveAllocateTemps
632 return self.temp_code
634 return self.calculate_result_code()
636 def allocate_target_temps(self, env, rhs):
637 self.allocate_subexpr_temps(env)
638 self.is_target = True
640 rhs.release_temp(env)
641 self.release_subexpr_temps(env)
643 def allocate_temps(self, env, result = None):
644 assert result is None, "deprecated, contact dagss if this triggers"
645 self.allocate_subexpr_temps(env)
647 self.release_subexpr_temps(env)
649 def allocate_temp(self, env, result = None):
650 assert result is None
652 def release_temp(self, env):
656 self.release_subexpr_temps(env)
658 def allocate_temp_result(self, code):
660 raise RuntimeError("Temp allocated multiple times")
664 type = PyrexTypes.py_object_type
665 self.temp_code = code.funcstate.allocate_temp(
666 type, manage_ref=True)
668 self.temp_code = None
670 def release_temp_result(self, code):
671 if not self.temp_code:
673 raise RuntimeError("temp %s released multiple times in %s" % (
674 self.old_temp, self.__class__.__name__))
676 raise RuntimeError("no temp, but release requested in %s" % (
677 self.__class__.__name__))
678 code.funcstate.release_temp(self.temp_code)
679 self.old_temp = self.temp_code
680 self.temp_code = None
682 def generate_evaluation_code(self, code):
683 code.mark_pos(self.pos)
685 # Generate code to evaluate this node and
686 # its sub-expressions, and dispose of any
687 # temporary results of its sub-expressions.
688 self.generate_subexpr_evaluation_code(code)
691 self.allocate_temp_result(code)
693 self.generate_result_code(code)
695 # If we are temp we do not need to wait until this node is disposed
696 # before disposing children.
697 self.generate_subexpr_disposal_code(code)
698 self.free_subexpr_temps(code)
700 def generate_disposal_code(self, code):
702 if self.type.is_pyobject:
703 code.put_decref_clear(self.result(), self.ctype())
705 # Already done if self.is_temp
706 self.generate_subexpr_disposal_code(code)
708 def generate_post_assignment_code(self, code):
710 if self.type.is_pyobject:
711 code.putln("%s = 0;" % self.result())
713 self.generate_subexpr_disposal_code(code)
715 def free_temps(self, code):
717 if not self.type.is_void:
718 self.release_temp_result(code)
720 self.free_subexpr_temps(code)
722 # ExprNode = NewTempExprNode
724 class AtomicExprNode(ExprNode):
725 # Abstract base class for expression nodes which have
726 # no sub-expressions.
730 class AtomicNewTempExprNode(NewTempExprNode):
731 # I do not dare to convert NameNode yet. This is now
732 # ancestor of all former AtomicExprNode except
733 # NameNode. Should be renamed to AtomicExprNode
736 # Abstract base class for expression nodes which have
737 # no sub-expressions.
741 # Override to optimize -- we know we have no children
742 def generate_subexpr_evaluation_code(self, code):
744 def generate_subexpr_disposal_code(self, code):
747 class PyConstNode(AtomicNewTempExprNode):
748 # Abstract base class for constant Python values.
755 def analyse_types(self, env):
756 self.type = py_object_type
758 def calculate_result_code(self):
761 def generate_result_code(self, code):
765 class NoneNode(PyConstNode):
766 # The constant value None
770 constant_result = None
772 def compile_time_value(self, denv):
775 class EllipsisNode(PyConstNode):
776 # '...' in a subscript list.
778 value = "Py_Ellipsis"
780 constant_result = Ellipsis
782 def compile_time_value(self, denv):
786 class ConstNode(AtomicNewTempExprNode):
787 # Abstract base type for literal constant nodes.
789 # value string C code fragment
796 def analyse_types(self, env):
797 pass # Types are held in class variables
799 def check_const(self):
802 def calculate_result_code(self):
803 return str(self.value)
805 def generate_result_code(self, code):
809 class BoolNode(ConstNode):
810 type = PyrexTypes.c_bint_type
811 # The constant value True or False
813 def calculate_constant_result(self):
814 self.constant_result = self.value
816 def compile_time_value(self, denv):
819 def calculate_result_code(self):
820 return str(int(self.value))
822 class NullNode(ConstNode):
823 type = PyrexTypes.c_null_ptr_type
828 class CharNode(ConstNode):
829 type = PyrexTypes.c_char_type
831 def calculate_constant_result(self):
832 self.constant_result = ord(self.value)
834 def compile_time_value(self, denv):
835 return ord(self.value)
837 def calculate_result_code(self):
838 return "'%s'" % StringEncoding.escape_character(self.value)
841 class IntNode(ConstNode):
844 # longness "" or "L" or "LL"
848 type = PyrexTypes.c_long_type
850 def coerce_to(self, dst_type, env):
851 if dst_type.is_numeric and not dst_type.is_complex:
852 self.type = PyrexTypes.c_long_type
854 # Arrange for a Python version of the number to be pre-allocated
855 # when coercing to a Python type.
856 if dst_type.is_pyobject:
857 self.entry = env.get_py_num(self.value, self.longness)
858 self.type = PyrexTypes.py_object_type
859 # We still need to perform normal coerce_to processing on the
860 # result, because we might be coercing to an extension type,
861 # in which case a type test node will be needed.
862 return ConstNode.coerce_to(self, dst_type, env)
864 def coerce_to_boolean(self, env):
865 self.type = PyrexTypes.c_bint_type
868 def calculate_result_code(self):
869 if self.type.is_pyobject:
870 return self.entry.cname
872 return str(self.value) + self.unsigned + self.longness
874 def calculate_constant_result(self):
875 self.constant_result = int(self.value, 0)
877 def compile_time_value(self, denv):
878 return int(self.value, 0)
881 class FloatNode(ConstNode):
882 type = PyrexTypes.c_double_type
884 def calculate_constant_result(self):
885 # calculating float values is usually not a good idea
886 #self.constant_result = float(self.value)
889 def compile_time_value(self, denv):
890 return float(self.value)
892 def calculate_result_code(self):
893 strval = repr(float(self.value))
895 return "(Py_HUGE_VAL * 0)"
896 elif strval == 'inf':
898 elif strval == '-inf':
899 return "(-Py_HUGE_VAL)"
904 class StringNode(ConstNode):
907 type = PyrexTypes.c_char_ptr_type
909 def compile_time_value(self, denv):
912 def analyse_types(self, env):
913 self.entry = env.add_string_const(self.value)
915 def analyse_as_type(self, env):
916 type = PyrexTypes.parse_basic_type(self.value)
919 from TreeFragment import TreeFragment
920 pos = (self.pos[0], self.pos[1], self.pos[2]-7)
921 declaration = TreeFragment(u"sizeof(%s)" % self.value, name=pos[0].filename, initial_pos=pos)
922 sizeof_node = declaration.root.stats[0].expr
923 sizeof_node.analyse_types(env)
924 if isinstance(sizeof_node, SizeofTypeNode):
925 return sizeof_node.arg_type
927 def coerce_to(self, dst_type, env):
928 if dst_type == PyrexTypes.c_char_ptr_type:
929 self.type = PyrexTypes.c_char_ptr_type
933 if not self.type.is_pyobject and len(self.entry.init) == 1:
934 return CharNode(self.pos, value=self.value)
936 error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
938 # Arrange for a Python version of the string to be pre-allocated
939 # when coercing to a Python type.
940 if dst_type.is_pyobject and not self.type.is_pyobject:
941 node = self.as_py_string_node(env)
944 # We still need to perform normal coerce_to processing on the
945 # result, because we might be coercing to an extension type,
946 # in which case a type test node will be needed.
947 return ConstNode.coerce_to(node, dst_type, env)
949 def as_py_string_node(self, env):
950 # Return a new StringNode with the same entry as this node
951 # but whose type is a Python type instead of a C type.
953 env.add_py_string(entry)
954 return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
956 def calculate_result_code(self):
957 if self.type.is_pyobject:
958 return self.entry.pystring_cname
960 return self.entry.cname
963 class UnicodeNode(PyConstNode):
968 def analyse_types(self, env):
969 self.entry = env.add_string_const(self.value)
970 env.add_py_string(self.entry)
972 def calculate_result_code(self):
973 return self.entry.pystring_cname
975 def _coerce_to(self, dst_type, env):
976 if not dst_type.is_pyobject:
977 node = StringNode(self.pos, entry = entry, type = py_object_type)
978 return ConstNode.coerce_to(node, dst_type, env)
981 # We still need to perform normal coerce_to processing on the
982 # result, because we might be coercing to an extension type,
983 # in which case a type test node will be needed.
985 def compile_time_value(self, env):
989 class IdentifierStringNode(ConstNode):
990 # A Python string that behaves like an identifier, e.g. for
991 # keyword arguments in a call, or for imported names
992 type = PyrexTypes.py_object_type
994 def analyse_types(self, env):
995 self.cname = env.intern_identifier(self.value)
997 def calculate_result_code(self):
1001 class LongNode(AtomicNewTempExprNode):
1002 # Python long integer literal
1006 def calculate_constant_result(self):
1007 self.constant_result = long(self.value)
1009 def compile_time_value(self, denv):
1010 return long(self.value)
1012 gil_message = "Constructing Python long int"
1014 def analyse_types(self, env):
1015 self.type = py_object_type
1019 gil_message = "Constructing Python long int"
1021 def generate_result_code(self, code):
1023 '%s = PyLong_FromString((char *)"%s", 0, 0); %s' % (
1026 code.error_goto_if_null(self.result(), self.pos)))
1027 code.put_gotref(self.py_result())
1030 class ImagNode(AtomicNewTempExprNode):
1031 # Imaginary number literal
1033 # value float imaginary part
1035 type = PyrexTypes.c_double_complex_type
1037 def calculate_constant_result(self):
1038 self.constant_result = complex(0.0, self.value)
1040 def compile_time_value(self, denv):
1041 return complex(0.0, self.value)
1043 def analyse_types(self, env):
1044 self.type.create_declaration_utility_code(env)
1046 def coerce_to(self, dst_type, env):
1047 # Arrange for a Python version of the number to be pre-allocated
1048 # when coercing to a Python type.
1049 if dst_type.is_pyobject:
1051 self.type = PyrexTypes.py_object_type
1053 # We still need to perform normal coerce_to processing on the
1054 # result, because we might be coercing to an extension type,
1055 # in which case a type test node will be needed.
1056 return AtomicNewTempExprNode.coerce_to(self, dst_type, env)
1058 gil_message = "Constructing complex number"
1060 def calculate_result_code(self):
1061 if self.type.is_pyobject:
1062 return self.result()
1063 elif self.c99_complex:
1064 return "%rj" % float(self.value)
1066 return "%s(0, %r)" % (self.type.from_parts, float(self.value))
1068 def generate_result_code(self, code):
1069 if self.type.is_pyobject:
1071 "%s = PyComplex_FromDoubles(0.0, %r); %s" % (
1074 code.error_goto_if_null(self.result(), self.pos)))
1075 code.put_gotref(self.py_result())
1077 self.c99_complex = code.globalstate.directives['c99_complex']
1080 class NewExprNode(AtomicExprNode):
1084 # cppclass string c++ class to create
1085 # template_parameters None or [ExprNode] temlate parameters, if any
1087 def analyse_types(self, env):
1088 entry = env.lookup(self.cppclass)
1089 if entry is None or not entry.is_cpp_class:
1090 error(self.pos, "new operator can only be applied to a C++ class")
1093 if self.template_parameters is not None:
1094 template_types = [v.analyse_as_type(env) for v in self.template_parameters]
1095 type = entry.type.specialize_here(self.pos, template_types)
1098 constructor = type.scope.lookup(u'<init>')
1099 if constructor is None:
1100 return_type = PyrexTypes.CFuncType(type, [])
1101 return_type = PyrexTypes.CPtrType(return_type)
1102 type.scope.declare_cfunction(u'<init>', return_type, self.pos)
1103 constructor = type.scope.lookup(u'<init>')
1104 self.class_type = type
1105 self.entry = constructor
1106 self.type = constructor.type
1108 def generate_result_code(self, code):
1111 def calculate_result_code(self):
1112 return "new " + self.class_type.declaration_code("")
1115 class NameNode(AtomicExprNode):
1116 # Reference to a local or global variable name.
1118 # name string Python name of the variable
1120 # entry Entry Symbol table entry
1121 # interned_cname string
1124 is_cython_module = False
1125 cython_attribute = None
1126 lhs_of_first_assignment = False
1129 def create_analysed_rvalue(pos, env, entry):
1130 node = NameNode(pos)
1131 node.analyse_types(env, entry=entry)
1134 def as_cython_attribute(self):
1135 return self.cython_attribute
1137 create_analysed_rvalue = staticmethod(create_analysed_rvalue)
1139 def compile_time_value(self, denv):
1141 return denv.lookup(self.name)
1143 error(self.pos, "Compile-time name '%s' not defined" % self.name)
1145 def coerce_to(self, dst_type, env):
1146 # If coercing to a generic pyobject and this is a builtin
1147 # C function with a Python equivalent, manufacture a NameNode
1148 # referring to the Python builtin.
1149 #print "NameNode.coerce_to:", self.name, dst_type ###
1150 if dst_type is py_object_type:
1152 if entry and entry.is_cfunction:
1153 var_entry = entry.as_variable
1155 if var_entry.is_builtin and Options.cache_builtins:
1156 var_entry = env.declare_builtin(var_entry.name, self.pos)
1157 node = NameNode(self.pos, name = self.name)
1158 node.entry = var_entry
1159 node.analyse_rvalue_entry(env)
1161 return AtomicExprNode.coerce_to(self, dst_type, env)
1163 def analyse_as_module(self, env):
1164 # Try to interpret this as a reference to a cimported module.
1165 # Returns the module scope, or None.
1168 entry = env.lookup(self.name)
1169 if entry and entry.as_module:
1170 return entry.as_module
1173 def analyse_as_type(self, env):
1174 if self.cython_attribute:
1175 type = PyrexTypes.parse_basic_type(self.cython_attribute)
1177 type = PyrexTypes.parse_basic_type(self.name)
1182 entry = env.lookup(self.name)
1183 if entry and entry.is_type:
1188 def analyse_as_extension_type(self, env):
1189 # Try to interpret this as a reference to an extension type.
1190 # Returns the extension type, or None.
1193 entry = env.lookup(self.name)
1194 if entry and entry.is_type and entry.type.is_extension_type:
1199 def analyse_target_declaration(self, env):
1201 self.entry = env.lookup_here(self.name)
1203 self.entry = env.declare_var(self.name, py_object_type, self.pos)
1204 env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
1205 env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
1206 if self.entry.is_declared_generic:
1207 self.result_ctype = py_object_type
1209 def analyse_types(self, env):
1210 if self.entry is None:
1211 self.entry = env.lookup(self.name)
1213 self.entry = env.declare_builtin(self.name, self.pos)
1215 self.type = PyrexTypes.error_type
1217 self.analyse_rvalue_entry(env)
1219 def analyse_target_types(self, env):
1220 self.analyse_entry(env)
1221 if not self.is_lvalue():
1222 error(self.pos, "Assignment to non-lvalue '%s'"
1224 self.type = PyrexTypes.error_type
1226 if self.entry.type.is_buffer:
1228 Buffer.used_buffer_aux_vars(self.entry)
1230 def analyse_rvalue_entry(self, env):
1231 #print "NameNode.analyse_rvalue_entry:", self.name ###
1232 #print "Entry:", self.entry.__dict__ ###
1233 self.analyse_entry(env)
1235 if entry.is_declared_generic:
1236 self.result_ctype = py_object_type
1237 if entry.is_pyglobal or entry.is_builtin:
1238 if Options.cache_builtins and entry.is_builtin:
1242 env.use_utility_code(get_name_interned_utility_code)
1245 gil_message = "Accessing Python global or builtin"
1247 def analyse_entry(self, env):
1248 #print "NameNode.analyse_entry:", self.name ###
1249 self.check_identifier_kind()
1253 if entry.is_pyglobal or entry.is_builtin:
1254 assert type.is_pyobject, "Python global or builtin not a Python object"
1255 self.interned_cname = self.entry.interned_cname = \
1256 env.intern_identifier(self.entry.name)
1258 def check_identifier_kind(self):
1259 #print "NameNode.check_identifier_kind:", self.entry.name ###
1260 #print self.entry.__dict__ ###
1263 if not (entry.is_const or entry.is_variable
1264 or entry.is_builtin or entry.is_cfunction
1265 or entry.is_cpp_class):
1266 if self.entry.as_variable:
1267 self.entry = self.entry.as_variable
1270 "'%s' is not a constant, variable or function identifier" % self.name)
1272 def is_simple(self):
1273 # If it's not a C variable, it'll be in a temp.
1276 def calculate_target_results(self, env):
1279 def check_const(self):
1281 if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
1284 def check_const_addr(self):
1286 if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
1287 self.addr_not_const()
1289 def is_lvalue(self):
1290 return self.entry.is_variable and \
1291 not self.entry.type.is_array and \
1292 not self.entry.is_readonly
1294 def is_ephemeral(self):
1295 # Name nodes are never ephemeral, even if the
1296 # result is in a temporary.
1299 def allocate_temp(self, env, result = None):
1300 AtomicExprNode.allocate_temp(self, env, result)
1304 if entry.type.is_buffer:
1306 Buffer.used_buffer_aux_vars(entry)
1307 if entry.utility_code:
1308 env.use_utility_code(entry.utility_code)
1310 def calculate_result_code(self):
1313 return "<error>" # There was an error earlier
1316 def generate_result_code(self, code):
1317 assert hasattr(self, 'entry')
1320 return # There was an error earlier
1321 if entry.is_builtin and Options.cache_builtins:
1322 return # Lookup already cached
1323 elif entry.is_pyglobal or entry.is_builtin:
1324 if entry.is_builtin:
1325 namespace = Naming.builtins_cname
1326 else: # entry.is_pyglobal
1327 namespace = entry.scope.namespace_cname
1329 '%s = __Pyx_GetName(%s, %s); %s' % (
1332 self.interned_cname,
1333 code.error_goto_if_null(self.result(), self.pos)))
1334 code.put_gotref(self.py_result())
1336 elif entry.is_local and False:
1337 # control flow not good enough yet
1338 assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1339 if assigned is False:
1340 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
1341 elif not Options.init_local_none and assigned is None:
1342 code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
1343 (entry.cname, entry.name, code.error_goto(self.pos)))
1344 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
1346 def generate_assignment_code(self, rhs, code):
1347 #print "NameNode.generate_assignment_code:", self.name ###
1350 return # There was an error earlier
1352 if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
1353 and not self.lhs_of_first_assignment):
1354 error(self.pos, "Literal list must be assigned to pointer at time of declaration")
1356 # is_pyglobal seems to be True for module level-globals only.
1357 # We use this to access class->tp_dict if necessary.
1358 if entry.is_pyglobal:
1359 namespace = self.entry.scope.namespace_cname
1361 # if the entry is a member we have to cheat: SetAttr does not work
1362 # on types, so we create a descriptor which is then added to tp_dict
1363 code.put_error_if_neg(self.pos,
1364 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
1366 self.interned_cname,
1368 rhs.generate_disposal_code(code)
1369 rhs.free_temps(code)
1370 # in Py2.6+, we need to invalidate the method cache
1371 code.putln("PyType_Modified(%s);" %
1372 entry.scope.parent_type.typeptr_cname)
1374 code.put_error_if_neg(self.pos,
1375 'PyObject_SetAttr(%s, %s, %s)' % (
1377 self.interned_cname,
1379 if debug_disposal_code:
1380 print("NameNode.generate_assignment_code:")
1381 print("...generating disposal code for %s" % rhs)
1382 rhs.generate_disposal_code(code)
1383 rhs.free_temps(code)
1385 if self.type.is_buffer:
1386 # Generate code for doing the buffer release/acquisition.
1387 # This might raise an exception in which case the assignment (done
1388 # below) will not happen.
1390 # The reason this is not in a typetest-like node is because the
1391 # variables that the acquired buffer info is stored to is allocated
1392 # per entry and coupled with it.
1393 self.generate_acquire_buffer(rhs, code)
1395 if self.type.is_pyobject:
1396 rhs.make_owned_reference(code)
1397 #print "NameNode.generate_assignment_code: to", self.name ###
1398 #print "...from", rhs ###
1399 #print "...LHS type", self.type, "ctype", self.ctype() ###
1400 #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
1401 if entry.is_cglobal:
1402 code.put_gotref(self.py_result())
1403 if not self.lhs_of_first_assignment:
1404 if entry.is_local and not Options.init_local_none:
1405 initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
1406 if initalized is True:
1407 code.put_decref(self.result(), self.ctype())
1408 elif initalized is None:
1409 code.put_xdecref(self.result(), self.ctype())
1411 code.put_decref(self.result(), self.ctype())
1412 if entry.is_cglobal:
1413 code.put_giveref(rhs.py_result())
1414 code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
1415 if debug_disposal_code:
1416 print("NameNode.generate_assignment_code:")
1417 print("...generating post-assignment code for %s" % rhs)
1418 rhs.generate_post_assignment_code(code)
1419 rhs.free_temps(code)
1421 def generate_acquire_buffer(self, rhs, code):
1422 # rhstmp is only used in case the rhs is a complicated expression leading to
1423 # the object, to avoid repeating the same C expression for every reference
1424 # to the rhs. It does NOT hold a reference.
1425 pretty_rhs = isinstance(rhs, NameNode) or rhs.is_temp
1427 rhstmp = rhs.result_as(self.ctype())
1429 rhstmp = code.funcstate.allocate_temp(self.entry.type, manage_ref=False)
1430 code.putln('%s = %s;' % (rhstmp, rhs.result_as(self.ctype())))
1432 buffer_aux = self.entry.buffer_aux
1433 bufstruct = buffer_aux.buffer_info_var.cname
1435 Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
1436 is_initialized=not self.lhs_of_first_assignment,
1437 pos=self.pos, code=code)
1440 code.putln("%s = 0;" % rhstmp)
1441 code.funcstate.release_temp(rhstmp)
1443 def generate_deletion_code(self, code):
1444 if self.entry is None:
1445 return # There was an error earlier
1446 if not self.entry.is_pyglobal:
1447 error(self.pos, "Deletion of local or C global name not supported")
1449 code.put_error_if_neg(self.pos,
1450 '__Pyx_DelAttrString(%s, "%s")' % (
1451 Naming.module_cname,
1454 def annotate(self, code):
1455 if hasattr(self, 'is_called') and self.is_called:
1456 pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
1457 if self.type.is_pyobject:
1458 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
1460 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
1462 class BackquoteNode(ExprNode):
1469 def analyse_types(self, env):
1470 self.arg.analyse_types(env)
1471 self.arg = self.arg.coerce_to_pyobject(env)
1472 self.type = py_object_type
1476 gil_message = "Backquote expression"
1478 def calculate_constant_result(self):
1479 self.constant_result = repr(self.arg.constant_result)
1481 def generate_result_code(self, code):
1483 "%s = PyObject_Repr(%s); %s" % (
1485 self.arg.py_result(),
1486 code.error_goto_if_null(self.result(), self.pos)))
1487 code.put_gotref(self.py_result())
1491 class ImportNode(ExprNode):
1492 # Used as part of import statement implementation.
1493 # Implements result =
1494 # __import__(module_name, globals(), None, name_list)
1496 # module_name IdentifierStringNode dotted name of module
1497 # name_list ListNode or None list of names to be imported
1499 subexprs = ['module_name', 'name_list']
1501 def analyse_types(self, env):
1502 self.module_name.analyse_types(env)
1503 self.module_name = self.module_name.coerce_to_pyobject(env)
1505 self.name_list.analyse_types(env)
1506 self.name_list.coerce_to_pyobject(env)
1507 self.type = py_object_type
1510 env.use_utility_code(import_utility_code)
1512 gil_message = "Python import"
1514 def generate_result_code(self, code):
1516 name_list_code = self.name_list.py_result()
1518 name_list_code = "0"
1520 "%s = __Pyx_Import(%s, %s); %s" % (
1522 self.module_name.py_result(),
1524 code.error_goto_if_null(self.result(), self.pos)))
1525 code.put_gotref(self.py_result())
1528 class IteratorNode(NewTempExprNode):
1529 # Used as part of for statement implementation.
1531 # allocate_counter_temp/release_counter_temp needs to be called
1532 # by parent (ForInStatNode)
1534 # Implements result = iter(sequence)
1538 subexprs = ['sequence']
1540 def analyse_types(self, env):
1541 self.sequence.analyse_types(env)
1542 self.sequence = self.sequence.coerce_to_pyobject(env)
1543 self.type = py_object_type
1547 gil_message = "Iterating over Python object"
1549 def allocate_counter_temp(self, code):
1550 self.counter_cname = code.funcstate.allocate_temp(
1551 PyrexTypes.c_py_ssize_t_type, manage_ref=False)
1553 def release_counter_temp(self, code):
1554 code.funcstate.release_temp(self.counter_cname)
1556 def generate_result_code(self, code):
1557 is_builtin_sequence = self.sequence.type is list_type or \
1558 self.sequence.type is tuple_type
1559 if is_builtin_sequence:
1561 "if (likely(%s != Py_None)) {" % self.sequence.py_result())
1564 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
1565 self.sequence.py_result(),
1566 self.sequence.py_result()))
1568 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
1571 self.sequence.py_result(),
1573 code.putln("} else {")
1574 if is_builtin_sequence:
1576 'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
1577 code.error_goto(self.pos))
1579 code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
1582 self.sequence.py_result(),
1583 code.error_goto_if_null(self.result(), self.pos)))
1584 code.put_gotref(self.py_result())
1588 class NextNode(AtomicNewTempExprNode):
1589 # Used as part of for statement implementation.
1590 # Implements result = iterator.next()
1591 # Created during analyse_types phase.
1592 # The iterator is not owned by this node.
1596 def __init__(self, iterator, env):
1597 self.pos = iterator.pos
1598 self.iterator = iterator
1599 self.type = py_object_type
1602 def generate_result_code(self, code):
1603 if self.iterator.sequence.type is list_type:
1604 type_checks = [(list_type, "List")]
1605 elif self.iterator.sequence.type is tuple_type:
1606 type_checks = [(tuple_type, "Tuple")]
1608 type_checks = [(list_type, "List"), (tuple_type, "Tuple")]
1610 for py_type, prefix in type_checks:
1611 if len(type_checks) > 1:
1613 "if (likely(Py%s_CheckExact(%s))) {" % (
1614 prefix, self.iterator.py_result()))
1616 "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
1617 self.iterator.counter_cname,
1619 self.iterator.py_result()))
1621 "%s = Py%s_GET_ITEM(%s, %s); __Pyx_INCREF(%s); %s++;" % (
1624 self.iterator.py_result(),
1625 self.iterator.counter_cname,
1627 self.iterator.counter_cname))
1628 if len(type_checks) > 1:
1630 if len(type_checks) == 1:
1634 "%s = PyIter_Next(%s);" % (
1636 self.iterator.py_result()))
1640 code.putln(code.error_goto_if_PyErr(self.pos))
1641 code.putln("break;")
1643 code.put_gotref(self.py_result())
1647 class ExcValueNode(AtomicNewTempExprNode):
1648 # Node created during analyse_types phase
1649 # of an ExceptClauseNode to fetch the current
1652 def __init__(self, pos, env, var):
1653 ExprNode.__init__(self, pos)
1654 self.type = py_object_type
1657 def calculate_result_code(self):
1660 def generate_result_code(self, code):
1663 def analyse_types(self, env):
1667 class TempNode(ExprNode):
1668 # Node created during analyse_types phase
1669 # of some nodes to hold a temporary value.
1673 def __init__(self, pos, type, env):
1674 ExprNode.__init__(self, pos)
1676 if type.is_pyobject:
1677 self.result_ctype = py_object_type
1680 def analyse_types(self, env):
1683 def generate_result_code(self, code):
1687 class PyTempNode(TempNode):
1688 # TempNode holding a Python value.
1690 def __init__(self, pos, env):
1691 TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
1694 #-------------------------------------------------------------------
1698 #-------------------------------------------------------------------
1700 class IndexNode(ExprNode):
1701 # Sequence indexing.
1705 # indices [ExprNode]
1706 # is_buffer_access boolean Whether this is a buffer access.
1708 # indices is used on buffer access, index on non-buffer access.
1709 # The former contains a clean list of index parameters, the
1710 # latter whatever Python object is needed for index access.
1712 subexprs = ['base', 'index', 'indices']
1715 def __init__(self, pos, index, *args, **kw):
1716 ExprNode.__init__(self, pos, index=index, *args, **kw)
1719 def calculate_constant_result(self):
1720 self.constant_result = \
1721 self.base.constant_result[self.index.constant_result]
1723 def compile_time_value(self, denv):
1724 base = self.base.compile_time_value(denv)
1725 index = self.index.compile_time_value(denv)
1728 except Exception, e:
1729 self.compile_time_value_error(e)
1731 def is_ephemeral(self):
1732 return self.base.is_ephemeral()
1734 def analyse_target_declaration(self, env):
1737 def analyse_as_type(self, env):
1738 base_type = self.base.analyse_as_type(env)
1739 if base_type and not base_type.is_pyobject:
1740 if base_type.is_cpp_class:
1741 if isinstance(self.index, TupleExprNode):
1742 template_values = self.index.args
1744 template_values = [self.index]
1746 type_node = Nodes.TemplatedTypeNode(
1748 positional_args = template_values,
1749 keyword_args = None)
1750 return type_node.analyse(env, base_type = base_type)
1752 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
1755 def analyse_types(self, env):
1756 self.analyse_base_and_index_types(env, getting = 1)
1758 def analyse_target_types(self, env):
1759 self.analyse_base_and_index_types(env, setting = 1)
1761 def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
1762 # Note: This might be cleaned up by having IndexNode
1763 # parsed in a saner way and only construct the tuple if
1766 # Note that this function must leave IndexNode in a cloneable state.
1767 # For buffers, self.index is packed out on the initial analysis, and
1768 # when cloning self.indices is copied.
1769 self.is_buffer_access = False
1771 self.base.analyse_types(env)
1772 # Handle the case where base is a literal char* (and we expect a string, not an int)
1773 if isinstance(self.base, StringNode):
1774 self.base = self.base.coerce_to_pyobject(env)
1776 skip_child_analysis = False
1777 buffer_access = False
1778 if self.base.type.is_buffer:
1779 assert hasattr(self.base, "entry") # Must be a NameNode-like node
1781 indices = self.indices
1783 if isinstance(self.index, TupleNode):
1784 indices = self.index.args
1786 indices = [self.index]
1787 if len(indices) == self.base.type.ndim:
1788 buffer_access = True
1789 skip_child_analysis = True
1791 x.analyse_types(env)
1792 if not x.type.is_int:
1793 buffer_access = False
1795 # On cloning, indices is cloned. Otherwise, unpack index into indices
1796 assert not (buffer_access and isinstance(self.index, CloneNode))
1799 self.indices = indices
1801 self.type = self.base.type.dtype
1802 self.is_buffer_access = True
1803 self.buffer_type = self.base.entry.type
1805 if getting and self.type.is_pyobject:
1808 if not self.base.entry.type.writable:
1809 error(self.pos, "Writing to readonly buffer")
1811 self.base.entry.buffer_aux.writable_needed = True
1813 if isinstance(self.index, TupleNode):
1814 self.index.analyse_types(env, skip_children=skip_child_analysis)
1815 elif not skip_child_analysis:
1816 self.index.analyse_types(env)
1817 self.original_index_type = self.index.type
1818 if self.base.type.is_pyobject:
1819 if self.index.type.is_int:
1820 self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
1822 self.index = self.index.coerce_to_pyobject(env)
1823 self.type = py_object_type
1826 if self.base.type.is_ptr or self.base.type.is_array:
1827 self.type = self.base.type.base_type
1830 "Attempting to index non-array type '%s'" %
1832 self.type = PyrexTypes.error_type
1833 if self.index.type.is_pyobject:
1834 self.index = self.index.coerce_to(
1835 PyrexTypes.c_py_ssize_t_type, env)
1836 if not self.index.type.is_int:
1838 "Invalid index type '%s'" %
1842 gil_message = "Indexing Python object"
1844 def gil_check(self, env):
1845 if self.is_buffer_access and env.nogil:
1846 if env.directives['boundscheck']:
1847 error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive")
1849 elif self.type.is_pyobject:
1850 error(self.pos, "Cannot access buffer with object dtype without gil")
1852 super(IndexNode, self).gil_check(env)
1855 def check_const_addr(self):
1856 self.base.check_const_addr()
1857 self.index.check_const()
1859 def is_lvalue(self):
1862 def calculate_result_code(self):
1863 if self.is_buffer_access:
1864 return "(*%s)" % self.buffer_ptr_code
1866 return "(%s[%s])" % (
1867 self.base.result(), self.index.result())
1869 def extra_index_params(self):
1870 if self.index.type.is_int:
1871 if self.original_index_type.signed:
1872 size_adjustment = ""
1874 size_adjustment = "+1"
1875 return ", sizeof(%s)%s, %s" % (self.original_index_type.declaration_code(""), size_adjustment, self.original_index_type.to_py_function)
1879 def generate_subexpr_evaluation_code(self, code):
1880 self.base.generate_evaluation_code(code)
1881 if not self.indices:
1882 self.index.generate_evaluation_code(code)
1884 for i in self.indices:
1885 i.generate_evaluation_code(code)
1887 def generate_subexpr_disposal_code(self, code):
1888 self.base.generate_disposal_code(code)
1889 if not self.indices:
1890 self.index.generate_disposal_code(code)
1892 for i in self.indices:
1893 i.generate_disposal_code(code)
1895 def free_subexpr_temps(self, code):
1896 self.base.free_temps(code)
1897 if not self.indices:
1898 self.index.free_temps(code)
1900 for i in self.indices:
1903 def generate_result_code(self, code):
1904 if self.is_buffer_access:
1905 if code.globalstate.directives['nonecheck']:
1906 self.put_nonecheck(code)
1907 self.buffer_ptr_code = self.buffer_lookup_code(code)
1908 if self.type.is_pyobject:
1909 # is_temp is True, so must pull out value and incref it.
1910 code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
1911 code.putln("__Pyx_INCREF((PyObject*)%s);" % self.result())
1912 elif self.type.is_pyobject:
1913 if self.index.type.is_int:
1914 index_code = self.index.result()
1915 if self.base.type is list_type:
1916 function = "__Pyx_GetItemInt_List"
1917 elif self.base.type is tuple_type:
1918 function = "__Pyx_GetItemInt_Tuple"
1920 function = "__Pyx_GetItemInt"
1921 code.globalstate.use_utility_code(getitem_int_utility_code)
1923 function = "PyObject_GetItem"
1924 index_code = self.index.py_result()
1927 "%s = %s(%s, %s%s); if (!%s) %s" % (
1930 self.base.py_result(),
1932 self.extra_index_params(),
1934 code.error_goto(self.pos)))
1935 code.put_gotref(self.py_result())
1937 def generate_setitem_code(self, value_code, code):
1938 if self.index.type.is_int:
1939 function = "__Pyx_SetItemInt"
1940 index_code = self.index.result()
1941 code.globalstate.use_utility_code(setitem_int_utility_code)
1943 index_code = self.index.py_result()
1944 if self.base.type is dict_type:
1945 function = "PyDict_SetItem"
1946 # It would seem that we could specalized lists/tuples, but that
1947 # shouldn't happen here.
1948 # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
1949 # not a PyObject*, and bad conversion here would give the wrong
1950 # exception. Also, tuples are supposed to be immutable, and raise
1951 # TypeErrors when trying to set their entries (PyTuple_SetItem
1952 # is for creating new tuples from).
1954 function = "PyObject_SetItem"
1956 "if (%s(%s, %s, %s%s) < 0) %s" % (
1958 self.base.py_result(),
1961 self.extra_index_params(),
1962 code.error_goto(self.pos)))
1964 def generate_buffer_setitem_code(self, rhs, code, op=""):
1965 # Used from generate_assignment_code and InPlaceAssignmentNode
1966 if code.globalstate.directives['nonecheck']:
1967 self.put_nonecheck(code)
1968 ptrexpr = self.buffer_lookup_code(code)
1969 if self.buffer_type.dtype.is_pyobject:
1970 # Must manage refcounts. Decref what is already there
1971 # and incref what we put in.
1972 ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
1973 rhs_code = rhs.result()
1974 code.putln("%s = %s;" % (ptr, ptrexpr))
1975 code.put_gotref("*%s" % ptr)
1976 code.putln("__Pyx_DECREF(*%s); __Pyx_INCREF(%s);" % (
1979 code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
1980 code.put_giveref("*%s" % ptr)
1981 code.funcstate.release_temp(ptr)
1984 code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
1986 def generate_assignment_code(self, rhs, code):
1987 self.generate_subexpr_evaluation_code(code)
1988 if self.is_buffer_access:
1989 self.generate_buffer_setitem_code(rhs, code)
1990 elif self.type.is_pyobject:
1991 self.generate_setitem_code(rhs.py_result(), code)
1995 self.result(), rhs.result()))
1996 self.generate_subexpr_disposal_code(code)
1997 self.free_subexpr_temps(code)
1998 rhs.generate_disposal_code(code)
1999 rhs.free_temps(code)
2001 def generate_deletion_code(self, code):
2002 self.generate_subexpr_evaluation_code(code)
2003 #if self.type.is_pyobject:
2004 if self.index.type.is_int:
2005 function = "__Pyx_DelItemInt"
2006 index_code = self.index.result()
2007 code.globalstate.use_utility_code(delitem_int_utility_code)
2009 index_code = self.index.py_result()
2010 if self.base.type is dict_type:
2011 function = "PyDict_DelItem"
2013 function = "PyObject_DelItem"
2015 "if (%s(%s, %s%s) < 0) %s" % (
2017 self.base.py_result(),
2019 self.extra_index_params(),
2020 code.error_goto(self.pos)))
2021 self.generate_subexpr_disposal_code(code)
2022 self.free_subexpr_temps(code)
2024 def buffer_lookup_code(self, code):
2025 # Assign indices to temps
2026 index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
2027 for temp, index in zip(index_temps, self.indices):
2028 code.putln("%s = %s;" % (temp, index.result()))
2029 # Generate buffer access code using these temps
2031 # The above could happen because child_attrs is wrong somewhere so that
2032 # options are not propagated.
2033 return Buffer.put_buffer_lookup_code(entry=self.base.entry,
2034 index_signeds=[i.type.signed for i in self.indices],
2035 index_cnames=index_temps,
2036 directives=code.globalstate.directives,
2037 pos=self.pos, code=code)
2039 def put_nonecheck(self, code):
2040 code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
2041 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.base.result_as(PyrexTypes.py_object_type))
2042 code.putln("__Pyx_RaiseNoneIndexingError();")
2043 code.putln(code.error_goto(self.pos))
2046 class SliceIndexNode(ExprNode):
2047 # 2-element slice indexing
2050 # start ExprNode or None
2051 # stop ExprNode or None
2053 subexprs = ['base', 'start', 'stop']
2055 def calculate_constant_result(self):
2056 self.constant_result = self.base.constant_result[
2057 self.start.constant_result : self.stop.constant_result]
2059 def compile_time_value(self, denv):
2060 base = self.base.compile_time_value(denv)
2061 if self.start is None:
2064 start = self.start.compile_time_value(denv)
2065 if self.stop is None:
2068 stop = self.stop.compile_time_value(denv)
2070 return base[start:stop]
2071 except Exception, e:
2072 self.compile_time_value_error(e)
2074 def analyse_target_declaration(self, env):
2077 def analyse_target_types(self, env):
2078 self.analyse_types(env)
2079 # when assigning, we must accept any Python type
2080 if self.type.is_pyobject:
2081 self.type = py_object_type
2083 def analyse_types(self, env):
2084 self.base.analyse_types(env)
2086 self.start.analyse_types(env)
2088 self.stop.analyse_types(env)
2089 base_type = self.base.type
2090 if base_type.is_string:
2091 self.type = bytes_type
2092 elif base_type.is_array or base_type.is_ptr:
2093 # we need a ptr type here instead of an array type, as
2094 # array types can result in invalid type casts in the C
2096 self.type = PyrexTypes.CPtrType(base_type.base_type)
2098 self.base = self.base.coerce_to_pyobject(env)
2099 self.type = py_object_type
2100 if base_type.is_builtin_type:
2101 # slicing builtin types returns something of the same type
2102 self.type = base_type
2103 c_int = PyrexTypes.c_py_ssize_t_type
2105 self.start = self.start.coerce_to(c_int, env)
2107 self.stop = self.stop.coerce_to(c_int, env)
2111 gil_message = "Slicing Python object"
2113 def generate_result_code(self, code):
2114 if not self.type.is_pyobject:
2116 "Slicing is not currently supported for '%s'." % self.type)
2118 if self.base.type.is_string:
2119 if self.stop is None:
2121 "%s = __Pyx_PyBytes_FromString(%s + %s); %s" % (
2125 code.error_goto_if_null(self.result(), self.pos)))
2128 "%s = __Pyx_PyBytes_FromStringAndSize(%s + %s, %s - %s); %s" % (
2134 code.error_goto_if_null(self.result(), self.pos)))
2137 "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
2139 self.base.py_result(),
2142 code.error_goto_if_null(self.result(), self.pos)))
2143 code.put_gotref(self.py_result())
2145 def generate_assignment_code(self, rhs, code):
2146 self.generate_subexpr_evaluation_code(code)
2147 if self.type.is_pyobject:
2148 code.put_error_if_neg(self.pos,
2149 "PySequence_SetSlice(%s, %s, %s, %s)" % (
2150 self.base.py_result(),
2157 start_offset = self.start_code()
2158 if start_offset == '0':
2162 if rhs.type.is_array:
2163 array_length = rhs.type.size
2164 self.generate_slice_guard_code(code, array_length)
2167 "Slice assignments from pointers are not yet supported.")
2168 # FIXME: fix the array size according to start/stop
2169 array_length = self.base.type.size
2170 for i in range(array_length):
2171 code.putln("%s[%s%s] = %s[%d];" % (
2172 self.base.result(), start_offset, i,
2174 self.generate_subexpr_disposal_code(code)
2175 self.free_subexpr_temps(code)
2176 rhs.generate_disposal_code(code)
2177 rhs.free_temps(code)
2179 def generate_deletion_code(self, code):
2180 if not self.base.type.is_pyobject:
2182 "Deleting slices is only supported for Python types, not '%s'." % self.type)
2184 self.generate_subexpr_evaluation_code(code)
2185 code.put_error_if_neg(self.pos,
2186 "PySequence_DelSlice(%s, %s, %s)" % (
2187 self.base.py_result(),
2190 self.generate_subexpr_disposal_code(code)
2192 def generate_slice_guard_code(self, code, target_size):
2193 if not self.base.type.is_array:
2195 slice_size = self.base.type.size
2198 stop = self.stop.result()
2202 slice_size = self.base.type.size + stop
2209 start = self.start.result()
2213 start = self.base.type.size + start
2221 error(self.pos, "Assignment to empty slice.")
2222 elif start is None and stop is None:
2223 # we know the exact slice length
2224 if target_size != slice_size:
2225 error(self.pos, "Assignment to slice of wrong length, expected %d, got %d" % (
2226 slice_size, target_size))
2227 elif start is not None:
2230 check = "(%s)-(%s)" % (stop, start)
2231 else: # stop is not None:
2234 code.putln("if (unlikely((%s) != %d)) {" % (check, target_size))
2235 code.putln('PyErr_Format(PyExc_ValueError, "Assignment to slice of wrong length, expected %%"PY_FORMAT_SIZE_T"d, got %%"PY_FORMAT_SIZE_T"d", (Py_ssize_t)%d, (Py_ssize_t)(%s));' % (
2236 target_size, check))
2237 code.putln(code.error_goto(self.pos))
2240 def start_code(self):
2242 return self.start.result()
2246 def stop_code(self):
2248 return self.stop.result()
2249 elif self.base.type.is_array:
2250 return self.base.type.size
2252 return "PY_SSIZE_T_MAX"
2254 def calculate_result_code(self):
2255 # self.result() is not used, but this method must exist
2259 class SliceNode(ExprNode):
2260 # start:stop:step in subscript list
2266 def calculate_constant_result(self):
2267 self.constant_result = self.base.constant_result[
2268 self.start.constant_result : \
2269 self.stop.constant_result : \
2270 self.step.constant_result]
2272 def compile_time_value(self, denv):
2273 start = self.start.compile_time_value(denv)
2274 if self.stop is None:
2277 stop = self.stop.compile_time_value(denv)
2278 if self.step is None:
2281 step = self.step.compile_time_value(denv)
2283 return slice(start, stop, step)
2284 except Exception, e:
2285 self.compile_time_value_error(e)
2287 subexprs = ['start', 'stop', 'step']
2289 def analyse_types(self, env):
2290 self.start.analyse_types(env)
2291 self.stop.analyse_types(env)
2292 self.step.analyse_types(env)
2293 self.start = self.start.coerce_to_pyobject(env)
2294 self.stop = self.stop.coerce_to_pyobject(env)
2295 self.step = self.step.coerce_to_pyobject(env)
2296 self.type = py_object_type
2300 gil_message = "Constructing Python slice object"
2302 def generate_result_code(self, code):
2304 "%s = PySlice_New(%s, %s, %s); %s" % (
2306 self.start.py_result(),
2307 self.stop.py_result(),
2308 self.step.py_result(),
2309 code.error_goto_if_null(self.result(), self.pos)))
2310 code.put_gotref(self.py_result())
2313 class CallNode(NewTempExprNode):
2314 def gil_check(self, env):
2315 # Make sure we're not in a nogil environment
2317 error(self.pos, "Calling gil-requiring function without gil")
2319 def analyse_as_type_constructor(self, env):
2320 type = self.function.analyse_as_type(env)
2321 if type and type.is_struct_or_union:
2322 args, kwds = self.explicit_args_kwds()
2324 for arg, member in zip(args, type.scope.var_entries):
2325 items.append(DictItemNode(pos=arg.pos, key=IdentifierStringNode(pos=arg.pos, value=member.name), value=arg))
2327 items += kwds.key_value_pairs
2328 self.key_value_pairs = items
2329 self.__class__ = DictNode
2330 self.analyse_types(env)
2331 self.coerce_to(type, env)
2335 class SimpleCallNode(CallNode):
2336 # Function call without keyword, * or ** args.
2340 # arg_tuple ExprNode or None used internally
2341 # self ExprNode or None used internally
2342 # coerced_self ExprNode or None used internally
2343 # wrapper_call bool used internally
2344 # has_optional_args bool used internally
2346 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
2351 wrapper_call = False
2352 has_optional_args = False
2354 def compile_time_value(self, denv):
2355 function = self.function.compile_time_value(denv)
2356 args = [arg.compile_time_value(denv) for arg in self.args]
2358 return function(*args)
2359 except Exception, e:
2360 self.compile_time_value_error(e)
2362 def analyse_as_type(self, env):
2363 attr = self.function.as_cython_attribute()
2364 if attr == 'pointer':
2365 if len(self.args) != 1:
2366 error(self.args.pos, "only one type allowed.")
2368 type = self.args[0].analyse_as_type(env)
2370 error(self.args[0].pos, "Unknown type")
2372 return PyrexTypes.CPtrType(type)
2374 def explicit_args_kwds(self):
2375 return self.args, None
2377 def analyse_types(self, env):
2378 if self.analyse_as_type_constructor(env):
2380 function = self.function
2381 function.is_called = 1
2382 self.function.analyse_types(env)
2383 if function.is_attribute and function.is_py_attr and \
2384 function.attribute == "append" and len(self.args) == 1:
2385 # L.append(x) is almost always applied to a list
2386 self.py_func = self.function
2387 self.function = NameNode(pos=self.function.pos, name="__Pyx_PyObject_Append")
2388 self.function.analyse_types(env)
2389 self.self = self.py_func.obj
2390 function.obj = CloneNode(self.self)
2391 env.use_utility_code(append_utility_code)
2392 if function.is_attribute and function.entry and function.entry.is_cmethod:
2393 # Take ownership of the object from which the attribute
2394 # was obtained, because we need to pass it as 'self'.
2395 self.self = function.obj
2396 function.obj = CloneNode(self.self)
2397 func_type = self.function_type()
2398 if func_type.is_pyobject:
2399 self.arg_tuple = TupleNode(self.pos, args = self.args)
2400 self.arg_tuple.analyse_types(env)
2402 self.type = py_object_type
2406 for arg in self.args:
2407 arg.analyse_types(env)
2408 if self.self and func_type.args:
2409 # Coerce 'self' to the type expected by the method.
2410 expected_type = func_type.args[0].type
2411 self.coerced_self = CloneNode(self.self).coerce_to(
2413 # Insert coerced 'self' argument into argument list.
2414 self.args.insert(0, self.coerced_self)
2415 self.analyse_c_function_call(env)
2417 def function_type(self):
2418 # Return the type of the function being called, coercing a function
2419 # pointer to a function if necessary.
2420 func_type = self.function.type
2421 if func_type.is_ptr:
2422 func_type = func_type.base_type
2425 def analyse_c_function_call(self, env):
2426 entry = PyrexTypes.best_match(self.args, self.function.entry.all_alternatives(), self.pos)
2428 self.type = PyrexTypes.error_type
2429 self.result_code = "<error>"
2431 self.function.entry = entry
2432 self.function.type = entry.type
2433 func_type = self.function_type()
2435 max_nargs = len(func_type.args)
2436 expected_nargs = max_nargs - func_type.optional_arg_count
2437 actual_nargs = len(self.args)
2439 for i in range(min(max_nargs, actual_nargs)):
2440 formal_type = func_type.args[i].type
2441 self.args[i] = self.args[i].coerce_to(formal_type, env)
2442 for i in range(max_nargs, actual_nargs):
2443 if self.args[i].type.is_pyobject:
2444 error(self.args[i].pos,
2445 "Python object cannot be passed as a varargs parameter")
2446 # Calc result type and code fragment
2447 if isinstance(self.function, NewExprNode):
2448 self.type = PyrexTypes.CPtrType(self.function.class_type)
2450 self.type = func_type.return_type
2451 if self.type.is_pyobject:
2452 self.result_ctype = py_object_type
2454 elif func_type.exception_value is not None \
2455 or func_type.exception_check:
2457 # C++ exception handler
2458 if func_type.exception_check == '+':
2459 if func_type.exception_value is None:
2460 env.use_utility_code(cpp_exception_utility_code)
2462 if not func_type.nogil:
2464 if func_type.optional_arg_count and expected_nargs != actual_nargs:
2465 self.has_optional_args = 1
2467 self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
2468 env.release_temp(self.opt_arg_struct)
2471 def calculate_result_code(self):
2472 return self.c_call_code()
2474 def c_call_code(self):
2475 func_type = self.function_type()
2476 if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
2478 formal_args = func_type.args
2480 args = zip(formal_args, self.args)
2481 max_nargs = len(func_type.args)
2482 expected_nargs = max_nargs - func_type.optional_arg_count
2483 actual_nargs = len(self.args)
2484 for formal_arg, actual_arg in args[:expected_nargs]:
2485 arg_code = actual_arg.result_as(formal_arg.type)
2486 arg_list_code.append(arg_code)
2488 if func_type.is_overridable:
2489 arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
2491 if func_type.optional_arg_count:
2492 if expected_nargs == actual_nargs:
2493 optional_args = 'NULL'
2495 optional_args = "&%s" % self.opt_arg_struct
2496 arg_list_code.append(optional_args)
2498 for actual_arg in self.args[len(formal_args):]:
2499 arg_list_code.append(actual_arg.result())
2500 result = "%s(%s)" % (self.function.result(),
2501 ', '.join(arg_list_code))
2502 # if self.wrapper_call or \
2503 # self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
2504 # result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
2507 def generate_result_code(self, code):
2508 func_type = self.function_type()
2509 if func_type.is_pyobject:
2510 arg_code = self.arg_tuple.py_result()
2512 "%s = PyObject_Call(%s, %s, NULL); %s" % (
2514 self.function.py_result(),
2516 code.error_goto_if_null(self.result(), self.pos)))
2517 code.put_gotref(self.py_result())
2518 elif func_type.is_cfunction:
2519 if self.has_optional_args:
2520 actual_nargs = len(self.args)
2521 expected_nargs = len(func_type.args) - func_type.optional_arg_count
2522 code.putln("%s.%s = %s;" % (
2523 self.opt_arg_struct,
2524 Naming.pyrex_prefix + "n",
2525 len(self.args) - expected_nargs))
2526 args = zip(func_type.args, self.args)
2527 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
2528 code.putln("%s.%s = %s;" % (
2529 self.opt_arg_struct,
2531 actual_arg.result_as(formal_arg.type)))
2533 if self.type.is_pyobject:
2534 exc_checks.append("!%s" % self.result())
2536 exc_val = func_type.exception_value
2537 exc_check = func_type.exception_check
2538 if exc_val is not None:
2539 exc_checks.append("%s == %s" % (self.result(), exc_val))
2541 exc_checks.append("PyErr_Occurred()")
2542 if self.is_temp or exc_checks:
2543 rhs = self.c_call_code()
2545 lhs = "%s = " % self.result()
2546 if self.is_temp and self.type.is_pyobject:
2547 #return_type = self.type # func_type.return_type
2548 #print "SimpleCallNode.generate_result_code: casting", rhs, \
2549 # "from", return_type, "to pyobject" ###
2550 rhs = typecast(py_object_type, self.type, rhs)
2553 if func_type.exception_check == '+':
2554 if func_type.exception_value is None:
2555 raise_py_exception = "__Pyx_CppExn2PyErr()"
2556 elif func_type.exception_value.type.is_pyobject:
2557 raise_py_exception = 'PyErr_SetString(%s, "")' % func_type.exception_value.entry.cname
2559 raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
2561 "try {%s%s;} catch(...) {%s; %s}" % (
2565 code.error_goto(self.pos)))
2568 goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
2571 code.putln("%s%s; %s" % (lhs, rhs, goto_error))
2572 if self.type.is_pyobject and self.result():
2573 code.put_gotref(self.py_result())
2576 class GeneralCallNode(CallNode):
2577 # General Python function call, including keyword,
2578 # * and ** arguments.
2581 # positional_args ExprNode Tuple of positional arguments
2582 # keyword_args ExprNode or None Dict of keyword arguments
2583 # starstar_arg ExprNode or None Dict of extra keyword args
2585 subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
2587 def compile_time_value(self, denv):
2588 function = self.function.compile_time_value(denv)
2589 positional_args = self.positional_args.compile_time_value(denv)
2590 keyword_args = self.keyword_args.compile_time_value(denv)
2591 starstar_arg = self.starstar_arg.compile_time_value(denv)
2593 keyword_args.update(starstar_arg)
2594 return function(*positional_args, **keyword_args)
2595 except Exception, e:
2596 self.compile_time_value_error(e)
2598 def explicit_args_kwds(self):
2599 if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
2600 raise PostParseError(self.pos,
2601 'Compile-time keyword arguments must be explicit.')
2602 return self.positional_args.args, self.keyword_args
2604 def analyse_types(self, env):
2605 if self.analyse_as_type_constructor(env):
2607 self.function.analyse_types(env)
2608 self.positional_args.analyse_types(env)
2609 if self.keyword_args:
2610 self.keyword_args.analyse_types(env)
2611 if self.starstar_arg:
2612 self.starstar_arg.analyse_types(env)
2613 if not self.function.type.is_pyobject:
2614 if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
2615 error(self.pos, "Keyword arguments not allowed in cdef functions.")
2617 self.function = self.function.coerce_to_pyobject(env)
2618 self.positional_args = \
2619 self.positional_args.coerce_to_pyobject(env)
2620 if self.starstar_arg:
2621 self.starstar_arg = \
2622 self.starstar_arg.coerce_to_pyobject(env)
2623 self.type = py_object_type
2627 def generate_result_code(self, code):
2628 if self.keyword_args and self.starstar_arg:
2629 code.put_error_if_neg(self.pos,
2630 "PyDict_Update(%s, %s)" % (
2631 self.keyword_args.py_result(),
2632 self.starstar_arg.py_result()))
2633 keyword_code = self.keyword_args.py_result()
2634 elif self.keyword_args:
2635 keyword_code = self.keyword_args.py_result()
2636 elif self.starstar_arg:
2637 keyword_code = self.starstar_arg.py_result()
2640 if not keyword_code:
2641 call_code = "PyObject_Call(%s, %s, NULL)" % (
2642 self.function.py_result(),
2643 self.positional_args.py_result())
2645 call_code = "PyEval_CallObjectWithKeywords(%s, %s, %s)" % (
2646 self.function.py_result(),
2647 self.positional_args.py_result(),
2653 code.error_goto_if_null(self.result(), self.pos)))
2654 code.put_gotref(self.py_result())
2657 class AsTupleNode(ExprNode):
2658 # Convert argument to tuple. Used for normalising
2659 # the * argument of a function call.
2665 def calculate_constant_result(self):
2666 self.constant_result = tuple(self.base.constant_result)
2668 def compile_time_value(self, denv):
2669 arg = self.arg.compile_time_value(denv)
2672 except Exception, e:
2673 self.compile_time_value_error(e)
2675 def analyse_types(self, env):
2676 self.arg.analyse_types(env)
2677 self.arg = self.arg.coerce_to_pyobject(env)
2678 self.type = tuple_type
2682 gil_message = "Constructing Python tuple"
2684 def generate_result_code(self, code):
2686 "%s = PySequence_Tuple(%s); %s" % (
2688 self.arg.py_result(),
2689 code.error_goto_if_null(self.result(), self.pos)))
2690 code.put_gotref(self.py_result())
2693 class AttributeNode(NewTempExprNode):
2698 # needs_none_check boolean Used if obj is an extension type.
2699 # If set to True, it is known that the type is not None.
2703 # is_py_attr boolean Is a Python getattr operation
2704 # member string C name of struct member
2705 # is_called boolean Function call is being done on result
2706 # entry Entry Symbol table entry of attribute
2707 # interned_attr_cname string C name of interned attribute name
2712 type = PyrexTypes.error_type
2715 needs_none_check = True
2717 def as_cython_attribute(self):
2718 if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
2719 return self.attribute
2721 def coerce_to(self, dst_type, env):
2722 # If coercing to a generic pyobject and this is a cpdef function
2723 # we can create the corresponding attribute
2724 if dst_type is py_object_type:
2726 if entry and entry.is_cfunction and entry.as_variable:
2727 # must be a cpdef function
2729 self.entry = entry.as_variable
2730 self.analyse_as_python_attribute(env)
2732 return ExprNode.coerce_to(self, dst_type, env)
2734 def calculate_constant_result(self):
2735 attr = self.attribute
2736 if attr.startswith("__") and attr.endswith("__"):
2738 self.constant_result = getattr(self.obj.constant_result, attr)
2740 def compile_time_value(self, denv):
2741 attr = self.attribute
2742 if attr.startswith("__") and attr.endswith("__"):
2744 "Invalid attribute name '%s' in compile-time expression" % attr)
2746 obj = self.obj.compile_time_value(denv)
2748 return getattr(obj, attr)
2749 except Exception, e:
2750 self.compile_time_value_error(e)
2752 def analyse_target_declaration(self, env):
2755 def analyse_target_types(self, env):
2756 self.analyse_types(env, target = 1)
2758 def analyse_types(self, env, target = 0):
2759 if self.analyse_as_cimported_attribute(env, target):
2761 if not target and self.analyse_as_unbound_cmethod(env):
2763 self.analyse_as_ordinary_attribute(env, target)
2765 def analyse_as_cimported_attribute(self, env, target):
2766 # Try to interpret this as a reference to an imported
2767 # C const, type, var or function. If successful, mutates
2768 # this node into a NameNode and returns 1, otherwise
2770 module_scope = self.obj.analyse_as_module(env)
2772 entry = module_scope.lookup_here(self.attribute)
2774 entry.is_cglobal or entry.is_cfunction
2775 or entry.is_type or entry.is_const):
2776 self.mutate_into_name_node(env, entry, target)
2780 def analyse_as_unbound_cmethod(self, env):
2781 # Try to interpret this as a reference to an unbound
2782 # C method of an extension type. If successful, mutates
2783 # this node into a NameNode and returns 1, otherwise
2785 type = self.obj.analyse_as_extension_type(env)
2787 entry = type.scope.lookup_here(self.attribute)
2788 if entry and entry.is_cmethod:
2789 # Create a temporary entry describing the C method
2790 # as an ordinary function.
2791 ubcm_entry = Symtab.Entry(entry.name,
2792 "%s->%s" % (type.vtabptr_cname, entry.cname),
2794 ubcm_entry.is_cfunction = 1
2795 ubcm_entry.func_cname = entry.func_cname
2796 ubcm_entry.is_unbound_cmethod = 1
2797 self.mutate_into_name_node(env, ubcm_entry, None)
2801 def analyse_as_type(self, env):
2802 module_scope = self.obj.analyse_as_module(env)
2804 return module_scope.lookup_type(self.attribute)
2807 def analyse_as_extension_type(self, env):
2808 # Try to interpret this as a reference to an extension type
2809 # in a cimported module. Returns the extension type, or None.
2810 module_scope = self.obj.analyse_as_module(env)
2812 entry = module_scope.lookup_here(self.attribute)
2813 if entry and entry.is_type and entry.type.is_extension_type:
2817 def analyse_as_module(self, env):
2818 # Try to interpret this as a reference to a cimported module
2819 # in another cimported module. Returns the module scope, or None.
2820 module_scope = self.obj.analyse_as_module(env)
2822 entry = module_scope.lookup_here(self.attribute)
2823 if entry and entry.as_module:
2824 return entry.as_module
2827 def mutate_into_name_node(self, env, entry, target):
2828 # Mutate this node into a NameNode and complete the
2829 # analyse_types phase.
2830 self.__class__ = NameNode
2831 self.name = self.attribute
2836 NameNode.analyse_target_types(self, env)
2838 NameNode.analyse_rvalue_entry(self, env)
2840 def analyse_as_ordinary_attribute(self, env, target):
2841 self.obj.analyse_types(env)
2842 self.analyse_attribute(env)
2843 if self.entry and self.entry.is_cmethod and not self.is_called:
2844 # error(self.pos, "C method can only be called")
2846 ## Reference to C array turns into pointer to first element.
2847 #while self.type.is_array:
2848 # self.type = self.type.element_ptr_type()
2852 self.result_ctype = py_object_type
2854 def analyse_attribute(self, env):
2855 # Look up attribute and set self.type and self.member.
2857 self.member = self.attribute
2858 if self.obj.type.is_string:
2859 self.obj = self.obj.coerce_to_pyobject(env)
2860 obj_type = self.obj.type
2861 if obj_type.is_ptr or obj_type.is_array:
2862 obj_type = obj_type.base_type
2864 elif obj_type.is_extension_type:
2868 if obj_type.has_attributes:
2870 if obj_type.attributes_known():
2871 entry = obj_type.scope.lookup_here(self.attribute)
2872 if entry and entry.is_member:
2876 "Cannot select attribute of incomplete type '%s'"
2878 self.type = PyrexTypes.error_type
2882 if obj_type.is_extension_type and entry.name == "__weakref__":
2883 error(self.pos, "Illegal use of special attribute __weakref__")
2884 # methods need the normal attribute lookup
2885 # because they do not have struct entries
2886 if entry.is_variable or entry.is_cmethod:
2887 self.type = entry.type
2888 self.member = entry.cname
2891 # If it's not a variable or C method, it must be a Python
2892 # method of an extension type, so we treat it like a Python
2895 # If we get here, the base object is not a struct/union/extension
2896 # type, or it is an extension type and the attribute is either not
2897 # declared or is declared as a Python method. Treat it as a Python
2898 # attribute reference.
2899 self.analyse_as_python_attribute(env)
2901 def analyse_as_python_attribute(self, env):
2902 obj_type = self.obj.type
2903 self.member = self.attribute
2904 if obj_type.is_pyobject:
2905 self.type = py_object_type
2907 self.interned_attr_cname = env.intern_identifier(self.attribute)
2910 if not obj_type.is_error:
2912 "Object of type '%s' has no attribute '%s'" %
2913 (obj_type, self.attribute))
2915 gil_message = "Accessing Python attribute"
2917 def is_simple(self):
2919 return self.result_in_temp() or self.obj.is_simple()
2921 return NameNode.is_simple(self)
2923 def is_lvalue(self):
2927 return NameNode.is_lvalue(self)
2929 def is_ephemeral(self):
2931 return self.obj.is_ephemeral()
2933 return NameNode.is_ephemeral(self)
2935 def calculate_result_code(self):
2936 #print "AttributeNode.calculate_result_code:", self.member ###
2937 #print "...obj node =", self.obj, "code", self.obj.result() ###
2938 #print "...obj type", self.obj.type, "ctype", self.obj.ctype() ###
2940 obj_code = obj.result_as(obj.type)
2941 #print "...obj_code =", obj_code ###
2942 if self.entry and self.entry.is_cmethod:
2943 if obj.type.is_extension_type:
2944 return "((struct %s *)%s%s%s)->%s" % (
2945 obj.type.vtabstruct_cname, obj_code, self.op,
2946 obj.type.vtabslot_cname, self.member)
2949 elif obj.type.is_complex:
2950 return "__Pyx_%s_PART(%s)" % (self.member.upper(), obj_code)
2952 return "%s%s%s" % (obj_code, self.op, self.member)
2954 def generate_result_code(self, code):
2957 '%s = PyObject_GetAttr(%s, %s); %s' % (
2959 self.obj.py_result(),
2960 self.interned_attr_cname,
2961 code.error_goto_if_null(self.result(), self.pos)))
2962 code.put_gotref(self.py_result())
2964 # result_code contains what is needed, but we may need to insert
2965 # a check and raise an exception
2966 if (self.obj.type.is_extension_type
2967 and self.needs_none_check
2968 and code.globalstate.directives['nonecheck']):
2969 self.put_nonecheck(code)
2971 def generate_assignment_code(self, rhs, code):
2972 self.obj.generate_evaluation_code(code)
2974 code.put_error_if_neg(self.pos,
2975 'PyObject_SetAttr(%s, %s, %s)' % (
2976 self.obj.py_result(),
2977 self.interned_attr_cname,
2979 rhs.generate_disposal_code(code)
2980 rhs.free_temps(code)
2982 if (self.obj.type.is_extension_type
2983 and self.needs_none_check
2984 and code.globalstate.directives['nonecheck']):
2985 self.put_nonecheck(code)
2987 select_code = self.result()
2988 if self.type.is_pyobject:
2989 rhs.make_owned_reference(code)
2990 code.put_giveref(rhs.py_result())
2991 code.put_gotref(select_code)
2992 code.put_decref(select_code, self.ctype())
2996 rhs.result_as(self.ctype())))
2998 rhs.generate_post_assignment_code(code)
2999 rhs.free_temps(code)
3000 self.obj.generate_disposal_code(code)
3001 self.obj.free_temps(code)
3003 def generate_deletion_code(self, code):
3004 self.obj.generate_evaluation_code(code)
3006 code.put_error_if_neg(self.pos,
3007 'PyObject_DelAttr(%s, %s)' % (
3008 self.obj.py_result(),
3009 self.interned_attr_cname))
3011 error(self.pos, "Cannot delete C attribute of extension type")
3012 self.obj.generate_disposal_code(code)
3013 self.obj.free_temps(code)
3015 def annotate(self, code):
3017 code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
3019 code.annotate(self.pos, AnnotationItem('c_attr', 'c attribute', size=len(self.attribute)))
3021 def put_nonecheck(self, code):
3022 code.globalstate.use_utility_code(raise_noneattr_error_utility_code)
3023 code.putln("if (%s) {" % code.unlikely("%s == Py_None") % self.obj.result_as(PyrexTypes.py_object_type))
3024 code.putln("__Pyx_RaiseNoneAttributeError(\"%s\");" % self.attribute.encode("UTF-8")) # todo: fix encoding
3025 code.putln(code.error_goto(self.pos))
3029 #-------------------------------------------------------------------
3033 #-------------------------------------------------------------------
3035 class SequenceNode(NewTempExprNode):
3036 # Base class for list and tuple constructor nodes.
3037 # Contains common code for performing sequence unpacking.
3041 # unpacked_items [ExprNode] or None
3042 # coerced_unpacked_items [ExprNode] or None
3046 is_sequence_constructor = 1
3047 unpacked_items = None
3049 def compile_time_value_list(self, denv):
3050 return [arg.compile_time_value(denv) for arg in self.args]
3052 def analyse_target_declaration(self, env):
3053 for arg in self.args:
3054 arg.analyse_target_declaration(env)
3056 def analyse_types(self, env, skip_children=False):
3057 for i in range(len(self.args)):
3059 if not skip_children: arg.analyse_types(env)
3060 self.args[i] = arg.coerce_to_pyobject(env)
3061 self.type = py_object_type
3065 def analyse_target_types(self, env):
3066 self.iterator = PyTempNode(self.pos, env)
3067 self.unpacked_items = []
3068 self.coerced_unpacked_items = []
3069 for arg in self.args:
3070 arg.analyse_target_types(env)
3071 unpacked_item = PyTempNode(self.pos, env)
3072 coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
3073 self.unpacked_items.append(unpacked_item)
3074 self.coerced_unpacked_items.append(coerced_unpacked_item)
3075 self.type = py_object_type
3076 env.use_utility_code(unpacking_utility_code)
3078 def allocate_target_temps(self, env, rhs):
3079 self.iterator.allocate_temps(env)
3080 for node in self.coerced_unpacked_items:
3081 node.allocate_temps(env)
3082 #arg.release_target_temp(env)
3083 #node.release_temp(env)
3084 for arg in self.args:
3085 arg.allocate_target_temps(env, None)
3087 rhs.release_temp(env)
3088 self.iterator.release_temp(env)
3089 for node in self.coerced_unpacked_items:
3090 node.release_temp(env)
3092 # def release_target_temp(self, env):
3093 # #for arg in self.args:
3094 # # arg.release_target_temp(env)
3095 # #for node in self.coerced_unpacked_items:
3096 # # node.release_temp(env)
3097 # self.iterator.release_temp(env)
3099 def generate_result_code(self, code):
3100 self.generate_operation_code(code)
3102 def generate_assignment_code(self, rhs, code):
3103 # Need to work around the fact that generate_evaluation_code
3104 # allocates the temps in a rather hacky way -- the assignment
3105 # is evaluated twice, within each if-block.
3107 if rhs.type is tuple_type:
3108 tuple_check = "likely(%s != Py_None)"
3110 tuple_check = "PyTuple_CheckExact(%s)"
3112 "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
3113 tuple_check % rhs.py_result(),
3116 code.putln("PyObject* tuple = %s;" % rhs.py_result())
3117 for i in range(len(self.args)):
3118 item = self.unpacked_items[i]
3120 "%s = PyTuple_GET_ITEM(tuple, %s); " % (
3123 code.put_incref(item.result(), item.ctype())
3124 value_node = self.coerced_unpacked_items[i]
3125 value_node.generate_evaluation_code(code)
3126 rhs.generate_disposal_code(code)
3128 for i in range(len(self.args)):
3129 self.args[i].generate_assignment_code(
3130 self.coerced_unpacked_items[i], code)
3132 code.putln("} else {")
3134 if rhs.type is tuple_type:
3135 code.globalstate.use_utility_code(tuple_unpacking_error_code)
3136 code.putln("__Pyx_UnpackTupleError(%s, %s);" % (
3137 rhs.py_result(), len(self.args)))
3138 code.putln(code.error_goto(self.pos))
3141 "%s = PyObject_GetIter(%s); %s" % (
3142 self.iterator.result(),
3144 code.error_goto_if_null(self.iterator.result(), self.pos)))
3145 code.put_gotref(self.iterator.py_result())
3146 rhs.generate_disposal_code(code)
3147 for i in range(len(self.args)):
3148 item = self.unpacked_items[i]
3149 unpack_code = "__Pyx_UnpackItem(%s, %d)" % (
3150 self.iterator.py_result(), i)
3154 typecast(item.ctype(), py_object_type, unpack_code),
3155 code.error_goto_if_null(item.result(), self.pos)))
3156 code.put_gotref(item.py_result())
3157 value_node = self.coerced_unpacked_items[i]
3158 value_node.generate_evaluation_code(code)
3159 code.put_error_if_neg(self.pos,
3160 "__Pyx_EndUnpack(%s)" % (
3161 self.iterator.py_result()))
3162 if debug_disposal_code:
3163 print("UnpackNode.generate_assignment_code:")
3164 print("...generating disposal code for %s" % self.iterator)
3165 self.iterator.generate_disposal_code(code)
3166 self.iterator.free_temps(code)
3168 for i in range(len(self.args)):
3169 self.args[i].generate_assignment_code(
3170 self.coerced_unpacked_items[i], code)
3173 rhs.free_temps(code)
3175 def annotate(self, code):
3176 for arg in self.args:
3178 if self.unpacked_items:
3179 for arg in self.unpacked_items:
3181 for arg in self.coerced_unpacked_items:
3185 class TupleNode(SequenceNode):
3186 # Tuple constructor.
3188 gil_message = "Constructing Python tuple"
3190 def analyse_types(self, env, skip_children=False):
3191 if len(self.args) == 0:
3195 SequenceNode.analyse_types(self, env, skip_children)
3196 self.type = tuple_type
3198 def calculate_result_code(self):
3199 if len(self.args) > 0:
3200 error(self.pos, "Positive length tuples must be constructed.")
3202 return Naming.empty_tuple
3204 def calculate_constant_result(self):
3205 self.constant_result = tuple([
3206 arg.constant_result for arg in self.args])
3208 def compile_time_value(self, denv):
3209 values = self.compile_time_value_list(denv)
3211 return tuple(values)
3212 except Exception, e:
3213 self.compile_time_value_error(e)
3215 def generate_operation_code(self, code):
3216 if len(self.args) == 0:
3217 # result_code is Naming.empty_tuple
3220 "%s = PyTuple_New(%s); %s" % (
3223 code.error_goto_if_null(self.result(), self.pos)))
3224 code.put_gotref(self.py_result())
3225 for i in range(len(self.args)):
3227 if not arg.result_in_temp():
3228 code.put_incref(arg.result(), arg.ctype())
3230 "PyTuple_SET_ITEM(%s, %s, %s);" % (
3234 code.put_giveref(arg.py_result())
3236 def generate_subexpr_disposal_code(self, code):
3237 # We call generate_post_assignment_code here instead
3238 # of generate_disposal_code, because values were stored
3239 # in the tuple using a reference-stealing operation.
3240 for arg in self.args:
3241 arg.generate_post_assignment_code(code)
3242 # Should NOT call free_temps -- this is invoked by the default
3243 # generate_evaluation_code which will do that.
3246 class ListNode(SequenceNode):
3249 # obj_conversion_errors [PyrexError] used internally
3250 # orignial_args [ExprNode] used internally
3252 gil_message = "Constructing Python list"
3254 def analyse_expressions(self, env):
3255 SequenceNode.analyse_expressions(self, env)
3256 self.coerce_to_pyobject(env)
3258 def analyse_types(self, env):
3260 self.original_args = list(self.args)
3261 SequenceNode.analyse_types(self, env)
3262 self.type = list_type
3263 self.obj_conversion_errors = held_errors()
3264 release_errors(ignore=True)
3266 def coerce_to(self, dst_type, env):
3267 if dst_type.is_pyobject:
3268 for err in self.obj_conversion_errors:
3270 self.obj_conversion_errors = []
3271 if not self.type.subtype_of(dst_type):
3272 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3273 elif dst_type.is_ptr:
3274 base_type = dst_type.base_type
3275 self.type = PyrexTypes.CArrayType(base_type, len(self.args))
3276 for i in range(len(self.original_args)):
3278 if isinstance(arg, CoerceToPyTypeNode):
3280 self.args[i] = arg.coerce_to(base_type, env)
3281 elif dst_type.is_struct:
3282 if len(self.args) > len(dst_type.scope.var_entries):
3283 error(self.pos, "Too may members for '%s'" % dst_type)
3285 if len(self.args) < len(dst_type.scope.var_entries):
3286 warning(self.pos, "Too few members for '%s'" % dst_type, 1)
3287 for i, (arg, member) in enumerate(zip(self.original_args, dst_type.scope.var_entries)):
3288 if isinstance(arg, CoerceToPyTypeNode):
3290 self.args[i] = arg.coerce_to(member.type, env)
3291 self.type = dst_type
3293 self.type = error_type
3294 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
3297 def release_temp(self, env):
3298 if self.type.is_array:
3299 # To be valid C++, we must allocate the memory on the stack
3300 # manually and be sure not to reuse it for something else.
3303 SequenceNode.release_temp(self, env)
3305 def calculate_constant_result(self):
3306 self.constant_result = [
3307 arg.constant_result for arg in self.args]
3309 def compile_time_value(self, denv):
3310 return self.compile_time_value_list(denv)
3312 def generate_operation_code(self, code):
3313 if self.type.is_pyobject:
3314 for err in self.obj_conversion_errors:
3316 code.putln("%s = PyList_New(%s); %s" %
3319 code.error_goto_if_null(self.result(), self.pos)))
3320 code.put_gotref(self.py_result())
3321 for i in range(len(self.args)):
3323 #if not arg.is_temp:
3324 if not arg.result_in_temp():
3325 code.put_incref(arg.result(), arg.ctype())
3326 code.putln("PyList_SET_ITEM(%s, %s, %s);" %
3330 code.put_giveref(arg.py_result())
3331 elif self.type.is_array:
3332 for i, arg in enumerate(self.args):
3333 code.putln("%s[%s] = %s;" % (
3337 elif self.type.is_struct:
3338 for arg, member in zip(self.args, self.type.scope.var_entries):
3339 code.putln("%s.%s = %s;" % (
3344 raise InternalError("List type never specified")
3346 def generate_subexpr_disposal_code(self, code):
3347 # We call generate_post_assignment_code here instead
3348 # of generate_disposal_code, because values were stored
3349 # in the list using a reference-stealing operation.
3350 for arg in self.args:
3351 arg.generate_post_assignment_code(code)
3352 # Should NOT call free_temps -- this is invoked by the default
3353 # generate_evaluation_code which will do that.
3356 class ComprehensionNode(NewTempExprNode):
3357 subexprs = ["target"]
3358 child_attrs = ["loop", "append"]
3360 def analyse_types(self, env):
3361 self.target.analyse_expressions(env)
3362 self.type = self.target.type
3363 self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
3364 self.loop.analyse_declarations(env)
3366 def allocate_temps(self, env, result = None):
3367 if debug_temp_alloc:
3368 print("%s Allocating temps" % self)
3369 self.allocate_temp(env, result)
3370 # call loop.analyse_expressions() now to make sure temps get
3371 # allocated at the right time
3372 self.loop.analyse_expressions(env)
3374 def calculate_result_code(self):
3375 return self.target.result()
3377 def generate_result_code(self, code):
3378 self.generate_operation_code(code)
3380 def generate_operation_code(self, code):
3381 self.loop.generate_execution_code(code)
3383 def annotate(self, code):
3384 self.loop.annotate(code)
3387 class ComprehensionAppendNode(NewTempExprNode):
3388 # Need to be careful to avoid infinite recursion:
3389 # target must not be in child_attrs/subexprs
3392 def analyse_types(self, env):
3393 self.expr.analyse_types(env)
3394 if not self.expr.type.is_pyobject:
3395 self.expr = self.expr.coerce_to_pyobject(env)
3396 self.type = PyrexTypes.c_int_type
3399 def generate_result_code(self, code):
3400 if self.target.type is list_type:
3401 function = "PyList_Append"
3402 elif self.target.type is set_type:
3403 function = "PySet_Add"
3405 raise InternalError(
3406 "Invalid type for comprehension node: %s" % self.target.type)
3408 code.putln("%s = %s(%s, (PyObject*)%s); %s" %
3411 self.target.result(),
3413 code.error_goto_if(self.result(), self.pos)))
3415 class DictComprehensionAppendNode(ComprehensionAppendNode):
3416 subexprs = ['key_expr', 'value_expr']
3418 def analyse_types(self, env):
3419 self.key_expr.analyse_types(env)
3420 if not self.key_expr.type.is_pyobject:
3421 self.key_expr = self.key_expr.coerce_to_pyobject(env)
3422 self.value_expr.analyse_types(env)
3423 if not self.value_expr.type.is_pyobject:
3424 self.value_expr = self.value_expr.coerce_to_pyobject(env)
3425 self.type = PyrexTypes.c_int_type
3428 def generate_result_code(self, code):
3429 code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
3431 self.target.result(),
3432 self.key_expr.result(),
3433 self.value_expr.result(),
3434 code.error_goto_if(self.result(), self.pos)))
3437 class SetNode(NewTempExprNode):
3442 gil_message = "Constructing Python set"
3444 def analyse_types(self, env):
3445 for i in range(len(self.args)):
3447 arg.analyse_types(env)
3448 self.args[i] = arg.coerce_to_pyobject(env)
3449 self.type = set_type
3453 def calculate_constant_result(self):
3454 self.constant_result = set([
3455 arg.constant_result for arg in self.args])
3457 def compile_time_value(self, denv):
3458 values = [arg.compile_time_value(denv) for arg in self.args]
3461 except Exception, e:
3462 self.compile_time_value_error(e)
3464 def generate_evaluation_code(self, code):
3465 code.globalstate.use_utility_code(Builtin.py23_set_utility_code)
3466 self.allocate_temp_result(code)
3468 "%s = PySet_New(0); %s" % (
3470 code.error_goto_if_null(self.result(), self.pos)))
3471 code.put_gotref(self.py_result())
3472 for arg in self.args:
3473 arg.generate_evaluation_code(code)
3475 code.error_goto_if_neg(
3476 "PySet_Add(%s, %s)" % (self.result(), arg.py_result()),
3478 arg.generate_disposal_code(code)
3479 arg.free_temps(code)
3482 class DictNode(ExprNode):
3483 # Dictionary constructor.
3485 # key_value_pairs [DictItemNode]
3487 # obj_conversion_errors [PyrexError] used internally
3489 subexprs = ['key_value_pairs']
3491 def calculate_constant_result(self):
3492 self.constant_result = dict([
3493 item.constant_result for item in self.key_value_pairs])
3495 def compile_time_value(self, denv):
3496 pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
3497 for item in self.key_value_pairs]
3500 except Exception, e:
3501 self.compile_time_value_error(e)
3503 def analyse_types(self, env):
3505 self.type = dict_type
3506 for item in self.key_value_pairs:
3507 item.analyse_types(env)
3509 self.obj_conversion_errors = held_errors()
3510 release_errors(ignore=True)
3513 def coerce_to(self, dst_type, env):
3514 if dst_type.is_pyobject:
3515 self.release_errors()
3516 if not self.type.subtype_of(dst_type):
3517 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3518 elif dst_type.is_struct_or_union:
3519 self.type = dst_type
3520 if not dst_type.is_struct and len(self.key_value_pairs) != 1:
3521 error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type)
3522 elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries):
3523 warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1)
3524 for item in self.key_value_pairs:
3525 if isinstance(item.key, CoerceToPyTypeNode):
3526 item.key = item.key.arg
3527 if not isinstance(item.key, (StringNode, IdentifierStringNode)):
3528 error(item.key.pos, "Invalid struct field identifier")
3529 item.key = IdentifierStringNode(item.key.pos, value="<error>")
3531 member = dst_type.scope.lookup_here(item.key.value)
3533 error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.value))
3536 if isinstance(value, CoerceToPyTypeNode):
3538 item.value = value.coerce_to(member.type, env)
3540 self.type = error_type
3541 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
3544 def release_errors(self):
3545 for err in self.obj_conversion_errors:
3547 self.obj_conversion_errors = []
3549 gil_message = "Constructing Python dict"
3551 def allocate_temps(self, env, result = None):
3552 # Custom method used here because key-value
3553 # pairs are evaluated and used one at a time.
3554 self.allocate_temp(env, result)
3555 for item in self.key_value_pairs:
3556 item.key.allocate_temps(env)
3557 item.value.allocate_temps(env)
3558 item.key.release_temp(env)
3559 item.value.release_temp(env)
3561 def generate_evaluation_code(self, code):
3562 # Custom method used here because key-value
3563 # pairs are evaluated and used one at a time.
3564 if self.type.is_pyobject:
3565 self.release_errors()
3567 "%s = PyDict_New(); %s" % (
3569 code.error_goto_if_null(self.result(), self.pos)))
3570 code.put_gotref(self.py_result())
3571 for item in self.key_value_pairs:
3572 item.generate_evaluation_code(code)
3573 if self.type.is_pyobject:
3574 code.put_error_if_neg(self.pos,
3575 "PyDict_SetItem(%s, %s, %s)" % (
3577 item.key.py_result(),
3578 item.value.py_result()))
3580 code.putln("%s.%s = %s;" % (
3583 item.value.result()))
3584 item.generate_disposal_code(code)
3585 item.free_temps(code)
3587 def annotate(self, code):
3588 for item in self.key_value_pairs:
3591 class DictItemNode(ExprNode):
3592 # Represents a single item in a DictNode
3596 subexprs = ['key', 'value']
3598 def calculate_constant_result(self):
3599 self.constant_result = (
3600 self.key.constant_result, self.value.constant_result)
3602 def analyse_types(self, env):
3603 self.key.analyse_types(env)
3604 self.value.analyse_types(env)
3605 self.key = self.key.coerce_to_pyobject(env)
3606 self.value = self.value.coerce_to_pyobject(env)
3608 def generate_evaluation_code(self, code):
3609 self.key.generate_evaluation_code(code)
3610 self.value.generate_evaluation_code(code)
3612 def generate_disposal_code(self, code):
3613 self.key.generate_disposal_code(code)
3614 self.value.generate_disposal_code(code)
3616 def free_temps(self, code):
3617 self.key.free_temps(code)
3618 self.value.free_temps(code)
3621 return iter([self.key, self.value])
3624 class ClassNode(ExprNode):
3625 # Helper class used in the implementation of Python
3626 # class definitions. Constructs a class object given
3627 # a name, tuple of bases and class dictionary.
3629 # name EncodedString Name of the class
3630 # cname string Class name as a Python string
3631 # bases ExprNode Base class tuple
3632 # dict ExprNode Class dict (not owned by this node)
3633 # doc ExprNode or None Doc string
3634 # module_name string Name of defining module
3636 subexprs = ['bases', 'doc']
3638 def analyse_types(self, env):
3639 self.cname = env.intern_identifier(self.name)
3640 self.bases.analyse_types(env)
3642 self.doc.analyse_types(env)
3643 self.doc = self.doc.coerce_to_pyobject(env)
3644 self.module_name = env.global_scope().qualified_name
3645 self.type = py_object_type
3648 env.use_utility_code(create_class_utility_code);
3650 gil_message = "Constructing Python class"
3652 def generate_result_code(self, code):
3654 code.put_error_if_neg(self.pos,
3655 'PyDict_SetItemString(%s, "__doc__", %s)' % (
3656 self.dict.py_result(),
3657 self.doc.py_result()))
3659 '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
3661 self.bases.py_result(),
3662 self.dict.py_result(),
3665 code.error_goto_if_null(self.result(), self.pos)))
3666 code.put_gotref(self.py_result())
3669 class UnboundMethodNode(ExprNode):
3670 # Helper class used in the implementation of Python
3671 # class definitions. Constructs an unbound method
3672 # object from a class and a function.
3674 # class_cname string C var holding the class object
3675 # function ExprNode Function object
3677 subexprs = ['function']
3679 def analyse_types(self, env):
3680 self.function.analyse_types(env)
3681 self.type = py_object_type
3685 gil_message = "Constructing an unbound method"
3687 def generate_result_code(self, code):
3689 "%s = PyMethod_New(%s, 0, %s); %s" % (
3691 self.function.py_result(),
3693 code.error_goto_if_null(self.result(), self.pos)))
3694 code.put_gotref(self.py_result())
3696 class PyCFunctionNode(AtomicNewTempExprNode):
3697 # Helper class used in the implementation of Python
3698 # class definitions. Constructs a PyCFunction object
3699 # from a PyMethodDef struct.
3701 # pymethdef_cname string PyMethodDef structure
3703 def analyse_types(self, env):
3704 self.type = py_object_type
3708 gil_message = "Constructing Python function"
3710 def generate_result_code(self, code):
3712 "%s = PyCFunction_New(&%s, 0); %s" % (
3714 self.pymethdef_cname,
3715 code.error_goto_if_null(self.result(), self.pos)))
3716 code.put_gotref(self.py_result())
3718 #-------------------------------------------------------------------
3720 # Unary operator nodes
3722 #-------------------------------------------------------------------
3724 compile_time_unary_operators = {
3725 'not': operator.not_,
3731 class UnopNode(ExprNode):
3735 # Processing during analyse_expressions phase:
3737 # analyse_c_operation
3738 # Called when the operand is not a pyobject.
3739 # - Check operand type and coerce if needed.
3740 # - Determine result type and result code fragment.
3741 # - Allocate temporary for result if needed.
3743 subexprs = ['operand']
3746 def calculate_constant_result(self):
3747 func = compile_time_unary_operators[self.operator]
3748 self.constant_result = func(self.operand.constant_result)
3750 def compile_time_value(self, denv):
3751 func = compile_time_unary_operators.get(self.operator)
3754 "Unary '%s' not supported in compile-time expression"
3756 operand = self.operand.compile_time_value(denv)
3758 return func(operand)
3759 except Exception, e:
3760 self.compile_time_value_error(e)
3762 def analyse_types(self, env):
3763 self.operand.analyse_types(env)
3764 if self.is_py_operation():
3765 self.coerce_operand_to_pyobject(env)
3766 self.type = py_object_type
3769 elif self.is_cpp_operation():
3770 self.analyse_cpp_operation(env)
3772 self.analyse_c_operation(env)
3774 def check_const(self):
3775 self.operand.check_const()
3777 def is_py_operation(self):
3778 return self.operand.type.is_pyobject
3780 def is_cpp_operation(self):
3781 return self.operand.type.is_cpp_class
3783 def coerce_operand_to_pyobject(self, env):
3784 self.operand = self.operand.coerce_to_pyobject(env)
3786 def generate_result_code(self, code):
3787 if self.operand.type.is_pyobject:
3788 self.generate_py_operation_code(code)
3791 self.generate_c_operation_code(code)
3793 def generate_py_operation_code(self, code):
3794 function = self.py_operation_function()
3796 "%s = %s(%s); %s" % (
3799 self.operand.py_result(),
3800 code.error_goto_if_null(self.result(), self.pos)))
3801 code.put_gotref(self.py_result())
3803 def type_error(self):
3804 if not self.operand.type.is_error:
3805 error(self.pos, "Invalid operand type for '%s' (%s)" %
3806 (self.operator, self.operand.type))
3807 self.type = PyrexTypes.error_type
3809 def analyse_cpp_operation(self, env):
3812 type = type.base_type
3813 entry = env.lookup(type.name)
3814 function = entry.type.scope.lookup("operator%s" % self.operator)
3816 error(self.pos, "'%s' operator not defined for %s"
3817 % (self.operator, type))
3820 self.type = function.type.return_type
3824 class NotNode(ExprNode):
3829 def calculate_constant_result(self):
3830 self.constant_result = not self.operand.constant_result
3832 def compile_time_value(self, denv):
3833 operand = self.operand.compile_time_value(denv)
3836 except Exception, e:
3837 self.compile_time_value_error(e)
3839 subexprs = ['operand']
3841 def analyse_types(self, env):
3842 self.operand.analyse_types(env)
3843 self.operand = self.operand.coerce_to_boolean(env)
3844 self.type = PyrexTypes.c_bint_type
3846 def calculate_result_code(self):
3847 return "(!%s)" % self.operand.result()
3849 def generate_result_code(self, code):
3853 class UnaryPlusNode(UnopNode):
3854 # unary '+' operator
3858 def analyse_c_operation(self, env):
3859 self.type = self.operand.type
3861 def py_operation_function(self):
3862 return "PyNumber_Positive"
3864 def calculate_result_code(self):
3865 return self.operand.result()
3868 class UnaryMinusNode(UnopNode):
3869 # unary '-' operator
3873 def analyse_c_operation(self, env):
3874 if self.operand.type.is_numeric:
3875 self.type = self.operand.type
3878 if self.type.is_complex:
3879 self.infix = env.directives['c99_complex']
3881 def py_operation_function(self):
3882 return "PyNumber_Negative"
3884 def calculate_result_code(self):
3886 return "(-%s)" % self.operand.result()
3888 return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result())
3890 class TildeNode(UnopNode):
3891 # unary '~' operator
3893 def analyse_c_operation(self, env):
3894 if self.operand.type.is_int:
3895 self.type = self.operand.type
3899 def py_operation_function(self):
3900 return "PyNumber_Invert"
3902 def calculate_result_code(self):
3903 return "(~%s)" % self.operand.result()
3906 class AmpersandNode(ExprNode):
3907 # The C address-of operator.
3911 subexprs = ['operand']
3913 def analyse_types(self, env):
3914 self.operand.analyse_types(env)
3915 argtype = self.operand.type
3916 if not (argtype.is_cfunction or self.operand.is_lvalue()):
3917 self.error("Taking address of non-lvalue")
3919 if argtype.is_pyobject:
3920 self.error("Cannot take address of Python variable")
3922 self.type = PyrexTypes.c_ptr_type(argtype)
3924 def check_const(self):
3925 self.operand.check_const_addr()
3927 def error(self, mess):
3928 error(self.pos, mess)
3929 self.type = PyrexTypes.error_type
3930 self.result_code = "<error>"
3932 def calculate_result_code(self):
3933 return "(&%s)" % self.operand.result()
3935 def generate_result_code(self, code):
3939 unop_node_classes = {
3941 "-": UnaryMinusNode,
3945 def unop_node(pos, operator, operand):
3946 # Construct unnop node of appropriate class for
3948 if isinstance(operand, IntNode) and operator == '-':
3949 return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
3950 elif isinstance(operand, UnopNode) and operand.operator == operator:
3951 warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
3952 return unop_node_classes[operator](pos,
3953 operator = operator,
3957 class TypecastNode(NewTempExprNode):
3961 # base_type CBaseTypeNode
3962 # declarator CDeclaratorNode
3964 # If used from a transform, one can if wanted specify the attribute
3965 # "type" directly and leave base_type and declarator to None
3967 subexprs = ['operand']
3968 base_type = declarator = type = None
3970 def analyse_types(self, env):
3971 if self.type is None:
3972 base_type = self.base_type.analyse(env)
3973 _, self.type = self.declarator.analyse(base_type, env)
3974 if self.type.is_cfunction:
3976 "Cannot cast to a function type")
3977 self.type = PyrexTypes.error_type
3978 self.operand.analyse_types(env)
3979 to_py = self.type.is_pyobject
3980 from_py = self.operand.type.is_pyobject
3981 if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
3982 error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
3983 if to_py and not from_py:
3984 if (self.operand.type.to_py_function and
3985 self.operand.type.create_to_py_utility_code(env)):
3986 self.result_ctype = py_object_type
3987 self.operand = self.operand.coerce_to_pyobject(env)
3989 if not (self.operand.type.is_ptr and self.operand.type.base_type.is_void):
3990 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
3991 self.operand = self.operand.coerce_to_simple(env)
3992 elif from_py and not to_py:
3993 if self.type.from_py_function:
3994 self.operand = self.operand.coerce_to(self.type, env)
3995 elif self.type.is_ptr and not (self.type.base_type.is_void or self.type.base_type.is_struct):
3996 error(self.pos, "Python objects cannot be casted to pointers of primitive types")
3998 warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.type, self.operand.type))
3999 elif from_py and to_py:
4000 if self.typecheck and self.type.is_extension_type:
4001 self.operand = PyTypeTestNode(self.operand, self.type, env)
4003 def check_const(self):
4004 self.operand.check_const()
4006 def calculate_constant_result(self):
4007 # we usually do not know the result of a type cast at code
4011 def calculate_result_code(self):
4013 return self.type.cast_code(opnd.result())
4015 def result_as(self, type):
4016 if self.type.is_pyobject and not self.is_temp:
4017 # Optimise away some unnecessary casting
4018 return self.operand.result_as(type)
4020 return ExprNode.result_as(self, type)
4022 def generate_result_code(self, code):
4025 "%s = (PyObject *)%s;" % (
4027 self.operand.result()))
4028 code.put_incref(self.result(), self.ctype())
4031 class SizeofNode(ExprNode):
4032 # Abstract base class for sizeof(x) expression nodes.
4034 type = PyrexTypes.c_size_t_type
4036 def check_const(self):
4039 def generate_result_code(self, code):
4043 class SizeofTypeNode(SizeofNode):
4044 # C sizeof function applied to a type
4046 # base_type CBaseTypeNode
4047 # declarator CDeclaratorNode
4052 def analyse_types(self, env):
4053 # we may have incorrectly interpreted a dotted name as a type rather than an attribute
4054 # this could be better handled by more uniformly treating types as runtime-available objects
4055 if 0 and self.base_type.module_path:
4056 path = self.base_type.module_path
4057 obj = env.lookup(path[0])
4058 if obj.as_module is None:
4059 operand = NameNode(pos=self.pos, name=path[0])
4060 for attr in path[1:]:
4061 operand = AttributeNode(pos=self.pos, obj=operand, attribute=attr)
4062 operand = AttributeNode(pos=self.pos, obj=operand, attribute=self.base_type.name)
4063 self.operand = operand
4064 self.__class__ = SizeofVarNode
4065 self.analyse_types(env)
4067 if self.arg_type is None:
4068 base_type = self.base_type.analyse(env)
4069 _, arg_type = self.declarator.analyse(base_type, env)
4070 self.arg_type = arg_type
4073 def check_type(self):
4074 arg_type = self.arg_type
4075 if arg_type.is_pyobject and not arg_type.is_extension_type:
4076 error(self.pos, "Cannot take sizeof Python object")
4077 elif arg_type.is_void:
4078 error(self.pos, "Cannot take sizeof void")
4079 elif not arg_type.is_complete():
4080 error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
4082 def calculate_result_code(self):
4083 if self.arg_type.is_extension_type:
4084 # the size of the pointer is boring
4085 # we want the size of the actual struct
4086 arg_code = self.arg_type.declaration_code("", deref=1)
4088 arg_code = self.arg_type.declaration_code("")
4089 return "(sizeof(%s))" % arg_code
4092 class SizeofVarNode(SizeofNode):
4093 # C sizeof function applied to a variable
4097 subexprs = ['operand']
4099 def analyse_types(self, env):
4100 # We may actually be looking at a type rather than a variable...
4101 # If we are, traditional analysis would fail...
4102 operand_as_type = self.operand.analyse_as_type(env)
4104 self.arg_type = operand_as_type
4105 self.__class__ = SizeofTypeNode
4108 self.operand.analyse_types(env)
4110 def calculate_result_code(self):
4111 return "(sizeof(%s))" % self.operand.result()
4113 def generate_result_code(self, code):
4117 #-------------------------------------------------------------------
4119 # Binary operator nodes
4121 #-------------------------------------------------------------------
4123 def _not_in(x, seq):
4126 compile_time_binary_operators = {
4134 'is_not': operator.is_not,
4138 '//': operator.floordiv,
4139 '<<': operator.lshift,
4144 '>>': operator.rshift,
4146 #'/': operator.truediv,
4148 'in': operator.contains,
4152 def get_compile_time_binop(node):
4153 func = compile_time_binary_operators.get(node.operator)
4156 "Binary '%s' not supported in compile-time expression"
4160 class BinopNode(NewTempExprNode):
4165 # Processing during analyse_expressions phase:
4167 # analyse_c_operation
4168 # Called when neither operand is a pyobject.
4169 # - Check operand types and coerce if needed.
4170 # - Determine result type and result code fragment.
4171 # - Allocate temporary for result if needed.
4173 subexprs = ['operand1', 'operand2']
4175 def calculate_constant_result(self):
4176 func = compile_time_binary_operators[self.operator]
4177 self.constant_result = func(
4178 self.operand1.constant_result,
4179 self.operand2.constant_result)
4181 def compile_time_value(self, denv):
4182 func = get_compile_time_binop(self)
4183 operand1 = self.operand1.compile_time_value(denv)
4184 operand2 = self.operand2.compile_time_value(denv)
4186 return func(operand1, operand2)
4187 except Exception, e:
4188 self.compile_time_value_error(e)
4190 def analyse_types(self, env):
4191 self.operand1.analyse_types(env)
4192 self.operand2.analyse_types(env)
4193 if self.is_py_operation():
4194 self.coerce_operands_to_pyobjects(env)
4195 self.type = py_object_type
4198 if Options.incref_local_binop and self.operand1.type.is_pyobject:
4199 self.operand1 = self.operand1.coerce_to_temp(env)
4200 elif self.is_cpp_operation():
4201 self.analyse_cpp_operation(env)
4203 self.analyse_c_operation(env)
4205 def is_py_operation(self):
4206 return (self.operand1.type.is_pyobject
4207 or self.operand2.type.is_pyobject)
4209 def is_cpp_operation(self):
4210 type1 = self.operand1.type
4211 type2 = self.operand2.type
4213 type1 = type1.base_type
4215 type2 = type2.base_type
4216 return (type1.is_cpp_class
4217 or type2.is_cpp_class)
4219 def coerce_operands_to_pyobjects(self, env):
4220 self.operand1 = self.operand1.coerce_to_pyobject(env)
4221 self.operand2 = self.operand2.coerce_to_pyobject(env)
4223 def check_const(self):
4224 self.operand1.check_const()
4225 self.operand2.check_const()
4227 def generate_result_code(self, code):
4228 #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
4229 if self.operand1.type.is_pyobject:
4230 function = self.py_operation_function()
4231 if function == "PyNumber_Power":
4232 extra_args = ", Py_None"
4236 "%s = %s(%s, %s%s); %s" % (
4239 self.operand1.py_result(),
4240 self.operand2.py_result(),
4242 code.error_goto_if_null(self.result(), self.pos)))
4243 code.put_gotref(self.py_result())
4246 self.generate_c_operation_code(code)
4248 def type_error(self):
4249 if not (self.operand1.type.is_error
4250 or self.operand2.type.is_error):
4251 error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
4252 (self.operator, self.operand1.type,
4253 self.operand2.type))
4254 self.type = PyrexTypes.error_type
4257 class NumBinopNode(BinopNode):
4258 # Binary operation taking numeric arguments.
4262 def analyse_c_operation(self, env):
4263 type1 = self.operand1.type
4264 type2 = self.operand2.type
4265 self.type = self.compute_c_result_type(type1, type2)
4269 if self.type.is_complex and not env.directives['c99_complex']:
4272 self.operand1 = self.operand1.coerce_to(self.type, env)
4273 self.operand2 = self.operand2.coerce_to(self.type, env)
4275 def analyse_cpp_operation(self, env):
4276 type1 = self.operand1.type
4277 type2 = self.operand2.type
4279 type1 = type1.base_type
4281 type2 = type2.base_type
4282 entry = env.lookup(type1.name)
4283 function = entry.type.scope.lookup("operator%s" % self.operator)
4284 if function is not None:
4285 operands = [self.operand2]
4287 function = env.lookup("operator%s" % self.operator)
4288 operands = [self.operand1, self.operand2]
4292 entry = PyrexTypes.best_match(operands, function.all_alternatives(), self.pos)
4294 self.type = PyrexTypes.error_type
4295 self.result_code = "<error>"
4297 if (entry.type.is_ptr):
4298 self.type = entry.type.base_type.return_type
4300 self.type = entry.type.return_type
4302 def compute_c_result_type(self, type1, type2):
4303 if self.c_types_okay(type1, type2):
4304 return PyrexTypes.widest_numeric_type(type1, type2)
4308 def c_types_okay(self, type1, type2):
4309 #print "NumBinopNode.c_types_okay:", type1, type2 ###
4310 return (type1.is_numeric or type1.is_enum) \
4311 and (type2.is_numeric or type2.is_enum)
4313 def calculate_result_code(self):
4315 return "(%s %s %s)" % (
4316 self.operand1.result(),
4318 self.operand2.result())
4320 func = self.type.binary_op(self.operator)
4322 error(self.pos, "binary operator %s not supported for %s" % (self.operator, self.type))
4323 return "%s(%s, %s)" % (
4325 self.operand1.result(),
4326 self.operand2.result())
4328 def py_operation_function(self):
4329 return self.py_functions[self.operator]
4334 "^": "PyNumber_Xor",
4335 "&": "PyNumber_And",
4336 "<<": "PyNumber_Lshift",
4337 ">>": "PyNumber_Rshift",
4338 "+": "PyNumber_Add",
4339 "-": "PyNumber_Subtract",
4340 "*": "PyNumber_Multiply",
4341 "/": "__Pyx_PyNumber_Divide",
4342 "//": "PyNumber_FloorDivide",
4343 "%": "PyNumber_Remainder",
4344 "**": "PyNumber_Power"
4348 class IntBinopNode(NumBinopNode):
4349 # Binary operation taking integer arguments.
4351 def c_types_okay(self, type1, type2):
4352 #print "IntBinopNode.c_types_okay:", type1, type2 ###
4353 return (type1.is_int or type1.is_enum) \
4354 and (type2.is_int or type2.is_enum)
4357 class AddNode(NumBinopNode):
4360 def is_py_operation(self):
4361 if self.operand1.type.is_string \
4362 and self.operand2.type.is_string:
4365 return NumBinopNode.is_py_operation(self)
4367 def compute_c_result_type(self, type1, type2):
4368 #print "AddNode.compute_c_result_type:", type1, self.operator, type2 ###
4369 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4371 elif (type2.is_ptr or type2.is_array) and (type1.is_int or type1.is_enum):
4374 return NumBinopNode.compute_c_result_type(
4378 class SubNode(NumBinopNode):
4381 def compute_c_result_type(self, type1, type2):
4382 if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
4384 elif (type1.is_ptr or type1.is_array) and (type2.is_ptr or type2.is_array):
4385 return PyrexTypes.c_int_type
4387 return NumBinopNode.compute_c_result_type(
4391 class MulNode(NumBinopNode):
4394 def is_py_operation(self):
4395 type1 = self.operand1.type
4396 type2 = self.operand2.type
4397 if (type1.is_string and type2.is_int) \
4398 or (type2.is_string and type1.is_int):
4401 return NumBinopNode.is_py_operation(self)
4404 class DivNode(NumBinopNode):
4405 # '/' or '//' operator.
4408 cdivision_warnings = False
4409 zerodivision_check = None
4411 def analyse_types(self, env):
4412 NumBinopNode.analyse_types(self, env)
4413 if not self.type.is_pyobject:
4414 self.zerodivision_check = self.cdivision is None and not env.directives['cdivision']
4415 if self.zerodivision_check or env.directives['cdivision_warnings']:
4416 # Need to check ahead of time to warn or raise zero division error
4417 self.operand1 = self.operand1.coerce_to_simple(env)
4418 self.operand2 = self.operand2.coerce_to_simple(env)
4420 error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
4422 def zero_division_message(self):
4423 if self.type.is_int:
4424 return "integer division or modulo by zero"
4426 return "float division"
4428 def generate_evaluation_code(self, code):
4429 if not self.type.is_pyobject and not self.type.is_complex:
4430 if self.cdivision is None:
4431 self.cdivision = (code.globalstate.directives['cdivision']
4432 or not self.type.signed
4433 or self.type.is_float)
4434 if not self.cdivision:
4435 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
4436 NumBinopNode.generate_evaluation_code(self, code)
4437 self.generate_div_warning_code(code)
4439 def generate_div_warning_code(self, code):
4440 if not self.type.is_pyobject:
4441 if self.zerodivision_check:
4443 zero_test = "%s(%s)" % (self.type.unary_op('zero'), self.operand2.result())
4445 zero_test = "%s == 0" % self.operand2.result()
4446 code.putln("if (unlikely(%s)) {" % zero_test)
4447 code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
4448 code.putln(code.error_goto(self.pos))
4450 if self.type.is_int and self.type.signed and self.operator != '%':
4451 code.globalstate.use_utility_code(division_overflow_test_code)
4452 code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
4453 self.type.declaration_code(''),
4454 self.operand2.result(),
4455 self.operand1.result()))
4456 code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
4457 code.putln(code.error_goto(self.pos))
4459 if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
4460 code.globalstate.use_utility_code(cdivision_warning_utility_code)
4461 code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
4462 self.operand1.result(),
4463 self.operand2.result()))
4464 code.putln(code.set_error_info(self.pos));
4465 code.put("if (__Pyx_cdivision_warning()) ")
4466 code.put_goto(code.error_label)
4469 def calculate_result_code(self):
4470 if self.type.is_complex:
4471 return NumBinopNode.calculate_result_code(self)
4472 elif self.type.is_float and self.operator == '//':
4473 return "floor(%s / %s)" % (
4474 self.operand1.result(),
4475 self.operand2.result())
4476 elif self.cdivision:
4477 return "(%s / %s)" % (
4478 self.operand1.result(),
4479 self.operand2.result())
4481 return "__Pyx_div_%s(%s, %s)" % (
4482 self.type.specalization_name(),
4483 self.operand1.result(),
4484 self.operand2.result())
4487 class ModNode(DivNode):
4490 def is_py_operation(self):
4491 return (self.operand1.type.is_string
4492 or self.operand2.type.is_string
4493 or NumBinopNode.is_py_operation(self))
4495 def zero_division_message(self):
4496 if self.type.is_int:
4497 return "integer division or modulo by zero"
4499 return "float divmod()"
4501 def generate_evaluation_code(self, code):
4502 if not self.type.is_pyobject:
4503 if self.cdivision is None:
4504 self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
4505 if not self.cdivision:
4506 if self.type.is_int:
4507 code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
4509 code.globalstate.use_utility_code(
4510 mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
4511 NumBinopNode.generate_evaluation_code(self, code)
4512 self.generate_div_warning_code(code)
4514 def calculate_result_code(self):
4516 if self.type.is_float:
4517 return "fmod%s(%s, %s)" % (
4518 self.type.math_h_modifier,
4519 self.operand1.result(),
4520 self.operand2.result())
4522 return "(%s %% %s)" % (
4523 self.operand1.result(),
4524 self.operand2.result())
4526 return "__Pyx_mod_%s(%s, %s)" % (
4527 self.type.specalization_name(),
4528 self.operand1.result(),
4529 self.operand2.result())
4531 class PowNode(NumBinopNode):
4534 def analyse_c_operation(self, env):
4535 NumBinopNode.analyse_c_operation(self, env)
4536 if self.type.is_complex:
4537 error(self.pos, "complex powers not yet supported")
4538 self.pow_func = "<error>"
4539 elif self.type.is_float:
4540 self.pow_func = "pow"
4542 self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
4543 env.use_utility_code(
4544 int_pow_utility_code.specialize(func_name=self.pow_func,
4545 type=self.type.declaration_code('')))
4547 def calculate_result_code(self):
4548 return "%s(%s, %s)" % (
4550 self.operand1.result(),
4551 self.operand2.result())
4554 # Note: This class is temporary "shut down" into an ineffective mode temp
4557 # More sophisticated temp reuse was going on before,
4558 # one could have a look at adding this again after /all/ classes
4559 # are converted to the new temp scheme. (The temp juggling cannot work
4561 class BoolBinopNode(NewTempExprNode):
4562 # Short-circuiting boolean operation.
4568 subexprs = ['operand1', 'operand2']
4570 def calculate_constant_result(self):
4571 if self.operator == 'and':
4572 self.constant_result = \
4573 self.operand1.constant_result and \
4574 self.operand2.constant_result
4576 self.constant_result = \
4577 self.operand1.constant_result or \
4578 self.operand2.constant_result
4580 def compile_time_value(self, denv):
4581 if self.operator == 'and':
4582 return self.operand1.compile_time_value(denv) \
4583 and self.operand2.compile_time_value(denv)
4585 return self.operand1.compile_time_value(denv) \
4586 or self.operand2.compile_time_value(denv)
4588 def coerce_to_boolean(self, env):
4589 self.operand1 = self.operand1.coerce_to_boolean(env)
4590 self.operand2 = self.operand2.coerce_to_boolean(env)
4591 self.type = PyrexTypes.c_bint_type
4594 def analyse_types(self, env):
4595 self.operand1.analyse_types(env)
4596 self.operand2.analyse_types(env)
4597 if self.operand1.type.is_pyobject or \
4598 self.operand2.type.is_pyobject:
4599 self.operand1 = self.operand1.coerce_to_pyobject(env)
4600 self.operand2 = self.operand2.coerce_to_pyobject(env)
4601 self.type = py_object_type
4604 self.operand1 = self.operand1.coerce_to_boolean(env)
4605 self.operand2 = self.operand2.coerce_to_boolean(env)
4606 self.type = PyrexTypes.c_bint_type
4608 # Below disabled for
4610 # For what we're about to do, it's vital that
4611 # both operands be temp nodes.
4612 # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
4613 # self.operand2 = self.operand2.coerce_to_temp(env)
4616 gil_message = "Truth-testing Python object"
4618 ## def allocate_temps(self, env, result_code = None):
4619 ## # We don't need both operands at the same time, and
4620 ## # one of the operands will also be our result. So we
4621 ## # use an allocation strategy here which results in
4622 ## # this node and both its operands sharing the same
4623 ## # result variable. This allows us to avoid some
4624 ## # assignments and increfs/decrefs that would otherwise
4626 ## self.allocate_temp(env, result_code)
4627 ## self.operand1.allocate_temps(env, self.result())
4628 ## self.operand2.allocate_temps(env, self.result())
4629 ## # We haven't called release_temp on either operand,
4630 ## # because although they are temp nodes, they don't own
4631 ## # their result variable. And because they are temp
4632 ## # nodes, any temps in their subnodes will have been
4633 ## # released before their allocate_temps returned.
4634 ## # Therefore, they contain no temp vars that need to
4637 def check_const(self):
4638 self.operand1.check_const()
4639 self.operand2.check_const()
4641 def calculate_result_code(self):
4642 return "(%s %s %s)" % (
4643 self.operand1.result(),
4644 self.py_to_c_op[self.operator],
4645 self.operand2.result())
4647 py_to_c_op = {'and': "&&", 'or': "||"}
4649 def generate_evaluation_code(self, code):
4650 code.mark_pos(self.pos)
4651 self.operand1.generate_evaluation_code(code)
4652 test_result, uses_temp = self.generate_operand1_test(code)
4653 if self.operator == 'and':
4662 code.funcstate.release_temp(test_result)
4663 self.operand1.generate_disposal_code(code)
4664 self.operand2.generate_evaluation_code(code)
4665 self.allocate_temp_result(code)
4666 self.operand2.make_owned_reference(code)
4667 code.putln("%s = %s;" % (self.result(), self.operand2.result()))
4668 self.operand2.generate_post_assignment_code(code)
4669 self.operand2.free_temps(code)
4670 code.putln("} else {")
4671 self.operand1.make_owned_reference(code)
4672 code.putln("%s = %s;" % (self.result(), self.operand1.result()))
4673 self.operand1.generate_post_assignment_code(code)
4674 self.operand1.free_temps(code)
4677 def generate_operand1_test(self, code):
4678 # Generate code to test the truth of the first operand.
4679 if self.type.is_pyobject:
4680 test_result = code.funcstate.allocate_temp(PyrexTypes.c_bint_type,
4683 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
4685 self.operand1.py_result(),
4686 code.error_goto_if_neg(test_result, self.pos)))
4688 test_result = self.operand1.result()
4689 return (test_result, self.type.is_pyobject)
4692 class CondExprNode(ExprNode):
4693 # Short-circuiting conditional expression.
4697 # false_val ExprNode
4702 subexprs = ['test', 'true_val', 'false_val']
4704 def calculate_constant_result(self):
4705 if self.test.constant_result:
4706 self.constant_result = self.true_val.constant_result
4708 self.constant_result = self.false_val.constant_result
4710 def analyse_types(self, env):
4711 self.test.analyse_types(env)
4712 self.test = self.test.coerce_to_boolean(env)
4713 self.true_val.analyse_types(env)
4714 self.false_val.analyse_types(env)
4715 self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
4716 if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
4717 self.true_val = self.true_val.coerce_to(self.type, env)
4718 self.false_val = self.false_val.coerce_to(self.type, env)
4720 if self.type == PyrexTypes.error_type:
4723 def compute_result_type(self, type1, type2):
4726 elif type1.is_numeric and type2.is_numeric:
4727 return PyrexTypes.widest_numeric_type(type1, type2)
4728 elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
4730 elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
4732 elif type1.is_pyobject or type2.is_pyobject:
4733 return py_object_type
4734 elif type1.assignable_from(type2):
4736 elif type2.assignable_from(type1):
4739 return PyrexTypes.error_type
4741 def type_error(self):
4742 if not (self.true_val.type.is_error or self.false_val.type.is_error):
4743 error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
4744 (self.true_val.type, self.false_val.type))
4745 self.type = PyrexTypes.error_type
4747 def check_const(self):
4748 self.test.check_const()
4749 self.true_val.check_const()
4750 self.false_val.check_const()
4752 def generate_evaluation_code(self, code):
4753 # Because subexprs may not be evaluated we can use a more optimal
4754 # subexpr allocation strategy than the default, so override evaluation_code.
4756 code.mark_pos(self.pos)
4757 #self.allocate_temp_result(code) # uncomment this when we switch to new temps
4758 self.test.generate_evaluation_code(code)
4759 code.putln("if (%s) {" % self.test.result() )
4760 self.eval_and_get(code, self.true_val)
4761 code.putln("} else {")
4762 self.eval_and_get(code, self.false_val)
4764 self.test.generate_disposal_code(code)
4765 self.test.free_temps(code)
4767 def eval_and_get(self, code, expr):
4768 expr.generate_evaluation_code(code)
4769 expr.make_owned_reference(code)
4770 code.putln("%s = %s;" % (self.result(), expr.result()))
4771 expr.generate_post_assignment_code(code)
4772 expr.free_temps(code)
4774 richcmp_constants = {
4784 class CmpNode(object):
4785 # Mixin class containing code common to PrimaryCmpNodes
4786 # and CascadedCmpNodes.
4788 def calculate_cascaded_constant_result(self, operand1_result):
4789 func = compile_time_binary_operators[self.operator]
4790 operand2_result = self.operand2.constant_result
4791 result = func(operand1_result, operand2_result)
4792 if result and self.cascade:
4793 result = result and \
4794 self.cascade.cascaded_compile_time_value(operand2_result)
4795 self.constant_result = result
4797 def cascaded_compile_time_value(self, operand1, denv):
4798 func = get_compile_time_binop(self)
4799 operand2 = self.operand2.compile_time_value(denv)
4801 result = func(operand1, operand2)
4802 except Exception, e:
4803 self.compile_time_value_error(e)
4806 cascade = self.cascade
4808 # FIXME: I bet this must call cascaded_compile_time_value()
4809 result = result and cascade.compile_time_value(operand2, denv)
4812 def is_cpp_comparison(self):
4813 type1 = self.operand1.type
4814 type2 = self.operand2.type
4816 type1 = type1.base_type
4818 type2 = type2.base_type
4819 return type1.is_cpp_class or type2.is_cpp_class
4821 def is_python_comparison(self):
4822 return (self.has_python_operands()
4823 or (self.cascade and self.cascade.is_python_comparison())
4824 or self.operator in ('in', 'not_in'))
4826 def is_python_result(self):
4827 return ((self.has_python_operands() and self.operator not in ('is', 'is_not', 'in', 'not_in'))
4828 or (self.cascade and self.cascade.is_python_result()))
4830 def check_types(self, env, operand1, op, operand2):
4831 if operand1.type.is_complex or operand2.type.is_complex:
4832 if op not in ('==', '!='):
4833 error(self.pos, "complex types unordered")
4834 common_type = PyrexTypes.widest_numeric_type(operand1.type, operand2.type)
4835 self.operand1 = operand1.coerce_to(common_type, env)
4836 self.operand2 = operand2.coerce_to(common_type, env)
4837 elif not self.types_okay(operand1, op, operand2):
4838 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4839 (self.operator, operand1.type, operand2.type))
4841 def types_okay(self, operand1, op, operand2):
4842 type1 = operand1.type
4843 type2 = operand2.type
4844 if type1.is_error or type2.is_error:
4846 if type1.is_pyobject: # type2 will be, too
4848 elif type1.is_ptr or type1.is_array:
4849 return type1.is_null_ptr or type2.is_null_ptr \
4850 or ((type2.is_ptr or type2.is_array)
4851 and type1.base_type.same_as(type2.base_type))
4852 elif ((type1.is_numeric and type2.is_numeric
4853 or type1.is_enum and (type1 is type2 or type2.is_int)
4854 or type1.is_int and type2.is_enum)
4855 and op not in ('is', 'is_not')):
4858 return type1.is_cfunction and type1.is_cfunction and type1 == type2
4860 def generate_operation_code(self, code, result_code,
4861 operand1, op , operand2):
4862 if self.type is PyrexTypes.py_object_type:
4863 coerce_result = "__Pyx_PyBool_FromLong"
4866 if 'not' in op: negation = "!"
4868 if op == 'in' or op == 'not_in':
4870 "%s = %s(%sPySequence_Contains(%s, %s)); %s" % (
4874 operand2.py_result(),
4875 operand1.py_result(),
4876 code.error_goto_if_neg(result_code, self.pos)))
4877 elif (operand1.type.is_pyobject
4878 and op not in ('is', 'is_not')):
4879 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
4881 operand1.py_result(),
4882 operand2.py_result(),
4883 richcmp_constants[op],
4884 code.error_goto_if_null(result_code, self.pos)))
4885 code.put_gotref(result_code)
4886 elif operand1.type.is_complex and not code.globalstate.directives['c99_complex']:
4887 if op == "!=": negation = "!"
4889 code.putln("%s = %s(%s%s(%s, %s));" % (
4893 operand1.type.unary_op('eq'),
4897 type1 = operand1.type
4898 type2 = operand2.type
4899 if (type1.is_extension_type or type2.is_extension_type) \
4900 and not type1.same_as(type2):
4901 common_type = py_object_type
4902 elif type1.is_numeric:
4903 common_type = PyrexTypes.widest_numeric_type(type1, type2)
4906 code1 = operand1.result_as(common_type)
4907 code2 = operand2.result_as(common_type)
4908 code.putln("%s = %s(%s %s %s);" % (
4912 self.c_operator(op),
4915 def c_operator(self, op):
4918 elif op == 'is_not':
4924 class PrimaryCmpNode(NewTempExprNode, CmpNode):
4925 # Non-cascaded comparison or first comparison of
4926 # a cascaded sequence.
4931 # cascade CascadedCmpNode
4933 # We don't use the subexprs mechanism, because
4934 # things here are too complicated for it to handle.
4935 # Instead, we override all the framework methods
4938 child_attrs = ['operand1', 'operand2', 'cascade']
4942 def calculate_constant_result(self):
4943 self.constant_result = self.calculate_cascaded_constant_result(
4944 self.operand1.constant_result)
4946 def compile_time_value(self, denv):
4947 operand1 = self.operand1.compile_time_value(denv)
4948 return self.cascaded_compile_time_value(operand1, denv)
4950 def analyse_types(self, env):
4951 self.operand1.analyse_types(env)
4952 self.operand2.analyse_types(env)
4953 if self.is_cpp_comparison():
4954 self.analyse_cpp_comparison(env)
4957 self.cascade.analyse_types(env, self.operand2)
4958 self.is_pycmp = self.is_python_comparison()
4960 self.coerce_operands_to_pyobjects(env)
4961 if self.has_int_operands():
4962 self.coerce_chars_to_ints(env)
4964 self.operand2 = self.operand2.coerce_to_simple(env)
4965 self.cascade.coerce_cascaded_operands_to_temp(env)
4966 self.check_operand_types(env)
4967 if self.is_python_result():
4968 self.type = PyrexTypes.py_object_type
4970 self.type = PyrexTypes.c_bint_type
4973 cdr.type = self.type
4975 if self.is_pycmp or self.cascade:
4978 def analyse_cpp_comparison(self, env):
4979 type1 = self.operand1.type
4980 type2 = self.operand2.type
4982 type1 = type1.base_type
4984 type2 = type2.base_type
4985 entry = env.lookup(type1.name)
4986 function = entry.type.scope.lookup("operator%s" % self.operator)
4988 error(self.pos, "Invalid types for '%s' (%s, %s)" %
4989 (self.operator, type1, type2))
4991 entry = PyrexTypes.best_match([self.operand1, self.operand2], function.all_alternatives(), self.pos)
4993 self.type = PyrexTypes.error_type
4994 self.result_code = "<error>"
4996 if (entry.type.is_ptr):
4997 self.type = entry.type.base_type.return_type
4999 self.type = entry.type.return_type
5001 def check_operand_types(self, env):
5002 self.check_types(env,
5003 self.operand1, self.operator, self.operand2)
5005 self.cascade.check_operand_types(env, self.operand2)
5007 def has_python_operands(self):
5008 return (self.operand1.type.is_pyobject
5009 or self.operand2.type.is_pyobject)
5011 def coerce_operands_to_pyobjects(self, env):
5012 self.operand1 = self.operand1.coerce_to_pyobject(env)
5013 self.operand2 = self.operand2.coerce_to_pyobject(env)
5015 self.cascade.coerce_operands_to_pyobjects(env)
5017 def has_int_operands(self):
5018 return (self.operand1.type.is_int or self.operand2.type.is_int) \
5019 or (self.cascade and self.cascade.has_int_operands())
5021 def coerce_chars_to_ints(self, env):
5022 # coerce literal single-char strings to c chars
5023 if self.operand1.type.is_string and isinstance(self.operand1, StringNode):
5024 self.operand1 = self.operand1.coerce_to(PyrexTypes.c_uchar_type, env)
5025 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
5026 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5028 self.cascade.coerce_chars_to_ints(env)
5030 def allocate_subexpr_temps(self, env):
5031 self.operand1.allocate_temps(env)
5032 self.operand2.allocate_temps(env)
5034 self.cascade.allocate_subexpr_temps(env)
5036 def release_subexpr_temps(self, env):
5037 self.operand1.release_temp(env)
5038 self.operand2.release_temp(env)
5040 self.cascade.release_subexpr_temps(env)
5042 def check_const(self):
5043 self.operand1.check_const()
5044 self.operand2.check_const()
5048 def calculate_result_code(self):
5049 if self.operand1.type.is_complex:
5050 if self.operator == "!=":
5054 return "(%s%s(%s, %s))" % (
5056 self.operand1.type.binary_op('=='),
5057 self.operand1.result(),
5058 self.operand2.result())
5060 return "(%s %s %s)" % (
5061 self.operand1.result(),
5062 self.c_operator(self.operator),
5063 self.operand2.result())
5065 def generate_evaluation_code(self, code):
5066 self.operand1.generate_evaluation_code(code)
5067 self.operand2.generate_evaluation_code(code)
5069 self.allocate_temp_result(code)
5070 self.generate_operation_code(code, self.result(),
5071 self.operand1, self.operator, self.operand2)
5073 self.cascade.generate_evaluation_code(code,
5074 self.result(), self.operand2)
5075 self.operand1.generate_disposal_code(code)
5076 self.operand1.free_temps(code)
5077 self.operand2.generate_disposal_code(code)
5078 self.operand2.free_temps(code)
5080 def generate_subexpr_disposal_code(self, code):
5081 # If this is called, it is a non-cascaded cmp,
5082 # so only need to dispose of the two main operands.
5083 self.operand1.generate_disposal_code(code)
5084 self.operand2.generate_disposal_code(code)
5086 def free_subexpr_temps(self, code):
5087 # If this is called, it is a non-cascaded cmp,
5088 # so only need to dispose of the two main operands.
5089 self.operand1.free_temps(code)
5090 self.operand2.free_temps(code)
5092 def annotate(self, code):
5093 self.operand1.annotate(code)
5094 self.operand2.annotate(code)
5096 self.cascade.annotate(code)
5099 class CascadedCmpNode(Node, CmpNode):
5100 # A CascadedCmpNode is not a complete expression node. It
5101 # hangs off the side of another comparison node, shares
5102 # its left operand with that node, and shares its result
5103 # with the PrimaryCmpNode at the head of the chain.
5107 # cascade CascadedCmpNode
5109 child_attrs = ['operand2', 'cascade']
5112 constant_result = constant_value_not_set # FIXME: where to calculate this?
5114 def analyse_types(self, env, operand1):
5115 self.operand2.analyse_types(env)
5117 self.cascade.analyse_types(env, self.operand2)
5119 def check_operand_types(self, env, operand1):
5120 self.check_types(env,
5121 operand1, self.operator, self.operand2)
5123 self.cascade.check_operand_types(env, self.operand2)
5125 def has_python_operands(self):
5126 return self.operand2.type.is_pyobject
5128 def coerce_operands_to_pyobjects(self, env):
5129 self.operand2 = self.operand2.coerce_to_pyobject(env)
5131 self.cascade.coerce_operands_to_pyobjects(env)
5133 def has_int_operands(self):
5134 return self.operand2.type.is_int
5136 def coerce_chars_to_ints(self, env):
5137 if self.operand2.type.is_string and isinstance(self.operand2, StringNode):
5138 self.operand2 = self.operand2.coerce_to(PyrexTypes.c_uchar_type, env)
5140 def coerce_cascaded_operands_to_temp(self, env):
5142 #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
5143 self.operand2 = self.operand2.coerce_to_simple(env)
5144 self.cascade.coerce_cascaded_operands_to_temp(env)
5146 def allocate_subexpr_temps(self, env):
5147 self.operand2.allocate_temps(env)
5149 self.cascade.allocate_subexpr_temps(env)
5151 def release_subexpr_temps(self, env):
5152 self.operand2.release_temp(env)
5154 self.cascade.release_subexpr_temps(env)
5156 def generate_evaluation_code(self, code, result, operand1):
5157 if self.type.is_pyobject:
5158 code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
5159 code.put_decref(result, self.type)
5161 code.putln("if (%s) {" % result)
5162 self.operand2.generate_evaluation_code(code)
5163 self.generate_operation_code(code, result,
5164 operand1, self.operator, self.operand2)
5166 self.cascade.generate_evaluation_code(
5167 code, result, self.operand2)
5168 # Cascaded cmp result is always temp
5169 self.operand2.generate_disposal_code(code)
5170 self.operand2.free_temps(code)
5173 def annotate(self, code):
5174 self.operand2.annotate(code)
5176 self.cascade.annotate(code)
5179 binop_node_classes = {
5180 "or": BoolBinopNode,
5181 "and": BoolBinopNode,
5196 def binop_node(pos, operator, operand1, operand2):
5197 # Construct binop node of appropriate class for
5199 return binop_node_classes[operator](pos,
5200 operator = operator,
5201 operand1 = operand1,
5202 operand2 = operand2)
5204 #-------------------------------------------------------------------
5208 # Coercion nodes are special in that they are created during
5209 # the analyse_types phase of parse tree processing.
5210 # Their __init__ methods consequently incorporate some aspects
5213 #-------------------------------------------------------------------
5215 class CoercionNode(NewTempExprNode):
5216 # Abstract base class for coercion nodes.
5218 # arg ExprNode node being coerced
5222 def __init__(self, arg):
5226 print("%s Coercing %s" % (self, self.arg))
5228 def calculate_constant_result(self):
5229 # constant folding can break type coercion, so this is disabled
5232 def annotate(self, code):
5233 self.arg.annotate(code)
5234 if self.arg.type != self.type:
5235 file, line, col = self.pos
5236 code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
5239 class CastNode(CoercionNode):
5240 # Wrap a node in a C type cast.
5242 def __init__(self, arg, new_type):
5243 CoercionNode.__init__(self, arg)
5244 self.type = new_type
5246 def calculate_result_code(self):
5247 return self.arg.result_as(self.type)
5249 def generate_result_code(self, code):
5250 self.arg.generate_result_code(code)
5253 class PyTypeTestNode(CoercionNode):
5254 # This node is used to check that a generic Python
5255 # object is an instance of a particular extension type.
5256 # This node borrows the result of its argument node.
5258 def __init__(self, arg, dst_type, env):
5259 # The arg is know to be a Python object, and
5260 # the dst_type is known to be an extension type.
5261 assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
5262 CoercionNode.__init__(self, arg)
5263 self.type = dst_type
5265 self.result_ctype = arg.ctype()
5267 gil_message = "Python type test"
5269 def analyse_types(self, env):
5272 def result_in_temp(self):
5273 return self.arg.result_in_temp()
5275 def is_ephemeral(self):
5276 return self.arg.is_ephemeral()
5278 def calculate_result_code(self):
5279 return self.arg.result()
5281 def generate_result_code(self, code):
5282 if self.type.typeobj_is_available():
5283 if not self.type.is_builtin_type:
5284 code.globalstate.use_utility_code(type_test_utility_code)
5287 self.type.type_test_code(self.arg.py_result()),
5288 code.error_goto(self.pos)))
5290 error(self.pos, "Cannot test type of extern C class "
5291 "without type object name specification")
5293 def generate_post_assignment_code(self, code):
5294 self.arg.generate_post_assignment_code(code)
5296 def free_temps(self, code):
5297 self.arg.free_temps(code)
5300 class CoerceToPyTypeNode(CoercionNode):
5301 # This node is used to convert a C data type
5302 # to a Python object.
5304 def __init__(self, arg, env):
5305 CoercionNode.__init__(self, arg)
5306 self.type = py_object_type
5309 if not arg.type.create_to_py_utility_code(env):
5311 "Cannot convert '%s' to Python object" % arg.type)
5313 gil_message = "Converting to Python object"
5315 def coerce_to_boolean(self, env):
5316 return self.arg.coerce_to_boolean(env).coerce_to_temp(env)
5318 def coerce_to_integer(self, env):
5319 # If not already some C integer type, coerce to longint.
5320 if self.arg.type.is_int:
5323 return self.arg.coerce_to(PyrexTypes.c_long_type, env)
5325 def analyse_types(self, env):
5326 # The arg is always already analysed
5329 def generate_result_code(self, code):
5330 function = self.arg.type.to_py_function
5331 code.putln('%s = %s(%s); %s' % (
5335 code.error_goto_if_null(self.result(), self.pos)))
5336 code.put_gotref(self.py_result())
5339 class CoerceFromPyTypeNode(CoercionNode):
5340 # This node is used to convert a Python object
5343 def __init__(self, result_type, arg, env):
5344 CoercionNode.__init__(self, arg)
5345 self.type = result_type
5347 if not result_type.create_from_py_utility_code(env):
5349 "Cannot convert Python object to '%s'" % result_type)
5350 if self.type.is_string and self.arg.is_ephemeral():
5352 "Obtaining char * from temporary Python value")
5354 def analyse_types(self, env):
5355 # The arg is always already analysed
5358 def generate_result_code(self, code):
5359 function = self.type.from_py_function
5360 operand = self.arg.py_result()
5361 rhs = "%s(%s)" % (function, operand)
5362 if self.type.is_enum:
5363 rhs = typecast(self.type, c_long_type, rhs)
5364 code.putln('%s = %s; %s' % (
5367 code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
5368 if self.type.is_pyobject:
5369 code.put_gotref(self.py_result())
5372 class CoerceToBooleanNode(CoercionNode):
5373 # This node is used when a result needs to be used
5374 # in a boolean context.
5376 def __init__(self, arg, env):
5377 CoercionNode.__init__(self, arg)
5378 self.type = PyrexTypes.c_bint_type
5379 if arg.type.is_pyobject:
5384 gil_message = "Truth-testing Python object"
5386 def check_const(self):
5389 self.arg.check_const()
5391 def calculate_result_code(self):
5392 return "(%s != 0)" % self.arg.result()
5394 def generate_result_code(self, code):
5395 if self.arg.type.is_pyobject:
5397 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
5399 self.arg.py_result(),
5400 code.error_goto_if_neg(self.result(), self.pos)))
5402 class CoerceToComplexNode(CoercionNode):
5404 def __init__(self, arg, dst_type, env):
5405 if arg.type.is_complex:
5406 arg = arg.coerce_to_simple(env)
5407 self.type = dst_type
5408 CoercionNode.__init__(self, arg)
5409 dst_type.create_declaration_utility_code(env)
5411 def calculate_result_code(self):
5412 if self.arg.type.is_complex:
5413 real_part = "__Pyx_REAL_PART(%s)" % self.arg.result()
5414 imag_part = "__Pyx_IMAG_PART(%s)" % self.arg.result()
5416 real_part = self.arg.result()
5418 return "%s(%s, %s)" % (
5419 self.type.from_parts,
5423 def generate_result_code(self, code):
5426 class CoerceToTempNode(CoercionNode):
5427 # This node is used to force the result of another node
5428 # to be stored in a temporary. It is only used if the
5429 # argument node's result is not already in a temporary.
5431 def __init__(self, arg, env):
5432 CoercionNode.__init__(self, arg)
5433 self.type = self.arg.type
5435 if self.type.is_pyobject:
5437 self.result_ctype = py_object_type
5439 gil_message = "Creating temporary Python reference"
5441 def analyse_types(self, env):
5442 # The arg is always already analysed
5445 def coerce_to_boolean(self, env):
5446 self.arg = self.arg.coerce_to_boolean(env)
5447 self.type = self.arg.type
5448 self.result_ctype = self.type
5451 def generate_result_code(self, code):
5452 #self.arg.generate_evaluation_code(code) # Already done
5453 # by generic generate_subexpr_evaluation_code!
5454 code.putln("%s = %s;" % (
5455 self.result(), self.arg.result_as(self.ctype())))
5456 if self.type.is_pyobject:
5457 code.put_incref(self.result(), self.ctype())
5460 class CloneNode(CoercionNode):
5461 # This node is employed when the result of another node needs
5462 # to be used multiple times. The argument node's result must
5463 # be in a temporary. This node "borrows" the result from the
5464 # argument node, and does not generate any evaluation or
5465 # disposal code for it. The original owner of the argument
5466 # node is responsible for doing those things.
5468 subexprs = [] # Arg is not considered a subexpr
5470 def __init__(self, arg):
5471 CoercionNode.__init__(self, arg)
5472 if hasattr(arg, 'type'):
5473 self.type = arg.type
5474 self.result_ctype = arg.result_ctype
5475 if hasattr(arg, 'entry'):
5476 self.entry = arg.entry
5479 return self.arg.result()
5481 def analyse_types(self, env):
5482 self.type = self.arg.type
5483 self.result_ctype = self.arg.result_ctype
5485 if hasattr(self.arg, 'entry'):
5486 self.entry = self.arg.entry
5488 def generate_evaluation_code(self, code):
5491 def generate_result_code(self, code):
5494 def generate_disposal_code(self, code):
5497 def allocate_temps(self, env):
5500 def release_temp(self, env):
5503 def free_temps(self, code):
5507 #------------------------------------------------------------------------------------
5509 # Runtime support code
5511 #------------------------------------------------------------------------------------
5513 get_name_interned_utility_code = UtilityCode(
5515 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
5518 static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
5520 result = PyObject_GetAttr(dict, name);
5522 PyErr_SetObject(PyExc_NameError, name);
5527 #------------------------------------------------------------------------------------
5529 import_utility_code = UtilityCode(
5531 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list); /*proto*/
5534 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list) {
5535 PyObject *__import__ = 0;
5536 PyObject *empty_list = 0;
5537 PyObject *module = 0;
5538 PyObject *global_dict = 0;
5539 PyObject *empty_dict = 0;
5541 __import__ = __Pyx_GetAttrString(%(BUILTINS)s, "__import__");
5547 empty_list = PyList_New(0);
5552 global_dict = PyModule_GetDict(%(GLOBALS)s);
5555 empty_dict = PyDict_New();
5558 module = PyObject_CallFunctionObjArgs(__import__,
5559 name, global_dict, empty_dict, list, NULL);
5561 Py_XDECREF(empty_list);
5562 Py_XDECREF(__import__);
5563 Py_XDECREF(empty_dict);
5567 "BUILTINS": Naming.builtins_cname,
5568 "GLOBALS": Naming.module_cname,
5571 #------------------------------------------------------------------------------------
5573 get_exception_utility_code = UtilityCode(
5575 static PyObject *__Pyx_GetExcValue(void); /*proto*/
5578 static PyObject *__Pyx_GetExcValue(void) {
5579 PyObject *type = 0, *value = 0, *tb = 0;
5580 PyObject *tmp_type, *tmp_value, *tmp_tb;
5581 PyObject *result = 0;
5582 PyThreadState *tstate = PyThreadState_Get();
5583 PyErr_Fetch(&type, &value, &tb);
5584 PyErr_NormalizeException(&type, &value, &tb);
5585 if (PyErr_Occurred())
5591 tmp_type = tstate->exc_type;
5592 tmp_value = tstate->exc_value;
5593 tmp_tb = tstate->exc_traceback;
5594 tstate->exc_type = type;
5595 tstate->exc_value = value;
5596 tstate->exc_traceback = tb;
5597 /* Make sure tstate is in a consistent state when we XDECREF
5598 these objects (XDECREF may run arbitrary code). */
5599 Py_XDECREF(tmp_type);
5600 Py_XDECREF(tmp_value);
5615 #------------------------------------------------------------------------------------
5617 type_test_utility_code = UtilityCode(
5619 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
5622 static int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
5624 PyErr_Format(PyExc_SystemError, "Missing type object");
5627 if (obj == Py_None || PyObject_TypeCheck(obj, type))
5629 PyErr_Format(PyExc_TypeError, "Cannot convert %s to %s",
5630 Py_TYPE(obj)->tp_name, type->tp_name);
5635 #------------------------------------------------------------------------------------
5637 create_class_utility_code = UtilityCode(
5639 static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
5642 static PyObject *__Pyx_CreateClass(
5643 PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
5645 PyObject *py_modname;
5646 PyObject *result = 0;
5648 #if PY_MAJOR_VERSION < 3
5649 py_modname = PyString_FromString(modname);
5651 py_modname = PyUnicode_FromString(modname);
5655 if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
5657 #if PY_MAJOR_VERSION < 3
5658 result = PyClass_New(bases, dict, name);
5660 result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
5663 Py_XDECREF(py_modname);
5668 #------------------------------------------------------------------------------------
5670 cpp_exception_utility_code = UtilityCode(
5672 #ifndef __Pyx_CppExn2PyErr
5673 static void __Pyx_CppExn2PyErr() {
5675 if (PyErr_Occurred())
5676 ; // let the latest Python exn pass through and ignore the current one
5679 } catch (const std::out_of_range& exn) {
5680 // catch out_of_range explicitly so the proper Python exn may be raised
5681 PyErr_SetString(PyExc_IndexError, exn.what());
5682 } catch (const std::exception& exn) {
5683 PyErr_SetString(PyExc_RuntimeError, exn.what());
5687 PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
5695 #------------------------------------------------------------------------------------
5697 append_utility_code = UtilityCode(
5699 static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
5700 if (likely(PyList_CheckExact(L))) {
5701 if (PyList_Append(L, x) < 0) return NULL;
5703 return Py_None; /* this is just to have an accurate signature */
5707 m = __Pyx_GetAttrString(L, "append");
5708 if (!m) return NULL;
5709 r = PyObject_CallFunctionObjArgs(m, x, NULL);
5718 #------------------------------------------------------------------------------------
5720 # If the is_unsigned flag is set, we need to do some extra work to make
5721 # sure the index doesn't become negative.
5723 getitem_int_utility_code = UtilityCode(
5726 static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
5728 if (!j) return NULL;
5729 r = PyObject_GetItem(o, j);
5736 #define __Pyx_GetItemInt_%(type)s(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5737 __Pyx_GetItemInt_%(type)s_Fast(o, i, size <= sizeof(long)) : \\
5738 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5740 static INLINE PyObject *__Pyx_GetItemInt_%(type)s_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5741 if (likely(o != Py_None)) {
5742 if (likely((0 <= i) & (i < Py%(type)s_GET_SIZE(o)))) {
5743 PyObject *r = Py%(type)s_GET_ITEM(o, i);
5747 else if ((-Py%(type)s_GET_SIZE(o) <= i) & (i < 0)) {
5748 PyObject *r = Py%(type)s_GET_ITEM(o, Py%(type)s_GET_SIZE(o) + i);
5753 return __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5755 """ % {'type' : type_name} for type_name in ('List', 'Tuple')
5758 #define __Pyx_GetItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5759 __Pyx_GetItemInt_Fast(o, i, size <= sizeof(long)) : \\
5760 __Pyx_GetItemInt_Generic(o, to_py_func(i)))
5762 static INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5764 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5765 r = PyList_GET_ITEM(o, i);
5768 else if (PyTuple_CheckExact(o) && ((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
5769 r = PyTuple_GET_ITEM(o, i);
5772 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_item && (likely(i >= 0))) {
5773 r = PySequence_GetItem(o, i);
5776 r = __Pyx_GetItemInt_Generic(o, fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i));
5786 #------------------------------------------------------------------------------------
5788 setitem_int_utility_code = UtilityCode(
5790 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5791 __Pyx_SetItemInt_Fast(o, i, v, size <= sizeof(long)) : \\
5792 __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
5794 static INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyObject *v) {
5797 r = PyObject_SetItem(o, j, v);
5802 static INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int fits_long) {
5803 if (PyList_CheckExact(o) && ((0 <= i) & (i < PyList_GET_SIZE(o)))) {
5805 Py_DECREF(PyList_GET_ITEM(o, i));
5806 PyList_SET_ITEM(o, i, v);
5809 else if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && (likely(i >= 0)))
5810 return PySequence_SetItem(o, i, v);
5812 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5813 return __Pyx_SetItemInt_Generic(o, j, v);
5820 #------------------------------------------------------------------------------------
5822 delitem_int_utility_code = UtilityCode(
5824 #define __Pyx_DelItemInt(o, i, size, to_py_func) ((size <= sizeof(Py_ssize_t)) ? \\
5825 __Pyx_DelItemInt_Fast(o, i, size <= sizeof(long)) : \\
5826 __Pyx_DelItem_Generic(o, to_py_func(i)))
5828 static INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
5831 r = PyObject_DelItem(o, j);
5836 static INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i, int fits_long) {
5837 if (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_ass_item && likely(i >= 0))
5838 return PySequence_DelItem(o, i);
5840 PyObject *j = fits_long ? PyInt_FromLong(i) : PyLong_FromLongLong(i);
5841 return __Pyx_DelItem_Generic(o, j);
5848 #------------------------------------------------------------------------------------
5850 raise_noneattr_error_utility_code = UtilityCode(
5852 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname);
5855 static INLINE void __Pyx_RaiseNoneAttributeError(const char* attrname) {
5856 PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", attrname);
5860 raise_noneindex_error_utility_code = UtilityCode(
5862 static INLINE void __Pyx_RaiseNoneIndexingError(void);
5865 static INLINE void __Pyx_RaiseNoneIndexingError(void) {
5866 PyErr_SetString(PyExc_TypeError, "'NoneType' object is unsubscriptable");
5870 raise_none_iter_error_utility_code = UtilityCode(
5872 static INLINE void __Pyx_RaiseNoneNotIterableError(void);
5875 static INLINE void __Pyx_RaiseNoneNotIterableError(void) {
5876 PyErr_SetString(PyExc_TypeError, "'NoneType' object is iterable");
5880 raise_too_many_values_to_unpack = UtilityCode(
5882 static INLINE void __Pyx_RaiseTooManyValuesError(void);
5885 static INLINE void __Pyx_RaiseTooManyValuesError(void) {
5886 PyErr_SetString(PyExc_ValueError, "too many values to unpack");
5890 raise_need_more_values_to_unpack = UtilityCode(
5892 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);
5895 static INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
5896 PyErr_Format(PyExc_ValueError,
5897 #if PY_VERSION_HEX < 0x02050000
5898 "need more than %d value%s to unpack", (int)index,
5900 "need more than %zd value%s to unpack", index,
5902 (index == 1) ? "" : "s");
5906 #------------------------------------------------------------------------------------
5908 tuple_unpacking_error_code = UtilityCode(
5910 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
5913 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
5915 __Pyx_RaiseNoneNotIterableError();
5916 } else if (PyTuple_GET_SIZE(t) < index) {
5917 __Pyx_RaiseNeedMoreValuesError(PyTuple_GET_SIZE(t));
5919 __Pyx_RaiseTooManyValuesError();
5923 requires = [raise_none_iter_error_utility_code,
5924 raise_need_more_values_to_unpack,
5925 raise_too_many_values_to_unpack]
5928 unpacking_utility_code = UtilityCode(
5930 static PyObject *__Pyx_UnpackItem(PyObject *, Py_ssize_t index); /*proto*/
5931 static int __Pyx_EndUnpack(PyObject *); /*proto*/
5934 static PyObject *__Pyx_UnpackItem(PyObject *iter, Py_ssize_t index) {
5936 if (!(item = PyIter_Next(iter))) {
5937 if (!PyErr_Occurred()) {
5938 __Pyx_RaiseNeedMoreValuesError(index);
5944 static int __Pyx_EndUnpack(PyObject *iter) {
5946 if ((item = PyIter_Next(iter))) {
5948 __Pyx_RaiseTooManyValuesError();
5951 else if (!PyErr_Occurred())
5957 requires = [raise_need_more_values_to_unpack,
5958 raise_too_many_values_to_unpack]
5962 #------------------------------------------------------------------------------------
5964 int_pow_utility_code = UtilityCode(
5966 static INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
5969 static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
5981 if (unlikely(e<0)) return 0;
5984 t *= (b * (e&1)) | ((~e)&1); /* 1 or b */
5992 # ------------------------------ Division ------------------------------------
5994 div_int_utility_code = UtilityCode(
5996 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
5999 static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
6001 %(type)s r = a - q*b;
6002 q -= ((r != 0) & ((r ^ b) < 0));
6007 mod_int_utility_code = UtilityCode(
6009 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6012 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6013 %(type)s r = a %% b;
6014 r += ((r != 0) & ((r ^ b) < 0)) * b;
6019 mod_float_utility_code = UtilityCode(
6021 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
6024 static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
6025 %(type)s r = fmod%(math_h_modifier)s(a, b);
6026 r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
6031 cdivision_warning_utility_code = UtilityCode(
6033 static int __Pyx_cdivision_warning(void); /* proto */
6036 static int __Pyx_cdivision_warning(void) {
6037 return PyErr_WarnExplicit(PyExc_RuntimeWarning,
6038 "division with oppositely signed operands, C and Python semantics differ",
6045 'FILENAME': Naming.filename_cname,
6046 'LINENO': Naming.lineno_cname,
6050 division_overflow_test_code = UtilityCode(
6052 #define UNARY_NEG_WOULD_OVERFLOW(x) \
6053 (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))